- Update to trunk
[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 INIT_FUNCTION
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 VOID
61 NTAPI
62 INIT_FUNCTION
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 INIT_FUNCTION
93 ExpInitLookasideLists()
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 = 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 = 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(&ExpNonPagedLookasideListHead,
317 &Lookaside->L.ListEntry,
318 &ExpNonPagedLookasideListLock);
319 }
320
321 /* EOF */