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