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