1 /* $Id: lookas.c,v 1.9 2003/07/11 01:23:14 royce 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)
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
;
110 ExAllocateFromPagedLookasideList (
111 PPAGED_LOOKASIDE_LIST Lookaside
116 /* Try to obtain an entry from the lookaside list. If that fails, try to
117 allocate a new entry with the allocate method for the lookaside list */
119 Lookaside
->TotalAllocates
++;
121 // ExAcquireFastMutex(&Lookaside->Lock);
123 Entry
= PopEntrySList(&Lookaside
->ListHead
);
125 // ExReleaseFastMutex(&Lookaside->Lock);
130 Lookaside
->AllocateMisses
++;
132 Entry
= (*Lookaside
->Allocate
)(Lookaside
->Type
,
144 ExDeleteNPagedLookasideList (
145 PNPAGED_LOOKASIDE_LIST Lookaside
151 /* Pop all entries off the stack and release the resources allocated
153 while ((Entry
= ExInterlockedPopEntrySList(
154 &Lookaside
->ListHead
,
155 &Lookaside
->Lock
)) != NULL
)
157 (*Lookaside
->Free
)(Entry
);
160 KeAcquireSpinLock(&ExpNonPagedLookasideListLock
, &OldIrql
);
161 RemoveEntryList(&Lookaside
->ListEntry
);
162 KeReleaseSpinLock(&ExpNonPagedLookasideListLock
, OldIrql
);
170 ExDeletePagedLookasideList (
171 PPAGED_LOOKASIDE_LIST Lookaside
177 /* Pop all entries off the stack and release the resources allocated
182 // ExAcquireFastMutex(&Lookaside->Lock);
184 Entry
= PopEntrySList(&Lookaside
->ListHead
);
188 // ExReleaseFastMutex(&Lookaside->Lock);
190 (*Lookaside
->Free
)(Entry
);
193 KeAcquireSpinLock(&ExpPagedLookasideListLock
, &OldIrql
);
194 RemoveEntryList(&Lookaside
->ListEntry
);
195 KeReleaseSpinLock(&ExpPagedLookasideListLock
, OldIrql
);
203 ExFreeToPagedLookasideList (
204 PPAGED_LOOKASIDE_LIST Lookaside
,
208 Lookaside
->TotalFrees
++;
210 if (ExQueryDepthSList(&Lookaside
->ListHead
) >= Lookaside
->MinimumDepth
)
212 Lookaside
->FreeMisses
++;
213 (*Lookaside
->Free
)(Entry
);
217 // ExAcquireFastMutex(&Lookaside->Lock);
218 PushEntrySList(&Lookaside
->ListHead
, (PSINGLE_LIST_ENTRY
)Entry
);
219 // ExReleaseFastMutex(&Lookaside->Lock);
228 ExInitializeNPagedLookasideList (
229 PNPAGED_LOOKASIDE_LIST Lookaside
,
230 PALLOCATE_FUNCTION Allocate
,
237 DPRINT("Initializing nonpaged lookaside list at 0x%X\n", Lookaside
);
239 Lookaside
->TotalAllocates
= 0;
240 Lookaside
->AllocateMisses
= 0;
241 Lookaside
->TotalFrees
= 0;
242 Lookaside
->FreeMisses
= 0;
243 Lookaside
->Type
= NonPagedPool
;
244 Lookaside
->Tag
= Tag
;
246 /* We use a field of type SINGLE_LIST_ENTRY as a link to the next entry in
247 the lookaside list so we must allocate at least sizeof(SINGLE_LIST_ENTRY) */
248 if (Size
< sizeof(SINGLE_LIST_ENTRY
))
249 Lookaside
->Size
= sizeof(SINGLE_LIST_ENTRY
);
251 Lookaside
->Size
= Size
;
254 Lookaside
->Allocate
= Allocate
;
256 Lookaside
->Allocate
= ExpDefaultAllocate
;
259 Lookaside
->Free
= Free
;
261 Lookaside
->Free
= ExpDefaultFree
;
263 ExInitializeSListHead(&Lookaside
->ListHead
);
264 KeInitializeSpinLock(&Lookaside
->Lock
);
266 /* Determine minimum and maximum number of entries on the lookaside list
267 using the configured algorithm */
271 &Lookaside
->MinimumDepth
,
272 &Lookaside
->MaximumDepth
);
274 ExInterlockedInsertTailList(
275 &ExpNonPagedLookasideListHead
,
276 &Lookaside
->ListEntry
,
277 &ExpNonPagedLookasideListLock
);
285 ExInitializePagedLookasideList (
286 PPAGED_LOOKASIDE_LIST Lookaside
,
287 PALLOCATE_FUNCTION Allocate
,
295 DPRINT("Initializing paged lookaside list at 0x%X\n", Lookaside
);
297 Lookaside
->TotalAllocates
= 0;
298 Lookaside
->AllocateMisses
= 0;
299 Lookaside
->TotalFrees
= 0;
300 Lookaside
->FreeMisses
= 0;
301 Lookaside
->Type
= PagedPool
;
302 Lookaside
->Tag
= Tag
;
304 /* We use a field of type SINGLE_LIST_ENTRY as a link to the next entry in
305 the lookaside list so we must allocate at least sizeof(SINGLE_LIST_ENTRY) */
306 if (Size
< sizeof(SINGLE_LIST_ENTRY
))
307 Lookaside
->Size
= sizeof(SINGLE_LIST_ENTRY
);
309 Lookaside
->Size
= Size
;
312 Lookaside
->Allocate
= Allocate
;
314 Lookaside
->Allocate
= ExpDefaultAllocate
;
317 Lookaside
->Free
= Free
;
319 Lookaside
->Free
= ExpDefaultFree
;
321 ExInitializeSListHead(&Lookaside
->ListHead
);
322 //ExInitializeFastMutex(&Lookaside->Lock);
324 /* Determine minimum and maximum number of entries on the lookaside list
325 using the configured algorithm */
329 &Lookaside
->MinimumDepth
,
330 &Lookaside
->MaximumDepth
);
332 ExInterlockedInsertTailList(
333 &ExpPagedLookasideListHead
,
334 &Lookaside
->ListEntry
,
335 &ExpPagedLookasideListLock
);