You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
502 lines
11 KiB
502 lines
11 KiB
/*++
|
|
|
|
Copyright (c) 1999-2002 Microsoft Corporation
|
|
|
|
Module Name:
|
|
|
|
pplasl.h
|
|
|
|
Abstract:
|
|
|
|
This file contains definitions and function prototypes of a per-processor
|
|
lookaside list manager.
|
|
|
|
Author:
|
|
|
|
Shaun Cox (shaunco) 25-Oct-1999
|
|
|
|
--*/
|
|
|
|
#ifndef _PPLASL_H_
|
|
#define _PPLASL_H_
|
|
|
|
|
|
typedef struct DECLSPEC_ALIGN(UL_CACHE_LINE) _UL_NPAGED_LOOKASIDE_LIST
|
|
{
|
|
NPAGED_LOOKASIDE_LIST List;
|
|
|
|
} UL_NPAGED_LOOKASIDE_LIST, *PUL_NPAGED_LOOKASIDE_LIST;
|
|
|
|
C_ASSERT(sizeof(UL_NPAGED_LOOKASIDE_LIST) % UL_CACHE_LINE == 0);
|
|
|
|
typedef struct DECLSPEC_ALIGN(UL_CACHE_LINE) _PER_PROC_SLISTS
|
|
{
|
|
SLIST_HEADER SL;
|
|
USHORT MaxDepth; // High water mark
|
|
USHORT MinDepth; // Low water mark
|
|
|
|
LONG Delta; // Delta between the entry serv rate of last two intervals
|
|
ULONG EntriesServed; // Entries served (frm this list) so far this interval
|
|
ULONG PrevEntriesServed; // Entries served during last interval
|
|
|
|
#if DBG
|
|
ULONG TotalServed; // Used for tracking backing list serv rate by the tracing code
|
|
#endif
|
|
|
|
} PER_PROC_SLISTS, *PPER_PROC_SLISTS;
|
|
|
|
C_ASSERT(sizeof(PER_PROC_SLISTS) % UL_CACHE_LINE == 0);
|
|
C_ASSERT(TYPE_ALIGNMENT(PER_PROC_SLISTS) == UL_CACHE_LINE);
|
|
|
|
#define UL_MAX_SLIST_DEPTH (0xfffe)
|
|
|
|
#define PER_PROC_SLIST(PoolHandle, Index) ((PPER_PROC_SLISTS) (PoolHandle) + Index)
|
|
#define BACKING_SLIST(PoolHandle) PER_PROC_SLIST((PoolHandle), g_UlNumberOfProcessors)
|
|
|
|
HANDLE
|
|
PplCreatePool(
|
|
IN PALLOCATE_FUNCTION Allocate,
|
|
IN PFREE_FUNCTION Free,
|
|
IN ULONG Flags,
|
|
IN SIZE_T Size,
|
|
IN ULONG Tag,
|
|
IN USHORT Depth
|
|
);
|
|
|
|
VOID
|
|
PplDestroyPool(
|
|
IN HANDLE PoolHandle,
|
|
IN ULONG Tag
|
|
);
|
|
|
|
__inline
|
|
PVOID
|
|
PplAllocate(
|
|
IN HANDLE PoolHandle
|
|
)
|
|
{
|
|
PUL_NPAGED_LOOKASIDE_LIST Lookaside;
|
|
PVOID Entry;
|
|
|
|
if (1 == g_UlNumberOfProcessors)
|
|
{
|
|
goto SingleProcessorCaseOrMissedPerProcessor;
|
|
}
|
|
|
|
// Try first for the per-processor lookaside list.
|
|
//
|
|
Lookaside = (PUL_NPAGED_LOOKASIDE_LIST)PoolHandle +
|
|
KeGetCurrentProcessorNumber() + 1;
|
|
|
|
Lookaside->List.L.TotalAllocates += 1;
|
|
Entry = InterlockedPopEntrySList(&Lookaside->List.L.ListHead);
|
|
if (!Entry)
|
|
{
|
|
Lookaside->List.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 = (PUL_NPAGED_LOOKASIDE_LIST)PoolHandle;
|
|
|
|
Lookaside->List.L.TotalAllocates += 1;
|
|
Entry = InterlockedPopEntrySList(&Lookaside->List.L.ListHead);
|
|
if (!Entry)
|
|
{
|
|
Lookaside->List.L.AllocateMisses += 1;
|
|
Entry = (Lookaside->List.L.Allocate)(
|
|
Lookaside->List.L.Type,
|
|
Lookaside->List.L.Size,
|
|
Lookaside->List.L.Tag);
|
|
}
|
|
}
|
|
return Entry;
|
|
}
|
|
|
|
__inline
|
|
VOID
|
|
PplFree(
|
|
IN HANDLE PoolHandle,
|
|
IN PVOID Entry
|
|
)
|
|
{
|
|
PUL_NPAGED_LOOKASIDE_LIST Lookaside;
|
|
|
|
if (1 == g_UlNumberOfProcessors)
|
|
{
|
|
goto SingleProcessorCaseOrMissedPerProcessor;
|
|
}
|
|
|
|
// Try first for the per-processor lookaside list.
|
|
//
|
|
Lookaside = (PUL_NPAGED_LOOKASIDE_LIST)PoolHandle +
|
|
KeGetCurrentProcessorNumber() + 1;
|
|
|
|
Lookaside->List.L.TotalFrees += 1;
|
|
if (ExQueryDepthSList(&Lookaside->List.L.ListHead) >=
|
|
Lookaside->List.L.Depth)
|
|
{
|
|
Lookaside->List.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 = (PUL_NPAGED_LOOKASIDE_LIST)PoolHandle;
|
|
|
|
Lookaside->List.L.TotalFrees += 1;
|
|
if (ExQueryDepthSList(&Lookaside->List.L.ListHead) >=
|
|
Lookaside->List.L.Depth)
|
|
{
|
|
Lookaside->List.L.FreeMisses += 1;
|
|
(Lookaside->List.L.Free)(Entry);
|
|
}
|
|
else
|
|
{
|
|
InterlockedPushEntrySList(
|
|
&Lookaside->List.L.ListHead,
|
|
(PSLIST_ENTRY)Entry);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
InterlockedPushEntrySList(
|
|
&Lookaside->List.L.ListHead,
|
|
(PSLIST_ENTRY)Entry);
|
|
}
|
|
}
|
|
|
|
|
|
HANDLE
|
|
PpslCreatePool(
|
|
IN ULONG Tag,
|
|
IN USHORT MaxDepth,
|
|
IN USHORT MinDepth
|
|
);
|
|
|
|
VOID
|
|
PpslDestroyPool(
|
|
IN HANDLE PoolHandle,
|
|
IN ULONG Tag
|
|
);
|
|
|
|
__inline
|
|
PSLIST_ENTRY
|
|
PpslAllocate(
|
|
IN HANDLE PoolHandle
|
|
)
|
|
{
|
|
PSLIST_ENTRY Entry;
|
|
PPER_PROC_SLISTS PPSList;
|
|
|
|
PPSList = PER_PROC_SLIST(PoolHandle, KeGetCurrentProcessorNumber());
|
|
|
|
Entry = InterlockedPopEntrySList(&(PPSList->SL));
|
|
|
|
if (!Entry)
|
|
{
|
|
|
|
PPSList = BACKING_SLIST(PoolHandle);
|
|
|
|
Entry = InterlockedPopEntrySList(&(PPSList->SL));
|
|
}
|
|
|
|
if (Entry)
|
|
{
|
|
InterlockedIncrement((PLONG) &PPSList->EntriesServed);
|
|
|
|
#if DBG
|
|
InterlockedIncrement((PLONG) &PPSList->TotalServed);
|
|
#endif
|
|
}
|
|
|
|
return Entry;
|
|
}
|
|
|
|
__inline
|
|
PSLIST_ENTRY
|
|
PpslAllocateToTrim(
|
|
IN HANDLE PoolHandle,
|
|
IN ULONG Processor
|
|
)
|
|
{
|
|
PSLIST_ENTRY Entry;
|
|
PPER_PROC_SLISTS PPSList;
|
|
|
|
ASSERT(Processor <= (ULONG)g_UlNumberOfProcessors);
|
|
|
|
PPSList = PER_PROC_SLIST(PoolHandle, Processor);
|
|
|
|
if (ExQueryDepthSList(&(PPSList->SL)) > PPSList->MinDepth)
|
|
{
|
|
Entry = InterlockedPopEntrySList(&(PPSList->SL));
|
|
}
|
|
else
|
|
{
|
|
Entry = NULL;
|
|
}
|
|
|
|
return Entry;
|
|
}
|
|
|
|
__inline
|
|
PSLIST_ENTRY
|
|
PpslAllocateToDrain(
|
|
IN HANDLE PoolHandle
|
|
)
|
|
{
|
|
PSLIST_ENTRY Entry = NULL;
|
|
PPER_PROC_SLISTS PPSList;
|
|
CLONG NumberSLists;
|
|
CLONG i;
|
|
|
|
|
|
NumberSLists = g_UlNumberOfProcessors + 1;
|
|
|
|
for (i = 0; i < NumberSLists; i++)
|
|
{
|
|
PPSList = PER_PROC_SLIST(PoolHandle, i);
|
|
|
|
Entry = InterlockedPopEntrySList(&(PPSList->SL));
|
|
|
|
if (Entry) {
|
|
|
|
break;
|
|
}
|
|
}
|
|
|
|
return Entry;
|
|
}
|
|
|
|
__inline
|
|
BOOLEAN
|
|
PpslFree(
|
|
IN HANDLE PoolHandle,
|
|
IN PVOID Entry
|
|
)
|
|
{
|
|
PPER_PROC_SLISTS PPSList;
|
|
BOOLEAN Freed = TRUE;
|
|
|
|
PPSList = PER_PROC_SLIST(PoolHandle, KeGetCurrentProcessorNumber());
|
|
|
|
if (ExQueryDepthSList(&(PPSList->SL)) < PPSList->MaxDepth &&
|
|
PPSList->Delta >= 0)
|
|
{
|
|
InterlockedPushEntrySList(&(PPSList->SL), (PSLIST_ENTRY)Entry);
|
|
}
|
|
else
|
|
{
|
|
PPSList = BACKING_SLIST(PoolHandle);
|
|
|
|
if (ExQueryDepthSList(&(PPSList->SL)) < PPSList->MaxDepth &&
|
|
PPSList->Delta >= 0)
|
|
{
|
|
InterlockedPushEntrySList(&(PPSList->SL), (PSLIST_ENTRY)Entry);
|
|
}
|
|
else
|
|
{
|
|
Freed = FALSE;
|
|
}
|
|
}
|
|
|
|
return Freed;
|
|
}
|
|
|
|
__inline
|
|
BOOLEAN
|
|
PpslFreeSpecifyList(
|
|
IN HANDLE PoolHandle,
|
|
IN PVOID Entry,
|
|
IN ULONG Processor
|
|
)
|
|
{
|
|
PPER_PROC_SLISTS PPSList;
|
|
BOOLEAN Freed = TRUE;
|
|
|
|
ASSERT(Processor <= (ULONG)g_UlNumberOfProcessors);
|
|
|
|
PPSList = PER_PROC_SLIST(PoolHandle, Processor);
|
|
|
|
if (ExQueryDepthSList(&(PPSList->SL)) < PPSList->MaxDepth)
|
|
{
|
|
InterlockedPushEntrySList(&(PPSList->SL), (PSLIST_ENTRY)Entry);
|
|
}
|
|
else
|
|
{
|
|
PPSList = BACKING_SLIST(PoolHandle);
|
|
|
|
if (ExQueryDepthSList(&(PPSList->SL)) < PPSList->MaxDepth)
|
|
{
|
|
InterlockedPushEntrySList(&(PPSList->SL), (PSLIST_ENTRY)Entry);
|
|
}
|
|
else
|
|
{
|
|
Freed = FALSE;
|
|
}
|
|
}
|
|
|
|
return Freed;
|
|
}
|
|
|
|
__inline
|
|
USHORT
|
|
PpslQueryBackingListDepth(
|
|
IN HANDLE PoolHandle
|
|
)
|
|
{
|
|
USHORT Depth;
|
|
PPER_PROC_SLISTS PPSList;
|
|
|
|
PPSList = BACKING_SLIST(PoolHandle);
|
|
|
|
Depth = ExQueryDepthSList(&(PPSList->SL));
|
|
|
|
return (Depth);
|
|
}
|
|
|
|
__inline
|
|
USHORT
|
|
PpslQueryDepth(
|
|
IN HANDLE PoolHandle,
|
|
IN ULONG Processor
|
|
)
|
|
{
|
|
USHORT Depth;
|
|
PPER_PROC_SLISTS PPSList;
|
|
|
|
ASSERT(Processor <= (ULONG)g_UlNumberOfProcessors);
|
|
|
|
PPSList = PER_PROC_SLIST(PoolHandle, Processor);
|
|
|
|
Depth = ExQueryDepthSList(&(PPSList->SL));
|
|
|
|
return (Depth);
|
|
}
|
|
|
|
__inline
|
|
USHORT
|
|
PpslQueryMinDepth(
|
|
IN HANDLE PoolHandle,
|
|
IN ULONG Processor
|
|
)
|
|
{
|
|
PPER_PROC_SLISTS PPSList;
|
|
|
|
ASSERT(Processor <= (ULONG)g_UlNumberOfProcessors);
|
|
|
|
PPSList = PER_PROC_SLIST(PoolHandle, Processor);
|
|
|
|
return PPSList->MinDepth;
|
|
}
|
|
|
|
__inline
|
|
USHORT
|
|
PpslQueryBackingListMinDepth(
|
|
IN HANDLE PoolHandle
|
|
)
|
|
{
|
|
PPER_PROC_SLISTS PPSList;
|
|
|
|
PPSList = BACKING_SLIST(PoolHandle);
|
|
|
|
return PPSList->MinDepth;
|
|
}
|
|
|
|
__inline
|
|
LONG
|
|
PpslAdjustActivityStats(
|
|
IN HANDLE PoolHandle,
|
|
IN ULONG Processor
|
|
)
|
|
{
|
|
PPER_PROC_SLISTS PPSList;
|
|
ULONG EntriesServed;
|
|
|
|
ASSERT(Processor <= (ULONG)g_UlNumberOfProcessors);
|
|
|
|
PPSList = PER_PROC_SLIST(PoolHandle, Processor);
|
|
|
|
EntriesServed =
|
|
InterlockedExchange((PLONG) &PPSList->EntriesServed, 0);
|
|
|
|
InterlockedExchange(
|
|
&PPSList->Delta,
|
|
EntriesServed - PPSList->PrevEntriesServed
|
|
);
|
|
|
|
PPSList->PrevEntriesServed = EntriesServed;
|
|
|
|
return PPSList->Delta;
|
|
}
|
|
|
|
__inline
|
|
ULONG
|
|
PpslQueryPrevServed(
|
|
IN HANDLE PoolHandle,
|
|
IN ULONG Processor
|
|
)
|
|
{
|
|
PPER_PROC_SLISTS PPSList;
|
|
|
|
ASSERT(Processor <= (ULONG)g_UlNumberOfProcessors);
|
|
|
|
PPSList = PER_PROC_SLIST(PoolHandle, Processor);
|
|
|
|
return PPSList->PrevEntriesServed;
|
|
}
|
|
|
|
#if DBG
|
|
|
|
__inline
|
|
LONG
|
|
PpslQueryDelta(
|
|
IN HANDLE PoolHandle,
|
|
IN ULONG Processor
|
|
)
|
|
{
|
|
PPER_PROC_SLISTS PPSList;
|
|
|
|
ASSERT(Processor <= (ULONG)g_UlNumberOfProcessors);
|
|
|
|
PPSList = PER_PROC_SLIST(PoolHandle, Processor);
|
|
|
|
return PPSList->Delta;
|
|
}
|
|
|
|
__inline
|
|
ULONG
|
|
PpslQueryTotalServed(
|
|
IN HANDLE PoolHandle
|
|
)
|
|
{
|
|
PPER_PROC_SLISTS PPSList;
|
|
|
|
PPSList = BACKING_SLIST(PoolHandle);
|
|
|
|
return PPSList->TotalServed;
|
|
}
|
|
|
|
__inline
|
|
ULONG
|
|
PpslQueryServed(
|
|
IN HANDLE PoolHandle,
|
|
IN ULONG Processor
|
|
)
|
|
{
|
|
PPER_PROC_SLISTS PPSList;
|
|
|
|
ASSERT(Processor <= (ULONG)g_UlNumberOfProcessors);
|
|
|
|
PPSList = PER_PROC_SLIST(PoolHandle, Processor);
|
|
|
|
return PPSList->EntriesServed;
|
|
}
|
|
|
|
#endif // DBG
|
|
|
|
|
|
#endif // _PPLASL_H_
|