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