-/* $Id$
- *
+/*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS kernel
* FILE: ntoskrnl/ex/lookas.c
* PURPOSE: Lookaside lists
- * PROGRAMMERS: David Welch (welch@mcmail.com)
+ * PROGRAMMERS: Alex Ionescu (alex@relsoft.net)
+ * David Welch (welch@mcmail.com)
* Casper S. Hornstrup (chorns@users.sourceforge.net)
- * TODO: Use InterlockedXxxEntrySList for binary compatibility
- * UPDATE HISTORY:
- * 22-05-1998 DW Created
- * 02-07-2001 CSH Implemented lookaside lists
*/
/* INCLUDES *****************************************************************/
#define NDEBUG
#include <internal/debug.h>
+#if defined (ALLOC_PRAGMA)
+#pragma alloc_text(INIT, ExpInitLookasideLists)
+#endif
+
/* GLOBALS *******************************************************************/
LIST_ENTRY ExpNonPagedLookasideListHead;
KSPIN_LOCK ExpNonPagedLookasideListLock;
-
LIST_ENTRY ExpPagedLookasideListHead;
KSPIN_LOCK ExpPagedLookasideListLock;
-PLOOKASIDE_MINMAX_ROUTINE ExpMinMaxRoutine;
-
-#define LookasideListLock(l)(&(l->Obsoleted))
-
/* FUNCTIONS *****************************************************************/
-static
-inline
-PSINGLE_LIST_ENTRY
- PopEntrySList(
- PSLIST_HEADER ListHead
- )
-{
- PSINGLE_LIST_ENTRY ListEntry;
-
- ListEntry = ListHead->Next.Next;
- if (ListEntry!=NULL)
- {
- ListHead->Next.Next = ListEntry->Next;
- ListHead->Depth++;
- ListHead->Sequence++;
- }
- return ListEntry;
-}
-
-
-static
-inline
VOID
-PushEntrySList (
- PSLIST_HEADER ListHead,
- PSINGLE_LIST_ENTRY Entry
- )
-{
- Entry->Next = ListHead->Next.Next;
- ListHead->Next.Next = Entry;
- ListHead->Depth++;
- ListHead->Sequence++;
-}
-
-
-VOID ExpDefaultMinMax(
- POOL_TYPE PoolType,
- ULONG Size,
- PUSHORT MinimumDepth,
- PUSHORT MaximumDepth)
-/*
- * FUNCTION: Determines the minimum and maximum depth of a new lookaside list
- * ARGUMENTS:
- * Type = Type of executive pool
- * Size = Size in bytes of each element in the new lookaside list
- * MinimumDepth = Buffer to store minimum depth of the new lookaside list in
- * MaximumDepth = Buffer to store maximum depth of the new lookaside list in
- */
-{
- /* FIXME: Could probably do some serious computing here */
- if ((PoolType == NonPagedPool) ||
- (PoolType == NonPagedPoolMustSucceed))
- {
- *MinimumDepth = 10;
- *MaximumDepth = 100;
- }
- else
- {
- *MinimumDepth = 20;
- *MaximumDepth = 200;
- }
-}
-
-
-PVOID STDCALL
-ExpDefaultAllocate(POOL_TYPE PoolType,
- ULONG NumberOfBytes,
- ULONG Tag)
-/*
- * FUNCTION: Default allocate function for lookaside lists
- * ARGUMENTS:
- * Type = Type of executive pool
- * NumberOfBytes = Number of bytes to allocate
- * Tag = Tag to use
- * RETURNS:
- * Pointer to allocated memory, or NULL if there is not enough free resources
- */
+INIT_FUNCTION
+STDCALL
+ExpInitLookasideLists()
{
- return ExAllocatePoolWithTag(PoolType, NumberOfBytes, Tag);
+ /* Initialize Lock and Listhead */
+ InitializeListHead(&ExpNonPagedLookasideListHead);
+ KeInitializeSpinLock(&ExpNonPagedLookasideListLock);
+ InitializeListHead(&ExpPagedLookasideListHead);
+ KeInitializeSpinLock(&ExpPagedLookasideListLock);
}
-
-VOID STDCALL
-ExpDefaultFree(PVOID Buffer)
/*
- * FUNCTION: Default free function for lookaside lists
- * ARGUMENTS:
- * Buffer = Pointer to memory to free
+ * @implemented
*/
-{
- ExFreePool(Buffer);
-}
-
-
-VOID INIT_FUNCTION
-ExpInitLookasideLists()
-{
- InitializeListHead(&ExpNonPagedLookasideListHead);
- KeInitializeSpinLock(&ExpNonPagedLookasideListLock);
-
- InitializeListHead(&ExpPagedLookasideListHead);
- KeInitializeSpinLock(&ExpPagedLookasideListLock);
-
- /* FIXME: Possibly configure the algorithm using the registry */
- ExpMinMaxRoutine = ExpDefaultMinMax;
-}
-
-
PVOID
-FASTCALL
-ExiAllocateFromPagedLookasideList (
- PPAGED_LOOKASIDE_LIST Lookaside
- )
+STDCALL
+ExiAllocateFromPagedLookasideList(IN PPAGED_LOOKASIDE_LIST Lookaside)
{
- PVOID Entry;
-
- /* Try to obtain an entry from the lookaside list. If that fails, try to
- allocate a new entry with the allocate method for the lookaside list */
-
- Lookaside->TotalAllocates++;
-
-// ExAcquireFastMutex(LookasideListLock(Lookaside));
-
- Entry = PopEntrySList(&Lookaside->ListHead);
-
-// ExReleaseFastMutex(LookasideListLock(Lookaside));
-
- if (Entry)
+ PVOID Entry;
+
+ Lookaside->L.TotalAllocates++;
+ Entry = InterlockedPopEntrySList(&Lookaside->L.ListHead);
+ if (!Entry)
+ {
+ Lookaside->L.AllocateMisses++;
+ Entry = (Lookaside->L.Allocate)(Lookaside->L.Type,
+ Lookaside->L.Size,
+ Lookaside->L.Tag);
+ }
return Entry;
-
- Lookaside->AllocateMisses++;
-
- Entry = (*Lookaside->Allocate)(Lookaside->Type,
- Lookaside->Size,
- Lookaside->Tag);
-
- return Entry;
}
-
/*
* @implemented
*/
VOID
STDCALL
-ExDeleteNPagedLookasideList (
- PNPAGED_LOOKASIDE_LIST Lookaside
- )
+ExiFreeToPagedLookasideList(IN PPAGED_LOOKASIDE_LIST Lookaside,
+ IN PVOID Entry)
{
- KIRQL OldIrql;
- PVOID Entry;
-
- /* Pop all entries off the stack and release the resources allocated
- for them */
- while ((Entry = ExInterlockedPopEntrySList(
- &Lookaside->ListHead,
- LookasideListLock(Lookaside))) != NULL)
- {
- (*Lookaside->Free)(Entry);
- }
-
- KeAcquireSpinLock(&ExpNonPagedLookasideListLock, &OldIrql);
- RemoveEntryList(&Lookaside->ListEntry);
- KeReleaseSpinLock(&ExpNonPagedLookasideListLock, OldIrql);
+ Lookaside->L.TotalFrees++;
+ if (ExQueryDepthSList(&Lookaside->L.ListHead) >= Lookaside->L.Depth)
+ {
+ Lookaside->L.FreeMisses++;
+ (Lookaside->L.Free)(Entry);
+ }
+ else
+ {
+ InterlockedPushEntrySList(&Lookaside->L.ListHead, (PSLIST_ENTRY)Entry);
+ }
}
-
/*
* @implemented
*/
VOID
STDCALL
-ExDeletePagedLookasideList (
- PPAGED_LOOKASIDE_LIST Lookaside
- )
+ExDeleteNPagedLookasideList(PNPAGED_LOOKASIDE_LIST Lookaside)
{
- KIRQL OldIrql;
- PVOID Entry;
-
- /* Pop all entries off the stack and release the resources allocated
- for them */
- for (;;)
- {
-
-// ExAcquireFastMutex(LookasideListLock(Lookaside));
-
- Entry = PopEntrySList(&Lookaside->ListHead);
- if (!Entry)
- break;
-
-// ExReleaseFastMutex(LookasideListLock(Lookaside));
-
- (*Lookaside->Free)(Entry);
- }
-
- KeAcquireSpinLock(&ExpPagedLookasideListLock, &OldIrql);
- RemoveEntryList(&Lookaside->ListEntry);
- KeReleaseSpinLock(&ExpPagedLookasideListLock, OldIrql);
+ KIRQL OldIrql;
+ PVOID Entry;
+
+ /* Pop all entries off the stack and release the resources allocated
+ for them */
+ for (;;)
+ {
+ Entry = InterlockedPopEntrySList(&Lookaside->L.ListHead);
+ if (!Entry) break;
+ (*Lookaside->L.Free)(Entry);
+ }
+
+ /* Remove from list */
+ KeAcquireSpinLock(&ExpNonPagedLookasideListLock, &OldIrql);
+ RemoveEntryList(&Lookaside->L.ListEntry);
+ KeReleaseSpinLock(&ExpNonPagedLookasideListLock, OldIrql);
}
-
+/*
+ * @implemented
+ */
VOID
STDCALL
-ExiFreeToPagedLookasideList (
- PPAGED_LOOKASIDE_LIST Lookaside,
- PVOID Entry
- )
+ExDeletePagedLookasideList(PPAGED_LOOKASIDE_LIST Lookaside)
{
- Lookaside->TotalFrees++;
-
- if (ExQueryDepthSList(&Lookaside->ListHead) >= Lookaside->Depth)
- {
- Lookaside->FreeMisses++;
- (*Lookaside->Free)(Entry);
- }
- else
- {
-// ExAcquireFastMutex(LookasideListLock(Lookaside));
- PushEntrySList(&Lookaside->ListHead, (PSINGLE_LIST_ENTRY)Entry);
-// ExReleaseFastMutex(LookasideListLock(Lookaside));
- }
+ KIRQL OldIrql;
+ PVOID Entry;
+
+ /* Pop all entries off the stack and release the resources allocated
+ for them */
+ for (;;)
+ {
+ Entry = InterlockedPopEntrySList(&Lookaside->L.ListHead);
+ if (!Entry) break;
+ (*Lookaside->L.Free)(Entry);
+ }
+
+ /* Remove from list */
+ KeAcquireSpinLock(&ExpPagedLookasideListLock, &OldIrql);
+ RemoveEntryList(&Lookaside->L.ListEntry);
+ KeReleaseSpinLock(&ExpPagedLookasideListLock, OldIrql);
}
-
/*
* @implemented
*/
VOID
STDCALL
-ExInitializeNPagedLookasideList (
- PNPAGED_LOOKASIDE_LIST Lookaside,
- PALLOCATE_FUNCTION Allocate,
- PFREE_FUNCTION Free,
- ULONG Flags,
- ULONG Size,
- ULONG Tag,
- USHORT Depth)
+ExInitializeNPagedLookasideList(PNPAGED_LOOKASIDE_LIST Lookaside,
+ PALLOCATE_FUNCTION Allocate,
+ PFREE_FUNCTION Free,
+ ULONG Flags,
+ ULONG Size,
+ ULONG Tag,
+ USHORT Depth)
{
- DPRINT("Initializing nonpaged lookaside list at 0x%X\n", Lookaside);
-
- Lookaside->TotalAllocates = 0;
- Lookaside->AllocateMisses = 0;
- Lookaside->TotalFrees = 0;
- Lookaside->FreeMisses = 0;
- Lookaside->Type = NonPagedPool;
- Lookaside->Tag = Tag;
-
- /* We use a field of type SINGLE_LIST_ENTRY as a link to the next entry in
- the lookaside list so we must allocate at least sizeof(SINGLE_LIST_ENTRY) */
- if (Size < sizeof(SINGLE_LIST_ENTRY))
- Lookaside->Size = sizeof(SINGLE_LIST_ENTRY);
- else
- Lookaside->Size = Size;
-
- if (Allocate)
- Lookaside->Allocate = Allocate;
- else
- Lookaside->Allocate = ExpDefaultAllocate;
-
- if (Free)
- Lookaside->Free = Free;
- else
- Lookaside->Free = ExpDefaultFree;
-
- ExInitializeSListHead(&Lookaside->ListHead);
- KeInitializeSpinLock(LookasideListLock(Lookaside));
-
- /* Determine minimum and maximum number of entries on the lookaside list
- using the configured algorithm */
- (*ExpMinMaxRoutine)(
- NonPagedPool,
- Lookaside->Size,
- &Lookaside->Depth,
- &Lookaside->MaximumDepth);
-
- ExInterlockedInsertTailList(
- &ExpNonPagedLookasideListHead,
- &Lookaside->ListEntry,
- &ExpNonPagedLookasideListLock);
+ DPRINT("Initializing nonpaged lookaside list at 0x%p\n", Lookaside);
+
+ /* Initialize the Header */
+ ExInitializeSListHead(&Lookaside->L.ListHead);
+ Lookaside->L.TotalAllocates = 0;
+ Lookaside->L.AllocateMisses = 0;
+ Lookaside->L.TotalFrees = 0;
+ Lookaside->L.FreeMisses = 0;
+ Lookaside->L.Type = NonPagedPool | Flags;
+ Lookaside->L.Tag = Tag;
+ Lookaside->L.Size = Size;
+ Lookaside->L.Depth = 4;
+ Lookaside->L.MaximumDepth = 256;
+ Lookaside->L.LastTotalAllocates = 0;
+ Lookaside->L.LastAllocateMisses = 0;
+
+ /* Set the Allocate/Free Routines */
+ if (Allocate)
+ {
+ Lookaside->L.Allocate = Allocate;
+ }
+ else
+ {
+ Lookaside->L.Allocate = ExAllocatePoolWithTag;
+ }
+
+ if (Free)
+ {
+ Lookaside->L.Free = Free;
+ }
+ else
+ {
+ Lookaside->L.Free = ExFreePool;
+ }
+
+ /* Insert it into the list */
+ ExInterlockedInsertTailList(&ExpNonPagedLookasideListHead,
+ &Lookaside->L.ListEntry,
+ &ExpNonPagedLookasideListLock);
}
-
/*
* @implemented
*/
VOID
STDCALL
-ExInitializePagedLookasideList (
- PPAGED_LOOKASIDE_LIST Lookaside,
- PALLOCATE_FUNCTION Allocate,
- PFREE_FUNCTION Free,
- ULONG Flags,
- ULONG Size,
- ULONG Tag,
- USHORT Depth
- )
+ExInitializePagedLookasideList (PPAGED_LOOKASIDE_LIST Lookaside,
+ PALLOCATE_FUNCTION Allocate,
+ PFREE_FUNCTION Free,
+ ULONG Flags,
+ ULONG Size,
+ ULONG Tag,
+ USHORT Depth)
{
- DPRINT("Initializing paged lookaside list at 0x%X\n", Lookaside);
-
- Lookaside->TotalAllocates = 0;
- Lookaside->AllocateMisses = 0;
- Lookaside->TotalFrees = 0;
- Lookaside->FreeMisses = 0;
- Lookaside->Type = PagedPool;
- Lookaside->Tag = Tag;
-
- /* We use a field of type SINGLE_LIST_ENTRY as a link to the next entry in
- the lookaside list so we must allocate at least sizeof(SINGLE_LIST_ENTRY) */
- if (Size < sizeof(SINGLE_LIST_ENTRY))
- Lookaside->Size = sizeof(SINGLE_LIST_ENTRY);
- else
- Lookaside->Size = Size;
-
- if (Allocate)
- Lookaside->Allocate = Allocate;
- else
- Lookaside->Allocate = ExpDefaultAllocate;
-
- if (Free)
- Lookaside->Free = Free;
- else
- Lookaside->Free = ExpDefaultFree;
-
- ExInitializeSListHead(&Lookaside->ListHead);
- //ExInitializeFastMutex(LookasideListLock(Lookaside));
-
- /* Determine minimum and maximum number of entries on the lookaside list
- using the configured algorithm */
- (*ExpMinMaxRoutine)(
- PagedPool,
- Lookaside->Size,
- &Lookaside->Depth,
- &Lookaside->MaximumDepth);
-
- ExInterlockedInsertTailList(
- &ExpPagedLookasideListHead,
- &Lookaside->ListEntry,
- &ExpPagedLookasideListLock);
+ DPRINT("Initializing paged lookaside list at 0x%p\n", Lookaside);
+
+ /* Initialize the Header */
+ ExInitializeSListHead(&Lookaside->L.ListHead);
+ Lookaside->L.TotalAllocates = 0;
+ Lookaside->L.AllocateMisses = 0;
+ Lookaside->L.TotalFrees = 0;
+ Lookaside->L.FreeMisses = 0;
+ Lookaside->L.Type = PagedPool | Flags;
+ Lookaside->L.Tag = Tag;
+ Lookaside->L.Size = Size;
+ Lookaside->L.Depth = 4;
+ Lookaside->L.MaximumDepth = 256;
+ Lookaside->L.LastTotalAllocates = 0;
+ Lookaside->L.LastAllocateMisses = 0;
+
+ /* Set the Allocate/Free Routines */
+ if (Allocate)
+ {
+ Lookaside->L.Allocate = Allocate;
+ }
+ else
+ {
+ Lookaside->L.Allocate = ExAllocatePoolWithTag;
+ }
+
+ if (Free)
+ {
+ Lookaside->L.Free = Free;
+ }
+ else
+ {
+ Lookaside->L.Free = ExFreePool;
+ }
+
+ /* Insert it into the list */
+ ExInterlockedInsertTailList(&ExpNonPagedLookasideListHead,
+ &Lookaside->L.ListEntry,
+ &ExpNonPagedLookasideListLock);
}
/* EOF */