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)
10 * 22-05-1998 DW Created
11 * 02-07-2001 CSH Implemented lookaside lists
14 /* INCLUDES *****************************************************************/
16 #include <ddk/ntddk.h>
17 #include <internal/ex.h>
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 /* FUNCTIONS *****************************************************************/
33 VOID ExpDefaultMinMax(
39 * FUNCTION: Determines the minimum and maximum depth of a new lookaside list
41 * Type = Type of executive pool
42 * Size = Size in bytes of each element in the new lookaside list
43 * MinimumDepth = Buffer to store minimum depth of the new lookaside list in
44 * MaximumDepth = Buffer to store maximum depth of the new lookaside list in
47 /* FIXME: Could probably do some serious computing here */
48 if ((PoolType == NonPagedPool) ||
49 (PoolType == NonPagedPoolMustSucceed))
63 ExpDefaultAllocate(POOL_TYPE PoolType,
67 * FUNCTION: Default allocate function for lookaside lists
69 * Type = Type of executive pool
70 * NumberOfBytes = Number of bytes to allocate
73 * Pointer to allocated memory, or NULL if there is not enough free resources
76 return ExAllocatePoolWithTag(PoolType, NumberOfBytes, Tag);
81 ExpDefaultFree(PVOID Buffer)
83 * FUNCTION: Default free function for lookaside lists
85 * Buffer = Pointer to memory to free
88 return ExFreePool(Buffer);
93 ExpInitLookasideLists()
95 InitializeListHead(&ExpNonPagedLookasideListHead);
96 KeInitializeSpinLock(&ExpNonPagedLookasideListLock);
98 InitializeListHead(&ExpPagedLookasideListHead);
99 KeInitializeSpinLock(&ExpPagedLookasideListLock);
101 /* FIXME: Possibly configure the algorithm using the registry */
102 ExpMinMaxRoutine = ExpDefaultMinMax;
109 ExAllocateFromPagedLookasideList (
110 PPAGED_LOOKASIDE_LIST Lookaside
115 /* Try to obtain an entry from the lookaside list. If that fails, try to
116 allocate a new entry with the allocate method for the lookaside list */
118 Lookaside->TotalAllocates++;
120 // ExAcquireFastMutex(&Lookaside->Lock);
122 Entry = PopEntrySList(&Lookaside->ListHead);
124 // ExReleaseFastMutex(&Lookaside->Lock);
129 Lookaside->AllocateMisses++;
131 Entry = (*Lookaside->Allocate)(Lookaside->Type,
138 #endif /* LIBCAPTIVE */
142 ExDeleteNPagedLookasideList (
143 PNPAGED_LOOKASIDE_LIST Lookaside
149 /* Pop all entries off the stack and release the resources allocated
151 while ((Entry = ExInterlockedPopEntrySList(
152 &Lookaside->ListHead,
153 &Lookaside->Lock)) != NULL)
155 (*Lookaside->Free)(Entry);
158 KeAcquireSpinLock(&ExpNonPagedLookasideListLock, &OldIrql);
159 RemoveEntryList(&Lookaside->ListEntry);
160 KeReleaseSpinLock(&ExpNonPagedLookasideListLock, OldIrql);
165 ExDeletePagedLookasideList (
166 PPAGED_LOOKASIDE_LIST Lookaside
172 /* Pop all entries off the stack and release the resources allocated
177 // ExAcquireFastMutex(&Lookaside->Lock);
179 Entry = PopEntrySList(&Lookaside->ListHead);
183 // ExReleaseFastMutex(&Lookaside->Lock);
185 (*Lookaside->Free)(Entry);
188 KeAcquireSpinLock(&ExpPagedLookasideListLock, &OldIrql);
189 RemoveEntryList(&Lookaside->ListEntry);
190 KeReleaseSpinLock(&ExpPagedLookasideListLock, OldIrql);
197 ExFreeToPagedLookasideList (
198 PPAGED_LOOKASIDE_LIST Lookaside,
202 Lookaside->TotalFrees++;
204 if (ExQueryDepthSList(&Lookaside->ListHead) >= Lookaside->MinimumDepth)
206 Lookaside->FreeMisses++;
207 (*Lookaside->Free)(Entry);
211 // ExAcquireFastMutex(&Lookaside->Lock);
212 PushEntrySList(&Lookaside->ListHead, (PSINGLE_LIST_ENTRY)Entry);
213 // ExReleaseFastMutex(&Lookaside->Lock);
217 #endif /* LIBCAPTIVE */
221 ExInitializeNPagedLookasideList (
222 PNPAGED_LOOKASIDE_LIST Lookaside,
223 PALLOCATE_FUNCTION Allocate,
230 DPRINT("Initializing nonpaged lookaside list at 0x%X\n", Lookaside);
232 Lookaside->TotalAllocates = 0;
233 Lookaside->AllocateMisses = 0;
234 Lookaside->TotalFrees = 0;
235 Lookaside->FreeMisses = 0;
236 Lookaside->Type = NonPagedPool;
237 Lookaside->Tag = Tag;
239 /* We use a field of type SINGLE_LIST_ENTRY as a link to the next entry in
240 the lookaside list so we must allocate at least sizeof(SINGLE_LIST_ENTRY) */
241 if (Size < sizeof(SINGLE_LIST_ENTRY))
242 Lookaside->Size = sizeof(SINGLE_LIST_ENTRY);
244 Lookaside->Size = Size;
247 Lookaside->Allocate = Allocate;
249 Lookaside->Allocate = ExpDefaultAllocate;
252 Lookaside->Free = Free;
254 Lookaside->Free = ExpDefaultFree;
256 ExInitializeSListHead(&Lookaside->ListHead);
257 KeInitializeSpinLock(&Lookaside->Lock);
259 /* Determine minimum and maximum number of entries on the lookaside list
260 using the configured algorithm */
264 &Lookaside->MinimumDepth,
265 &Lookaside->MaximumDepth);
267 ExInterlockedInsertTailList(
268 &ExpNonPagedLookasideListHead,
269 &Lookaside->ListEntry,
270 &ExpNonPagedLookasideListLock);
275 ExInitializePagedLookasideList (
276 PPAGED_LOOKASIDE_LIST Lookaside,
277 PALLOCATE_FUNCTION Allocate,
285 DPRINT("Initializing paged lookaside list at 0x%X\n", Lookaside);
287 Lookaside->TotalAllocates = 0;
288 Lookaside->AllocateMisses = 0;
289 Lookaside->TotalFrees = 0;
290 Lookaside->FreeMisses = 0;
291 Lookaside->Type = PagedPool;
292 Lookaside->Tag = Tag;
294 /* We use a field of type SINGLE_LIST_ENTRY as a link to the next entry in
295 the lookaside list so we must allocate at least sizeof(SINGLE_LIST_ENTRY) */
296 if (Size < sizeof(SINGLE_LIST_ENTRY))
297 Lookaside->Size = sizeof(SINGLE_LIST_ENTRY);
299 Lookaside->Size = Size;
302 Lookaside->Allocate = Allocate;
304 Lookaside->Allocate = ExpDefaultAllocate;
307 Lookaside->Free = Free;
309 Lookaside->Free = ExpDefaultFree;
311 ExInitializeSListHead(&Lookaside->ListHead);
312 //ExInitializeFastMutex(&Lookaside->Lock);
314 /* Determine minimum and maximum number of entries on the lookaside list
315 using the configured algorithm */
319 &Lookaside->MinimumDepth,
320 &Lookaside->MaximumDepth);
322 ExInterlockedInsertTailList(
323 &ExpPagedLookasideListHead,
324 &Lookaside->ListEntry,
325 &ExpPagedLookasideListLock);