reactos/ntoskrnl/ex/lookas.c

318 lines
8.7 KiB
C

/*
* PROJECT: ReactOS Kernel
* LICENSE: GPL - See COPYING in the top level directory
* FILE: ntoskrnl/ex/lookas.c
* PURPOSE: Lookaside Lists
* PROGRAMMERS: Alex Ionescu (alex.ionescu@reactos.org)
*/
/* INCLUDES ******************************************************************/
#include <ntoskrnl.h>
#define NDEBUG
#include <debug.h>
/* GLOBALS *******************************************************************/
LIST_ENTRY ExpNonPagedLookasideListHead;
KSPIN_LOCK ExpNonPagedLookasideListLock;
LIST_ENTRY ExpPagedLookasideListHead;
KSPIN_LOCK ExpPagedLookasideListLock;
LIST_ENTRY ExSystemLookasideListHead;
LIST_ENTRY ExPoolLookasideListHead;
GENERAL_LOOKASIDE ExpSmallNPagedPoolLookasideLists[NUMBER_POOL_LOOKASIDE_LISTS];
GENERAL_LOOKASIDE ExpSmallPagedPoolLookasideLists[NUMBER_POOL_LOOKASIDE_LISTS];
/* PRIVATE FUNCTIONS *********************************************************/
CODE_SEG("INIT")
VOID
NTAPI
ExInitializeSystemLookasideList(IN PGENERAL_LOOKASIDE List,
IN POOL_TYPE Type,
IN ULONG Size,
IN ULONG Tag,
IN USHORT MaximumDepth,
IN PLIST_ENTRY ListHead)
{
/* Initialize the list */
List->Tag = Tag;
List->Type = Type;
List->Size = Size;
InsertHeadList(ListHead, &List->ListEntry);
List->MaximumDepth = MaximumDepth;
List->Depth = 2;
List->Allocate = ExAllocatePoolWithTag;
List->Free = ExFreePool;
InitializeSListHead(&List->ListHead);
List->TotalAllocates = 0;
List->AllocateHits = 0;
List->TotalFrees = 0;
List->FreeHits = 0;
List->LastTotalAllocates = 0;
List->LastAllocateHits = 0;
}
CODE_SEG("INIT")
VOID
NTAPI
ExInitPoolLookasidePointers(VOID)
{
ULONG i;
PKPRCB Prcb = KeGetCurrentPrcb();
PGENERAL_LOOKASIDE Entry;
/* Loop for all pool lists */
for (i = 0; i < NUMBER_POOL_LOOKASIDE_LISTS; i++)
{
/* Initialize the non-paged list */
Entry = &ExpSmallNPagedPoolLookasideLists[i];
InitializeSListHead(&Entry->ListHead);
/* Bind to PRCB */
Prcb->PPNPagedLookasideList[i].P = Entry;
Prcb->PPNPagedLookasideList[i].L = Entry;
/* Initialize the paged list */
Entry = &ExpSmallPagedPoolLookasideLists[i];
InitializeSListHead(&Entry->ListHead);
/* Bind to PRCB */
Prcb->PPPagedLookasideList[i].P = Entry;
Prcb->PPPagedLookasideList[i].L = Entry;
}
}
CODE_SEG("INIT")
VOID
NTAPI
ExpInitLookasideLists(VOID)
{
ULONG i;
/* Initialize locks and lists */
InitializeListHead(&ExpNonPagedLookasideListHead);
InitializeListHead(&ExpPagedLookasideListHead);
InitializeListHead(&ExSystemLookasideListHead);
InitializeListHead(&ExPoolLookasideListHead);
KeInitializeSpinLock(&ExpNonPagedLookasideListLock);
KeInitializeSpinLock(&ExpPagedLookasideListLock);
/* Initialize the system lookaside lists */
for (i = 0; i < NUMBER_POOL_LOOKASIDE_LISTS; i++)
{
/* Initialize the non-paged list */
ExInitializeSystemLookasideList(&ExpSmallNPagedPoolLookasideLists[i],
NonPagedPool,
(i + 1) * 8,
'looP',
256,
&ExPoolLookasideListHead);
/* Initialize the paged list */
ExInitializeSystemLookasideList(&ExpSmallPagedPoolLookasideLists[i],
PagedPool,
(i + 1) * 8,
'looP',
256,
&ExPoolLookasideListHead);
}
}
/* PUBLIC FUNCTIONS **********************************************************/
/*
* @implemented
*/
PVOID
NTAPI
ExiAllocateFromPagedLookasideList(IN PPAGED_LOOKASIDE_LIST Lookaside)
{
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;
}
/*
* @implemented
*/
VOID
NTAPI
ExiFreeToPagedLookasideList(IN PPAGED_LOOKASIDE_LIST Lookaside,
IN PVOID Entry)
{
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
NTAPI
ExDeleteNPagedLookasideList(IN PNPAGED_LOOKASIDE_LIST Lookaside)
{
KIRQL OldIrql;
PVOID Entry;
/* Pop all entries off the stack and release their resources */
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
NTAPI
ExDeletePagedLookasideList(IN PPAGED_LOOKASIDE_LIST Lookaside)
{
KIRQL OldIrql;
PVOID Entry;
/* Pop all entries off the stack and release their resources */
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
NTAPI
ExInitializeNPagedLookasideList(IN PNPAGED_LOOKASIDE_LIST Lookaside,
IN PALLOCATE_FUNCTION Allocate OPTIONAL,
IN PFREE_FUNCTION Free OPTIONAL,
IN ULONG Flags,
IN SIZE_T Size,
IN ULONG Tag,
IN USHORT Depth)
{
/* 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 = (ULONG)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
NTAPI
ExInitializePagedLookasideList(IN PPAGED_LOOKASIDE_LIST Lookaside,
IN PALLOCATE_FUNCTION Allocate OPTIONAL,
IN PFREE_FUNCTION Free OPTIONAL,
IN ULONG Flags,
IN SIZE_T Size,
IN ULONG Tag,
IN USHORT Depth)
{
/* 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 = (ULONG)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(&ExpPagedLookasideListHead,
&Lookaside->L.ListEntry,
&ExpPagedLookasideListLock);
}
/* EOF */