Source code of Windows XP (NT5)
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.

488 lines
9.9 KiB

  1. /*++
  2. Copyright (c) 2000 Microsoft Corporation
  3. Module Name :
  4. kLKRhash.h
  5. Abstract:
  6. Kernel-mode version of LKRhash: a fast, scalable,
  7. cache- and MP-friendly hash table
  8. Author:
  9. George V. Reilly (GeorgeRe) 24-Oct-2000
  10. Environment:
  11. Win32 - Kernel Mode
  12. Project:
  13. Internet Information Server Http.sys
  14. Revision History:
  15. --*/
  16. #ifndef __KLKRHASH_H__
  17. #define __KLKRHASH_H__
  18. #ifdef __LKRHASH_H__
  19. #error Do not #include <LKRhash.h> before <kLKRhash.h>
  20. #endif
  21. #define LKRHASH_KERNEL_MODE
  22. // BUGBUG: temporarily disable global list of LKRhash tables, to avoid
  23. // dealing with issues of constructing/destructing global objects
  24. #define LKR_NO_GLOBAL_LIST
  25. #ifdef __IRTLDBG_H__
  26. # error Do not #include <IrtlDbg.h> before <kLKRhash.h>
  27. #else // !__IRTLDBG_H__
  28. # define IRTLDBG_KERNEL_MODE
  29. # include <IrtlDbg.h>
  30. #endif // !__IRTLDBG_H__
  31. // Fake up some Windows types for kernel mode
  32. #define WINAPI NTAPI /* __stdcall */
  33. typedef void* LPVOID;
  34. typedef const void* LPCVOID;
  35. typedef unsigned long DWORD;
  36. typedef unsigned int UINT;
  37. typedef unsigned short WORD;
  38. typedef unsigned char BYTE;
  39. typedef BYTE* PBYTE;
  40. typedef BYTE* LPBYTE;
  41. typedef int BOOL;
  42. typedef const TCHAR* LPCTSTR;
  43. #define KLKRHASH_TAG ((ULONG) 'hRKL')
  44. #ifndef LKRHASH_KERNEL_NO_NEW
  45. // Override operator new and operator delete
  46. extern ULONG __Pool_Tag__;
  47. // Prototype for function that sets the pool tag
  48. inline
  49. void
  50. SetPoolTag(
  51. ULONG tag)
  52. {
  53. __Pool_Tag__ = tag;
  54. }
  55. inline
  56. void*
  57. __cdecl
  58. operator new(
  59. size_t nSize)
  60. {
  61. return ((nSize > 0)
  62. ? ExAllocatePoolWithTag(NonPagedPool, nSize, __Pool_Tag__)
  63. : NULL);
  64. }
  65. inline
  66. void*
  67. __cdecl
  68. operator new(
  69. size_t nSize,
  70. POOL_TYPE iType)
  71. {
  72. return ((nSize > 0)
  73. ? ExAllocatePoolWithTag(iType, nSize, __Pool_Tag__)
  74. : NULL);
  75. }
  76. inline
  77. void*
  78. __cdecl
  79. operator new(
  80. size_t nSize,
  81. POOL_TYPE iType,
  82. ULONG tag)
  83. {
  84. return ((nSize > 0)
  85. ? ExAllocatePoolWithTag(iType, nSize, tag)
  86. : NULL);
  87. }
  88. inline
  89. void
  90. __cdecl
  91. operator delete(
  92. void* p)
  93. {
  94. if (p != NULL)
  95. ExFreePool(p);
  96. }
  97. inline
  98. void
  99. __cdecl
  100. operator delete[](
  101. void* p)
  102. {
  103. if (p != NULL)
  104. ExFreePool(p);
  105. }
  106. #endif // !LKRHASH_KERNEL_NO_NEW
  107. // Pool Allocators
  108. template <POOL_TYPE _pt>
  109. class CPoolAllocator
  110. {
  111. private:
  112. SIZE_T m_cb;
  113. const ULONG m_ulTag;
  114. #ifdef IRTLDEBUG
  115. ULONG m_cAllocs;
  116. ULONG m_cFrees;
  117. #endif // IRTLDEBUG
  118. public:
  119. CPoolAllocator(
  120. SIZE_T cb,
  121. ULONG ulTag)
  122. : m_cb(cb),
  123. m_ulTag(ulTag)
  124. #ifdef IRTLDEBUG
  125. , m_cAllocs(0)
  126. , m_cFrees(0)
  127. #endif // IRTLDEBUG
  128. {}
  129. ~CPoolAllocator()
  130. {
  131. IRTLASSERT(m_cAllocs == m_cFrees);
  132. }
  133. LPVOID Alloc()
  134. {
  135. LPVOID pvMem = ExAllocatePoolWithTag(_pt, m_cb, m_ulTag);
  136. #ifdef IRTLDEBUG
  137. InterlockedIncrement((PLONG) &m_cAllocs);
  138. #endif // IRTLDEBUG
  139. return pvMem;
  140. }
  141. BOOL Free(LPVOID pvMem)
  142. {
  143. IRTLASSERT(pvMem != NULL);
  144. #ifdef IRTLDEBUG
  145. InterlockedIncrement((PLONG) &m_cFrees);
  146. #endif // IRTLDEBUG
  147. // return ExFreePoolWithTag(pvMem, m_ulTag);
  148. ExFreePool(pvMem);
  149. return TRUE;
  150. }
  151. SIZE_T ByteSize() const
  152. {
  153. return m_cb;
  154. }
  155. }; // class CPoolAllocator<_pt>
  156. class CNonPagedHeap : public CPoolAllocator<NonPagedPool>
  157. {
  158. public:
  159. static const TCHAR* ClassName() {return _TEXT("CNonPagedHeap");}
  160. }; // class CNonPagedHeap
  161. class CPagedHeap : public CPoolAllocator<PagedPool>
  162. {
  163. public:
  164. static const TCHAR* ClassName() {return _TEXT("CPagedHeap");}
  165. }; // class CPagedHeap
  166. // Lookaside Lists
  167. class CNonPagedLookasideList
  168. {
  169. private:
  170. PNPAGED_LOOKASIDE_LIST m_pnpla;
  171. const SIZE_T m_cb;
  172. const ULONG m_ulTag;
  173. enum {
  174. PNPAGED_LOOKASIDE_LIST_TAG = 'aLPn',
  175. };
  176. #ifdef IRTLDEBUG
  177. ULONG m_cAllocs;
  178. ULONG m_cFrees;
  179. static PVOID
  180. AllocateFunction(
  181. IN POOL_TYPE PoolType,
  182. IN SIZE_T NumberOfBytes,
  183. IN ULONG Tag
  184. )
  185. {
  186. IRTLASSERT( PoolType == NonPagedPool );
  187. // TODO: better bookkeeping
  188. return ExAllocatePoolWithTag(PoolType, NumberOfBytes, Tag);
  189. }
  190. static VOID
  191. FreeFunction(
  192. IN PVOID Buffer
  193. )
  194. {
  195. // TODO: better bookkeeping
  196. ExFreePool(Buffer);
  197. }
  198. #endif // IRTLDEBUG
  199. public:
  200. CNonPagedLookasideList(
  201. SIZE_T cb,
  202. ULONG ulTag)
  203. : m_cb(cb),
  204. m_ulTag(ulTag)
  205. #ifdef IRTLDEBUG
  206. , m_cAllocs(0)
  207. , m_cFrees(0)
  208. #endif // IRTLDEBUG
  209. {
  210. m_pnpla = static_cast<PNPAGED_LOOKASIDE_LIST>(
  211. ExAllocatePoolWithTag(
  212. NonPagedPool,
  213. sizeof(NPAGED_LOOKASIDE_LIST),
  214. PNPAGED_LOOKASIDE_LIST_TAG));
  215. if (m_pnpla != NULL)
  216. {
  217. ExInitializeNPagedLookasideList(
  218. m_pnpla, // Lookaside
  219. #ifdef IRTLDEBUG
  220. AllocateFunction, // Allocate
  221. FreeFunction, // Free
  222. #else // !IRTLDEBUG
  223. NULL, // default Allocate
  224. NULL, // default Free
  225. #endif // !IRTLDEBUG
  226. 0, // Flags
  227. m_cb, // Size
  228. m_ulTag, // Tag
  229. 0 // Depth
  230. );
  231. }
  232. }
  233. ~CNonPagedLookasideList()
  234. {
  235. IRTLASSERT(m_cAllocs == m_cFrees);
  236. if (m_pnpla != NULL)
  237. {
  238. ExDeleteNPagedLookasideList(m_pnpla);
  239. ExFreePool(m_pnpla);
  240. }
  241. }
  242. LPVOID Alloc()
  243. {
  244. LPVOID pvMem = ExAllocateFromNPagedLookasideList(m_pnpla);
  245. #ifdef IRTLDEBUG
  246. InterlockedIncrement((PLONG) &m_cAllocs);
  247. #endif // IRTLDEBUG
  248. return pvMem;
  249. }
  250. BOOL Free(LPVOID pvMem)
  251. {
  252. IRTLASSERT(pvMem != NULL);
  253. #ifdef IRTLDEBUG
  254. InterlockedIncrement((PLONG) &m_cFrees);
  255. #endif // IRTLDEBUG
  256. ExFreeToNPagedLookasideList(m_pnpla, pvMem);
  257. return TRUE;
  258. }
  259. SIZE_T ByteSize() const
  260. {
  261. return m_cb;
  262. }
  263. static const TCHAR* ClassName() {return _TEXT("CNonPagedLookasideList");}
  264. }; // class CNonPagedLookasideList
  265. class CPagedLookasideList
  266. {
  267. private:
  268. PPAGED_LOOKASIDE_LIST m_ppla;
  269. const SIZE_T m_cb;
  270. const ULONG m_ulTag;
  271. enum {
  272. PPAGED_LOOKASIDE_LIST_TAG = 'aLPp',
  273. };
  274. #ifdef IRTLDEBUG
  275. ULONG m_cAllocs;
  276. ULONG m_cFrees;
  277. static PVOID
  278. AllocateFunction(
  279. IN POOL_TYPE PoolType,
  280. IN SIZE_T NumberOfBytes,
  281. IN ULONG Tag
  282. )
  283. {
  284. IRTLASSERT( PoolType == PagedPool );
  285. // TODO: better bookkeeping
  286. return ExAllocatePoolWithTag(PoolType, NumberOfBytes, Tag);
  287. }
  288. static VOID
  289. FreeFunction(
  290. IN PVOID Buffer
  291. )
  292. {
  293. // TODO: better bookkeeping
  294. ExFreePool(Buffer);
  295. }
  296. #endif // IRTLDEBUG
  297. public:
  298. CPagedLookasideList(
  299. SIZE_T cb,
  300. ULONG ulTag)
  301. : m_cb(cb),
  302. m_ulTag(ulTag)
  303. #ifdef IRTLDEBUG
  304. , m_cAllocs(0)
  305. , m_cFrees(0)
  306. #endif // IRTLDEBUG
  307. {
  308. m_ppla = static_cast<PPAGED_LOOKASIDE_LIST>(
  309. ExAllocatePoolWithTag(
  310. NonPagedPool,
  311. sizeof(PAGED_LOOKASIDE_LIST),
  312. PPAGED_LOOKASIDE_LIST_TAG));
  313. if (m_ppla != NULL)
  314. {
  315. ExInitializePagedLookasideList(
  316. m_ppla, // Lookaside
  317. #ifdef IRTLDEBUG
  318. AllocateFunction, // Allocate
  319. FreeFunction, // Free
  320. #else // !IRTLDEBUG
  321. NULL, // Allocate
  322. NULL, // Free
  323. #endif // !IRTLDEBUG
  324. 0, // Flags
  325. m_cb, // Size
  326. m_ulTag, // Tag
  327. 0 // Depth
  328. );
  329. }
  330. }
  331. ~CPagedLookasideList()
  332. {
  333. IRTLASSERT(m_cAllocs == m_cFrees);
  334. if (m_ppla != NULL)
  335. {
  336. ExDeletePagedLookasideList(m_ppla);
  337. ExFreePool(m_ppla);
  338. }
  339. }
  340. LPVOID Alloc()
  341. {
  342. LPVOID pvMem = ExAllocateFromPagedLookasideList(m_ppla);
  343. #ifdef IRTLDEBUG
  344. InterlockedIncrement((PLONG) &m_cAllocs);
  345. #endif // IRTLDEBUG
  346. return pvMem;
  347. }
  348. BOOL Free(LPVOID pvMem)
  349. {
  350. IRTLASSERT(pvMem != NULL);
  351. #ifdef IRTLDEBUG
  352. InterlockedIncrement((PLONG) &m_cFrees);
  353. #endif // IRTLDEBUG
  354. ExFreeToPagedLookasideList(m_ppla, pvMem);
  355. return TRUE;
  356. }
  357. SIZE_T ByteSize() const
  358. {
  359. return m_cb;
  360. }
  361. static const TCHAR* ClassName() {return _TEXT("CPagedLookasideList");}
  362. }; // class CPagedLookasideList
  363. #if 0
  364. # define LKRHASH_NONPAGEDHEAP
  365. typedef CNonPagedHeap CLKRhashAllocator;
  366. # define LKRHASH_ALLOCATOR_NEW(C, N, Tag) \
  367. C::sm_palloc = new CNonPagedHeap(sizeof(C), Tag)
  368. #elif 0
  369. # define LKRHASH_PAGEDHEAP
  370. typedef CPagedHeap CLKRhashAllocator;
  371. # define LKRHASH_ALLOCATOR_NEW(C, N, Tag) \
  372. C::sm_palloc = new CPagedHeap(sizeof(C), Tag)
  373. #elif 1 // <----
  374. # define LKRHASH_NONPAGEDLOOKASIDE
  375. typedef CNonPagedLookasideList CLKRhashAllocator;
  376. # define LKRHASH_ALLOCATOR_NEW(C, N, Tag) \
  377. C::sm_palloc = new CNonPagedLookasideList(sizeof(C), Tag)
  378. #elif 0
  379. # define LKRHASH_PAGEDLOOKASIDE
  380. typedef CPagedLookasideList CLKRhashAllocator;
  381. # define LKRHASH_ALLOCATOR_NEW(C, N, Tag) \
  382. C::sm_palloc = new CPagedLookasideList(sizeof(C), Tag)
  383. #endif
  384. // TODO: lookaside lists
  385. #include <kLocks.h>
  386. // #define LKR_TABLE_LOCK CEResource
  387. // #define LKR_BUCKET_LOCK CSpinLock
  388. #define LKR_TABLE_LOCK CReaderWriterLock3
  389. #define LKR_BUCKET_LOCK CSmallSpinLock
  390. #define LSTENTRY_LOCK LKR_BUCKET_LOCK
  391. #include <LKRhash.h>
  392. #endif // __KLKRHASH_H__