489 lines
9.9 KiB
C
489 lines
9.9 KiB
C
|
/*++
|
|||
|
|
|||
|
Copyright (c) 2000 Microsoft Corporation
|
|||
|
|
|||
|
Module Name :
|
|||
|
kLKRhash.h
|
|||
|
|
|||
|
Abstract:
|
|||
|
Kernel-mode version of LKRhash: a fast, scalable,
|
|||
|
cache- and MP-friendly hash table
|
|||
|
|
|||
|
Author:
|
|||
|
George V. Reilly (GeorgeRe) 24-Oct-2000
|
|||
|
|
|||
|
Environment:
|
|||
|
Win32 - Kernel Mode
|
|||
|
|
|||
|
Project:
|
|||
|
Internet Information Server Http.sys
|
|||
|
|
|||
|
Revision History:
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
|
|||
|
#ifndef __KLKRHASH_H__
|
|||
|
#define __KLKRHASH_H__
|
|||
|
|
|||
|
#ifdef __LKRHASH_H__
|
|||
|
#error Do not #include <LKRhash.h> before <kLKRhash.h>
|
|||
|
#endif
|
|||
|
|
|||
|
#define LKRHASH_KERNEL_MODE
|
|||
|
|
|||
|
// BUGBUG: temporarily disable global list of LKRhash tables, to avoid
|
|||
|
// dealing with issues of constructing/destructing global objects
|
|||
|
#define LKR_NO_GLOBAL_LIST
|
|||
|
|
|||
|
#ifdef __IRTLDBG_H__
|
|||
|
# error Do not #include <IrtlDbg.h> before <kLKRhash.h>
|
|||
|
#else // !__IRTLDBG_H__
|
|||
|
# define IRTLDBG_KERNEL_MODE
|
|||
|
# include <IrtlDbg.h>
|
|||
|
#endif // !__IRTLDBG_H__
|
|||
|
|
|||
|
|
|||
|
// Fake up some Windows types for kernel mode
|
|||
|
#define WINAPI NTAPI /* __stdcall */
|
|||
|
typedef void* LPVOID;
|
|||
|
typedef const void* LPCVOID;
|
|||
|
typedef unsigned long DWORD;
|
|||
|
typedef unsigned int UINT;
|
|||
|
typedef unsigned short WORD;
|
|||
|
typedef unsigned char BYTE;
|
|||
|
typedef BYTE* PBYTE;
|
|||
|
typedef BYTE* LPBYTE;
|
|||
|
typedef int BOOL;
|
|||
|
typedef const TCHAR* LPCTSTR;
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
#define KLKRHASH_TAG ((ULONG) 'hRKL')
|
|||
|
|
|||
|
|
|||
|
#ifndef LKRHASH_KERNEL_NO_NEW
|
|||
|
// Override operator new and operator delete
|
|||
|
|
|||
|
extern ULONG __Pool_Tag__;
|
|||
|
|
|||
|
// Prototype for function that sets the pool tag
|
|||
|
|
|||
|
inline
|
|||
|
void
|
|||
|
SetPoolTag(
|
|||
|
ULONG tag)
|
|||
|
{
|
|||
|
__Pool_Tag__ = tag;
|
|||
|
}
|
|||
|
|
|||
|
inline
|
|||
|
void*
|
|||
|
__cdecl
|
|||
|
operator new(
|
|||
|
size_t nSize)
|
|||
|
{
|
|||
|
return ((nSize > 0)
|
|||
|
? ExAllocatePoolWithTag(NonPagedPool, nSize, __Pool_Tag__)
|
|||
|
: NULL);
|
|||
|
}
|
|||
|
|
|||
|
inline
|
|||
|
void*
|
|||
|
__cdecl
|
|||
|
operator new(
|
|||
|
size_t nSize,
|
|||
|
POOL_TYPE iType)
|
|||
|
{
|
|||
|
return ((nSize > 0)
|
|||
|
? ExAllocatePoolWithTag(iType, nSize, __Pool_Tag__)
|
|||
|
: NULL);
|
|||
|
}
|
|||
|
|
|||
|
inline
|
|||
|
void*
|
|||
|
__cdecl
|
|||
|
operator new(
|
|||
|
size_t nSize,
|
|||
|
POOL_TYPE iType,
|
|||
|
ULONG tag)
|
|||
|
{
|
|||
|
return ((nSize > 0)
|
|||
|
? ExAllocatePoolWithTag(iType, nSize, tag)
|
|||
|
: NULL);
|
|||
|
}
|
|||
|
|
|||
|
inline
|
|||
|
void
|
|||
|
__cdecl
|
|||
|
operator delete(
|
|||
|
void* p)
|
|||
|
{
|
|||
|
if (p != NULL)
|
|||
|
ExFreePool(p);
|
|||
|
}
|
|||
|
|
|||
|
inline
|
|||
|
void
|
|||
|
__cdecl
|
|||
|
operator delete[](
|
|||
|
void* p)
|
|||
|
{
|
|||
|
if (p != NULL)
|
|||
|
ExFreePool(p);
|
|||
|
}
|
|||
|
|
|||
|
#endif // !LKRHASH_KERNEL_NO_NEW
|
|||
|
|
|||
|
|
|||
|
|
|||
|
// Pool Allocators
|
|||
|
|
|||
|
template <POOL_TYPE _pt>
|
|||
|
class CPoolAllocator
|
|||
|
{
|
|||
|
private:
|
|||
|
SIZE_T m_cb;
|
|||
|
const ULONG m_ulTag;
|
|||
|
|
|||
|
#ifdef IRTLDEBUG
|
|||
|
ULONG m_cAllocs;
|
|||
|
ULONG m_cFrees;
|
|||
|
#endif // IRTLDEBUG
|
|||
|
|
|||
|
public:
|
|||
|
CPoolAllocator(
|
|||
|
SIZE_T cb,
|
|||
|
ULONG ulTag)
|
|||
|
: m_cb(cb),
|
|||
|
m_ulTag(ulTag)
|
|||
|
#ifdef IRTLDEBUG
|
|||
|
, m_cAllocs(0)
|
|||
|
, m_cFrees(0)
|
|||
|
#endif // IRTLDEBUG
|
|||
|
{}
|
|||
|
|
|||
|
~CPoolAllocator()
|
|||
|
{
|
|||
|
IRTLASSERT(m_cAllocs == m_cFrees);
|
|||
|
}
|
|||
|
|
|||
|
LPVOID Alloc()
|
|||
|
{
|
|||
|
LPVOID pvMem = ExAllocatePoolWithTag(_pt, m_cb, m_ulTag);
|
|||
|
#ifdef IRTLDEBUG
|
|||
|
InterlockedIncrement((PLONG) &m_cAllocs);
|
|||
|
#endif // IRTLDEBUG
|
|||
|
return pvMem;
|
|||
|
}
|
|||
|
|
|||
|
BOOL Free(LPVOID pvMem)
|
|||
|
{
|
|||
|
IRTLASSERT(pvMem != NULL);
|
|||
|
#ifdef IRTLDEBUG
|
|||
|
InterlockedIncrement((PLONG) &m_cFrees);
|
|||
|
#endif // IRTLDEBUG
|
|||
|
// return ExFreePoolWithTag(pvMem, m_ulTag);
|
|||
|
ExFreePool(pvMem);
|
|||
|
return TRUE;
|
|||
|
}
|
|||
|
|
|||
|
SIZE_T ByteSize() const
|
|||
|
{
|
|||
|
return m_cb;
|
|||
|
}
|
|||
|
}; // class CPoolAllocator<_pt>
|
|||
|
|
|||
|
|
|||
|
class CNonPagedHeap : public CPoolAllocator<NonPagedPool>
|
|||
|
{
|
|||
|
public:
|
|||
|
static const TCHAR* ClassName() {return _TEXT("CNonPagedHeap");}
|
|||
|
}; // class CNonPagedHeap
|
|||
|
|
|||
|
|
|||
|
class CPagedHeap : public CPoolAllocator<PagedPool>
|
|||
|
{
|
|||
|
public:
|
|||
|
static const TCHAR* ClassName() {return _TEXT("CPagedHeap");}
|
|||
|
}; // class CPagedHeap
|
|||
|
|
|||
|
|
|||
|
|
|||
|
// Lookaside Lists
|
|||
|
|
|||
|
class CNonPagedLookasideList
|
|||
|
{
|
|||
|
private:
|
|||
|
PNPAGED_LOOKASIDE_LIST m_pnpla;
|
|||
|
const SIZE_T m_cb;
|
|||
|
const ULONG m_ulTag;
|
|||
|
|
|||
|
enum {
|
|||
|
PNPAGED_LOOKASIDE_LIST_TAG = 'aLPn',
|
|||
|
};
|
|||
|
|
|||
|
#ifdef IRTLDEBUG
|
|||
|
ULONG m_cAllocs;
|
|||
|
ULONG m_cFrees;
|
|||
|
|
|||
|
static PVOID
|
|||
|
AllocateFunction(
|
|||
|
IN POOL_TYPE PoolType,
|
|||
|
IN SIZE_T NumberOfBytes,
|
|||
|
IN ULONG Tag
|
|||
|
)
|
|||
|
{
|
|||
|
IRTLASSERT( PoolType == NonPagedPool );
|
|||
|
// TODO: better bookkeeping
|
|||
|
return ExAllocatePoolWithTag(PoolType, NumberOfBytes, Tag);
|
|||
|
}
|
|||
|
|
|||
|
static VOID
|
|||
|
FreeFunction(
|
|||
|
IN PVOID Buffer
|
|||
|
)
|
|||
|
{
|
|||
|
// TODO: better bookkeeping
|
|||
|
ExFreePool(Buffer);
|
|||
|
}
|
|||
|
#endif // IRTLDEBUG
|
|||
|
|
|||
|
public:
|
|||
|
CNonPagedLookasideList(
|
|||
|
SIZE_T cb,
|
|||
|
ULONG ulTag)
|
|||
|
: m_cb(cb),
|
|||
|
m_ulTag(ulTag)
|
|||
|
#ifdef IRTLDEBUG
|
|||
|
, m_cAllocs(0)
|
|||
|
, m_cFrees(0)
|
|||
|
#endif // IRTLDEBUG
|
|||
|
{
|
|||
|
|
|||
|
m_pnpla = static_cast<PNPAGED_LOOKASIDE_LIST>(
|
|||
|
ExAllocatePoolWithTag(
|
|||
|
NonPagedPool,
|
|||
|
sizeof(NPAGED_LOOKASIDE_LIST),
|
|||
|
PNPAGED_LOOKASIDE_LIST_TAG));
|
|||
|
|
|||
|
if (m_pnpla != NULL)
|
|||
|
{
|
|||
|
ExInitializeNPagedLookasideList(
|
|||
|
m_pnpla, // Lookaside
|
|||
|
#ifdef IRTLDEBUG
|
|||
|
AllocateFunction, // Allocate
|
|||
|
FreeFunction, // Free
|
|||
|
#else // !IRTLDEBUG
|
|||
|
NULL, // default Allocate
|
|||
|
NULL, // default Free
|
|||
|
#endif // !IRTLDEBUG
|
|||
|
0, // Flags
|
|||
|
m_cb, // Size
|
|||
|
m_ulTag, // Tag
|
|||
|
0 // Depth
|
|||
|
);
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
~CNonPagedLookasideList()
|
|||
|
{
|
|||
|
IRTLASSERT(m_cAllocs == m_cFrees);
|
|||
|
|
|||
|
if (m_pnpla != NULL)
|
|||
|
{
|
|||
|
ExDeleteNPagedLookasideList(m_pnpla);
|
|||
|
ExFreePool(m_pnpla);
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
LPVOID Alloc()
|
|||
|
{
|
|||
|
LPVOID pvMem = ExAllocateFromNPagedLookasideList(m_pnpla);
|
|||
|
#ifdef IRTLDEBUG
|
|||
|
InterlockedIncrement((PLONG) &m_cAllocs);
|
|||
|
#endif // IRTLDEBUG
|
|||
|
return pvMem;
|
|||
|
}
|
|||
|
|
|||
|
BOOL Free(LPVOID pvMem)
|
|||
|
{
|
|||
|
IRTLASSERT(pvMem != NULL);
|
|||
|
#ifdef IRTLDEBUG
|
|||
|
InterlockedIncrement((PLONG) &m_cFrees);
|
|||
|
#endif // IRTLDEBUG
|
|||
|
ExFreeToNPagedLookasideList(m_pnpla, pvMem);
|
|||
|
return TRUE;
|
|||
|
}
|
|||
|
|
|||
|
SIZE_T ByteSize() const
|
|||
|
{
|
|||
|
return m_cb;
|
|||
|
}
|
|||
|
|
|||
|
static const TCHAR* ClassName() {return _TEXT("CNonPagedLookasideList");}
|
|||
|
}; // class CNonPagedLookasideList
|
|||
|
|
|||
|
|
|||
|
|
|||
|
class CPagedLookasideList
|
|||
|
{
|
|||
|
private:
|
|||
|
PPAGED_LOOKASIDE_LIST m_ppla;
|
|||
|
const SIZE_T m_cb;
|
|||
|
const ULONG m_ulTag;
|
|||
|
|
|||
|
enum {
|
|||
|
PPAGED_LOOKASIDE_LIST_TAG = 'aLPp',
|
|||
|
};
|
|||
|
|
|||
|
#ifdef IRTLDEBUG
|
|||
|
ULONG m_cAllocs;
|
|||
|
ULONG m_cFrees;
|
|||
|
|
|||
|
static PVOID
|
|||
|
AllocateFunction(
|
|||
|
IN POOL_TYPE PoolType,
|
|||
|
IN SIZE_T NumberOfBytes,
|
|||
|
IN ULONG Tag
|
|||
|
)
|
|||
|
{
|
|||
|
IRTLASSERT( PoolType == PagedPool );
|
|||
|
// TODO: better bookkeeping
|
|||
|
return ExAllocatePoolWithTag(PoolType, NumberOfBytes, Tag);
|
|||
|
}
|
|||
|
|
|||
|
static VOID
|
|||
|
FreeFunction(
|
|||
|
IN PVOID Buffer
|
|||
|
)
|
|||
|
{
|
|||
|
// TODO: better bookkeeping
|
|||
|
ExFreePool(Buffer);
|
|||
|
}
|
|||
|
#endif // IRTLDEBUG
|
|||
|
|
|||
|
public:
|
|||
|
CPagedLookasideList(
|
|||
|
SIZE_T cb,
|
|||
|
ULONG ulTag)
|
|||
|
: m_cb(cb),
|
|||
|
m_ulTag(ulTag)
|
|||
|
#ifdef IRTLDEBUG
|
|||
|
, m_cAllocs(0)
|
|||
|
, m_cFrees(0)
|
|||
|
#endif // IRTLDEBUG
|
|||
|
{
|
|||
|
m_ppla = static_cast<PPAGED_LOOKASIDE_LIST>(
|
|||
|
ExAllocatePoolWithTag(
|
|||
|
NonPagedPool,
|
|||
|
sizeof(PAGED_LOOKASIDE_LIST),
|
|||
|
PPAGED_LOOKASIDE_LIST_TAG));
|
|||
|
|
|||
|
if (m_ppla != NULL)
|
|||
|
{
|
|||
|
ExInitializePagedLookasideList(
|
|||
|
m_ppla, // Lookaside
|
|||
|
#ifdef IRTLDEBUG
|
|||
|
AllocateFunction, // Allocate
|
|||
|
FreeFunction, // Free
|
|||
|
#else // !IRTLDEBUG
|
|||
|
NULL, // Allocate
|
|||
|
NULL, // Free
|
|||
|
#endif // !IRTLDEBUG
|
|||
|
0, // Flags
|
|||
|
m_cb, // Size
|
|||
|
m_ulTag, // Tag
|
|||
|
0 // Depth
|
|||
|
);
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
~CPagedLookasideList()
|
|||
|
{
|
|||
|
IRTLASSERT(m_cAllocs == m_cFrees);
|
|||
|
|
|||
|
if (m_ppla != NULL)
|
|||
|
{
|
|||
|
ExDeletePagedLookasideList(m_ppla);
|
|||
|
ExFreePool(m_ppla);
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
LPVOID Alloc()
|
|||
|
{
|
|||
|
LPVOID pvMem = ExAllocateFromPagedLookasideList(m_ppla);
|
|||
|
#ifdef IRTLDEBUG
|
|||
|
InterlockedIncrement((PLONG) &m_cAllocs);
|
|||
|
#endif // IRTLDEBUG
|
|||
|
return pvMem;
|
|||
|
}
|
|||
|
|
|||
|
BOOL Free(LPVOID pvMem)
|
|||
|
{
|
|||
|
IRTLASSERT(pvMem != NULL);
|
|||
|
#ifdef IRTLDEBUG
|
|||
|
InterlockedIncrement((PLONG) &m_cFrees);
|
|||
|
#endif // IRTLDEBUG
|
|||
|
ExFreeToPagedLookasideList(m_ppla, pvMem);
|
|||
|
return TRUE;
|
|||
|
}
|
|||
|
|
|||
|
SIZE_T ByteSize() const
|
|||
|
{
|
|||
|
return m_cb;
|
|||
|
}
|
|||
|
|
|||
|
static const TCHAR* ClassName() {return _TEXT("CPagedLookasideList");}
|
|||
|
}; // class CPagedLookasideList
|
|||
|
|
|||
|
|
|||
|
|
|||
|
#if 0
|
|||
|
|
|||
|
# define LKRHASH_NONPAGEDHEAP
|
|||
|
typedef CNonPagedHeap CLKRhashAllocator;
|
|||
|
# define LKRHASH_ALLOCATOR_NEW(C, N, Tag) \
|
|||
|
C::sm_palloc = new CNonPagedHeap(sizeof(C), Tag)
|
|||
|
|
|||
|
#elif 0
|
|||
|
|
|||
|
# define LKRHASH_PAGEDHEAP
|
|||
|
typedef CPagedHeap CLKRhashAllocator;
|
|||
|
# define LKRHASH_ALLOCATOR_NEW(C, N, Tag) \
|
|||
|
C::sm_palloc = new CPagedHeap(sizeof(C), Tag)
|
|||
|
|
|||
|
#elif 1 // <----
|
|||
|
|
|||
|
# define LKRHASH_NONPAGEDLOOKASIDE
|
|||
|
typedef CNonPagedLookasideList CLKRhashAllocator;
|
|||
|
# define LKRHASH_ALLOCATOR_NEW(C, N, Tag) \
|
|||
|
C::sm_palloc = new CNonPagedLookasideList(sizeof(C), Tag)
|
|||
|
|
|||
|
#elif 0
|
|||
|
|
|||
|
# define LKRHASH_PAGEDLOOKASIDE
|
|||
|
typedef CPagedLookasideList CLKRhashAllocator;
|
|||
|
# define LKRHASH_ALLOCATOR_NEW(C, N, Tag) \
|
|||
|
C::sm_palloc = new CPagedLookasideList(sizeof(C), Tag)
|
|||
|
|
|||
|
#endif
|
|||
|
|
|||
|
|
|||
|
|
|||
|
// TODO: lookaside lists
|
|||
|
|
|||
|
#include <kLocks.h>
|
|||
|
|
|||
|
// #define LKR_TABLE_LOCK CEResource
|
|||
|
// #define LKR_BUCKET_LOCK CSpinLock
|
|||
|
#define LKR_TABLE_LOCK CReaderWriterLock3
|
|||
|
#define LKR_BUCKET_LOCK CSmallSpinLock
|
|||
|
#define LSTENTRY_LOCK LKR_BUCKET_LOCK
|
|||
|
|
|||
|
#include <LKRhash.h>
|
|||
|
|
|||
|
#endif // __KLKRHASH_H__
|
|||
|
|