3 * COPYRIGHT: See COPYING in the top level directory
4 * PROJECT: ReactOS kernel
5 * FILE: ntoskrnl/ex/lookas.c
6 * PURPOSE: Lookaside lists
8 * PROGRAMMERS: David Welch (welch@mcmail.com)
9 * Casper S. Hornstrup (chorns@users.sourceforge.net)
14 * TODO: Use InterlockedXxxEntrySList for binary compatibility
17 /* INCLUDES *****************************************************************/
21 #include <internal/debug.h>
23 /* GLOBALS *******************************************************************/
25 LIST_ENTRY ExpNonPagedLookasideListHead
;
26 KSPIN_LOCK ExpNonPagedLookasideListLock
;
28 LIST_ENTRY ExpPagedLookasideListHead
;
29 KSPIN_LOCK ExpPagedLookasideListLock
;
31 PLOOKASIDE_MINMAX_ROUTINE ExpMinMaxRoutine
;
33 #define LookasideListLock(l)(&(l->Obsoleted))
35 /* FUNCTIONS *****************************************************************/
41 PSLIST_HEADER ListHead
44 PSINGLE_LIST_ENTRY ListEntry
;
46 ListEntry
= ListHead
->Next
.Next
;
49 ListHead
->Next
.Next
= ListEntry
->Next
;
61 PSLIST_HEADER ListHead
,
62 PSINGLE_LIST_ENTRY Entry
65 Entry
->Next
= ListHead
->Next
.Next
;
66 ListHead
->Next
.Next
= Entry
;
72 VOID
ExpDefaultMinMax(
78 * FUNCTION: Determines the minimum and maximum depth of a new lookaside list
80 * Type = Type of executive pool
81 * Size = Size in bytes of each element in the new lookaside list
82 * MinimumDepth = Buffer to store minimum depth of the new lookaside list in
83 * MaximumDepth = Buffer to store maximum depth of the new lookaside list in
86 /* FIXME: Could probably do some serious computing here */
87 if ((PoolType
== NonPagedPool
) ||
88 (PoolType
== NonPagedPoolMustSucceed
))
102 ExpDefaultAllocate(POOL_TYPE PoolType
,
106 * FUNCTION: Default allocate function for lookaside lists
108 * Type = Type of executive pool
109 * NumberOfBytes = Number of bytes to allocate
112 * Pointer to allocated memory, or NULL if there is not enough free resources
115 return ExAllocatePoolWithTag(PoolType
, NumberOfBytes
, Tag
);
120 ExpDefaultFree(PVOID Buffer
)
122 * FUNCTION: Default free function for lookaside lists
124 * Buffer = Pointer to memory to free
132 ExpInitLookasideLists()
134 InitializeListHead(&ExpNonPagedLookasideListHead
);
135 KeInitializeSpinLock(&ExpNonPagedLookasideListLock
);
137 InitializeListHead(&ExpPagedLookasideListHead
);
138 KeInitializeSpinLock(&ExpPagedLookasideListLock
);
140 /* FIXME: Possibly configure the algorithm using the registry */
141 ExpMinMaxRoutine
= ExpDefaultMinMax
;
147 ExiAllocateFromPagedLookasideList (
148 PPAGED_LOOKASIDE_LIST Lookaside
153 /* Try to obtain an entry from the lookaside list. If that fails, try to
154 allocate a new entry with the allocate method for the lookaside list */
156 Lookaside
->TotalAllocates
++;
158 // ExAcquireFastMutex(LookasideListLock(Lookaside));
160 Entry
= PopEntrySList(&Lookaside
->ListHead
);
162 // ExReleaseFastMutex(LookasideListLock(Lookaside));
167 Lookaside
->AllocateMisses
++;
169 Entry
= (*Lookaside
->Allocate
)(Lookaside
->Type
,
182 ExDeleteNPagedLookasideList (
183 PNPAGED_LOOKASIDE_LIST Lookaside
189 /* Pop all entries off the stack and release the resources allocated
191 while ((Entry
= ExInterlockedPopEntrySList(
192 &Lookaside
->ListHead
,
193 LookasideListLock(Lookaside
))) != NULL
)
195 (*Lookaside
->Free
)(Entry
);
198 KeAcquireSpinLock(&ExpNonPagedLookasideListLock
, &OldIrql
);
199 RemoveEntryList(&Lookaside
->ListEntry
);
200 KeReleaseSpinLock(&ExpNonPagedLookasideListLock
, OldIrql
);
209 ExDeletePagedLookasideList (
210 PPAGED_LOOKASIDE_LIST Lookaside
216 /* Pop all entries off the stack and release the resources allocated
221 // ExAcquireFastMutex(LookasideListLock(Lookaside));
223 Entry
= PopEntrySList(&Lookaside
->ListHead
);
227 // ExReleaseFastMutex(LookasideListLock(Lookaside));
229 (*Lookaside
->Free
)(Entry
);
232 KeAcquireSpinLock(&ExpPagedLookasideListLock
, &OldIrql
);
233 RemoveEntryList(&Lookaside
->ListEntry
);
234 KeReleaseSpinLock(&ExpPagedLookasideListLock
, OldIrql
);
240 ExiFreeToPagedLookasideList (
241 PPAGED_LOOKASIDE_LIST Lookaside
,
245 Lookaside
->TotalFrees
++;
247 if (ExQueryDepthSList(&Lookaside
->ListHead
) >= Lookaside
->Depth
)
249 Lookaside
->FreeMisses
++;
250 (*Lookaside
->Free
)(Entry
);
254 // ExAcquireFastMutex(LookasideListLock(Lookaside));
255 PushEntrySList(&Lookaside
->ListHead
, (PSINGLE_LIST_ENTRY
)Entry
);
256 // ExReleaseFastMutex(LookasideListLock(Lookaside));
266 ExInitializeNPagedLookasideList (
267 PNPAGED_LOOKASIDE_LIST Lookaside
,
268 PALLOCATE_FUNCTION Allocate
,
275 DPRINT("Initializing nonpaged lookaside list at 0x%X\n", Lookaside
);
277 Lookaside
->TotalAllocates
= 0;
278 Lookaside
->AllocateMisses
= 0;
279 Lookaside
->TotalFrees
= 0;
280 Lookaside
->FreeMisses
= 0;
281 Lookaside
->Type
= NonPagedPool
;
282 Lookaside
->Tag
= Tag
;
284 /* We use a field of type SINGLE_LIST_ENTRY as a link to the next entry in
285 the lookaside list so we must allocate at least sizeof(SINGLE_LIST_ENTRY) */
286 if (Size
< sizeof(SINGLE_LIST_ENTRY
))
287 Lookaside
->Size
= sizeof(SINGLE_LIST_ENTRY
);
289 Lookaside
->Size
= Size
;
292 Lookaside
->Allocate
= Allocate
;
294 Lookaside
->Allocate
= ExpDefaultAllocate
;
297 Lookaside
->Free
= Free
;
299 Lookaside
->Free
= ExpDefaultFree
;
301 ExInitializeSListHead(&Lookaside
->ListHead
);
302 KeInitializeSpinLock(LookasideListLock(Lookaside
));
304 /* Determine minimum and maximum number of entries on the lookaside list
305 using the configured algorithm */
310 &Lookaside
->MaximumDepth
);
312 ExInterlockedInsertTailList(
313 &ExpNonPagedLookasideListHead
,
314 &Lookaside
->ListEntry
,
315 &ExpNonPagedLookasideListLock
);
324 ExInitializePagedLookasideList (
325 PPAGED_LOOKASIDE_LIST Lookaside
,
326 PALLOCATE_FUNCTION Allocate
,
334 DPRINT("Initializing paged lookaside list at 0x%X\n", Lookaside
);
336 Lookaside
->TotalAllocates
= 0;
337 Lookaside
->AllocateMisses
= 0;
338 Lookaside
->TotalFrees
= 0;
339 Lookaside
->FreeMisses
= 0;
340 Lookaside
->Type
= PagedPool
;
341 Lookaside
->Tag
= Tag
;
343 /* We use a field of type SINGLE_LIST_ENTRY as a link to the next entry in
344 the lookaside list so we must allocate at least sizeof(SINGLE_LIST_ENTRY) */
345 if (Size
< sizeof(SINGLE_LIST_ENTRY
))
346 Lookaside
->Size
= sizeof(SINGLE_LIST_ENTRY
);
348 Lookaside
->Size
= Size
;
351 Lookaside
->Allocate
= Allocate
;
353 Lookaside
->Allocate
= ExpDefaultAllocate
;
356 Lookaside
->Free
= Free
;
358 Lookaside
->Free
= ExpDefaultFree
;
360 ExInitializeSListHead(&Lookaside
->ListHead
);
361 //ExInitializeFastMutex(LookasideListLock(Lookaside));
363 /* Determine minimum and maximum number of entries on the lookaside list
364 using the configured algorithm */
369 &Lookaside
->MaximumDepth
);
371 ExInterlockedInsertTailList(
372 &ExpPagedLookasideListHead
,
373 &Lookaside
->ListEntry
,
374 &ExpPagedLookasideListLock
);