xref: /reactos/ntoskrnl/ex/lookas.c (revision 4561998a)
1 /*
2 * PROJECT:         ReactOS Kernel
3 * LICENSE:         GPL - See COPYING in the top level directory
4 * FILE:            ntoskrnl/ex/lookas.c
5 * PURPOSE:         Lookaside Lists
6 * PROGRAMMERS:     Alex Ionescu (alex.ionescu@reactos.org)
7 */
8 
9 /* INCLUDES ******************************************************************/
10 
11 #include <ntoskrnl.h>
12 #define NDEBUG
13 #include <debug.h>
14 
15 #if defined (ALLOC_PRAGMA)
16 #pragma alloc_text(INIT, ExpInitLookasideLists)
17 #endif
18 
19 /* GLOBALS *******************************************************************/
20 
21 LIST_ENTRY ExpNonPagedLookasideListHead;
22 KSPIN_LOCK ExpNonPagedLookasideListLock;
23 LIST_ENTRY ExpPagedLookasideListHead;
24 KSPIN_LOCK ExpPagedLookasideListLock;
25 LIST_ENTRY ExSystemLookasideListHead;
26 LIST_ENTRY ExPoolLookasideListHead;
27 GENERAL_LOOKASIDE ExpSmallNPagedPoolLookasideLists[MAXIMUM_PROCESSORS];
28 GENERAL_LOOKASIDE ExpSmallPagedPoolLookasideLists[MAXIMUM_PROCESSORS];
29 
30 /* PRIVATE FUNCTIONS *********************************************************/
31 
32 INIT_FUNCTION
33 VOID
34 NTAPI
35 ExInitializeSystemLookasideList(IN PGENERAL_LOOKASIDE List,
36                                 IN POOL_TYPE Type,
37                                 IN ULONG Size,
38                                 IN ULONG Tag,
39                                 IN USHORT MaximumDepth,
40                                 IN PLIST_ENTRY ListHead)
41 {
42     /* Initialize the list */
43     List->Tag = Tag;
44     List->Type = Type;
45     List->Size = Size;
46     InsertHeadList(ListHead, &List->ListEntry);
47     List->MaximumDepth = MaximumDepth;
48     List->Depth = 2;
49     List->Allocate = ExAllocatePoolWithTag;
50     List->Free = ExFreePool;
51     InitializeSListHead(&List->ListHead);
52     List->TotalAllocates = 0;
53     List->AllocateHits = 0;
54     List->TotalFrees = 0;
55     List->FreeHits = 0;
56     List->LastTotalAllocates = 0;
57     List->LastAllocateHits = 0;
58 }
59 
60 INIT_FUNCTION
61 VOID
62 NTAPI
63 ExInitPoolLookasidePointers(VOID)
64 {
65     ULONG i;
66     PKPRCB Prcb = KeGetCurrentPrcb();
67     PGENERAL_LOOKASIDE Entry;
68 
69     /* Loop for all pool lists */
70     for (i = 0; i < MAXIMUM_PROCESSORS; i++)
71     {
72         /* Initialize the non-paged list */
73         Entry = &ExpSmallNPagedPoolLookasideLists[i];
74         InitializeSListHead(&Entry->ListHead);
75 
76         /* Bind to PRCB */
77         Prcb->PPNPagedLookasideList[i].P = Entry;
78         Prcb->PPNPagedLookasideList[i].L = Entry;
79 
80         /* Initialize the paged list */
81         Entry = &ExpSmallPagedPoolLookasideLists[i];
82         InitializeSListHead(&Entry->ListHead);
83 
84         /* Bind to PRCB */
85         Prcb->PPPagedLookasideList[i].P = Entry;
86         Prcb->PPPagedLookasideList[i].L = Entry;
87     }
88 }
89 
90 INIT_FUNCTION
91 VOID
92 NTAPI
93 ExpInitLookasideLists(VOID)
94 {
95     ULONG i;
96 
97     /* Initialize locks and lists */
98     InitializeListHead(&ExpNonPagedLookasideListHead);
99     InitializeListHead(&ExpPagedLookasideListHead);
100     InitializeListHead(&ExSystemLookasideListHead);
101     InitializeListHead(&ExPoolLookasideListHead);
102     KeInitializeSpinLock(&ExpNonPagedLookasideListLock);
103     KeInitializeSpinLock(&ExpPagedLookasideListLock);
104 
105     /* Initialize the system lookaside lists */
106     for (i = 0; i < MAXIMUM_PROCESSORS; i++)
107     {
108         /* Initialize the non-paged list */
109         ExInitializeSystemLookasideList(&ExpSmallNPagedPoolLookasideLists[i],
110                                         NonPagedPool,
111                                         (i + 1) * 8,
112                                         'looP',
113                                         256,
114                                         &ExPoolLookasideListHead);
115 
116         /* Initialize the paged list */
117         ExInitializeSystemLookasideList(&ExpSmallPagedPoolLookasideLists[i],
118                                         PagedPool,
119                                         (i + 1) * 8,
120                                         'looP',
121                                         256,
122                                         &ExPoolLookasideListHead);
123     }
124 }
125 
126 /* PUBLIC FUNCTIONS **********************************************************/
127 
128 /*
129  * @implemented
130  */
131 PVOID
132 NTAPI
133 ExiAllocateFromPagedLookasideList(IN PPAGED_LOOKASIDE_LIST Lookaside)
134 {
135     PVOID Entry;
136 
137     Lookaside->L.TotalAllocates++;
138     Entry = InterlockedPopEntrySList(&Lookaside->L.ListHead);
139     if (!Entry)
140     {
141         Lookaside->L.AllocateMisses++;
142         Entry = (Lookaside->L.Allocate)(Lookaside->L.Type,
143                                         Lookaside->L.Size,
144                                         Lookaside->L.Tag);
145     }
146     return Entry;
147 }
148 
149 /*
150  * @implemented
151  */
152 VOID
153 NTAPI
154 ExiFreeToPagedLookasideList(IN PPAGED_LOOKASIDE_LIST  Lookaside,
155                             IN PVOID  Entry)
156 {
157     Lookaside->L.TotalFrees++;
158     if (ExQueryDepthSList(&Lookaside->L.ListHead) >= Lookaside->L.Depth)
159     {
160         Lookaside->L.FreeMisses++;
161         (Lookaside->L.Free)(Entry);
162     }
163     else
164     {
165         InterlockedPushEntrySList(&Lookaside->L.ListHead, (PSLIST_ENTRY)Entry);
166     }
167 }
168 
169 /*
170  * @implemented
171  */
172 VOID
173 NTAPI
174 ExDeleteNPagedLookasideList(IN PNPAGED_LOOKASIDE_LIST Lookaside)
175 {
176     KIRQL OldIrql;
177     PVOID Entry;
178 
179     /* Pop all entries off the stack and release their resources */
180     for (;;)
181     {
182         Entry = InterlockedPopEntrySList(&Lookaside->L.ListHead);
183         if (!Entry) break;
184         (*Lookaside->L.Free)(Entry);
185     }
186 
187     /* Remove from list */
188     KeAcquireSpinLock(&ExpNonPagedLookasideListLock, &OldIrql);
189     RemoveEntryList(&Lookaside->L.ListEntry);
190     KeReleaseSpinLock(&ExpNonPagedLookasideListLock, OldIrql);
191 }
192 
193 /*
194  * @implemented
195  */
196 VOID
197 NTAPI
198 ExDeletePagedLookasideList(IN PPAGED_LOOKASIDE_LIST Lookaside)
199 {
200     KIRQL OldIrql;
201     PVOID Entry;
202 
203     /* Pop all entries off the stack and release their resources */
204     for (;;)
205     {
206         Entry = InterlockedPopEntrySList(&Lookaside->L.ListHead);
207         if (!Entry) break;
208         (*Lookaside->L.Free)(Entry);
209     }
210 
211     /* Remove from list */
212     KeAcquireSpinLock(&ExpPagedLookasideListLock, &OldIrql);
213     RemoveEntryList(&Lookaside->L.ListEntry);
214     KeReleaseSpinLock(&ExpPagedLookasideListLock, OldIrql);
215 }
216 
217 /*
218  * @implemented
219  */
220 VOID
221 NTAPI
222 ExInitializeNPagedLookasideList(IN PNPAGED_LOOKASIDE_LIST Lookaside,
223                                 IN PALLOCATE_FUNCTION Allocate OPTIONAL,
224                                 IN PFREE_FUNCTION Free OPTIONAL,
225                                 IN ULONG Flags,
226                                 IN SIZE_T Size,
227                                 IN ULONG Tag,
228                                 IN USHORT Depth)
229 {
230     /* Initialize the Header */
231     ExInitializeSListHead(&Lookaside->L.ListHead);
232     Lookaside->L.TotalAllocates = 0;
233     Lookaside->L.AllocateMisses = 0;
234     Lookaside->L.TotalFrees = 0;
235     Lookaside->L.FreeMisses = 0;
236     Lookaside->L.Type = NonPagedPool | Flags;
237     Lookaside->L.Tag = Tag;
238     Lookaside->L.Size = (ULONG)Size;
239     Lookaside->L.Depth = 4;
240     Lookaside->L.MaximumDepth = 256;
241     Lookaside->L.LastTotalAllocates = 0;
242     Lookaside->L.LastAllocateMisses = 0;
243 
244     /* Set the Allocate/Free Routines */
245     if (Allocate)
246     {
247         Lookaside->L.Allocate = Allocate;
248     }
249     else
250     {
251         Lookaside->L.Allocate = ExAllocatePoolWithTag;
252     }
253 
254     if (Free)
255     {
256         Lookaside->L.Free = Free;
257     }
258     else
259     {
260         Lookaside->L.Free = ExFreePool;
261     }
262 
263     /* Insert it into the list */
264     ExInterlockedInsertTailList(&ExpNonPagedLookasideListHead,
265                                 &Lookaside->L.ListEntry,
266                                 &ExpNonPagedLookasideListLock);
267 }
268 
269 /*
270  * @implemented
271  */
272 VOID
273 NTAPI
274 ExInitializePagedLookasideList(IN PPAGED_LOOKASIDE_LIST Lookaside,
275                                IN PALLOCATE_FUNCTION Allocate OPTIONAL,
276                                IN PFREE_FUNCTION Free OPTIONAL,
277                                IN ULONG Flags,
278                                IN SIZE_T Size,
279                                IN ULONG Tag,
280                                IN USHORT Depth)
281 {
282     /* Initialize the Header */
283     ExInitializeSListHead(&Lookaside->L.ListHead);
284     Lookaside->L.TotalAllocates = 0;
285     Lookaside->L.AllocateMisses = 0;
286     Lookaside->L.TotalFrees = 0;
287     Lookaside->L.FreeMisses = 0;
288     Lookaside->L.Type = PagedPool | Flags;
289     Lookaside->L.Tag = Tag;
290     Lookaside->L.Size = (ULONG)Size;
291     Lookaside->L.Depth = 4;
292     Lookaside->L.MaximumDepth = 256;
293     Lookaside->L.LastTotalAllocates = 0;
294     Lookaside->L.LastAllocateMisses = 0;
295 
296     /* Set the Allocate/Free Routines */
297     if (Allocate)
298     {
299         Lookaside->L.Allocate = Allocate;
300     }
301     else
302     {
303         Lookaside->L.Allocate = ExAllocatePoolWithTag;
304     }
305 
306     if (Free)
307     {
308         Lookaside->L.Free = Free;
309     }
310     else
311     {
312         Lookaside->L.Free = ExFreePool;
313     }
314 
315     /* Insert it into the list */
316     ExInterlockedInsertTailList(&ExpPagedLookasideListHead,
317                                 &Lookaside->L.ListEntry,
318                                 &ExpPagedLookasideListLock);
319 }
320 
321 /* EOF */
322