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.

454 lines
10 KiB

  1. /*++
  2. Copyright (c) 1998-2001 Microsoft Corporation
  3. Module Name:
  4. hash.h
  5. Abstract:
  6. The public definition of response cache hash table.
  7. Author:
  8. Alex Chen (alexch) 28-Mar-2001
  9. Revision History:
  10. --*/
  11. #ifndef _HASH_H_
  12. #define _HASH_H_
  13. #include "cachep.h"
  14. #ifdef __cplusplus
  15. extern "C" {
  16. #endif
  17. //
  18. // Reader-Writer Spinlock definitions
  19. //
  20. #define RWSL_LOCKED ((ULONG) (-1))
  21. #define RWSL_FREE (0)
  22. typedef struct _RWSPINLOCK
  23. {
  24. union
  25. {
  26. struct
  27. {
  28. // 0 == RWSL_FREE => unowned
  29. // >0 => count of readers (shared)
  30. // <0 == RWSL_LOCKED => exclusively owned
  31. volatile LONG CurrentState;
  32. // all writers, including the one that holds the lock
  33. // exclusively, if at all
  34. volatile LONG WritersWaiting;
  35. };
  36. ULONGLONG Alignment;
  37. };
  38. } RWSPINLOCK, *PRWSPINLOCK;
  39. //
  40. // Hash Table definitions
  41. //
  42. typedef struct _HASH_BUCKET *PHASHBUCKET;
  43. typedef struct _HASH_TABLE
  44. {
  45. ULONG Signature; //UL_HASH_TABLE_POOL_TAG
  46. POOL_TYPE PoolType;
  47. SIZE_T NumberOfBytes;
  48. PHASHBUCKET pAllocMem;
  49. PHASHBUCKET pBuckets;
  50. } HASHTABLE, *PHASHTABLE;
  51. #define IS_VALID_HASHTABLE(pHashTable) \
  52. (NULL != (pHashTable) \
  53. && NULL != (pHashTable)->pAllocMem \
  54. && UL_HASH_TABLE_POOL_TAG == (pHashTable)->Signature)
  55. /***************************************************************************++
  56. Routine Description:
  57. Initialize the Reader-Writer lock.
  58. Return Value:
  59. --***************************************************************************/
  60. __inline
  61. VOID
  62. UlInitializeRWSpinLock(
  63. PRWSPINLOCK pRWSpinLock
  64. )
  65. {
  66. // pRWSpinLock->CurrentState: Number of Readers, RWSL_FREE: 0
  67. pRWSpinLock->CurrentState = RWSL_FREE;
  68. // pRWSpinLock->WritersWaiting: Number of Writers
  69. pRWSpinLock->WritersWaiting = 0;
  70. } // UlInitializeRWSpinLock
  71. /***************************************************************************++
  72. Routine Description:
  73. Acquire the Reader lock.
  74. Return Value:
  75. --***************************************************************************/
  76. __inline
  77. VOID
  78. UlAcquireRWSpinLockShared(
  79. PRWSPINLOCK pRWSpinLock
  80. )
  81. {
  82. LONG CurrentState, WritersWaiting;
  83. while (1)
  84. {
  85. CurrentState = pRWSpinLock->CurrentState;
  86. WritersWaiting = pRWSpinLock->WritersWaiting;
  87. //
  88. // If either (1) write lock is acquired (CurrentState == RWSL_LOCKED)
  89. // or (2) there is a writer waiting for the lock
  90. // then skip it this time and try in a tight loop
  91. //
  92. if ((CurrentState != RWSL_LOCKED) && (WritersWaiting == 0))
  93. {
  94. //
  95. // Check if number of readers is unchanged
  96. // increase it by 1
  97. //
  98. if (
  99. CurrentState ==
  100. (LONG) InterlockedCompareExchange(
  101. (PLONG) &pRWSpinLock->CurrentState,
  102. CurrentState + 1,
  103. CurrentState)
  104. )
  105. {
  106. return;
  107. }
  108. else
  109. {
  110. // BUGBUG: This is bogus on a uniprocessor system.
  111. // We'll spin and spin and spin until this thread's
  112. // quantum is exhausted. We should yield immediately
  113. // so that the thread that holds the lock has a chance
  114. // to proceed and release the lock sooner.
  115. // That's assuming we're running at passive level. If
  116. // we're running at dispatch level and the owning thread
  117. // isn't running, we have a biiiig problem.
  118. // Busy loop
  119. PAUSE_PROCESSOR;
  120. continue;
  121. }
  122. }
  123. }
  124. } // UlAcquireRWSpinLockShared
  125. /***************************************************************************++
  126. Routine Description:
  127. Release the Reader lock.
  128. Return Value:
  129. --***************************************************************************/
  130. __inline
  131. VOID
  132. UlReleaseRWSpinLockShared(
  133. PRWSPINLOCK pRWSpinLock
  134. )
  135. {
  136. // decrease number of readers by 1
  137. LONG NewState = InterlockedDecrement((PLONG) &pRWSpinLock->CurrentState);
  138. ASSERT(NewState >= 0);
  139. } // UlReleaseRWSpinLockShared
  140. /***************************************************************************++
  141. Routine Description:
  142. Acquire the Writer lock.
  143. Return Value:
  144. --***************************************************************************/
  145. __inline
  146. VOID
  147. UlAcquireRWSpinLockExclusive(
  148. PRWSPINLOCK pRWSpinLock
  149. )
  150. {
  151. //
  152. // First, increment the number of writers by 1
  153. // such that block the readers
  154. // By doing so, writers have the priority over readers.
  155. //
  156. LONG WritersWaiting = InterlockedIncrement(
  157. (PLONG) &pRWSpinLock->WritersWaiting);
  158. ASSERT(WritersWaiting > 0);
  159. //
  160. // Interlocked change the number of readers to -1 (RWSL_LOCKED)
  161. // loop until done
  162. //
  163. if (pRWSpinLock->CurrentState == RWSL_FREE)
  164. {
  165. if (
  166. RWSL_FREE ==
  167. InterlockedCompareExchange(
  168. (PLONG) &pRWSpinLock->CurrentState,
  169. RWSL_LOCKED,
  170. RWSL_FREE)
  171. )
  172. {
  173. return;
  174. }
  175. }
  176. while (1)
  177. {
  178. if (pRWSpinLock->CurrentState == RWSL_FREE)
  179. {
  180. if (
  181. RWSL_FREE ==
  182. InterlockedCompareExchange(
  183. (PLONG) &pRWSpinLock->CurrentState,
  184. RWSL_LOCKED,
  185. RWSL_FREE)
  186. )
  187. {
  188. return;
  189. }
  190. else
  191. {
  192. // BUGBUG: see comments above about uniprocessor systems
  193. // Busy loop
  194. PAUSE_PROCESSOR;
  195. continue;
  196. }
  197. }
  198. }
  199. } // UlAcquireRWSpinLockExclusive
  200. /***************************************************************************++
  201. Routine Description:
  202. Release the Writer lock.
  203. Return Value:
  204. --***************************************************************************/
  205. __inline
  206. void
  207. UlReleaseRWSpinLockExclusive(
  208. PRWSPINLOCK pRWSpinLock
  209. )
  210. {
  211. LONG OldState, NewWaiting;
  212. //
  213. // Update pRWSpinLock->CurrentState and pRWSpinLock->WritersWaiting back
  214. // in the reverse order of AcquireRWSpinLockExclusive()
  215. //
  216. OldState = InterlockedExchange(
  217. (PLONG) &pRWSpinLock->CurrentState,
  218. RWSL_FREE);
  219. ASSERT(OldState = RWSL_LOCKED);
  220. NewWaiting = InterlockedDecrement((PLONG) &pRWSpinLock->WritersWaiting);
  221. ASSERT(NewWaiting >= 0);
  222. } // UlReleaseRWSpinLockExclusive
  223. /***************************************************************************++
  224. Routine Description:
  225. Check if the Reader lock is acquired.
  226. Return Value:
  227. TRUE - Acquired
  228. FALSE - NOT Acquired
  229. --***************************************************************************/
  230. __inline
  231. BOOLEAN
  232. UlIsLockedShared(
  233. PRWSPINLOCK pRWSpinLock
  234. )
  235. {
  236. // BUGBUG: this routine does not prove that THIS thread is one
  237. // of the shared holders of the lock, merely that at least one
  238. // thread holds the lock in a shared state. Perhaps some extra
  239. // instrumentation for debug builds?
  240. return (pRWSpinLock->CurrentState > 0);
  241. } // UlIsLockedShared
  242. /***************************************************************************++
  243. Routine Description:
  244. Check if the Writer lock is acquired.
  245. Return Value:
  246. TRUE - Acquired
  247. FALSE - NOT Acquired
  248. --***************************************************************************/
  249. __inline
  250. BOOLEAN
  251. UlIsLockedExclusive(
  252. PRWSPINLOCK pRWSpinLock
  253. )
  254. {
  255. // BUGBUG: this routine does not prove that THIS thread holds the lock
  256. // exclusively, merely that someone does.
  257. BOOLEAN IsLocked = (pRWSpinLock->CurrentState == RWSL_LOCKED);
  258. // If it's locked, then we must have added ourselves to WritersWaiting
  259. ASSERT(!IsLocked || pRWSpinLock->WritersWaiting > 0);
  260. return IsLocked;
  261. } // UlIsLockedExclusive
  262. /***************************************************************************++
  263. Routine Description:
  264. Wrapper around RtlEqualUnicodeString
  265. Return Value:
  266. TRUE - Equal
  267. FALSE - NOT Equal
  268. --***************************************************************************/
  269. __inline
  270. BOOLEAN
  271. UlEqualUnicodeString(
  272. IN PWSTR pString1,
  273. IN PWSTR pString2,
  274. IN ULONG StringLength,
  275. IN BOOLEAN CaseInSensitive
  276. )
  277. {
  278. UNICODE_STRING UnicodeString1, UnicodeString2;
  279. UnicodeString1.Length = (USHORT) StringLength;
  280. UnicodeString1.MaximumLength = (USHORT) StringLength;
  281. UnicodeString1.Buffer = pString1;
  282. UnicodeString2.Length = (USHORT) StringLength;
  283. UnicodeString2.MaximumLength = (USHORT) StringLength;
  284. UnicodeString2.Buffer = pString2;
  285. return RtlEqualUnicodeString(
  286. &UnicodeString1,
  287. &UnicodeString2,
  288. CaseInSensitive
  289. );
  290. } // UlEqualUnicodeString
  291. NTSTATUS
  292. UlInitializeHashTable(
  293. IN OUT PHASHTABLE pHashTable,
  294. IN POOL_TYPE PoolType,
  295. IN LONG HashTableBits
  296. );
  297. VOID
  298. UlTerminateHashTable(
  299. IN PHASHTABLE pHashTable
  300. );
  301. PUL_URI_CACHE_ENTRY
  302. UlGetFromHashTable(
  303. IN PHASHTABLE pHashTable,
  304. IN PURI_KEY pUriKey
  305. );
  306. PUL_URI_CACHE_ENTRY
  307. UlDeleteFromHashTable(
  308. IN PHASHTABLE pHashTable,
  309. IN PURI_KEY pUriKey
  310. );
  311. ULC_RETCODE
  312. UlAddToHashTable(
  313. IN PHASHTABLE pHashTable,
  314. IN PUL_URI_CACHE_ENTRY pUriCacheEntry
  315. );
  316. ULONG
  317. UlFilterFlushHashTable(
  318. IN PHASHTABLE pHashTable,
  319. IN PUL_URI_FILTER pFilterRoutine,
  320. IN PVOID pContext
  321. );
  322. VOID
  323. UlClearHashTable(
  324. IN PHASHTABLE pHashTable
  325. );
  326. #ifdef __cplusplus
  327. }; // extern "C"
  328. #endif
  329. #endif // _HASH_H_