241 lines
5.4 KiB
C
241 lines
5.4 KiB
C
|
/*++
|
||
|
|
||
|
Copyright (c) 1999-2000 Microsoft Corporation
|
||
|
|
||
|
Module Name:
|
||
|
|
||
|
pplasl.c
|
||
|
|
||
|
Abstract:
|
||
|
|
||
|
This file contains the implementation of a per-processor lookaside
|
||
|
list manager.
|
||
|
|
||
|
Author:
|
||
|
|
||
|
Shaun Cox (shaunco) 25-Oct-1999
|
||
|
|
||
|
--*/
|
||
|
|
||
|
#include "ntddk.h"
|
||
|
#include "pplasl.h"
|
||
|
|
||
|
|
||
|
HANDLE
|
||
|
PplCreatePool(
|
||
|
IN PALLOCATE_FUNCTION Allocate,
|
||
|
IN PFREE_FUNCTION Free,
|
||
|
IN ULONG Flags,
|
||
|
IN SIZE_T Size,
|
||
|
IN ULONG Tag,
|
||
|
IN USHORT Depth
|
||
|
)
|
||
|
{
|
||
|
HANDLE PoolHandle;
|
||
|
SIZE_T PoolSize;
|
||
|
CCHAR NumberProcessors;
|
||
|
CCHAR NumberLookasideLists;
|
||
|
CCHAR i;
|
||
|
PNPAGED_LOOKASIDE_LIST Lookaside;
|
||
|
|
||
|
#if MILLEN
|
||
|
NumberProcessors = 1;
|
||
|
#else // MILLEN
|
||
|
NumberProcessors = KeNumberProcessors;
|
||
|
#endif // !MILLEN
|
||
|
|
||
|
// Allocate room for 1 lookaside list per processor plus 1 extra
|
||
|
// lookaside list for overflow. Only allocate 1 lookaside list if
|
||
|
// we're on a single processor machine.
|
||
|
//
|
||
|
NumberLookasideLists = NumberProcessors;
|
||
|
if (NumberProcessors > 1)
|
||
|
{
|
||
|
NumberLookasideLists++;
|
||
|
}
|
||
|
|
||
|
PoolSize = sizeof(NPAGED_LOOKASIDE_LIST) * NumberLookasideLists;
|
||
|
|
||
|
PoolHandle = ExAllocatePoolWithTagPriority(NonPagedPool, PoolSize, Tag,
|
||
|
NormalPoolPriority);
|
||
|
if (PoolHandle)
|
||
|
{
|
||
|
for (i = 0, Lookaside = (PNPAGED_LOOKASIDE_LIST)PoolHandle;
|
||
|
i < NumberLookasideLists;
|
||
|
i++, Lookaside++)
|
||
|
{
|
||
|
ExInitializeNPagedLookasideList(
|
||
|
Lookaside,
|
||
|
Allocate,
|
||
|
Free,
|
||
|
Flags,
|
||
|
Size,
|
||
|
Tag,
|
||
|
Depth);
|
||
|
|
||
|
// ExInitializeNPagedLookasideList doesn't really set the
|
||
|
// maximum depth to Depth, so we'll do it here.
|
||
|
//
|
||
|
if (Depth != 0) {
|
||
|
Lookaside->L.MaximumDepth = Depth;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return PoolHandle;
|
||
|
}
|
||
|
|
||
|
VOID
|
||
|
PplDestroyPool(
|
||
|
IN HANDLE PoolHandle
|
||
|
)
|
||
|
{
|
||
|
CCHAR NumberProcessors;
|
||
|
CCHAR NumberLookasideLists;
|
||
|
CCHAR i;
|
||
|
PNPAGED_LOOKASIDE_LIST Lookaside;
|
||
|
|
||
|
if (!PoolHandle)
|
||
|
{
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
#if MILLEN
|
||
|
NumberProcessors = 1;
|
||
|
#else // MILLEN
|
||
|
NumberProcessors = KeNumberProcessors;
|
||
|
#endif // !MILLEN
|
||
|
|
||
|
NumberLookasideLists = NumberProcessors;
|
||
|
if (NumberProcessors > 1)
|
||
|
{
|
||
|
NumberLookasideLists++;
|
||
|
}
|
||
|
|
||
|
for (i = 0, Lookaside = (PNPAGED_LOOKASIDE_LIST)PoolHandle;
|
||
|
i < NumberLookasideLists;
|
||
|
i++, Lookaside++)
|
||
|
{
|
||
|
ExDeleteNPagedLookasideList(Lookaside);
|
||
|
}
|
||
|
|
||
|
ExFreePool(PoolHandle);
|
||
|
}
|
||
|
|
||
|
PVOID
|
||
|
PplAllocate(
|
||
|
IN HANDLE PoolHandle,
|
||
|
OUT LOGICAL *FromList
|
||
|
)
|
||
|
{
|
||
|
PNPAGED_LOOKASIDE_LIST Lookaside;
|
||
|
CCHAR NumberProcessors;
|
||
|
PVOID Entry;
|
||
|
|
||
|
// Assume we'll get the item from the lookaside list.
|
||
|
//
|
||
|
*FromList = TRUE;
|
||
|
|
||
|
#if MILLEN
|
||
|
NumberProcessors = 1;
|
||
|
#else // MILLEN
|
||
|
NumberProcessors = KeNumberProcessors;
|
||
|
#endif // !MILLEN
|
||
|
|
||
|
if (1 == NumberProcessors)
|
||
|
{
|
||
|
goto SingleProcessorCaseOrMissedPerProcessor;
|
||
|
}
|
||
|
|
||
|
// Try first for the per-processor lookaside list.
|
||
|
//
|
||
|
Lookaside = (PNPAGED_LOOKASIDE_LIST)PoolHandle +
|
||
|
KeGetCurrentProcessorNumber() + 1;
|
||
|
|
||
|
Lookaside->L.TotalAllocates += 1;
|
||
|
Entry = InterlockedPopEntrySList(&Lookaside->L.ListHead);
|
||
|
if (!Entry)
|
||
|
{
|
||
|
Lookaside->L.AllocateMisses += 1;
|
||
|
|
||
|
SingleProcessorCaseOrMissedPerProcessor:
|
||
|
// We missed on the per-processor lookaside list, (or we're
|
||
|
// running on a single processor machine) so try for
|
||
|
// the overflow lookaside list.
|
||
|
//
|
||
|
Lookaside = (PNPAGED_LOOKASIDE_LIST)PoolHandle;
|
||
|
|
||
|
Lookaside->L.TotalAllocates += 1;
|
||
|
Entry = InterlockedPopEntrySList(&Lookaside->L.ListHead);
|
||
|
if (!Entry)
|
||
|
{
|
||
|
Lookaside->L.AllocateMisses += 1;
|
||
|
Entry = (Lookaside->L.Allocate)(
|
||
|
Lookaside->L.Type,
|
||
|
Lookaside->L.Size,
|
||
|
Lookaside->L.Tag);
|
||
|
*FromList = FALSE;
|
||
|
}
|
||
|
}
|
||
|
return Entry;
|
||
|
}
|
||
|
|
||
|
VOID
|
||
|
PplFree(
|
||
|
IN HANDLE PoolHandle,
|
||
|
IN PVOID Entry
|
||
|
)
|
||
|
{
|
||
|
PNPAGED_LOOKASIDE_LIST Lookaside;
|
||
|
CCHAR NumberProcessors;
|
||
|
|
||
|
#if MILLEN
|
||
|
NumberProcessors = 1;
|
||
|
#else // MILLEN
|
||
|
NumberProcessors = KeNumberProcessors;
|
||
|
#endif // !MILLEN
|
||
|
|
||
|
if (1 == NumberProcessors)
|
||
|
{
|
||
|
goto SingleProcessorCaseOrMissedPerProcessor;
|
||
|
}
|
||
|
|
||
|
// Try first for the per-processor lookaside list.
|
||
|
//
|
||
|
Lookaside = (PNPAGED_LOOKASIDE_LIST)PoolHandle +
|
||
|
KeGetCurrentProcessorNumber() + 1;
|
||
|
|
||
|
Lookaside->L.TotalFrees += 1;
|
||
|
if (ExQueryDepthSList(&Lookaside->L.ListHead) >= Lookaside->L.Depth)
|
||
|
{
|
||
|
Lookaside->L.FreeMisses += 1;
|
||
|
|
||
|
SingleProcessorCaseOrMissedPerProcessor:
|
||
|
// We missed on the per-processor lookaside list, (or we're
|
||
|
// running on a single processor machine) so try for
|
||
|
// the overflow lookaside list.
|
||
|
//
|
||
|
Lookaside = (PNPAGED_LOOKASIDE_LIST)PoolHandle;
|
||
|
|
||
|
Lookaside->L.TotalFrees += 1;
|
||
|
if (ExQueryDepthSList(&Lookaside->L.ListHead) >= Lookaside->L.Depth)
|
||
|
{
|
||
|
Lookaside->L.FreeMisses += 1;
|
||
|
(Lookaside->L.Free)(Entry);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
InterlockedPushEntrySList(
|
||
|
&Lookaside->L.ListHead,
|
||
|
(PSINGLE_LIST_ENTRY)Entry);
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
InterlockedPushEntrySList(
|
||
|
&Lookaside->L.ListHead,
|
||
|
(PSINGLE_LIST_ENTRY)Entry);
|
||
|
}
|
||
|
}
|
||
|
|