1 /* $Id: lookas.c,v 1.11 2003/08/14 18:30:28 silverblade Exp $
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
;
149 ExiAllocateFromPagedLookasideList (
150 PPAGED_LOOKASIDE_LIST Lookaside
155 /* Try to obtain an entry from the lookaside list. If that fails, try to
156 allocate a new entry with the allocate method for the lookaside list */
158 Lookaside
->TotalAllocates
++;
160 // ExAcquireFastMutex(LookasideListLock(Lookaside));
162 Entry
= PopEntrySList(&Lookaside
->ListHead
);
164 // ExReleaseFastMutex(LookasideListLock(Lookaside));
169 Lookaside
->AllocateMisses
++;
171 Entry
= (*Lookaside
->Allocate
)(Lookaside
->Type
,
184 ExDeleteNPagedLookasideList (
185 PNPAGED_LOOKASIDE_LIST Lookaside
191 /* Pop all entries off the stack and release the resources allocated
193 while ((Entry
= ExInterlockedPopEntrySList(
194 &Lookaside
->ListHead
,
195 LookasideListLock(Lookaside
))) != NULL
)
197 (*Lookaside
->Free
)(Entry
);
200 KeAcquireSpinLock(&ExpNonPagedLookasideListLock
, &OldIrql
);
201 RemoveEntryList(&Lookaside
->ListEntry
);
202 KeReleaseSpinLock(&ExpNonPagedLookasideListLock
, OldIrql
);
211 ExDeletePagedLookasideList (
212 PPAGED_LOOKASIDE_LIST Lookaside
218 /* Pop all entries off the stack and release the resources allocated
223 // ExAcquireFastMutex(LookasideListLock(Lookaside));
225 Entry
= PopEntrySList(&Lookaside
->ListHead
);
229 // ExReleaseFastMutex(LookasideListLock(Lookaside));
231 (*Lookaside
->Free
)(Entry
);
234 KeAcquireSpinLock(&ExpPagedLookasideListLock
, &OldIrql
);
235 RemoveEntryList(&Lookaside
->ListEntry
);
236 KeReleaseSpinLock(&ExpPagedLookasideListLock
, OldIrql
);
242 ExiFreeToPagedLookasideList (
243 PPAGED_LOOKASIDE_LIST Lookaside
,
247 Lookaside
->TotalFrees
++;
249 if (ExQueryDepthSList(&Lookaside
->ListHead
) >= Lookaside
->Depth
)
251 Lookaside
->FreeMisses
++;
252 (*Lookaside
->Free
)(Entry
);
256 // ExAcquireFastMutex(LookasideListLock(Lookaside));
257 PushEntrySList(&Lookaside
->ListHead
, (PSINGLE_LIST_ENTRY
)Entry
);
258 // ExReleaseFastMutex(LookasideListLock(Lookaside));
268 ExInitializeNPagedLookasideList (
269 PNPAGED_LOOKASIDE_LIST Lookaside
,
270 PALLOCATE_FUNCTION Allocate
,
277 DPRINT("Initializing nonpaged lookaside list at 0x%X\n", Lookaside
);
279 Lookaside
->TotalAllocates
= 0;
280 Lookaside
->AllocateMisses
= 0;
281 Lookaside
->TotalFrees
= 0;
282 Lookaside
->FreeMisses
= 0;
283 Lookaside
->Type
= NonPagedPool
;
284 Lookaside
->Tag
= Tag
;
286 /* We use a field of type SINGLE_LIST_ENTRY as a link to the next entry in
287 the lookaside list so we must allocate at least sizeof(SINGLE_LIST_ENTRY) */
288 if (Size
< sizeof(SINGLE_LIST_ENTRY
))
289 Lookaside
->Size
= sizeof(SINGLE_LIST_ENTRY
);
291 Lookaside
->Size
= Size
;
294 Lookaside
->Allocate
= Allocate
;
296 Lookaside
->Allocate
= ExpDefaultAllocate
;
299 Lookaside
->Free
= Free
;
301 Lookaside
->Free
= ExpDefaultFree
;
303 ExInitializeSListHead(&Lookaside
->ListHead
);
304 KeInitializeSpinLock(LookasideListLock(Lookaside
));
306 /* Determine minimum and maximum number of entries on the lookaside list
307 using the configured algorithm */
312 &Lookaside
->MaximumDepth
);
314 ExInterlockedInsertTailList(
315 &ExpNonPagedLookasideListHead
,
316 &Lookaside
->ListEntry
,
317 &ExpNonPagedLookasideListLock
);
326 ExInitializePagedLookasideList (
327 PPAGED_LOOKASIDE_LIST Lookaside
,
328 PALLOCATE_FUNCTION Allocate
,
336 DPRINT("Initializing paged lookaside list at 0x%X\n", Lookaside
);
338 Lookaside
->TotalAllocates
= 0;
339 Lookaside
->AllocateMisses
= 0;
340 Lookaside
->TotalFrees
= 0;
341 Lookaside
->FreeMisses
= 0;
342 Lookaside
->Type
= PagedPool
;
343 Lookaside
->Tag
= Tag
;
345 /* We use a field of type SINGLE_LIST_ENTRY as a link to the next entry in
346 the lookaside list so we must allocate at least sizeof(SINGLE_LIST_ENTRY) */
347 if (Size
< sizeof(SINGLE_LIST_ENTRY
))
348 Lookaside
->Size
= sizeof(SINGLE_LIST_ENTRY
);
350 Lookaside
->Size
= Size
;
353 Lookaside
->Allocate
= Allocate
;
355 Lookaside
->Allocate
= ExpDefaultAllocate
;
358 Lookaside
->Free
= Free
;
360 Lookaside
->Free
= ExpDefaultFree
;
362 ExInitializeSListHead(&Lookaside
->ListHead
);
363 //ExInitializeFastMutex(LookasideListLock(Lookaside));
365 /* Determine minimum and maximum number of entries on the lookaside list
366 using the configured algorithm */
371 &Lookaside
->MaximumDepth
);
373 ExInterlockedInsertTailList(
374 &ExpPagedLookasideListHead
,
375 &Lookaside
->ListEntry
,
376 &ExpPagedLookasideListLock
);