1 /* COPYRIGHT: See COPYING in the top level directory
2 * PROJECT: ReactOS system libraries
3 * FILE: lib/rtl/bitmap.c
4 * PURPOSE: Bitmap functions
5 * PROGRAMMER: Eric Kohl
8 /* INCLUDES *****************************************************************/
16 /* MACROS *******************************************************************/
18 #define MASK(Count, Shift) \
19 ((Count) == 32 ? 0xFFFFFFFF : ~(0xFFFFFFFF << (Count)) << (Shift))
22 /* FUNCTIONS ****************************************************************/
28 RtlInitializeBitMap(PRTL_BITMAP BitMapHeader
,
32 BitMapHeader
->SizeOfBitMap
= SizeOfBitMap
;
33 BitMapHeader
->Buffer
= BitMapBuffer
;
41 RtlAreBitsClear(PRTL_BITMAP BitMapHeader
,
50 Size
= BitMapHeader
->SizeOfBitMap
;
51 if (StartingIndex
>= Size
||
53 (StartingIndex
+ Length
> Size
))
56 Ptr
= (PULONG
)BitMapHeader
->Buffer
+ (StartingIndex
/ 32);
59 /* Get bit shift in current ulong */
60 Shift
= StartingIndex
& 0x1F;
62 /* Get number of bits to check in current ulong */
63 Count
= (Length
> 32 - Shift
) ? 32 - Shift
: Length
;
66 if (*Ptr
++ & MASK(Count
, Shift
))
70 StartingIndex
+= Count
;
81 RtlAreBitsSet(PRTL_BITMAP BitMapHeader
,
90 Size
= BitMapHeader
->SizeOfBitMap
;
91 if (StartingIndex
>= Size
||
93 (StartingIndex
+ Length
> Size
))
96 Ptr
= (PULONG
)BitMapHeader
->Buffer
+ (StartingIndex
/ 32);
99 /* Get bit shift in current ulong */
100 Shift
= StartingIndex
& 0x1F;
102 /* Get number of bits to check in current ulong */
103 Count
= (Length
> 32 - Shift
) ? 32 - Shift
: Length
;
106 if (~*Ptr
++ & MASK(Count
, Shift
))
110 StartingIndex
+= Count
;
120 * Note: According to the documentation, SizeOfBitmap is in bits, so the
121 * ROUND_UP(...) must be divided by the number of bits per byte here.
122 * This function is exercised by the whole page allocator in npool.c
123 * which is how i came across this error.
126 RtlClearAllBits(IN OUT PRTL_BITMAP BitMapHeader
)
128 if (BitMapHeader
!= NULL
)
130 if (BitMapHeader
->Buffer
!= NULL
)
132 memset(BitMapHeader
->Buffer
,
134 ROUND_UP(BitMapHeader
->SizeOfBitMap
, 8) / 8);
144 RtlClearBit(PRTL_BITMAP BitMapHeader
,
149 if (BitNumber
>= BitMapHeader
->SizeOfBitMap
)
152 Ptr
= (PULONG
)BitMapHeader
->Buffer
+ (BitNumber
/ 32);
154 *Ptr
&= ~(1 << (BitNumber
% 32));
162 RtlClearBits(PRTL_BITMAP BitMapHeader
,
171 Size
= BitMapHeader
->SizeOfBitMap
;
172 if (StartingIndex
>= Size
|| NumberToClear
== 0)
175 ASSERT(StartingIndex
+ NumberToClear
<= Size
);
177 Ptr
= (PULONG
)BitMapHeader
->Buffer
+ (StartingIndex
/ 32);
178 while (NumberToClear
)
180 /* Bit shift in current ulong */
181 Shift
= StartingIndex
& 0x1F;
183 /* Number of bits to change in current ulong */
184 Count
= (NumberToClear
> 32 - Shift
) ? 32 - Shift
: NumberToClear
;
187 *Ptr
++ &= ~MASK(Count
, Shift
);
188 NumberToClear
-= Count
;
189 StartingIndex
+= Count
;
198 RtlFindClearBits(PRTL_BITMAP BitMapHeader
,
209 ULONG OriginalHint
= HintIndex
;
211 Size
= BitMapHeader
->SizeOfBitMap
;
212 if (NumberToFind
> Size
|| NumberToFind
== 0)
215 if (HintIndex
>= Size
)
218 /* Initialize the values to the hint location. */
220 Ptr
= BitMapHeader
->Buffer
+ (Index
/ 32);
221 Mask
= 1 << (Index
& 0x1F);
224 /* The outer loop does the magic of first searching from the
225 * hint to the bitmap end and then going again from beginning
226 * of the bitmap to the hint location.
228 for (Loop
= 0; Loop
< 2; Loop
++)
230 while (HintIndex
< End
)
232 /* Count clear bits */
233 for (Count
= 0; Index
< End
&& ~*Ptr
& Mask
; Index
++)
235 if (++Count
>= NumberToFind
)
248 for (; Index
< End
&& *Ptr
& Mask
; Index
++)
262 if (OriginalHint
== 0)
265 /* Initialize the values for the beginning -> hint loop. */
266 HintIndex
= Index
= 0;
267 End
= OriginalHint
+ NumberToFind
- 1;
268 End
= End
> Size
? Size
: End
;
269 Ptr
= BitMapHeader
->Buffer
;
281 RtlFindClearBitsAndSet(PRTL_BITMAP BitMapHeader
,
287 Index
= RtlFindClearBits(BitMapHeader
,
290 if (Index
!= (ULONG
)-1)
292 RtlSetBits(BitMapHeader
,
305 RtlFindFirstRunClear(PRTL_BITMAP BitMapHeader
,
306 PULONG StartingIndex
)
314 Size
= BitMapHeader
->SizeOfBitMap
;
315 if (*StartingIndex
> Size
)
317 *StartingIndex
= (ULONG
)-1;
321 Index
= *StartingIndex
;
322 Ptr
= (PULONG
)BitMapHeader
->Buffer
+ (Index
/ 32);
323 Mask
= 1 << (Index
& 0x1F);
326 for (; Index
< Size
&& *Ptr
& Mask
; Index
++)
337 /* Return index of first clear bit */
340 *StartingIndex
= (ULONG
)-1;
345 *StartingIndex
= Index
;
348 /* Count clear bits */
349 for (Count
= 0; Index
< Size
&& ~*Ptr
& Mask
; Index
++)
369 RtlFindClearRuns(PRTL_BITMAP BitMapHeader
,
370 PRTL_BITMAP_RUN RunArray
,
371 ULONG SizeOfRunArray
,
372 BOOLEAN LocateLongestRuns
)
383 RtlFindLastBackwardRunClear(IN PRTL_BITMAP BitMapHeader
,
385 IN PULONG StartingRunIndex
)
396 RtlFindNextForwardRunClear(IN PRTL_BITMAP BitMapHeader
,
398 IN PULONG StartingRunIndex
)
409 RtlFindFirstRunSet(IN PRTL_BITMAP BitMapHeader
,
410 IN PULONG StartingIndex
)
418 Size
= BitMapHeader
->SizeOfBitMap
;
419 if (*StartingIndex
> Size
)
421 *StartingIndex
= (ULONG
)-1;
425 Index
= *StartingIndex
;
426 Ptr
= (PULONG
)BitMapHeader
->Buffer
+ (Index
/ 32);
427 Mask
= 1 << (Index
& 0x1F);
429 /* Skip clear bits */
430 for (; Index
< Size
&& ~*Ptr
& Mask
; Index
++)
441 /* Return index of first set bit */
444 *StartingIndex
= (ULONG
)-1;
449 *StartingIndex
= Index
;
453 for (Count
= 0; Index
< Size
&& *Ptr
& Mask
; Index
++)
473 RtlFindLongestRunClear(PRTL_BITMAP BitMapHeader
,
474 PULONG StartingIndex
)
485 Size
= BitMapHeader
->SizeOfBitMap
;
486 Ptr
= (PULONG
)BitMapHeader
->Buffer
;
492 /* Count clear bits */
493 for (Count
= 0; Index
< Size
&& ~*Ptr
& Mask
; Index
++)
506 for (; Index
< Size
&& *Ptr
& Mask
; Index
++)
524 if (StartingIndex
!= NULL
)
526 *StartingIndex
= Maxstart
;
537 RtlFindLongestRunSet(PRTL_BITMAP BitMapHeader
,
538 PULONG StartingIndex
)
549 Size
= BitMapHeader
->SizeOfBitMap
;
550 Ptr
= (PULONG
)BitMapHeader
->Buffer
;
557 for (Count
= 0; Index
< Size
&& *Ptr
& Mask
; Index
++)
569 /* Skip clear bits */
570 for (; Index
< Size
&& ~*Ptr
& Mask
; Index
++)
588 if (StartingIndex
!= NULL
)
590 *StartingIndex
= Maxstart
;
601 RtlFindSetBits(PRTL_BITMAP BitMapHeader
,
612 ULONG OriginalHint
= HintIndex
;
614 Size
= BitMapHeader
->SizeOfBitMap
;
615 if (NumberToFind
> Size
|| NumberToFind
== 0)
618 if (HintIndex
>= Size
)
621 /* Initialize the values to the hint location. */
623 Ptr
= BitMapHeader
->Buffer
+ (Index
/ 32);
624 Mask
= 1 << (Index
& 0x1F);
627 /* The outer loop does the magic of first searching from the
628 * hint to the bitmap end and then going again from beginning
629 * of the bitmap to the hint location.
631 for (Loop
= 0; Loop
< 2; Loop
++)
633 while (HintIndex
< End
)
636 for (Count
= 0; Index
< End
&& *Ptr
& Mask
; Index
++)
638 if (++Count
>= NumberToFind
)
650 /* Skip clear bits */
651 for (; Index
< End
&& ~*Ptr
& Mask
; Index
++)
666 if (OriginalHint
== 0)
669 /* Initialize the values for the beginning -> hint loop. */
670 HintIndex
= Index
= 0;
671 End
= OriginalHint
+ NumberToFind
- 1;
672 End
= End
> Size
? Size
: End
;
673 Ptr
= BitMapHeader
->Buffer
;
685 RtlFindSetBitsAndClear(PRTL_BITMAP BitMapHeader
,
691 Index
= RtlFindSetBits(BitMapHeader
,
694 if (Index
!= (ULONG
)-1)
696 RtlClearBits(BitMapHeader
,
709 RtlNumberOfClearBits(PRTL_BITMAP BitMapHeader
)
717 Size
= BitMapHeader
->SizeOfBitMap
;
718 Ptr
= (PULONG
)BitMapHeader
->Buffer
;
720 for (Mask
= 1, Index
= 0, Count
= 0; Index
< Size
; Index
++)
741 RtlNumberOfSetBits(PRTL_BITMAP BitMapHeader
)
749 Ptr
= (PULONG
)BitMapHeader
->Buffer
;
750 Size
= BitMapHeader
->SizeOfBitMap
;
751 for (Mask
= 1, Index
= 0, Count
= 0; Index
< Size
; Index
++)
772 * Note: According to the documentation, SizeOfBitmap is in bits, so the
773 * ROUND_UP(...) must be divided by the number of bits per byte here.
774 * The companion function, RtlClearAllBits, is exercised by the whole page
775 * allocator in npool.c which is how i came across this error.
778 RtlSetAllBits(IN OUT PRTL_BITMAP BitMapHeader
)
780 memset(BitMapHeader
->Buffer
,
782 ROUND_UP(BitMapHeader
->SizeOfBitMap
, 8) / 8);
790 RtlSetBit(PRTL_BITMAP BitMapHeader
,
795 if (BitNumber
>= BitMapHeader
->SizeOfBitMap
)
798 Ptr
= (PULONG
)BitMapHeader
->Buffer
+ (BitNumber
/ 32);
800 *Ptr
|= (1 << (BitNumber
% 32));
808 RtlSetBits(PRTL_BITMAP BitMapHeader
,
817 Size
= BitMapHeader
->SizeOfBitMap
;
818 if (StartingIndex
>= Size
|| NumberToSet
== 0)
821 ASSERT(StartingIndex
+ NumberToSet
<= Size
);
823 Ptr
= (PULONG
)BitMapHeader
->Buffer
+ (StartingIndex
/ 32);
826 /* Bit shift in current ulong */
827 Shift
= StartingIndex
& 0x1F;
829 /* Number of bits to change in current ulong */
830 Count
= (NumberToSet
> 32 - Shift
) ? 32 - Shift
: NumberToSet
;
833 *Ptr
++ |= MASK(Count
, Shift
);
834 NumberToSet
-= Count
;
835 StartingIndex
+= Count
;
844 RtlTestBit(PRTL_BITMAP BitMapHeader
,
849 if (BitNumber
>= BitMapHeader
->SizeOfBitMap
)
852 Ptr
= (PULONG
)BitMapHeader
->Buffer
+ (BitNumber
/ 32);
854 return (*Ptr
& (1 << (BitNumber
% 32)));