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 *****************************************************************/
18 // #define NONAMELESSUNION
20 #include <ddk/ntddk.h>
21 #include <internal/ex.h>
23 #include <internal/debug.h>
25 /* GLOBALS *******************************************************************/
27 LIST_ENTRY ExpNonPagedLookasideListHead;
28 KSPIN_LOCK ExpNonPagedLookasideListLock;
30 LIST_ENTRY ExpPagedLookasideListHead;
31 KSPIN_LOCK ExpPagedLookasideListLock;
33 PLOOKASIDE_MINMAX_ROUTINE ExpMinMaxRoutine;
35 #define LookasideListLock(l)(&(l->Obsoleted))
37 /* FUNCTIONS *****************************************************************/
43 PSLIST_HEADER ListHead
46 PSINGLE_LIST_ENTRY ListEntry;
48 ListEntry = ListHead->Next.Next;
51 ListHead->Next.Next = ListEntry->Next;
63 PSLIST_HEADER ListHead,
64 PSINGLE_LIST_ENTRY Entry
67 Entry->Next = ListHead->Next.Next;
68 ListHead->Next.Next = Entry;
74 VOID ExpDefaultMinMax(
80 * FUNCTION: Determines the minimum and maximum depth of a new lookaside list
82 * Type = Type of executive pool
83 * Size = Size in bytes of each element in the new lookaside list
84 * MinimumDepth = Buffer to store minimum depth of the new lookaside list in
85 * MaximumDepth = Buffer to store maximum depth of the new lookaside list in
88 /* FIXME: Could probably do some serious computing here */
89 if ((PoolType == NonPagedPool) ||
90 (PoolType == NonPagedPoolMustSucceed))
104 ExpDefaultAllocate(POOL_TYPE PoolType,
108 * FUNCTION: Default allocate function for lookaside lists
110 * Type = Type of executive pool
111 * NumberOfBytes = Number of bytes to allocate
114 * Pointer to allocated memory, or NULL if there is not enough free resources
117 return ExAllocatePoolWithTag(PoolType, NumberOfBytes, Tag);
122 ExpDefaultFree(PVOID Buffer)
124 * FUNCTION: Default free function for lookaside lists
126 * Buffer = Pointer to memory to free
129 return ExFreePool(Buffer);
134 ExpInitLookasideLists()
136 InitializeListHead(&ExpNonPagedLookasideListHead);
137 KeInitializeSpinLock(&ExpNonPagedLookasideListLock);
139 InitializeListHead(&ExpPagedLookasideListHead);
140 KeInitializeSpinLock(&ExpPagedLookasideListLock);
142 /* FIXME: Possibly configure the algorithm using the registry */
143 ExpMinMaxRoutine = ExpDefaultMinMax;
150 ExiAllocateFromPagedLookasideList (
151 PPAGED_LOOKASIDE_LIST Lookaside
156 /* Try to obtain an entry from the lookaside list. If that fails, try to
157 allocate a new entry with the allocate method for the lookaside list */
159 Lookaside->TotalAllocates++;
161 // ExAcquireFastMutex(LookasideListLock(Lookaside));
163 Entry = PopEntrySList(&Lookaside->ListHead);
165 // ExReleaseFastMutex(LookasideListLock(Lookaside));
170 Lookaside->AllocateMisses++;
172 Entry = (*Lookaside->Allocate)(Lookaside->Type,
179 #endif /* LIBCAPTIVE */
186 ExDeleteNPagedLookasideList (
187 PNPAGED_LOOKASIDE_LIST Lookaside
193 /* Pop all entries off the stack and release the resources allocated
195 while ((Entry = ExInterlockedPopEntrySList(
196 &Lookaside->ListHead,
197 LookasideListLock(Lookaside))) != NULL)
199 (*Lookaside->Free)(Entry);
202 KeAcquireSpinLock(&ExpNonPagedLookasideListLock, &OldIrql);
203 RemoveEntryList(&Lookaside->ListEntry);
204 KeReleaseSpinLock(&ExpNonPagedLookasideListLock, OldIrql);
213 ExDeletePagedLookasideList (
214 PPAGED_LOOKASIDE_LIST Lookaside
220 /* Pop all entries off the stack and release the resources allocated
225 // ExAcquireFastMutex(LookasideListLock(Lookaside));
227 Entry = PopEntrySList(&Lookaside->ListHead);
231 // ExReleaseFastMutex(LookasideListLock(Lookaside));
233 (*Lookaside->Free)(Entry);
236 KeAcquireSpinLock(&ExpPagedLookasideListLock, &OldIrql);
237 RemoveEntryList(&Lookaside->ListEntry);
238 KeReleaseSpinLock(&ExpPagedLookasideListLock, OldIrql);
245 ExiFreeToPagedLookasideList (
246 PPAGED_LOOKASIDE_LIST Lookaside,
250 Lookaside->TotalFrees++;
252 if (ExQueryDepthSList(&Lookaside->ListHead) >= Lookaside->Depth)
254 Lookaside->FreeMisses++;
255 (*Lookaside->Free)(Entry);
259 // ExAcquireFastMutex(LookasideListLock(Lookaside));
260 PushEntrySList(&Lookaside->ListHead, (PSINGLE_LIST_ENTRY)Entry);
261 // ExReleaseFastMutex(LookasideListLock(Lookaside));
265 #endif /* LIBCAPTIVE */
272 ExInitializeNPagedLookasideList (
273 PNPAGED_LOOKASIDE_LIST Lookaside,
274 PALLOCATE_FUNCTION Allocate,
281 DPRINT("Initializing nonpaged lookaside list at 0x%X\n", Lookaside);
283 Lookaside->TotalAllocates = 0;
284 Lookaside->AllocateMisses = 0;
285 Lookaside->TotalFrees = 0;
286 Lookaside->FreeMisses = 0;
287 Lookaside->Type = NonPagedPool;
288 Lookaside->Tag = Tag;
290 /* We use a field of type SINGLE_LIST_ENTRY as a link to the next entry in
291 the lookaside list so we must allocate at least sizeof(SINGLE_LIST_ENTRY) */
292 if (Size < sizeof(SINGLE_LIST_ENTRY))
293 Lookaside->Size = sizeof(SINGLE_LIST_ENTRY);
295 Lookaside->Size = Size;
298 Lookaside->Allocate = Allocate;
300 Lookaside->Allocate = ExpDefaultAllocate;
303 Lookaside->Free = Free;
305 Lookaside->Free = ExpDefaultFree;
307 ExInitializeSListHead(&Lookaside->ListHead);
308 KeInitializeSpinLock(LookasideListLock(Lookaside));
310 /* Determine minimum and maximum number of entries on the lookaside list
311 using the configured algorithm */
316 &Lookaside->MaximumDepth);
318 ExInterlockedInsertTailList(
319 &ExpNonPagedLookasideListHead,
320 &Lookaside->ListEntry,
321 &ExpNonPagedLookasideListLock);
330 ExInitializePagedLookasideList (
331 PPAGED_LOOKASIDE_LIST Lookaside,
332 PALLOCATE_FUNCTION Allocate,
340 DPRINT("Initializing paged lookaside list at 0x%X\n", Lookaside);
342 Lookaside->TotalAllocates = 0;
343 Lookaside->AllocateMisses = 0;
344 Lookaside->TotalFrees = 0;
345 Lookaside->FreeMisses = 0;
346 Lookaside->Type = PagedPool;
347 Lookaside->Tag = Tag;
349 /* We use a field of type SINGLE_LIST_ENTRY as a link to the next entry in
350 the lookaside list so we must allocate at least sizeof(SINGLE_LIST_ENTRY) */
351 if (Size < sizeof(SINGLE_LIST_ENTRY))
352 Lookaside->Size = sizeof(SINGLE_LIST_ENTRY);
354 Lookaside->Size = Size;
357 Lookaside->Allocate = Allocate;
359 Lookaside->Allocate = ExpDefaultAllocate;
362 Lookaside->Free = Free;
364 Lookaside->Free = ExpDefaultFree;
366 ExInitializeSListHead(&Lookaside->ListHead);
367 //ExInitializeFastMutex(LookasideListLock(Lookaside));
369 /* Determine minimum and maximum number of entries on the lookaside list
370 using the configured algorithm */
375 &Lookaside->MaximumDepth);
377 ExInterlockedInsertTailList(
378 &ExpPagedLookasideListHead,
379 &Lookaside->ListEntry,
380 &ExpPagedLookasideListLock);