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.

3159 lines
78 KiB

  1. /*++
  2. Copyright (c) 1989 Microsoft Corporation
  3. Module Name:
  4. BitMap.c
  5. Abstract:
  6. Implementation of the bit map routines for the NT rtl.
  7. Bit numbers within the bit map are zero based. The first is numbered
  8. zero.
  9. The bit map routines keep track of the number of bits clear or set by
  10. subtracting or adding the number of bits operated on as bit ranges
  11. are cleared or set; individual bit states are not tested.
  12. This means that if a range of bits is set,
  13. it is assumed that the total range is currently clear.
  14. Author:
  15. Gary Kimura (GaryKi) & Lou Perazzoli (LouP) 29-Jan-1990
  16. Revision History:
  17. --*/
  18. #include "ntrtlp.h"
  19. #if defined(ALLOC_PRAGMA) && defined(NTOS_KERNEL_RUNTIME)
  20. #pragma alloc_text(PAGE,RtlInitializeBitMap)
  21. #endif
  22. #define RightShiftUlong(E1,E2) ((E2) < 32 ? (E1) >> (E2) : 0)
  23. #define LeftShiftUlong(E1,E2) ((E2) < 32 ? (E1) << (E2) : 0)
  24. #if DBG
  25. VOID
  26. DumpBitMap (
  27. PRTL_BITMAP BitMap
  28. )
  29. {
  30. ULONG i;
  31. BOOLEAN AllZeros, AllOnes;
  32. DbgPrint(" BitMap:%08lx", BitMap);
  33. DbgPrint(" (%08x)", BitMap->SizeOfBitMap);
  34. DbgPrint(" %08lx\n", BitMap->Buffer);
  35. AllZeros = FALSE;
  36. AllOnes = FALSE;
  37. for (i = 0; i < ((BitMap->SizeOfBitMap + 31) / 32); i += 1) {
  38. if (BitMap->Buffer[i] == 0) {
  39. if (AllZeros) {
  40. NOTHING;
  41. } else {
  42. DbgPrint("%4d:", i);
  43. DbgPrint(" %08lx\n", BitMap->Buffer[i]);
  44. }
  45. AllZeros = TRUE;
  46. AllOnes = FALSE;
  47. } else if (BitMap->Buffer[i] == 0xFFFFFFFF) {
  48. if (AllOnes) {
  49. NOTHING;
  50. } else {
  51. DbgPrint("%4d:", i);
  52. DbgPrint(" %08lx\n", BitMap->Buffer[i]);
  53. }
  54. AllZeros = FALSE;
  55. AllOnes = TRUE;
  56. } else {
  57. AllZeros = FALSE;
  58. AllOnes = FALSE;
  59. DbgPrint("%4d:", i);
  60. DbgPrint(" %08lx\n", BitMap->Buffer[i]);
  61. }
  62. }
  63. }
  64. #endif
  65. //
  66. // There are three macros to make reading the bytes in a bitmap easier.
  67. //
  68. #define GET_BYTE_DECLARATIONS() \
  69. PUCHAR _CURRENT_POSITION;
  70. #define GET_BYTE_INITIALIZATION(RTL_BITMAP,BYTE_INDEX) { \
  71. _CURRENT_POSITION = &((PUCHAR)((RTL_BITMAP)->Buffer))[BYTE_INDEX]; \
  72. }
  73. #define GET_BYTE(THIS_BYTE) ( \
  74. THIS_BYTE = *(_CURRENT_POSITION++) \
  75. )
  76. //
  77. // Lookup table that tells how many contiguous bits are clear (i.e., 0) in
  78. // a byte
  79. //
  80. CONST CCHAR RtlpBitsClearAnywhere[] =
  81. { 8,7,6,6,5,5,5,5,4,4,4,4,4,4,4,4,
  82. 4,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,
  83. 5,4,3,3,2,2,2,2,3,2,2,2,2,2,2,2,
  84. 4,3,2,2,2,2,2,2,3,2,2,2,2,2,2,2,
  85. 6,5,4,4,3,3,3,3,3,2,2,2,2,2,2,2,
  86. 4,3,2,2,2,1,1,1,3,2,1,1,2,1,1,1,
  87. 5,4,3,3,2,2,2,2,3,2,1,1,2,1,1,1,
  88. 4,3,2,2,2,1,1,1,3,2,1,1,2,1,1,1,
  89. 7,6,5,5,4,4,4,4,3,3,3,3,3,3,3,3,
  90. 4,3,2,2,2,2,2,2,3,2,2,2,2,2,2,2,
  91. 5,4,3,3,2,2,2,2,3,2,1,1,2,1,1,1,
  92. 4,3,2,2,2,1,1,1,3,2,1,1,2,1,1,1,
  93. 6,5,4,4,3,3,3,3,3,2,2,2,2,2,2,2,
  94. 4,3,2,2,2,1,1,1,3,2,1,1,2,1,1,1,
  95. 5,4,3,3,2,2,2,2,3,2,1,1,2,1,1,1,
  96. 4,3,2,2,2,1,1,1,3,2,1,1,2,1,1,0 };
  97. //
  98. // Lookup table that tells how many contiguous LOW order bits are clear
  99. // (i.e., 0) in a byte
  100. //
  101. CONST CCHAR RtlpBitsClearLow[] =
  102. { 8,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,
  103. 4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,
  104. 5,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,
  105. 4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,
  106. 6,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,
  107. 4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,
  108. 5,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,
  109. 4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,
  110. 7,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,
  111. 4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,
  112. 5,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,
  113. 4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,
  114. 6,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,
  115. 4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,
  116. 5,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,
  117. 4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0 };
  118. //
  119. // Lookup table that tells how many contiguous HIGH order bits are clear
  120. // (i.e., 0) in a byte
  121. //
  122. CONST CCHAR RtlpBitsClearHigh[] =
  123. { 8,7,6,6,5,5,5,5,4,4,4,4,4,4,4,4,
  124. 3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,
  125. 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,
  126. 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,
  127. 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
  128. 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
  129. 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
  130. 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
  131. 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
  132. 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
  133. 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
  134. 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
  135. 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
  136. 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
  137. 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
  138. 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 };
  139. //
  140. // Lookup table that tells how many clear bits (i.e., 0) there are in a byte
  141. //
  142. CONST CCHAR RtlpBitsClearTotal[] =
  143. { 8,7,7,6,7,6,6,5,7,6,6,5,6,5,5,4,
  144. 7,6,6,5,6,5,5,4,6,5,5,4,5,4,4,3,
  145. 7,6,6,5,6,5,5,4,6,5,5,4,5,4,4,3,
  146. 6,5,5,4,5,4,4,3,5,4,4,3,4,3,3,2,
  147. 7,6,6,5,6,5,5,4,6,5,5,4,5,4,4,3,
  148. 6,5,5,4,5,4,4,3,5,4,4,3,4,3,3,2,
  149. 6,5,5,4,5,4,4,3,5,4,4,3,4,3,3,2,
  150. 5,4,4,3,4,3,3,2,4,3,3,2,3,2,2,1,
  151. 7,6,6,5,6,5,5,4,6,5,5,4,5,4,4,3,
  152. 6,5,5,4,5,4,4,3,5,4,4,3,4,3,3,2,
  153. 6,5,5,4,5,4,4,3,5,4,4,3,4,3,3,2,
  154. 5,4,4,3,4,3,3,2,4,3,3,2,3,2,2,1,
  155. 6,5,5,4,5,4,4,3,5,4,4,3,4,3,3,2,
  156. 5,4,4,3,4,3,3,2,4,3,3,2,3,2,2,1,
  157. 5,4,4,3,4,3,3,2,4,3,3,2,3,2,2,1,
  158. 4,3,3,2,3,2,2,1,3,2,2,1,2,1,1,0 };
  159. //
  160. // Bit Mask for clearing and setting bits within bytes. FillMask[i] has the first
  161. // i bits set to 1. ZeroMask[i] has the first i bits set to zero.
  162. //
  163. static CONST UCHAR FillMask[] = { 0x00, 0x01, 0x03, 0x07, 0x0F, 0x1F, 0x3F, 0x7F, 0xFF };
  164. static CONST UCHAR ZeroMask[] = { 0xFF, 0xFE, 0xFC, 0xF8, 0xf0, 0xe0, 0xc0, 0x80, 0x00 };
  165. VOID
  166. RtlInitializeBitMap (
  167. IN PRTL_BITMAP BitMapHeader,
  168. IN PULONG BitMapBuffer,
  169. IN ULONG SizeOfBitMap
  170. )
  171. /*++
  172. Routine Description:
  173. This procedure initializes a bit map.
  174. Arguments:
  175. BitMapHeader - Supplies a pointer to the BitMap Header to initialize
  176. BitMapBuffer - Supplies a pointer to the buffer that is to serve as the
  177. BitMap. This must be an a multiple number of longwords in size.
  178. SizeOfBitMap - Supplies the number of bits required in the Bit Map.
  179. Return Value:
  180. None.
  181. --*/
  182. {
  183. RTL_PAGED_CODE();
  184. //
  185. // Initialize the BitMap header.
  186. //
  187. BitMapHeader->SizeOfBitMap = SizeOfBitMap;
  188. BitMapHeader->Buffer = BitMapBuffer;
  189. //
  190. // And return to our caller
  191. //
  192. //DbgPrint("InitializeBitMap"); DumpBitMap(BitMapHeader);
  193. return;
  194. }
  195. VOID
  196. RtlClearBit (
  197. IN PRTL_BITMAP BitMapHeader,
  198. IN ULONG BitNumber
  199. )
  200. /*++
  201. Routine Description:
  202. This procedure clears a single bit in the specified bit map.
  203. Arguments:
  204. BitMapHeader - Supplies a pointer to the previously initialized bit map.
  205. BitNumber - Supplies the number of the bit to be cleared in the bit map.
  206. Return Value:
  207. None.
  208. --*/
  209. {
  210. PCHAR ByteAddress;
  211. ULONG ShiftCount;
  212. ASSERT(BitNumber < BitMapHeader->SizeOfBitMap);
  213. ByteAddress = (PCHAR)BitMapHeader->Buffer + (BitNumber >> 3);
  214. ShiftCount = BitNumber & 0x7;
  215. *ByteAddress &= (CHAR)(~(1 << ShiftCount));
  216. return;
  217. }
  218. VOID
  219. RtlSetBit (
  220. IN PRTL_BITMAP BitMapHeader,
  221. IN ULONG BitNumber
  222. )
  223. /*++
  224. Routine Description:
  225. This procedure sets a single bit in the specified bit map.
  226. Arguments:
  227. BitMapHeader - Supplies a pointer to the previously initialized bit map.
  228. BitNumber - Supplies the number of the bit to be set in the bit map.
  229. Return Value:
  230. None.
  231. --*/
  232. {
  233. PCHAR ByteAddress;
  234. ULONG ShiftCount;
  235. ASSERT(BitNumber < BitMapHeader->SizeOfBitMap);
  236. ByteAddress = (PCHAR)BitMapHeader->Buffer + (BitNumber >> 3);
  237. ShiftCount = BitNumber & 0x7;
  238. *ByteAddress |= (CHAR)(1 << ShiftCount);
  239. return;
  240. }
  241. BOOLEAN
  242. RtlTestBit (
  243. IN PRTL_BITMAP BitMapHeader,
  244. IN ULONG BitNumber
  245. )
  246. /*++
  247. Routine Description:
  248. This procedure tests the state of a single bit in the specified bit map.
  249. Arguments:
  250. BitMapHeader - Supplies a pointer to the previously initialized bit map.
  251. BitNumber - Supplies the number of the bit to be tested in the bit map.
  252. Return Value:
  253. The state of the specified bit is returned as the function value.
  254. --*/
  255. {
  256. PCHAR ByteAddress;
  257. ULONG ShiftCount;
  258. ASSERT(BitNumber < BitMapHeader->SizeOfBitMap);
  259. ByteAddress = (PCHAR)BitMapHeader->Buffer + (BitNumber >> 3);
  260. ShiftCount = BitNumber & 0x7;
  261. return (BOOLEAN)((*ByteAddress >> ShiftCount) & 1);
  262. }
  263. VOID
  264. RtlClearAllBits (
  265. IN PRTL_BITMAP BitMapHeader
  266. )
  267. /*++
  268. Routine Description:
  269. This procedure clears all bits in the specified Bit Map.
  270. Arguments:
  271. BitMapHeader - Supplies a pointer to the previously initialized BitMap
  272. Return Value:
  273. None.
  274. --*/
  275. {
  276. //
  277. // Clear all the bits
  278. //
  279. RtlZeroMemory( BitMapHeader->Buffer,
  280. ((BitMapHeader->SizeOfBitMap + 31) / 32) * 4
  281. );
  282. //
  283. // And return to our caller
  284. //
  285. //DbgPrint("ClearAllBits"); DumpBitMap(BitMapHeader);
  286. return;
  287. }
  288. VOID
  289. RtlSetAllBits (
  290. IN PRTL_BITMAP BitMapHeader
  291. )
  292. /*++
  293. Routine Description:
  294. This procedure sets all bits in the specified Bit Map.
  295. Arguments:
  296. BitMapHeader - Supplies a pointer to the previously initialized BitMap
  297. Return Value:
  298. None.
  299. --*/
  300. {
  301. //
  302. // Set all the bits
  303. //
  304. RtlFillMemoryUlong( BitMapHeader->Buffer,
  305. ((BitMapHeader->SizeOfBitMap + 31) / 32) * 4,
  306. 0xffffffff
  307. );
  308. //
  309. // And return to our caller
  310. //
  311. //DbgPrint("SetAllBits"); DumpBitMap(BitMapHeader);
  312. return;
  313. }
  314. ULONG
  315. RtlFindClearBits (
  316. IN PRTL_BITMAP BitMapHeader,
  317. IN ULONG NumberToFind,
  318. IN ULONG HintIndex
  319. )
  320. /*++
  321. Routine Description:
  322. This procedure searches the specified bit map for the specified
  323. contiguous region of clear bits. If a run is not found from the
  324. hint to the end of the bitmap, we will search again from the
  325. beginning of the bitmap.
  326. Arguments:
  327. BitMapHeader - Supplies a pointer to the previously initialized BitMap.
  328. NumberToFind - Supplies the size of the contiguous region to find.
  329. HintIndex - Supplies the index (zero based) of where we should start
  330. the search from within the bitmap.
  331. Return Value:
  332. ULONG - Receives the starting index (zero based) of the contiguous
  333. region of clear bits found. If not such a region cannot be found
  334. a -1 (i.e. 0xffffffff) is returned.
  335. --*/
  336. {
  337. ULONG SizeOfBitMap;
  338. ULONG SizeInBytes;
  339. ULONG HintBit;
  340. ULONG MainLoopIndex;
  341. GET_BYTE_DECLARATIONS();
  342. //
  343. // To make the loops in our test run faster we'll extract the
  344. // fields from the bitmap header
  345. //
  346. SizeOfBitMap = BitMapHeader->SizeOfBitMap;
  347. SizeInBytes = (SizeOfBitMap + 7) / 8;
  348. //
  349. // Set any unused bits in the last byte so we won't count them. We do
  350. // this by first checking if there is any odd bits in the last byte.
  351. //
  352. if ((SizeOfBitMap % 8) != 0) {
  353. //
  354. // The last byte has some odd bits so we'll set the high unused
  355. // bits in the last byte to 1's
  356. //
  357. ((PUCHAR)BitMapHeader->Buffer)[SizeInBytes - 1] |=
  358. ZeroMask[SizeOfBitMap % 8];
  359. }
  360. //
  361. // Calculate from the hint index where the hint byte is and set ourselves
  362. // up to read the hint on the next call to GET_BYTE. To make the
  363. // algorithm run fast we'll only honor hints down to the byte level of
  364. // granularity. There is a possibility that we'll need to execute
  365. // our main logic twice. Once to test from the hint byte to the end of
  366. // the bitmap and the other to test from the start of the bitmap. First
  367. // we need to make sure the Hint Index is within range.
  368. //
  369. if (HintIndex >= SizeOfBitMap) {
  370. HintIndex = 0;
  371. }
  372. HintBit = HintIndex % 8;
  373. for (MainLoopIndex = 0; MainLoopIndex < 2; MainLoopIndex += 1) {
  374. ULONG StartByteIndex;
  375. ULONG EndByteIndex;
  376. UCHAR CurrentByte;
  377. //
  378. // Check for the first time through the main loop, which indicates
  379. // that we are going to start our search at our hint byte
  380. //
  381. if (MainLoopIndex == 0) {
  382. StartByteIndex = HintIndex / 8;
  383. EndByteIndex = SizeInBytes;
  384. //
  385. // This is the second time through the loop, make sure there is
  386. // actually something to check before the hint byte
  387. //
  388. } else if (HintIndex != 0) {
  389. //
  390. // The end index for the second time around is based on the
  391. // number of bits we need to find. We need to use this inorder
  392. // to take the case where the preceding byte to the hint byte
  393. // is the start of our run, and the run includes the hint byte
  394. // and some following bytes, based on the number of bits needed
  395. // The computation is to take the number of bits needed minus
  396. // 2 divided by 8 and then add 2. This will take in to account
  397. // the worst possible case where we have one bit hanging off
  398. // of each end byte, and all intervening bytes are all zero.
  399. //
  400. if (NumberToFind < 2) {
  401. EndByteIndex = (HintIndex + 7) / 8;
  402. } else {
  403. EndByteIndex = (HintIndex + 7) / 8 + ((NumberToFind - 2) / 8) + 2;
  404. //
  405. // Make sure we don't overrun the end of the bitmap
  406. //
  407. if (EndByteIndex > SizeInBytes) {
  408. EndByteIndex = SizeInBytes;
  409. }
  410. }
  411. HintIndex = 0;
  412. HintBit = 0;
  413. StartByteIndex = 0;
  414. //
  415. // Otherwise we already did a complete loop through the bitmap
  416. // so we should simply return -1 to say nothing was found
  417. //
  418. } else {
  419. return 0xffffffff;
  420. }
  421. //
  422. // Set ourselves up to get the next byte
  423. //
  424. GET_BYTE_INITIALIZATION(BitMapHeader, StartByteIndex);
  425. //
  426. // Get the first byte, and set any bits before the hint bit.
  427. //
  428. GET_BYTE( CurrentByte );
  429. CurrentByte |= FillMask[HintBit];
  430. //
  431. // If the number of bits can only fit in 1 or 2 bytes (i.e., 9 bits or
  432. // less) we do the following test case.
  433. //
  434. if (NumberToFind <= 9) {
  435. ULONG CurrentBitIndex;
  436. UCHAR PreviousByte;
  437. PreviousByte = 0xff;
  438. //
  439. // Examine all the bytes within our test range searching
  440. // for a fit
  441. //
  442. CurrentBitIndex = StartByteIndex * 8;
  443. while (TRUE) {
  444. //
  445. // If this is the first itteration of the loop, mask Current
  446. // byte with the real hint.
  447. //
  448. //
  449. // Check to see if the current byte coupled with the previous
  450. // byte will satisfy the requirement. The check uses the high
  451. // part of the previous byte and low part of the current byte.
  452. //
  453. if (((ULONG)RtlpBitsClearHigh[PreviousByte] +
  454. (ULONG)RtlpBitsClearLow[CurrentByte]) >= NumberToFind) {
  455. ULONG StartingIndex;
  456. //
  457. // It all fits in these two bytes, so we can compute
  458. // the starting index. This is done by taking the
  459. // index of the current byte (bit 0) and subtracting the
  460. // number of bits its takes to get to the first cleared
  461. // high bit.
  462. //
  463. StartingIndex = CurrentBitIndex -
  464. (LONG)RtlpBitsClearHigh[PreviousByte];
  465. //
  466. // Now make sure the total size isn't beyond the bitmap
  467. //
  468. if ((StartingIndex + NumberToFind) <= SizeOfBitMap) {
  469. return StartingIndex;
  470. }
  471. }
  472. //
  473. // The previous byte does not help, so check the current byte.
  474. //
  475. if ((ULONG)RtlpBitsClearAnywhere[CurrentByte] >= NumberToFind) {
  476. UCHAR BitMask;
  477. ULONG i;
  478. //
  479. // It all fits in a single byte, so calculate the bit
  480. // number. We do this by taking a mask of the appropriate
  481. // size and shifting it over until it fits. It fits when
  482. // we can bitwise-and the current byte with the bitmask
  483. // and get a zero back.
  484. //
  485. BitMask = FillMask[ NumberToFind ];
  486. for (i = 0; (BitMask & CurrentByte) != 0; i += 1) {
  487. BitMask <<= 1;
  488. }
  489. //
  490. // return to our caller the located bit index, and the
  491. // number that we found.
  492. //
  493. return CurrentBitIndex + i;
  494. }
  495. //
  496. // For the next iteration through our loop we need to make
  497. // the current byte into the previous byte, and go to the
  498. // top of the loop again.
  499. //
  500. PreviousByte = CurrentByte;
  501. //
  502. // Increment our Bit Index, and either exit, or get the
  503. // next byte.
  504. //
  505. CurrentBitIndex += 8;
  506. if ( CurrentBitIndex < EndByteIndex * 8 ) {
  507. GET_BYTE( CurrentByte );
  508. } else {
  509. break;
  510. }
  511. } // end loop CurrentBitIndex
  512. //
  513. // The number to find is greater than 9 but if it is less than 15
  514. // then we know it can be satisfied with at most 2 bytes, or 3 bytes
  515. // if the middle byte (of the 3) is all zeros.
  516. //
  517. } else if (NumberToFind < 15) {
  518. ULONG CurrentBitIndex;
  519. UCHAR PreviousPreviousByte;
  520. UCHAR PreviousByte;
  521. PreviousByte = 0xff;
  522. //
  523. // Examine all the bytes within our test range searching
  524. // for a fit
  525. //
  526. CurrentBitIndex = StartByteIndex * 8;
  527. while (TRUE) {
  528. //
  529. // For the next iteration through our loop we need to make
  530. // the current byte into the previous byte, the previous
  531. // byte into the previous previous byte, and go forward.
  532. //
  533. PreviousPreviousByte = PreviousByte;
  534. PreviousByte = CurrentByte;
  535. //
  536. // Increment our Bit Index, and either exit, or get the
  537. // next byte.
  538. //
  539. CurrentBitIndex += 8;
  540. if ( CurrentBitIndex < EndByteIndex * 8 ) {
  541. GET_BYTE( CurrentByte );
  542. } else {
  543. break;
  544. }
  545. //
  546. // if the previous byte is all zeros then maybe the
  547. // request can be satisfied using the Previous Previous Byte
  548. // Previous Byte, and the Current Byte.
  549. //
  550. if ((PreviousByte == 0)
  551. &&
  552. (((ULONG)RtlpBitsClearHigh[PreviousPreviousByte] + 8 +
  553. (ULONG)RtlpBitsClearLow[CurrentByte]) >= NumberToFind)) {
  554. ULONG StartingIndex;
  555. //
  556. // It all fits in these three bytes, so we can compute
  557. // the starting index. This is done by taking the
  558. // index of the previous byte (bit 0) and subtracting
  559. // the number of bits its takes to get to the first
  560. // cleared high bit.
  561. //
  562. StartingIndex = (CurrentBitIndex - 8) -
  563. (LONG)RtlpBitsClearHigh[PreviousPreviousByte];
  564. //
  565. // Now make sure the total size isn't beyond the bitmap
  566. //
  567. if ((StartingIndex + NumberToFind) <= SizeOfBitMap) {
  568. return StartingIndex;
  569. }
  570. }
  571. //
  572. // Check to see if the Previous byte and current byte
  573. // together satisfy the request.
  574. //
  575. if (((ULONG)RtlpBitsClearHigh[PreviousByte] +
  576. (ULONG)RtlpBitsClearLow[CurrentByte]) >= NumberToFind) {
  577. ULONG StartingIndex;
  578. //
  579. // It all fits in these two bytes, so we can compute
  580. // the starting index. This is done by taking the
  581. // index of the current byte (bit 0) and subtracting the
  582. // number of bits its takes to get to the first cleared
  583. // high bit.
  584. //
  585. StartingIndex = CurrentBitIndex -
  586. (LONG)RtlpBitsClearHigh[PreviousByte];
  587. //
  588. // Now make sure the total size isn't beyond the bitmap
  589. //
  590. if ((StartingIndex + NumberToFind) <= SizeOfBitMap) {
  591. return StartingIndex;
  592. }
  593. }
  594. } // end loop CurrentBitIndex
  595. //
  596. // The number to find is greater than or equal to 15. This request
  597. // has to have at least one byte of all zeros to be satisfied
  598. //
  599. } else {
  600. ULONG CurrentByteIndex;
  601. ULONG ZeroBytesNeeded;
  602. ULONG ZeroBytesFound;
  603. UCHAR StartOfRunByte;
  604. LONG StartOfRunIndex;
  605. //
  606. // First precalculate how many zero bytes we're going to need
  607. //
  608. ZeroBytesNeeded = (NumberToFind - 7) / 8;
  609. //
  610. // Indicate for the first time through our loop that we haven't
  611. // found a zero byte yet, and indicate that the start of the
  612. // run is the byte just before the start byte index
  613. //
  614. ZeroBytesFound = 0;
  615. StartOfRunByte = 0xff;
  616. StartOfRunIndex = StartByteIndex - 1;
  617. //
  618. // Examine all the bytes in our test range searching for a fit
  619. //
  620. CurrentByteIndex = StartByteIndex;
  621. while (TRUE) {
  622. //
  623. // If the number of zero bytes fits our minimum requirements
  624. // then we can do the additional test to see if we
  625. // actually found a fit
  626. //
  627. if ((ZeroBytesFound >= ZeroBytesNeeded - 1)
  628. &&
  629. ((ULONG)RtlpBitsClearHigh[StartOfRunByte] + ZeroBytesFound*8 +
  630. (ULONG)RtlpBitsClearLow[CurrentByte]) >= NumberToFind) {
  631. ULONG StartingIndex;
  632. //
  633. // It all fits in these bytes, so we can compute
  634. // the starting index. This is done by taking the
  635. // StartOfRunIndex times 8 and adding the number of bits
  636. // it takes to get to the first cleared high bit.
  637. //
  638. StartingIndex = (StartOfRunIndex * 8) +
  639. (8 - (LONG)RtlpBitsClearHigh[StartOfRunByte]);
  640. //
  641. // Now make sure the total size isn't beyond the bitmap
  642. //
  643. if ((StartingIndex + NumberToFind) <= SizeOfBitMap) {
  644. return StartingIndex;
  645. }
  646. }
  647. //
  648. // Check to see if the byte is zero and increment
  649. // the number of zero bytes found
  650. //
  651. if (CurrentByte == 0) {
  652. ZeroBytesFound += 1;
  653. //
  654. // The byte isn't a zero so we need to start over again
  655. // looking for zero bytes.
  656. //
  657. } else {
  658. ZeroBytesFound = 0;
  659. StartOfRunByte = CurrentByte;
  660. StartOfRunIndex = CurrentByteIndex;
  661. }
  662. //
  663. // Increment our Byte Index, and either exit, or get the
  664. // next byte.
  665. //
  666. CurrentByteIndex += 1;
  667. if ( CurrentByteIndex < EndByteIndex ) {
  668. GET_BYTE( CurrentByte );
  669. } else {
  670. break;
  671. }
  672. } // end loop CurrentByteIndex
  673. }
  674. }
  675. //
  676. // We never found a fit so we'll return -1
  677. //
  678. return 0xffffffff;
  679. }
  680. ULONG
  681. RtlFindSetBits (
  682. IN PRTL_BITMAP BitMapHeader,
  683. IN ULONG NumberToFind,
  684. IN ULONG HintIndex
  685. )
  686. /*++
  687. Routine Description:
  688. This procedure searches the specified bit map for the specified
  689. contiguous region of set bits.
  690. Arguments:
  691. BitMapHeader - Supplies a pointer to the previously initialized BitMap.
  692. NumberToFind - Supplies the size of the contiguous region to find.
  693. HintIndex - Supplies the index (zero based) of where we should start
  694. the search from within the bitmap.
  695. Return Value:
  696. ULONG - Receives the starting index (zero based) of the contiguous
  697. region of set bits found. If such a region cannot be found then
  698. a -1 (i.e., 0xffffffff) is returned.
  699. --*/
  700. {
  701. ULONG SizeOfBitMap;
  702. ULONG SizeInBytes;
  703. ULONG HintBit;
  704. ULONG MainLoopIndex;
  705. GET_BYTE_DECLARATIONS();
  706. //
  707. // To make the loops in our test run faster we'll extract the
  708. // fields from the bitmap header
  709. //
  710. SizeOfBitMap = BitMapHeader->SizeOfBitMap;
  711. SizeInBytes = (SizeOfBitMap + 7) / 8;
  712. //
  713. // Set any unused bits in the last byte so we won't count them. We do
  714. // this by first checking if there is any odd bits in the last byte.
  715. //
  716. if ((SizeOfBitMap % 8) != 0) {
  717. //
  718. // The last byte has some odd bits so we'll set the high unused
  719. // bits in the last byte to 0's
  720. //
  721. ((PUCHAR)BitMapHeader->Buffer)[SizeInBytes - 1] &=
  722. FillMask[SizeOfBitMap % 8];
  723. }
  724. //
  725. // Calculate from the hint index where the hint byte is and set ourselves
  726. // up to read the hint on the next call to GET_BYTE. To make the
  727. // algorithm run fast we'll only honor hints down to the byte level of
  728. // granularity. There is a possibility that we'll need to execute
  729. // our main logic twice. Once to test from the hint byte to the end of
  730. // the bitmap and the other to test from the start of the bitmap. First
  731. // we need to make sure the Hint Index is within range.
  732. //
  733. if (HintIndex >= SizeOfBitMap) {
  734. HintIndex = 0;
  735. }
  736. HintBit = HintIndex % 8;
  737. for (MainLoopIndex = 0; MainLoopIndex < 2; MainLoopIndex += 1) {
  738. ULONG StartByteIndex;
  739. ULONG EndByteIndex;
  740. UCHAR CurrentByte;
  741. //
  742. // Check for the first time through the main loop, which indicates
  743. // that we are going to start our search at our hint byte
  744. //
  745. if (MainLoopIndex == 0) {
  746. StartByteIndex = HintIndex / 8;
  747. EndByteIndex = SizeInBytes;
  748. //
  749. // This is the second time through the loop, make sure there is
  750. // actually something to check before the hint byte
  751. //
  752. } else if (HintIndex != 0) {
  753. //
  754. // The end index for the second time around is based on the
  755. // number of bits we need to find. We need to use this inorder
  756. // to take the case where the preceding byte to the hint byte
  757. // is the start of our run, and the run includes the hint byte
  758. // and some following bytes, based on the number of bits needed
  759. // The computation is to take the number of bits needed minus
  760. // 2 divided by 8 and then add 2. This will take in to account
  761. // the worst possible case where we have one bit hanging off
  762. // of each end byte, and all intervening bytes are all zero.
  763. // We only need to add one in the following equation because
  764. // HintByte is already counted.
  765. //
  766. if (NumberToFind < 2) {
  767. EndByteIndex = (HintIndex + 7) / 8;
  768. } else {
  769. EndByteIndex = (HintIndex + 7) / 8 + ((NumberToFind - 2) / 8) + 2;
  770. //
  771. // Make sure we don't overrun the end of the bitmap
  772. //
  773. if (EndByteIndex > SizeInBytes) {
  774. EndByteIndex = SizeInBytes;
  775. }
  776. }
  777. StartByteIndex = 0;
  778. HintIndex = 0;
  779. HintBit = 0;
  780. //
  781. // Otherwise we already did a complete loop through the bitmap
  782. // so we should simply return -1 to say nothing was found
  783. //
  784. } else {
  785. return 0xffffffff;
  786. }
  787. //
  788. // Set ourselves up to get the next byte
  789. //
  790. GET_BYTE_INITIALIZATION(BitMapHeader, StartByteIndex);
  791. //
  792. // Get the first byte, and clear any bits before the hint bit.
  793. //
  794. GET_BYTE( CurrentByte );
  795. CurrentByte &= ZeroMask[HintBit];
  796. //
  797. // If the number of bits can only fit in 1 or 2 bytes (i.e., 9 bits or
  798. // less) we do the following test case.
  799. //
  800. if (NumberToFind <= 9) {
  801. ULONG CurrentBitIndex;
  802. UCHAR PreviousByte;
  803. PreviousByte = 0x00;
  804. //
  805. // Examine all the bytes within our test range searching
  806. // for a fit
  807. //
  808. CurrentBitIndex = StartByteIndex * 8;
  809. while (TRUE) {
  810. //
  811. // Check to see if the current byte coupled with the previous
  812. // byte will satisfy the requirement. The check uses the high
  813. // part of the previous byte and low part of the current byte.
  814. //
  815. if (((ULONG)RtlpBitsSetHigh(PreviousByte) +
  816. (ULONG)RtlpBitsSetLow(CurrentByte)) >= NumberToFind) {
  817. ULONG StartingIndex;
  818. //
  819. // It all fits in these two bytes, so we can compute
  820. // the starting index. This is done by taking the
  821. // index of the current byte (bit 0) and subtracting the
  822. // number of bits its takes to get to the first set
  823. // high bit.
  824. //
  825. StartingIndex = CurrentBitIndex -
  826. (LONG)RtlpBitsSetHigh(PreviousByte);
  827. //
  828. // Now make sure the total size isn't beyond the bitmap
  829. //
  830. if ((StartingIndex + NumberToFind) <= SizeOfBitMap) {
  831. return StartingIndex;
  832. }
  833. }
  834. //
  835. // The previous byte does not help, so check the current byte.
  836. //
  837. if ((ULONG)RtlpBitSetAnywhere(CurrentByte) >= NumberToFind) {
  838. UCHAR BitMask;
  839. ULONG i;
  840. //
  841. // It all fits in a single byte, so calculate the bit
  842. // number. We do this by taking a mask of the appropriate
  843. // size and shifting it over until it fits. It fits when
  844. // we can bitwise-and the current byte with the bit mask
  845. // and get back the bit mask.
  846. //
  847. BitMask = FillMask[ NumberToFind ];
  848. for (i = 0; (BitMask & CurrentByte) != BitMask; i += 1) {
  849. BitMask <<= 1;
  850. }
  851. //
  852. // return to our caller the located bit index, and the
  853. // number that we found.
  854. //
  855. return CurrentBitIndex + i;
  856. }
  857. //
  858. // For the next iteration through our loop we need to make
  859. // the current byte into the previous byte, and go to the
  860. // top of the loop again.
  861. //
  862. PreviousByte = CurrentByte;
  863. //
  864. // Increment our Bit Index, and either exit, or get the
  865. // next byte.
  866. //
  867. CurrentBitIndex += 8;
  868. if ( CurrentBitIndex < EndByteIndex * 8 ) {
  869. GET_BYTE( CurrentByte );
  870. } else {
  871. break;
  872. }
  873. } // end loop CurrentBitIndex
  874. //
  875. // The number to find is greater than 9 but if it is less than 15
  876. // then we know it can be satisfied with at most 2 bytes, or 3 bytes
  877. // if the middle byte (of the 3) is all ones.
  878. //
  879. } else if (NumberToFind < 15) {
  880. ULONG CurrentBitIndex;
  881. UCHAR PreviousPreviousByte;
  882. UCHAR PreviousByte;
  883. PreviousByte = 0x00;
  884. //
  885. // Examine all the bytes within our test range searching
  886. // for a fit
  887. //
  888. CurrentBitIndex = StartByteIndex * 8;
  889. while (TRUE) {
  890. //
  891. // For the next iteration through our loop we need to make
  892. // the current byte into the previous byte, the previous
  893. // byte into the previous previous byte, and go to the
  894. // top of the loop again.
  895. //
  896. PreviousPreviousByte = PreviousByte;
  897. PreviousByte = CurrentByte;
  898. //
  899. // Increment our Bit Index, and either exit, or get the
  900. // next byte.
  901. //
  902. CurrentBitIndex += 8;
  903. if ( CurrentBitIndex < EndByteIndex * 8 ) {
  904. GET_BYTE( CurrentByte );
  905. } else {
  906. break;
  907. }
  908. //
  909. // if the previous byte is all ones then maybe the
  910. // request can be satisfied using the Previous Previous Byte
  911. // Previous Byte, and the Current Byte.
  912. //
  913. if ((PreviousByte == 0xff)
  914. &&
  915. (((ULONG)RtlpBitsSetHigh(PreviousPreviousByte) + 8 +
  916. (ULONG)RtlpBitsSetLow(CurrentByte)) >= NumberToFind)) {
  917. ULONG StartingIndex;
  918. //
  919. // It all fits in these three bytes, so we can compute
  920. // the starting index. This is done by taking the
  921. // index of the previous byte (bit 0) and subtracting
  922. // the number of bits its takes to get to the first
  923. // set high bit.
  924. //
  925. StartingIndex = (CurrentBitIndex - 8) -
  926. (LONG)RtlpBitsSetHigh(PreviousPreviousByte);
  927. //
  928. // Now make sure the total size isn't beyond the bitmap
  929. //
  930. if ((StartingIndex + NumberToFind) <= SizeOfBitMap) {
  931. return StartingIndex;
  932. }
  933. }
  934. //
  935. // Check to see if the Previous byte and current byte
  936. // together satisfy the request.
  937. //
  938. if (((ULONG)RtlpBitsSetHigh(PreviousByte) +
  939. (ULONG)RtlpBitsSetLow(CurrentByte)) >= NumberToFind) {
  940. ULONG StartingIndex;
  941. //
  942. // It all fits in these two bytes, so we can compute
  943. // the starting index. This is done by taking the
  944. // index of the current byte (bit 0) and subtracting the
  945. // number of bits its takes to get to the first set
  946. // high bit.
  947. //
  948. StartingIndex = CurrentBitIndex -
  949. (LONG)RtlpBitsSetHigh(PreviousByte);
  950. //
  951. // Now make sure the total size isn't beyond the bitmap
  952. //
  953. if ((StartingIndex + NumberToFind) <= SizeOfBitMap) {
  954. return StartingIndex;
  955. }
  956. }
  957. } // end loop CurrentBitIndex
  958. //
  959. // The number to find is greater than or equal to 15. This request
  960. // has to have at least one byte of all ones to be satisfied
  961. //
  962. } else {
  963. ULONG CurrentByteIndex;
  964. ULONG OneBytesNeeded;
  965. ULONG OneBytesFound;
  966. UCHAR StartOfRunByte;
  967. LONG StartOfRunIndex;
  968. //
  969. // First precalculate how many one bytes we're going to need
  970. //
  971. OneBytesNeeded = (NumberToFind - 7) / 8;
  972. //
  973. // Indicate for the first time through our loop that we haven't
  974. // found a one byte yet, and indicate that the start of the
  975. // run is the byte just before the start byte index
  976. //
  977. OneBytesFound = 0;
  978. StartOfRunByte = 0x00;
  979. StartOfRunIndex = StartByteIndex - 1;
  980. //
  981. // Examine all the bytes in our test range searching for a fit
  982. //
  983. CurrentByteIndex = StartByteIndex;
  984. while (TRUE) {
  985. //
  986. // If the number of zero bytes fits our minimum requirements
  987. // then we can do the additional test to see if we
  988. // actually found a fit
  989. //
  990. if ((OneBytesFound >= OneBytesNeeded - 1)
  991. &&
  992. ((ULONG)RtlpBitsSetHigh(StartOfRunByte) + OneBytesFound*8 +
  993. (ULONG)RtlpBitsSetLow(CurrentByte)) >= NumberToFind) {
  994. ULONG StartingIndex;
  995. //
  996. // It all fits in these bytes, so we can compute
  997. // the starting index. This is done by taking the
  998. // StartOfRunIndex times 8 and adding the number of bits
  999. // it takes to get to the first set high bit.
  1000. //
  1001. StartingIndex = (StartOfRunIndex * 8) +
  1002. (8 - (LONG)RtlpBitsSetHigh(StartOfRunByte));
  1003. //
  1004. // Now make sure the total size isn't beyond the bitmap
  1005. //
  1006. if ((StartingIndex + NumberToFind) <= SizeOfBitMap) {
  1007. return StartingIndex;
  1008. }
  1009. }
  1010. //
  1011. // Check to see if the byte is all ones and increment
  1012. // the number of one bytes found
  1013. //
  1014. if (CurrentByte == 0xff) {
  1015. OneBytesFound += 1;
  1016. //
  1017. // The byte isn't all ones so we need to start over again
  1018. // looking for one bytes.
  1019. //
  1020. } else {
  1021. OneBytesFound = 0;
  1022. StartOfRunByte = CurrentByte;
  1023. StartOfRunIndex = CurrentByteIndex;
  1024. }
  1025. //
  1026. // Increment our Byte Index, and either exit, or get the
  1027. // next byte.
  1028. //
  1029. CurrentByteIndex += 1;
  1030. if ( CurrentByteIndex < EndByteIndex ) {
  1031. GET_BYTE( CurrentByte );
  1032. } else {
  1033. break;
  1034. }
  1035. } // end loop CurrentByteIndex
  1036. }
  1037. }
  1038. //
  1039. // We never found a fit so we'll return -1
  1040. //
  1041. return 0xffffffff;
  1042. }
  1043. ULONG
  1044. RtlFindClearBitsAndSet (
  1045. IN PRTL_BITMAP BitMapHeader,
  1046. IN ULONG NumberToFind,
  1047. IN ULONG HintIndex
  1048. )
  1049. /*++
  1050. Routine Description:
  1051. This procedure searches the specified bit map for the specified
  1052. contiguous region of clear bits, sets the bits and returns the
  1053. number of bits found, and the starting bit number which was clear
  1054. then set.
  1055. Arguments:
  1056. BitMapHeader - Supplies a pointer to the previously initialized BitMap.
  1057. NumberToFind - Supplies the size of the contiguous region to find.
  1058. HintIndex - Supplies the index (zero based) of where we should start
  1059. the search from within the bitmap.
  1060. Return Value:
  1061. ULONG - Receives the starting index (zero based) of the contiguous
  1062. region found. If such a region cannot be located a -1 (i.e.,
  1063. 0xffffffff) is returned.
  1064. --*/
  1065. {
  1066. ULONG StartingIndex;
  1067. //
  1068. // First look for a run of clear bits that equals the size requested
  1069. //
  1070. StartingIndex = RtlFindClearBits( BitMapHeader,
  1071. NumberToFind,
  1072. HintIndex );
  1073. //DbgPrint("FindClearBits %08lx, ", NumberToFind);
  1074. //DbgPrint("%08lx", StartingIndex);
  1075. //DumpBitMap(BitMapHeader);
  1076. if (StartingIndex != 0xffffffff) {
  1077. //
  1078. // We found a large enough run of clear bits so now set them
  1079. //
  1080. RtlSetBits( BitMapHeader, StartingIndex, NumberToFind );
  1081. }
  1082. //
  1083. // And return to our caller
  1084. //
  1085. return StartingIndex;
  1086. }
  1087. ULONG
  1088. RtlFindSetBitsAndClear (
  1089. IN PRTL_BITMAP BitMapHeader,
  1090. IN ULONG NumberToFind,
  1091. IN ULONG HintIndex
  1092. )
  1093. /*++
  1094. Routine Description:
  1095. This procedure searches the specified bit map for the specified
  1096. contiguous region of set bits, clears the bits and returns the
  1097. number of bits found and the starting bit number which was set then
  1098. clear.
  1099. Arguments:
  1100. BitMapHeader - Supplies a pointer to the previously initialized BitMap.
  1101. NumberToFind - Supplies the size of the contiguous region to find.
  1102. HintIndex - Supplies the index (zero based) of where we should start
  1103. the search from within the bitmap.
  1104. Return Value:
  1105. ULONG - Receives the starting index (zero based) of the contiguous
  1106. region found. If such a region cannot be located a -1 (i.e.,
  1107. 0xffffffff) is returned.
  1108. --*/
  1109. {
  1110. ULONG StartingIndex;
  1111. //
  1112. // First look for a run of set bits that equals the size requested
  1113. //
  1114. if ((StartingIndex = RtlFindSetBits( BitMapHeader,
  1115. NumberToFind,
  1116. HintIndex )) != 0xffffffff) {
  1117. //
  1118. // We found a large enough run of set bits so now clear them
  1119. //
  1120. RtlClearBits( BitMapHeader, StartingIndex, NumberToFind );
  1121. }
  1122. //
  1123. // And return to our caller
  1124. //
  1125. return StartingIndex;
  1126. }
  1127. VOID
  1128. RtlClearBits (
  1129. IN PRTL_BITMAP BitMapHeader,
  1130. IN ULONG StartingIndex,
  1131. IN ULONG NumberToClear
  1132. )
  1133. /*++
  1134. Routine Description:
  1135. This procedure clears the specified range of bits within the
  1136. specified bit map.
  1137. Arguments:
  1138. BitMapHeader - Supplies a pointer to the previously initialized Bit Map.
  1139. StartingIndex - Supplies the index (zero based) of the first bit to clear.
  1140. NumberToClear - Supplies the number of bits to clear.
  1141. Return Value:
  1142. None.
  1143. --*/
  1144. {
  1145. PCHAR CurrentByte;
  1146. ULONG BitOffset;
  1147. //DbgPrint("ClearBits %08lx, ", NumberToClear);
  1148. //DbgPrint("%08lx", StartingIndex);
  1149. ASSERT( StartingIndex + NumberToClear <= BitMapHeader->SizeOfBitMap );
  1150. //
  1151. // Special case the situation where the number of bits to clear is
  1152. // zero. Turn this into a noop.
  1153. //
  1154. if (NumberToClear == 0) {
  1155. return;
  1156. }
  1157. //
  1158. // Get a pointer to the first byte that needs to be cleared.
  1159. //
  1160. CurrentByte = ((PCHAR) BitMapHeader->Buffer) + (StartingIndex / 8);
  1161. //
  1162. // If all the bit's we're setting are in the same byte just do it and
  1163. // get out.
  1164. //
  1165. BitOffset = StartingIndex % 8;
  1166. if ((BitOffset + NumberToClear) <= 8) {
  1167. *CurrentByte &= ~(FillMask[ NumberToClear ] << BitOffset);
  1168. } else {
  1169. //
  1170. // Do the first byte manually because the first bit may not be byte aligned.
  1171. //
  1172. // Note: The first longword will always be cleared byte wise to simplify the
  1173. // logic of checking for short copies (<32 bits).
  1174. //
  1175. if (BitOffset > 0) {
  1176. *CurrentByte &= FillMask[ BitOffset ];
  1177. CurrentByte += 1;
  1178. NumberToClear -= 8 - BitOffset;
  1179. }
  1180. //
  1181. // Fill the full bytes in the middle. Use the RtlZeroMemory() because its
  1182. // going to be hand tuned asm code spit out by the compiler.
  1183. //
  1184. if (NumberToClear > 8) {
  1185. RtlZeroMemory( CurrentByte, NumberToClear / 8 );
  1186. CurrentByte += NumberToClear / 8;
  1187. NumberToClear %= 8;
  1188. }
  1189. //
  1190. // Clear the remaining bits, if there are any, in the last byte.
  1191. //
  1192. if (NumberToClear > 0) {
  1193. *CurrentByte &= ZeroMask[ NumberToClear ];
  1194. }
  1195. }
  1196. //
  1197. // And return to our caller
  1198. //
  1199. //DumpBitMap(BitMapHeader);
  1200. return;
  1201. }
  1202. VOID
  1203. RtlSetBits (
  1204. IN PRTL_BITMAP BitMapHeader,
  1205. IN ULONG StartingIndex,
  1206. IN ULONG NumberToSet
  1207. )
  1208. /*++
  1209. Routine Description:
  1210. This procedure sets the specified range of bits within the
  1211. specified bit map.
  1212. Arguments:
  1213. BitMapHeader - Supplies a pointer to the previously initialied BitMap.
  1214. StartingIndex - Supplies the index (zero based) of the first bit to set.
  1215. NumberToSet - Supplies the number of bits to set.
  1216. Return Value:
  1217. None.
  1218. --*/
  1219. {
  1220. PCHAR CurrentByte;
  1221. ULONG BitOffset;
  1222. //DbgPrint("SetBits %08lx, ", NumberToSet);
  1223. //DbgPrint("%08lx", StartingIndex);
  1224. ASSERT( StartingIndex + NumberToSet <= BitMapHeader->SizeOfBitMap );
  1225. //
  1226. // Special case the situation where the number of bits to set is
  1227. // zero. Turn this into a noop.
  1228. //
  1229. if (NumberToSet == 0) {
  1230. return;
  1231. }
  1232. //
  1233. // Get a pointer to the first byte that needs to be set.
  1234. //
  1235. CurrentByte = ((PCHAR) BitMapHeader->Buffer) + (StartingIndex / 8);
  1236. //
  1237. // If all the bit's we're setting are in the same byte just do it and
  1238. // get out.
  1239. //
  1240. BitOffset = StartingIndex % 8;
  1241. if ((BitOffset + NumberToSet) <= 8) {
  1242. *CurrentByte |= (FillMask[ NumberToSet ] << BitOffset);
  1243. } else {
  1244. //
  1245. // Do the first byte manually because the first bit may not be byte aligned.
  1246. //
  1247. // Note: The first longword will always be set byte wise to simplify the
  1248. // logic of checking for short copies (<32 bits).
  1249. //
  1250. if (BitOffset > 0) {
  1251. *CurrentByte |= ZeroMask[ BitOffset ];
  1252. CurrentByte += 1;
  1253. NumberToSet -= 8 - BitOffset;
  1254. }
  1255. //
  1256. // Fill the full bytes in the middle. Use the RtlFillMemory() because its
  1257. // going to be hand tuned asm code spit out by the compiler.
  1258. //
  1259. if (NumberToSet > 8) {
  1260. RtlFillMemory( CurrentByte, NumberToSet / 8, 0xff );
  1261. CurrentByte += NumberToSet / 8;
  1262. NumberToSet %= 8;
  1263. }
  1264. //
  1265. // Set the remaining bits, if there are any, in the last byte.
  1266. //
  1267. if (NumberToSet > 0) {
  1268. *CurrentByte |= FillMask[ NumberToSet ];
  1269. }
  1270. }
  1271. //
  1272. // And return to our caller
  1273. //
  1274. //DumpBitMap(BitMapHeader);
  1275. return;
  1276. }
  1277. #if DBG
  1278. BOOLEAN NtfsDebugIt = FALSE;
  1279. #endif
  1280. ULONG
  1281. RtlFindClearRuns (
  1282. IN PRTL_BITMAP BitMapHeader,
  1283. PRTL_BITMAP_RUN RunArray,
  1284. ULONG SizeOfRunArray,
  1285. BOOLEAN LocateLongestRuns
  1286. )
  1287. /*++
  1288. Routine Description:
  1289. This procedure finds N contiguous runs of clear bits
  1290. within the specified bit map.
  1291. Arguments:
  1292. BitMapHeader - Supplies a pointer to the previously initialized BitMap.
  1293. RunArray - Receives the bit position, and length of each of the free runs
  1294. that the procedure locates. The array will be sorted according to
  1295. length.
  1296. SizeOfRunArray - Supplies the maximum number of entries the caller wants
  1297. returned in RunArray
  1298. LocateLongestRuns - Indicates if this routine is to return the longest runs
  1299. it can find or just the first N runs.
  1300. Return Value:
  1301. ULONG - Receives the number of runs that the procedure has located and
  1302. returned in RunArray
  1303. --*/
  1304. {
  1305. ULONG RunIndex;
  1306. ULONG i;
  1307. LONG j;
  1308. ULONG SizeOfBitMap;
  1309. ULONG SizeInBytes;
  1310. ULONG CurrentRunSize;
  1311. ULONG CurrentRunIndex;
  1312. ULONG CurrentByteIndex;
  1313. UCHAR CurrentByte;
  1314. UCHAR BitMask;
  1315. UCHAR TempNumber;
  1316. GET_BYTE_DECLARATIONS();
  1317. //
  1318. // Reference the bitmap header to make the loop run faster
  1319. //
  1320. SizeOfBitMap = BitMapHeader->SizeOfBitMap;
  1321. SizeInBytes = (SizeOfBitMap + 7) / 8;
  1322. //
  1323. // Set any unused bits in the last byte so we won't count them. We do
  1324. // this by first checking if there is any odd bits in the last byte.
  1325. //
  1326. if ((SizeOfBitMap % 8) != 0) {
  1327. //
  1328. // The last byte has some odd bits so we'll set the high unused
  1329. // bits in the last byte to 1's
  1330. //
  1331. ((PUCHAR)BitMapHeader->Buffer)[SizeInBytes - 1] |= ZeroMask[SizeOfBitMap % 8];
  1332. }
  1333. //
  1334. // Set it up so we can the use GET_BYTE macro
  1335. //
  1336. GET_BYTE_INITIALIZATION( BitMapHeader, 0);
  1337. //
  1338. // Set our RunIndex and current run variables. Run Index allays is the index
  1339. // of the next location to fill in or it could be one beyond the end of the
  1340. // array.
  1341. //
  1342. RunIndex = 0;
  1343. for (i = 0; i < SizeOfRunArray; i += 1) { RunArray[i].NumberOfBits = 0; }
  1344. CurrentRunSize = 0;
  1345. CurrentRunIndex = 0;
  1346. //
  1347. // Examine every byte in the BitMap
  1348. //
  1349. for (CurrentByteIndex = 0;
  1350. CurrentByteIndex < SizeInBytes;
  1351. CurrentByteIndex += 1) {
  1352. GET_BYTE( CurrentByte );
  1353. #if DBG
  1354. if (NtfsDebugIt) { DbgPrint("%d: %08lx %08lx %08lx %08lx %08lx\n",__LINE__,RunIndex,CurrentRunSize,CurrentRunIndex,CurrentByteIndex,CurrentByte); }
  1355. #endif
  1356. //
  1357. // If the current byte is not all zeros we need to (1) check if
  1358. // the current run is big enough to be inserted in the output
  1359. // array, and (2) check if the current byte inside of itself can
  1360. // be inserted, and (3) start a new current run
  1361. //
  1362. if (CurrentByte != 0x00) {
  1363. //
  1364. // Compute the final size of the current run
  1365. //
  1366. CurrentRunSize += RtlpBitsClearLow[CurrentByte];
  1367. //
  1368. // Check if the current run be stored in the output array by either
  1369. // there being room in the array or the last entry is smaller than
  1370. // the current entry
  1371. //
  1372. if (CurrentRunSize > 0) {
  1373. if ((RunIndex < SizeOfRunArray) ||
  1374. (RunArray[RunIndex-1].NumberOfBits < CurrentRunSize)) {
  1375. //
  1376. // If necessary increment the RunIndex and shift over the output
  1377. // array until we find the slot where the new run belongs. We only
  1378. // do the shifting if we're returning longest runs.
  1379. //
  1380. if (RunIndex < SizeOfRunArray) { RunIndex += 1; }
  1381. for (j = RunIndex-2; LocateLongestRuns && (j >= 0) && (RunArray[j].NumberOfBits < CurrentRunSize); j -= 1) {
  1382. RunArray[j+1] = RunArray[j];
  1383. }
  1384. RunArray[j+1].NumberOfBits = CurrentRunSize;
  1385. RunArray[j+1].StartingIndex = CurrentRunIndex;
  1386. #if DBG
  1387. if (NtfsDebugIt) { DbgPrint("%d: %08lx %08lx %08lx %08lx %08lx %08lx %08lx %08lx\n",
  1388. __LINE__,RunIndex,CurrentRunSize,CurrentRunIndex,CurrentByteIndex,CurrentByte,j,RunArray[j+1].NumberOfBits,RunArray[j+1].StartingIndex); }
  1389. #endif
  1390. //
  1391. // Now if the array is full and we are not doing longest runs return
  1392. // to our caller
  1393. //
  1394. if (!LocateLongestRuns && (RunIndex >= SizeOfRunArray)) {
  1395. return RunIndex;
  1396. }
  1397. }
  1398. }
  1399. //
  1400. // The next run starts with the remaining clear bits in the
  1401. // current byte. We set this up before we check inside the
  1402. // current byte for a longer run, because the latter test
  1403. // might require extra work.
  1404. //
  1405. CurrentRunSize = RtlpBitsClearHigh[ CurrentByte ];
  1406. CurrentRunIndex = (CurrentByteIndex * 8) + (8 - CurrentRunSize);
  1407. //
  1408. // Set the low and high bits, otherwise we'll wind up thinking that we have a
  1409. // small run that needs to get added to the array, but these bits have
  1410. // just been accounting for
  1411. //
  1412. CurrentByte |= FillMask[RtlpBitsClearLow[CurrentByte]] |
  1413. ZeroMask[8-RtlpBitsClearHigh[CurrentByte]];
  1414. //
  1415. // Check if the current byte contains a run inside of it that
  1416. // should go into the output array. There may be multiple
  1417. // runs in the byte that we need to insert.
  1418. //
  1419. while ((CurrentByte != 0xff)
  1420. &&
  1421. ((RunIndex < SizeOfRunArray) ||
  1422. (RunArray[RunIndex-1].NumberOfBits < (ULONG)RtlpBitsClearAnywhere[CurrentByte]))) {
  1423. TempNumber = RtlpBitsClearAnywhere[CurrentByte];
  1424. //
  1425. // Somewhere in the current byte is a run to be inserted of
  1426. // size TempNumber. All we need to do is find the index for this run.
  1427. //
  1428. BitMask = FillMask[ TempNumber ];
  1429. for (i = 0; (BitMask & CurrentByte) != 0; i += 1) {
  1430. BitMask <<= 1;
  1431. }
  1432. //
  1433. // If necessary increment the RunIndex and shift over the output
  1434. // array until we find the slot where the new run belongs. We only
  1435. // do the shifting if we're returning longest runs.
  1436. //
  1437. if (RunIndex < SizeOfRunArray) { RunIndex += 1; }
  1438. for (j = RunIndex-2; LocateLongestRuns && (j >= 0) && (RunArray[j].NumberOfBits < TempNumber); j -= 1) {
  1439. RunArray[j+1] = RunArray[j];
  1440. }
  1441. RunArray[j+1].NumberOfBits = TempNumber;
  1442. RunArray[j+1].StartingIndex = (CurrentByteIndex * 8) + i;
  1443. #if DBG
  1444. if (NtfsDebugIt) { DbgPrint("%d: %08lx %08lx %08lx %08lx %08lx %08lx %08lx %08lx\n",
  1445. __LINE__,RunIndex,CurrentRunSize,CurrentRunIndex,CurrentByteIndex,CurrentByte,j,RunArray[j+1].NumberOfBits,RunArray[j+1].StartingIndex); }
  1446. #endif
  1447. //
  1448. // Now if the array is full and we are not doing longest runs return
  1449. // to our caller
  1450. //
  1451. if (!LocateLongestRuns && (RunIndex >= SizeOfRunArray)) {
  1452. return RunIndex;
  1453. }
  1454. //
  1455. // Mask out the bits and look for another run in the current byte
  1456. //
  1457. CurrentByte |= BitMask;
  1458. }
  1459. //
  1460. // Otherwise the current byte is all zeros and
  1461. // we simply continue with the current run
  1462. //
  1463. } else {
  1464. CurrentRunSize += 8;
  1465. }
  1466. }
  1467. #if DBG
  1468. if (NtfsDebugIt) { DbgPrint("%d: %08lx %08lx %08lx %08lx %08lx\n",__LINE__,RunIndex,CurrentRunSize,CurrentRunIndex,CurrentByteIndex,CurrentByte); }
  1469. #endif
  1470. //
  1471. // See if we finished looking over the bitmap with an open current
  1472. // run that should be inserted in the output array
  1473. //
  1474. if (CurrentRunSize > 0) {
  1475. if ((RunIndex < SizeOfRunArray) ||
  1476. (RunArray[RunIndex-1].NumberOfBits < CurrentRunSize)) {
  1477. //
  1478. // If necessary increment the RunIndex and shift over the output
  1479. // array until we find the slot where the new run belongs.
  1480. //
  1481. if (RunIndex < SizeOfRunArray) { RunIndex += 1; }
  1482. for (j = RunIndex-2; LocateLongestRuns && (j >= 0) && (RunArray[j].NumberOfBits < CurrentRunSize); j -= 1) {
  1483. RunArray[j+1] = RunArray[j];
  1484. }
  1485. RunArray[j+1].NumberOfBits = CurrentRunSize;
  1486. RunArray[j+1].StartingIndex = CurrentRunIndex;
  1487. #if DBG
  1488. if (NtfsDebugIt) { DbgPrint("%d: %08lx %08lx %08lx %08lx %08lx %08lx %08lx %08lx\n",
  1489. __LINE__,RunIndex,CurrentRunSize,CurrentRunIndex,CurrentByteIndex,CurrentByte,j,RunArray[j+1].NumberOfBits,RunArray[j+1].StartingIndex); }
  1490. #endif
  1491. }
  1492. }
  1493. //
  1494. // Return to our caller
  1495. //
  1496. return RunIndex;
  1497. }
  1498. ULONG
  1499. RtlFindLongestRunClear (
  1500. IN PRTL_BITMAP BitMapHeader,
  1501. OUT PULONG StartingIndex
  1502. )
  1503. /*++
  1504. Routine Description:
  1505. This procedure finds the largest contiguous range of clear bits
  1506. within the specified bit map.
  1507. Arguments:
  1508. BitMapHeader - Supplies a pointer to the previously initialized BitMap.
  1509. StartingIndex - Receives the index (zero based) of the first run
  1510. equal to the longest run of clear bits in the BitMap.
  1511. Return Value:
  1512. ULONG - Receives the number of bits contained in the largest contiguous
  1513. run of clear bits.
  1514. --*/
  1515. {
  1516. RTL_BITMAP_RUN RunArray[1];
  1517. //
  1518. // Locate the longest run in the bitmap. If there is one then
  1519. // return that run otherwise return the error condition.
  1520. //
  1521. if (RtlFindClearRuns( BitMapHeader, RunArray, 1, TRUE ) == 1) {
  1522. *StartingIndex = RunArray[0].StartingIndex;
  1523. return RunArray[0].NumberOfBits;
  1524. }
  1525. *StartingIndex = 0;
  1526. return 0;
  1527. }
  1528. ULONG
  1529. RtlFindFirstRunClear (
  1530. IN PRTL_BITMAP BitMapHeader,
  1531. OUT PULONG StartingIndex
  1532. )
  1533. /*++
  1534. Routine Description:
  1535. This procedure finds the first contiguous range of clear bits
  1536. within the specified bit map.
  1537. Arguments:
  1538. BitMapHeader - Supplies a pointer to the previously initialized BitMap.
  1539. StartingIndex - Receives the index (zero based) of the first run
  1540. equal to the longest run of clear bits in the BitMap.
  1541. Return Value:
  1542. ULONG - Receives the number of bits contained in the first contiguous
  1543. run of clear bits.
  1544. --*/
  1545. {
  1546. return RtlFindNextForwardRunClear(BitMapHeader, 0, StartingIndex);
  1547. }
  1548. ULONG
  1549. RtlNumberOfClearBits (
  1550. IN PRTL_BITMAP BitMapHeader
  1551. )
  1552. /*++
  1553. Routine Description:
  1554. This procedure counts and returns the number of clears bits within
  1555. the specified bitmap.
  1556. Arguments:
  1557. BitMapHeader - Supplies a pointer to the previously initialized bitmap.
  1558. Return Value:
  1559. ULONG - The total number of clear bits in the bitmap
  1560. --*/
  1561. {
  1562. ULONG SizeOfBitMap;
  1563. ULONG SizeInBytes;
  1564. ULONG i;
  1565. UCHAR CurrentByte;
  1566. ULONG TotalClear;
  1567. GET_BYTE_DECLARATIONS();
  1568. //
  1569. // Reference the bitmap header to make the loop run faster
  1570. //
  1571. SizeOfBitMap = BitMapHeader->SizeOfBitMap;
  1572. SizeInBytes = (SizeOfBitMap + 7) / 8;
  1573. //
  1574. // Set any unused bits in the last byte so we don't count them. We
  1575. // do this by first checking if there are any odd bits in the last byte
  1576. //
  1577. if ((SizeOfBitMap % 8) != 0) {
  1578. //
  1579. // The last byte has some odd bits so we'll set the high unused
  1580. // bits in the last byte to 1's
  1581. //
  1582. ((PUCHAR)BitMapHeader->Buffer)[SizeInBytes - 1] |=
  1583. ZeroMask[SizeOfBitMap % 8];
  1584. }
  1585. //
  1586. // Set if up so we can use the GET_BYTE macro
  1587. //
  1588. GET_BYTE_INITIALIZATION( BitMapHeader, 0 );
  1589. //
  1590. // Examine every byte in the bitmap
  1591. //
  1592. TotalClear = 0;
  1593. for (i = 0; i < SizeInBytes; i += 1) {
  1594. GET_BYTE( CurrentByte );
  1595. TotalClear += RtlpBitsClearTotal[CurrentByte];
  1596. }
  1597. return TotalClear;
  1598. }
  1599. ULONG
  1600. RtlNumberOfSetBits (
  1601. IN PRTL_BITMAP BitMapHeader
  1602. )
  1603. /*++
  1604. Routine Description:
  1605. This procedure counts and returns the number of set bits within
  1606. the specified bitmap.
  1607. Arguments:
  1608. BitMapHeader - Supplies a pointer to the previously initialized bitmap.
  1609. Return Value:
  1610. ULONG - The total number of set bits in the bitmap
  1611. --*/
  1612. {
  1613. ULONG SizeOfBitMap;
  1614. ULONG SizeInBytes;
  1615. ULONG i;
  1616. UCHAR CurrentByte;
  1617. ULONG TotalSet;
  1618. GET_BYTE_DECLARATIONS();
  1619. //
  1620. // Reference the bitmap header to make the loop run faster
  1621. //
  1622. SizeOfBitMap = BitMapHeader->SizeOfBitMap;
  1623. SizeInBytes = (SizeOfBitMap + 7) / 8;
  1624. //
  1625. // Clear any unused bits in the last byte so we don't count them. We
  1626. // do this by first checking if there are any odd bits in the last byte
  1627. //
  1628. if ((SizeOfBitMap % 8) != 0) {
  1629. //
  1630. // The last byte has some odd bits so we'll set the high unused
  1631. // bits in the last byte to 0's
  1632. //
  1633. ((PUCHAR)BitMapHeader->Buffer)[SizeInBytes - 1] &=
  1634. FillMask[SizeOfBitMap % 8];
  1635. }
  1636. //
  1637. // Set if up so we can use the GET_BYTE macro
  1638. //
  1639. GET_BYTE_INITIALIZATION( BitMapHeader, 0 );
  1640. //
  1641. // Examine every byte in the bitmap
  1642. //
  1643. TotalSet = 0;
  1644. for (i = 0; i < SizeInBytes; i += 1) {
  1645. GET_BYTE( CurrentByte );
  1646. TotalSet += RtlpBitsSetTotal(CurrentByte);
  1647. }
  1648. return TotalSet;
  1649. }
  1650. BOOLEAN
  1651. RtlAreBitsClear (
  1652. IN PRTL_BITMAP BitMapHeader,
  1653. IN ULONG StartingIndex,
  1654. IN ULONG Length
  1655. )
  1656. /*++
  1657. Routine Description:
  1658. This procedure determines if the range of specified bits are all clear.
  1659. Arguments:
  1660. BitMapHeader - Supplies a pointer to the previously initialized bitmap.
  1661. StartingIndex - Supplies the starting bit index to examine
  1662. Length - Supplies the number of bits to examine
  1663. Return Value:
  1664. BOOLEAN - TRUE if the specified bits in the bitmap are all clear, and
  1665. FALSE if any are set or if the range is outside the bitmap or if
  1666. Length is zero.
  1667. --*/
  1668. {
  1669. ULONG SizeOfBitMap;
  1670. ULONG SizeInBytes;
  1671. ULONG EndingIndex;
  1672. ULONG StartingByte;
  1673. ULONG EndingByte;
  1674. ULONG StartingOffset;
  1675. ULONG EndingOffset;
  1676. ULONG i;
  1677. UCHAR Byte;
  1678. GET_BYTE_DECLARATIONS();
  1679. //
  1680. // To make the loops in our test run faster we'll extract the fields
  1681. // from the bitmap header
  1682. //
  1683. SizeOfBitMap = BitMapHeader->SizeOfBitMap;
  1684. SizeInBytes = (SizeOfBitMap + 7) / 8;
  1685. //
  1686. // First make sure that the specified range is contained within the
  1687. // bitmap, and the length is not zero.
  1688. //
  1689. if ((StartingIndex + Length > SizeOfBitMap) || (Length == 0)) {
  1690. return FALSE;
  1691. }
  1692. //
  1693. // Compute the ending index, starting and ending byte, and the starting
  1694. // and ending offset within each byte
  1695. //
  1696. EndingIndex = StartingIndex + Length - 1;
  1697. StartingByte = StartingIndex / 8;
  1698. EndingByte = EndingIndex / 8;
  1699. StartingOffset = StartingIndex % 8;
  1700. EndingOffset = EndingIndex % 8;
  1701. //
  1702. // Set ourselves up to get the next byte
  1703. //
  1704. GET_BYTE_INITIALIZATION( BitMapHeader, StartingByte );
  1705. //
  1706. // Special case the situation where the starting byte and ending
  1707. // byte are one in the same
  1708. //
  1709. if (StartingByte == EndingByte) {
  1710. //
  1711. // Get the single byte we are to look at
  1712. //
  1713. GET_BYTE( Byte );
  1714. //
  1715. // Now we compute the mask of bits we're after and then AND it with
  1716. // the byte. If it is zero then the bits in question are all clear
  1717. // otherwise at least one of them is set.
  1718. //
  1719. if ((ZeroMask[StartingOffset] & FillMask[EndingOffset+1] & Byte) == 0) {
  1720. return TRUE;
  1721. } else {
  1722. return FALSE;
  1723. }
  1724. } else {
  1725. //
  1726. // Get the first byte that we're after, and then
  1727. // compute the mask of bits we're after for the first byte then
  1728. // AND it with the byte itself.
  1729. //
  1730. GET_BYTE( Byte );
  1731. if ((ZeroMask[StartingOffset] & Byte) != 0) {
  1732. return FALSE;
  1733. }
  1734. //
  1735. // Now for every whole byte inbetween read in the byte,
  1736. // and make sure it is all zeros
  1737. //
  1738. for (i = StartingByte+1; i < EndingByte; i += 1) {
  1739. GET_BYTE( Byte );
  1740. if (Byte != 0) {
  1741. return FALSE;
  1742. }
  1743. }
  1744. //
  1745. // Get the last byte we're after, and then
  1746. // compute the mask of bits we're after for the last byte then
  1747. // AND it with the byte itself.
  1748. //
  1749. GET_BYTE( Byte );
  1750. if ((FillMask[EndingOffset+1] & Byte) != 0) {
  1751. return FALSE;
  1752. }
  1753. }
  1754. return TRUE;
  1755. }
  1756. BOOLEAN
  1757. RtlAreBitsSet (
  1758. IN PRTL_BITMAP BitMapHeader,
  1759. IN ULONG StartingIndex,
  1760. IN ULONG Length
  1761. )
  1762. /*++
  1763. Routine Description:
  1764. This procedure determines if the range of specified bits are all set.
  1765. Arguments:
  1766. BitMapHeader - Supplies a pointer to the previously initialized bitmap.
  1767. StartingIndex - Supplies the starting bit index to examine
  1768. Length - Supplies the number of bits to examine
  1769. Return Value:
  1770. BOOLEAN - TRUE if the specified bits in the bitmap are all set, and
  1771. FALSE if any are clear or if the range is outside the bitmap or if
  1772. Length is zero.
  1773. --*/
  1774. {
  1775. ULONG SizeOfBitMap;
  1776. ULONG SizeInBytes;
  1777. ULONG EndingIndex;
  1778. ULONG StartingByte;
  1779. ULONG EndingByte;
  1780. ULONG StartingOffset;
  1781. ULONG EndingOffset;
  1782. ULONG i;
  1783. UCHAR Byte;
  1784. GET_BYTE_DECLARATIONS();
  1785. //
  1786. // To make the loops in our test run faster we'll extract the fields
  1787. // from the bitmap header
  1788. //
  1789. SizeOfBitMap = BitMapHeader->SizeOfBitMap;
  1790. SizeInBytes = (SizeOfBitMap + 7) / 8;
  1791. //
  1792. // First make sure that the specified range is contained within the
  1793. // bitmap, and the length is not zero.
  1794. //
  1795. if ((StartingIndex + Length > SizeOfBitMap) || (Length == 0)) {
  1796. return FALSE;
  1797. }
  1798. //
  1799. // Compute the ending index, starting and ending byte, and the starting
  1800. // and ending offset within each byte
  1801. //
  1802. EndingIndex = StartingIndex + Length - 1;
  1803. StartingByte = StartingIndex / 8;
  1804. EndingByte = EndingIndex / 8;
  1805. StartingOffset = StartingIndex % 8;
  1806. EndingOffset = EndingIndex % 8;
  1807. //
  1808. // Set ourselves up to get the next byte
  1809. //
  1810. GET_BYTE_INITIALIZATION( BitMapHeader, StartingByte );
  1811. //
  1812. // Special case the situation where the starting byte and ending
  1813. // byte are one in the same
  1814. //
  1815. if (StartingByte == EndingByte) {
  1816. //
  1817. // Get the single byte we are to look at
  1818. //
  1819. GET_BYTE( Byte );
  1820. //
  1821. // Now we compute the mask of bits we're after and then AND it with
  1822. // the complement of the byte If it is zero then the bits in question
  1823. // are all clear otherwise at least one of them is clear.
  1824. //
  1825. if ((ZeroMask[StartingOffset] & FillMask[EndingOffset+1] & ~Byte) == 0) {
  1826. return TRUE;
  1827. } else {
  1828. return FALSE;
  1829. }
  1830. } else {
  1831. //
  1832. // Get the first byte that we're after, and then
  1833. // compute the mask of bits we're after for the first byte then
  1834. // AND it with the complement of the byte itself.
  1835. //
  1836. GET_BYTE( Byte );
  1837. if ((ZeroMask[StartingOffset] & ~Byte) != 0) {
  1838. return FALSE;
  1839. }
  1840. //
  1841. // Now for every whole byte inbetween read in the byte,
  1842. // and make sure it is all ones
  1843. //
  1844. for (i = StartingByte+1; i < EndingByte; i += 1) {
  1845. GET_BYTE( Byte );
  1846. if (Byte != 0xff) {
  1847. return FALSE;
  1848. }
  1849. }
  1850. //
  1851. // Get the last byte we're after, and then
  1852. // compute the mask of bits we're after for the last byte then
  1853. // AND it with the complement of the byte itself.
  1854. //
  1855. GET_BYTE( Byte );
  1856. if ((FillMask[EndingOffset+1] & ~Byte) != 0) {
  1857. return FALSE;
  1858. }
  1859. }
  1860. return TRUE;
  1861. }
  1862. static CONST ULONG FillMaskUlong[] = {
  1863. 0x00000000, 0x00000001, 0x00000003, 0x00000007,
  1864. 0x0000000f, 0x0000001f, 0x0000003f, 0x0000007f,
  1865. 0x000000ff, 0x000001ff, 0x000003ff, 0x000007ff,
  1866. 0x00000fff, 0x00001fff, 0x00003fff, 0x00007fff,
  1867. 0x0000ffff, 0x0001ffff, 0x0003ffff, 0x0007ffff,
  1868. 0x000fffff, 0x001fffff, 0x003fffff, 0x007fffff,
  1869. 0x00ffffff, 0x01ffffff, 0x03ffffff, 0x07ffffff,
  1870. 0x0fffffff, 0x1fffffff, 0x3fffffff, 0x7fffffff,
  1871. 0xffffffff
  1872. };
  1873. ULONG
  1874. RtlFindNextForwardRunClear (
  1875. IN PRTL_BITMAP BitMapHeader,
  1876. IN ULONG FromIndex,
  1877. IN PULONG StartingRunIndex
  1878. )
  1879. {
  1880. ULONG Start;
  1881. ULONG End;
  1882. PULONG PHunk, BitMapEnd;
  1883. ULONG Hunk;
  1884. //
  1885. // Take care of the boundary case of the null bitmap
  1886. //
  1887. if (BitMapHeader->SizeOfBitMap == 0) {
  1888. *StartingRunIndex = FromIndex;
  1889. return 0;
  1890. }
  1891. //
  1892. // Compute the last word address in the bitmap
  1893. //
  1894. BitMapEnd = BitMapHeader->Buffer + ((BitMapHeader->SizeOfBitMap - 1) / 32);
  1895. //
  1896. // Scan forward for the first clear bit
  1897. //
  1898. Start = FromIndex;
  1899. //
  1900. // Build pointer to the ULONG word in the bitmap
  1901. // containing the Start bit
  1902. //
  1903. PHunk = BitMapHeader->Buffer + (Start / 32);
  1904. //
  1905. // If the first subword is set then we can proceed to
  1906. // take big steps in the bitmap since we are now ULONG
  1907. // aligned in the search. Make sure we aren't improperly
  1908. // looking at the last word in the bitmap.
  1909. //
  1910. if (PHunk != BitMapEnd) {
  1911. //
  1912. // Read in the bitmap hunk. Set the previous bits in this word.
  1913. //
  1914. Hunk = *PHunk | FillMaskUlong[Start % 32];
  1915. if (Hunk == (ULONG)~0) {
  1916. //
  1917. // Adjust the pointers forward
  1918. //
  1919. Start += 32 - (Start % 32);
  1920. PHunk++;
  1921. while ( PHunk < BitMapEnd ) {
  1922. //
  1923. // Stop at first word with unset bits
  1924. //
  1925. if (*PHunk != (ULONG)~0) break;
  1926. PHunk++;
  1927. Start += 32;
  1928. }
  1929. }
  1930. }
  1931. //
  1932. // Bitwise search forward for the clear bit
  1933. //
  1934. while ((Start < BitMapHeader->SizeOfBitMap) && (RtlCheckBit( BitMapHeader, Start ) == 1)) { Start += 1; }
  1935. //
  1936. // Scan forward for the first set bit
  1937. //
  1938. End = Start;
  1939. //
  1940. // If we aren't in the last word of the bitmap we may be
  1941. // able to keep taking big steps
  1942. //
  1943. if (PHunk != BitMapEnd) {
  1944. //
  1945. // We know that the clear bit was in the last word we looked at,
  1946. // so continue from there to find the next set bit, clearing the
  1947. // previous bits in the word
  1948. //
  1949. Hunk = *PHunk & ~FillMaskUlong[End % 32];
  1950. if (Hunk == (ULONG)0) {
  1951. //
  1952. // Adjust the pointers forward
  1953. //
  1954. End += 32 - (End % 32);
  1955. PHunk++;
  1956. while ( PHunk < BitMapEnd ) {
  1957. //
  1958. // Stop at first word with set bits
  1959. //
  1960. if (*PHunk != (ULONG)0) break;
  1961. PHunk++;
  1962. End += 32;
  1963. }
  1964. }
  1965. }
  1966. //
  1967. // Bitwise search forward for the set bit
  1968. //
  1969. while ((End < BitMapHeader->SizeOfBitMap) && (RtlCheckBit( BitMapHeader, End ) == 0)) { End += 1; }
  1970. //
  1971. // Compute the index and return the length
  1972. //
  1973. *StartingRunIndex = Start;
  1974. return (End - Start);
  1975. }
  1976. ULONG
  1977. RtlFindLastBackwardRunClear (
  1978. IN PRTL_BITMAP BitMapHeader,
  1979. IN ULONG FromIndex,
  1980. IN PULONG StartingRunIndex
  1981. )
  1982. {
  1983. ULONG Start;
  1984. ULONG End;
  1985. PULONG PHunk;
  1986. ULONG Hunk;
  1987. RTL_PAGED_CODE();
  1988. //
  1989. // Take care of the boundary case of the null bitmap
  1990. //
  1991. if (BitMapHeader->SizeOfBitMap == 0) {
  1992. *StartingRunIndex = FromIndex;
  1993. return 0;
  1994. }
  1995. //
  1996. // Scan backwards for the first clear bit
  1997. //
  1998. End = FromIndex;
  1999. //
  2000. // Build pointer to the ULONG word in the bitmap
  2001. // containing the End bit, then read in the bitmap
  2002. // hunk. Set the rest of the bits in this word, NOT
  2003. // inclusive of the FromIndex bit.
  2004. //
  2005. PHunk = BitMapHeader->Buffer + (End / 32);
  2006. Hunk = *PHunk | ~FillMaskUlong[(End % 32) + 1];
  2007. //
  2008. // If the first subword is set then we can proceed to
  2009. // take big steps in the bitmap since we are now ULONG
  2010. // aligned in the search
  2011. //
  2012. if (Hunk == (ULONG)~0) {
  2013. //
  2014. // Adjust the pointers backwards
  2015. //
  2016. End -= (End % 32) + 1;
  2017. PHunk--;
  2018. while ( PHunk > BitMapHeader->Buffer ) {
  2019. //
  2020. // Stop at first word with set bits
  2021. //
  2022. if (*PHunk != (ULONG)~0) break;
  2023. PHunk--;
  2024. End -= 32;
  2025. }
  2026. }
  2027. //
  2028. // Bitwise search backward for the clear bit
  2029. //
  2030. while ((End != MAXULONG) && (RtlCheckBit( BitMapHeader, End ) == 1)) { End -= 1; }
  2031. //
  2032. // Scan backwards for the first set bit
  2033. //
  2034. Start = End;
  2035. //
  2036. // We know that the clear bit was in the last word we looked at,
  2037. // so continue from there to find the next set bit, clearing the
  2038. // previous bits in the word.
  2039. //
  2040. Hunk = *PHunk & FillMaskUlong[Start % 32];
  2041. //
  2042. // If the subword is unset then we can proceed in big steps
  2043. //
  2044. if (Hunk == (ULONG)0) {
  2045. //
  2046. // Adjust the pointers backward
  2047. //
  2048. Start -= (Start % 32) + 1;
  2049. PHunk--;
  2050. while ( PHunk > BitMapHeader->Buffer ) {
  2051. //
  2052. // Stop at first word with set bits
  2053. //
  2054. if (*PHunk != (ULONG)0) break;
  2055. PHunk--;
  2056. Start -= 32;
  2057. }
  2058. }
  2059. //
  2060. // Bitwise search backward for the set bit
  2061. //
  2062. while ((Start != MAXULONG) && (RtlCheckBit( BitMapHeader, Start ) == 0)) { Start -= 1; }
  2063. //
  2064. // Compute the index and return the length
  2065. //
  2066. *StartingRunIndex = Start + 1;
  2067. return (End - Start);
  2068. }
  2069. #define BM_4567 0xFFFFFFFF00000000UI64
  2070. #define BM_67 0xFFFF000000000000UI64
  2071. #define BM_7 0xFF00000000000000UI64
  2072. #define BM_5 0x0000FF0000000000UI64
  2073. #define BM_23 0x00000000FFFF0000UI64
  2074. #define BM_3 0x00000000FF000000UI64
  2075. #define BM_1 0x000000000000FF00UI64
  2076. #define BM_0123 0x00000000FFFFFFFFUI64
  2077. #define BM_01 0x000000000000FFFFUI64
  2078. #define BM_0 0x00000000000000FFUI64
  2079. #define BM_2 0x0000000000FF0000UI64
  2080. #define BM_45 0x0000FFFF00000000UI64
  2081. #define BM_4 0x000000FF00000000UI64
  2082. #define BM_6 0x00FF000000000000UI64
  2083. CCHAR
  2084. RtlFindMostSignificantBit (
  2085. IN ULONGLONG Set
  2086. )
  2087. /*++
  2088. Routine Description:
  2089. This procedure finds the most significant non-zero bit in Set and
  2090. returns it's zero-based position.
  2091. Arguments:
  2092. Set - Supplies the 64-bit bitmap.
  2093. Return Value:
  2094. Set != 0:
  2095. Bit position of the most significant set bit in Set.
  2096. Set == 0:
  2097. -1.
  2098. --*/
  2099. {
  2100. UCHAR index;
  2101. UCHAR bitOffset;
  2102. UCHAR lookup;
  2103. if ((Set & BM_4567) != 0) {
  2104. if ((Set & BM_67) != 0) {
  2105. if ((Set & BM_7) != 0) {
  2106. bitOffset = 7 * 8;
  2107. } else {
  2108. bitOffset = 6 * 8;
  2109. }
  2110. } else {
  2111. if ((Set & BM_5) != 0) {
  2112. bitOffset = 5 * 8;
  2113. } else {
  2114. bitOffset = 4 * 8;
  2115. }
  2116. }
  2117. } else {
  2118. if ((Set & BM_23) != 0) {
  2119. if ((Set & BM_3) != 0) {
  2120. bitOffset = 3 * 8;
  2121. } else {
  2122. bitOffset = 2 * 8;
  2123. }
  2124. } else {
  2125. if ((Set & BM_1) != 0) {
  2126. bitOffset = 1 * 8;
  2127. } else {
  2128. //
  2129. // The test for Set == 0 is postponed to here, it is expected
  2130. // to be rare. Note that if we had our own version of
  2131. // RtlpBitsClearHigh[] we could eliminate this test entirely,
  2132. // reducing the average number of tests from 3.125 to 3.
  2133. //
  2134. if (Set == 0) {
  2135. return -1;
  2136. }
  2137. bitOffset = 0 * 8;
  2138. }
  2139. }
  2140. }
  2141. lookup = (UCHAR)(Set >> bitOffset);
  2142. index = (7 - RtlpBitsClearHigh[lookup]) + bitOffset;
  2143. return index;
  2144. }
  2145. CCHAR
  2146. RtlFindLeastSignificantBit (
  2147. IN ULONGLONG Set
  2148. )
  2149. /*++
  2150. Routine Description:
  2151. This procedure finds the least significant non-zero bit in Set and
  2152. returns it's zero-based position.
  2153. Arguments:
  2154. Set - Supplies the 64-bit bitmap.
  2155. Return Value:
  2156. Set != 0:
  2157. Bit position of the least significant non-zero bit in Set.
  2158. Set == 0:
  2159. -1.
  2160. --*/
  2161. {
  2162. UCHAR index;
  2163. UCHAR bitOffset;
  2164. UCHAR lookup;
  2165. if ((Set & BM_0123) != 0) {
  2166. if ((Set & BM_01) != 0) {
  2167. if ((Set & BM_0) != 0) {
  2168. bitOffset = 0 * 8;
  2169. } else {
  2170. bitOffset = 1 * 8;
  2171. }
  2172. } else {
  2173. if ((Set & BM_2) != 0) {
  2174. bitOffset = 2 * 8;
  2175. } else {
  2176. bitOffset = 3 * 8;
  2177. }
  2178. }
  2179. } else {
  2180. if ((Set & BM_45) != 0) {
  2181. if ((Set & BM_4) != 0) {
  2182. bitOffset = 4 * 8;
  2183. } else {
  2184. bitOffset = 5 * 8;
  2185. }
  2186. } else {
  2187. if ((Set & BM_6) != 0) {
  2188. bitOffset = 6 * 8;
  2189. } else {
  2190. //
  2191. // The test for Set == 0 is postponed to here, it is expected
  2192. // to be rare. Note that if we had our own version of
  2193. // RtlpBitsClearHigh[] we could eliminate this test entirely,
  2194. // reducing the average number of tests from 3.125 to 3.
  2195. //
  2196. if (Set == 0) {
  2197. return -1;
  2198. }
  2199. bitOffset = 7 * 8;
  2200. }
  2201. }
  2202. }
  2203. lookup = (UCHAR)(Set >> bitOffset);
  2204. index = RtlpBitsClearLow[lookup] + bitOffset;
  2205. return index;
  2206. }