Leaked source code of windows server 2003
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

/*++
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_