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.

270 lines
5.7 KiB

  1. /*++ Copyright(c) 2001 Microsoft Corporation
  2. Module Name:
  3. NLB Driver
  4. File Name:
  5. diplist.c
  6. Abstract:
  7. Code to lookup if a DIP is in a list of DIPs, without holding any locks.
  8. History:
  9. 04/24/2002 JosephJ Created
  10. --*/
  11. #include <ntddk.h>
  12. #include "wlbsparm.h"
  13. #include "diplist.h"
  14. #include "univ.h"
  15. #include "trace.h"
  16. #include "diplist.tmh"
  17. #define BITS_PER_HASHWORD (8*sizeof((DIPLIST*)0)->BitVector[0])
  18. #define SELECTED_BIT(_hash_value) \
  19. (0x1L << ((_hash_value) % BITS_PER_HASHWORD))
  20. VOID
  21. DipListInitialize(
  22. DIPLIST *pDL
  23. )
  24. //
  25. // Initialize a DIP List
  26. // Must be called with lock held and before calls to any other DIP List
  27. // function.
  28. //
  29. {
  30. NdisZeroMemory(pDL, sizeof(*pDL));
  31. }
  32. VOID
  33. DipListDeinitialize(
  34. DIPLIST *pDL
  35. )
  36. //
  37. // Deinitialize a DIP List
  38. // Must be called with lock held and should be the last call to the DipList.
  39. //
  40. {
  41. //
  42. // Print out stats...
  43. //
  44. TRACE_INFO(
  45. "DIPLIST: NumChecks=%lu NumFastChecks=%lu NumArrayLookups=%lu",
  46. pDL->stats.NumChecks,
  47. pDL->stats.NumFastChecks,
  48. pDL->stats.NumArrayLookups
  49. );
  50. //
  51. // Clear out the structure...
  52. //
  53. NdisZeroMemory(pDL, sizeof(*pDL));
  54. }
  55. VOID
  56. DipListClear(
  57. DIPLIST *pDL
  58. )
  59. //
  60. // Clear all the items in a dip list.
  61. // Must be called with lock held.
  62. //
  63. {
  64. NdisZeroMemory(pDL->Items, sizeof(pDL->Items));
  65. NdisZeroMemory(pDL->BitVector, sizeof(pDL->BitVector));
  66. NdisZeroMemory(pDL->HashTable, sizeof(pDL->HashTable));
  67. }
  68. VOID
  69. DipListSetItem(
  70. DIPLIST *pDL,
  71. ULONG Index,
  72. ULONG Value
  73. )
  74. //
  75. // Set the value of a specific iten the the DIP list.
  76. // Must be called with lock held.
  77. //
  78. {
  79. if (Index >= MAX_ITEMS)
  80. {
  81. ASSERT(!"DipListSetItem Index >= MAX_ITEMS");
  82. goto end;
  83. }
  84. if (pDL->Items[Index] == Value)
  85. {
  86. // nothing to do...
  87. goto end;
  88. }
  89. pDL->Items[Index] = Value;
  90. //
  91. // recompute hash table and bit table.
  92. //
  93. {
  94. UCHAR iItem;
  95. NdisZeroMemory(pDL->BitVector, sizeof(pDL->BitVector));
  96. NdisZeroMemory(pDL->HashTable, sizeof(pDL->HashTable));
  97. for (iItem=0;iItem<MAX_ITEMS;iItem++)
  98. {
  99. Value = pDL->Items[iItem];
  100. if (Value == NULL_VALUE)
  101. {
  102. // Empty slot -- skip;
  103. continue;
  104. }
  105. //
  106. // set bitvalue
  107. //
  108. {
  109. ULONG Hash1 = Value % HASH1_SIZE;
  110. ULONG u = Hash1/BITS_PER_HASHWORD;
  111. pDL->BitVector[u] |= SELECTED_BIT(Hash1);
  112. }
  113. // set hash table entry
  114. {
  115. ULONG Hash2 = Value % HASH2_SIZE;
  116. UCHAR *pItem = pDL->HashTable+Hash2;
  117. while (*pItem!=0)
  118. {
  119. pItem++;
  120. }
  121. //
  122. // Note we set *pItem to 1+Index, so that 0 can be used
  123. // as a sentinel.
  124. //
  125. *pItem = (iItem+1);
  126. }
  127. }
  128. }
  129. end:
  130. return;
  131. }
  132. BOOLEAN
  133. DipListCheckItem(
  134. DIPLIST *pDL,
  135. ULONG Value
  136. )
  137. //
  138. // Returns TRUE IFF an item exists with the specified value.
  139. // May NOT be called with the lock held. If it's called concurrently
  140. // with one of the other functions, the return value is indeterminate.
  141. //
  142. {
  143. BOOLEAN fRet = FALSE;
  144. #if DBG
  145. ULONG fRetDbg = FALSE;
  146. //
  147. // Debug only: search for the Items array for the specified value...
  148. //
  149. {
  150. int i;
  151. ULONG *pItem = pDL->Items;
  152. for (i=0; i<MAX_ITEMS; i++)
  153. {
  154. if (pItem[i] == Value)
  155. {
  156. fRetDbg = TRUE;
  157. break;
  158. }
  159. }
  160. }
  161. pDL->stats.NumChecks++;
  162. #endif
  163. //
  164. // check bitvalue
  165. //
  166. {
  167. ULONG Hash1 = Value % HASH1_SIZE;
  168. ULONG u = Hash1/BITS_PER_HASHWORD;
  169. if (!(pDL->BitVector[u] & SELECTED_BIT(Hash1)))
  170. {
  171. // Can't find it!
  172. #if DBG
  173. pDL->stats.NumFastChecks++;
  174. #endif // DBG
  175. goto end;
  176. }
  177. }
  178. // check hash table
  179. {
  180. ULONG Hash2 = Value % HASH2_SIZE;
  181. UCHAR *pItem = pDL->HashTable+Hash2;
  182. UCHAR iItem;
  183. //
  184. // Because of the size of HashTable, we are guaranteed that the LAST
  185. // entry in the table is ALWAYS NULL. Let's assert this important
  186. // condition...
  187. //
  188. if (pDL->HashTable[(sizeof(pDL->HashTable)/sizeof(pDL->HashTable[0]))-1] != 0)
  189. {
  190. ASSERT(!"DipListCheckItem: End of pDL->HashTable not NULL!");
  191. goto end;
  192. }
  193. while ((iItem = *pItem)!=0)
  194. {
  195. #if DBG
  196. pDL->stats.NumArrayLookups++;
  197. #endif // DBG
  198. //
  199. // Note (iItem-1) is the index in pDL->Items where the
  200. // value is located.
  201. //
  202. if (pDL->Items[iItem-1] == Value)
  203. {
  204. fRet = TRUE; // Found it!
  205. break;
  206. }
  207. pItem++;
  208. }
  209. }
  210. end:
  211. #if DBG
  212. if (fRet != fRetDbg)
  213. {
  214. //
  215. // We can't break here because we don't hold any locks when we
  216. // check, so can't GUARANTEE that fRet == fRetDbg.
  217. // But it'd be highly unusual
  218. //
  219. UNIV_PRINT_CRIT(("DipListCheckItem: fRet (%u) != fRetDbg (%u)", fRet, fRetDbg));
  220. TRACE_CRIT("%!FUNC! fRet (%u) != fRetDbg (%u)", fRet, fRetDbg);
  221. }
  222. #endif //DBG
  223. return fRet;
  224. }