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