3 * COPYRIGHT: See COPYING in the top level directory
4 * PROJECT: ReactOS kernel
5 * FILE: ntoskrnl/ex/lookas.c
6 * PURPOSE: Lookaside lists
7 * PROGRAMMERS: David Welch (welch@mcmail.com)
8 * Casper S. Hornstrup (chorns@users.sourceforge.net)
9 * TODO: Use InterlockedXxxEntrySList for binary compatibility
11 * 22-05-1998 DW Created
12 * 02-07-2001 CSH Implemented lookaside lists
15 /* INCLUDES *****************************************************************/
19 #include <internal/debug.h>
21 /* GLOBALS *******************************************************************/
23 LIST_ENTRY ExpNonPagedLookasideListHead
;
24 KSPIN_LOCK ExpNonPagedLookasideListLock
;
26 LIST_ENTRY ExpPagedLookasideListHead
;
27 KSPIN_LOCK ExpPagedLookasideListLock
;
29 PLOOKASIDE_MINMAX_ROUTINE ExpMinMaxRoutine
;
31 #define LookasideListLock(l)(&(l->Obsoleted))
33 /* FUNCTIONS *****************************************************************/
39 PSLIST_HEADER ListHead
42 PSINGLE_LIST_ENTRY ListEntry
;
44 ListEntry
= ListHead
->Next
.Next
;
47 ListHead
->Next
.Next
= ListEntry
->Next
;
59 PSLIST_HEADER ListHead
,
60 PSINGLE_LIST_ENTRY Entry
63 Entry
->Next
= ListHead
->Next
.Next
;
64 ListHead
->Next
.Next
= Entry
;
70 VOID
ExpDefaultMinMax(
76 * FUNCTION: Determines the minimum and maximum depth of a new lookaside list
78 * Type = Type of executive pool
79 * Size = Size in bytes of each element in the new lookaside list
80 * MinimumDepth = Buffer to store minimum depth of the new lookaside list in
81 * MaximumDepth = Buffer to store maximum depth of the new lookaside list in
84 /* FIXME: Could probably do some serious computing here */
85 if ((PoolType
== NonPagedPool
) ||
86 (PoolType
== NonPagedPoolMustSucceed
))
100 ExpDefaultAllocate(POOL_TYPE PoolType
,
104 * FUNCTION: Default allocate function for lookaside lists
106 * Type = Type of executive pool
107 * NumberOfBytes = Number of bytes to allocate
110 * Pointer to allocated memory, or NULL if there is not enough free resources
113 return ExAllocatePoolWithTag(PoolType
, NumberOfBytes
, Tag
);
118 ExpDefaultFree(PVOID Buffer
)
120 * FUNCTION: Default free function for lookaside lists
122 * Buffer = Pointer to memory to free
130 ExpInitLookasideLists()
132 InitializeListHead(&ExpNonPagedLookasideListHead
);
133 KeInitializeSpinLock(&ExpNonPagedLookasideListLock
);
135 InitializeListHead(&ExpPagedLookasideListHead
);
136 KeInitializeSpinLock(&ExpPagedLookasideListLock
);
138 /* FIXME: Possibly configure the algorithm using the registry */
139 ExpMinMaxRoutine
= ExpDefaultMinMax
;
145 ExiAllocateFromPagedLookasideList (
146 PPAGED_LOOKASIDE_LIST Lookaside
151 /* Try to obtain an entry from the lookaside list. If that fails, try to
152 allocate a new entry with the allocate method for the lookaside list */
154 Lookaside
->TotalAllocates
++;
156 // ExAcquireFastMutex(LookasideListLock(Lookaside));
158 Entry
= PopEntrySList(&Lookaside
->ListHead
);
160 // ExReleaseFastMutex(LookasideListLock(Lookaside));
165 Lookaside
->AllocateMisses
++;
167 Entry
= (*Lookaside
->Allocate
)(Lookaside
->Type
,
180 ExDeleteNPagedLookasideList (
181 PNPAGED_LOOKASIDE_LIST Lookaside
187 /* Pop all entries off the stack and release the resources allocated
189 while ((Entry
= ExInterlockedPopEntrySList(
190 &Lookaside
->ListHead
,
191 LookasideListLock(Lookaside
))) != NULL
)
193 (*Lookaside
->Free
)(Entry
);
196 KeAcquireSpinLock(&ExpNonPagedLookasideListLock
, &OldIrql
);
197 RemoveEntryList(&Lookaside
->ListEntry
);
198 KeReleaseSpinLock(&ExpNonPagedLookasideListLock
, OldIrql
);
207 ExDeletePagedLookasideList (
208 PPAGED_LOOKASIDE_LIST Lookaside
214 /* Pop all entries off the stack and release the resources allocated
219 // ExAcquireFastMutex(LookasideListLock(Lookaside));
221 Entry
= PopEntrySList(&Lookaside
->ListHead
);
225 // ExReleaseFastMutex(LookasideListLock(Lookaside));
227 (*Lookaside
->Free
)(Entry
);
230 KeAcquireSpinLock(&ExpPagedLookasideListLock
, &OldIrql
);
231 RemoveEntryList(&Lookaside
->ListEntry
);
232 KeReleaseSpinLock(&ExpPagedLookasideListLock
, OldIrql
);
238 ExiFreeToPagedLookasideList (
239 PPAGED_LOOKASIDE_LIST Lookaside
,
243 Lookaside
->TotalFrees
++;
245 if (ExQueryDepthSList(&Lookaside
->ListHead
) >= Lookaside
->Depth
)
247 Lookaside
->FreeMisses
++;
248 (*Lookaside
->Free
)(Entry
);
252 // ExAcquireFastMutex(LookasideListLock(Lookaside));
253 PushEntrySList(&Lookaside
->ListHead
, (PSINGLE_LIST_ENTRY
)Entry
);
254 // ExReleaseFastMutex(LookasideListLock(Lookaside));
264 ExInitializeNPagedLookasideList (
265 PNPAGED_LOOKASIDE_LIST Lookaside
,
266 PALLOCATE_FUNCTION Allocate
,
273 DPRINT("Initializing nonpaged lookaside list at 0x%X\n", Lookaside
);
275 Lookaside
->TotalAllocates
= 0;
276 Lookaside
->AllocateMisses
= 0;
277 Lookaside
->TotalFrees
= 0;
278 Lookaside
->FreeMisses
= 0;
279 Lookaside
->Type
= NonPagedPool
;
280 Lookaside
->Tag
= Tag
;
282 /* We use a field of type SINGLE_LIST_ENTRY as a link to the next entry in
283 the lookaside list so we must allocate at least sizeof(SINGLE_LIST_ENTRY) */
284 if (Size
< sizeof(SINGLE_LIST_ENTRY
))
285 Lookaside
->Size
= sizeof(SINGLE_LIST_ENTRY
);
287 Lookaside
->Size
= Size
;
290 Lookaside
->Allocate
= Allocate
;
292 Lookaside
->Allocate
= ExpDefaultAllocate
;
295 Lookaside
->Free
= Free
;
297 Lookaside
->Free
= ExpDefaultFree
;
299 ExInitializeSListHead(&Lookaside
->ListHead
);
300 KeInitializeSpinLock(LookasideListLock(Lookaside
));
302 /* Determine minimum and maximum number of entries on the lookaside list
303 using the configured algorithm */
308 &Lookaside
->MaximumDepth
);
310 ExInterlockedInsertTailList(
311 &ExpNonPagedLookasideListHead
,
312 &Lookaside
->ListEntry
,
313 &ExpNonPagedLookasideListLock
);
322 ExInitializePagedLookasideList (
323 PPAGED_LOOKASIDE_LIST Lookaside
,
324 PALLOCATE_FUNCTION Allocate
,
332 DPRINT("Initializing paged lookaside list at 0x%X\n", Lookaside
);
334 Lookaside
->TotalAllocates
= 0;
335 Lookaside
->AllocateMisses
= 0;
336 Lookaside
->TotalFrees
= 0;
337 Lookaside
->FreeMisses
= 0;
338 Lookaside
->Type
= PagedPool
;
339 Lookaside
->Tag
= Tag
;
341 /* We use a field of type SINGLE_LIST_ENTRY as a link to the next entry in
342 the lookaside list so we must allocate at least sizeof(SINGLE_LIST_ENTRY) */
343 if (Size
< sizeof(SINGLE_LIST_ENTRY
))
344 Lookaside
->Size
= sizeof(SINGLE_LIST_ENTRY
);
346 Lookaside
->Size
= Size
;
349 Lookaside
->Allocate
= Allocate
;
351 Lookaside
->Allocate
= ExpDefaultAllocate
;
354 Lookaside
->Free
= Free
;
356 Lookaside
->Free
= ExpDefaultFree
;
358 ExInitializeSListHead(&Lookaside
->ListHead
);
359 //ExInitializeFastMutex(LookasideListLock(Lookaside));
361 /* Determine minimum and maximum number of entries on the lookaside list
362 using the configured algorithm */
367 &Lookaside
->MaximumDepth
);
369 ExInterlockedInsertTailList(
370 &ExpPagedLookasideListHead
,
371 &Lookaside
->ListEntry
,
372 &ExpPagedLookasideListLock
);