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[NUMBER_POOL_LOOKASIDE_LISTS];
24 GENERAL_LOOKASIDE ExpSmallPagedPoolLookasideLists[NUMBER_POOL_LOOKASIDE_LISTS];
25
26 /* PRIVATE FUNCTIONS *********************************************************/
27
28 CODE_SEG("INIT")
29 VOID
30 NTAPI
ExInitializeSystemLookasideList(IN PGENERAL_LOOKASIDE List,IN POOL_TYPE Type,IN ULONG Size,IN ULONG Tag,IN USHORT MaximumDepth,IN PLIST_ENTRY ListHead)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
ExInitPoolLookasidePointers(VOID)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
ExpInitLookasideLists(VOID)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 < NUMBER_POOL_LOOKASIDE_LISTS; 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
ExiAllocateFromPagedLookasideList(IN PPAGED_LOOKASIDE_LIST Lookaside)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
ExiFreeToPagedLookasideList(IN PPAGED_LOOKASIDE_LIST Lookaside,IN PVOID Entry)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
ExDeleteNPagedLookasideList(IN PNPAGED_LOOKASIDE_LIST Lookaside)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
ExDeletePagedLookasideList(IN PPAGED_LOOKASIDE_LIST Lookaside)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
ExInitializeNPagedLookasideList(IN PNPAGED_LOOKASIDE_LIST Lookaside,IN PALLOCATE_FUNCTION Allocate OPTIONAL,IN PFREE_FUNCTION Free OPTIONAL,IN ULONG Flags,IN SIZE_T Size,IN ULONG Tag,IN USHORT Depth)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
ExInitializePagedLookasideList(IN PPAGED_LOOKASIDE_LIST Lookaside,IN PALLOCATE_FUNCTION Allocate OPTIONAL,IN PFREE_FUNCTION Free OPTIONAL,IN ULONG Flags,IN SIZE_T Size,IN ULONG Tag,IN USHORT Depth)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