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.

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