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 memset(BitMapHeader
->Buffer
,
130 ROUND_UP(BitMapHeader
->SizeOfBitMap
, 8) / 8);
139 RtlClearBit(PRTL_BITMAP BitMapHeader
,
144 if (BitNumber
>= BitMapHeader
->SizeOfBitMap
)
147 Ptr
= (PULONG
)BitMapHeader
->Buffer
+ (BitNumber
/ 32);
149 *Ptr
&= ~(1 << (BitNumber
% 32));
157 RtlClearBits(PRTL_BITMAP BitMapHeader
,
166 Size
= BitMapHeader
->SizeOfBitMap
;
167 if (StartingIndex
>= Size
|| NumberToClear
== 0)
170 ASSERT(StartingIndex
+ NumberToClear
<= Size
);
172 Ptr
= (PULONG
)BitMapHeader
->Buffer
+ (StartingIndex
/ 32);
173 while (NumberToClear
)
175 /* Bit shift in current ulong */
176 Shift
= StartingIndex
& 0x1F;
178 /* Number of bits to change in current ulong */
179 Count
= (NumberToClear
> 32 - Shift
) ? 32 - Shift
: NumberToClear
;
182 *Ptr
++ &= ~MASK(Count
, Shift
);
183 NumberToClear
-= Count
;
184 StartingIndex
+= Count
;
193 RtlFindClearBits(PRTL_BITMAP BitMapHeader
,
204 ULONG OriginalHint
= HintIndex
;
206 Size
= BitMapHeader
->SizeOfBitMap
;
207 if (NumberToFind
> Size
|| NumberToFind
== 0)
210 if (HintIndex
>= Size
)
213 /* Initialize the values to the hint location. */
215 Ptr
= BitMapHeader
->Buffer
+ (Index
/ 32);
216 Mask
= 1 << (Index
& 0x1F);
219 /* The outer loop does the magic of first searching from the
220 * hint to the bitmap end and then going again from beginning
221 * of the bitmap to the hint location.
223 for (Loop
= 0; Loop
< 2; Loop
++)
225 while (HintIndex
< End
)
227 /* Count clear bits */
228 for (Count
= 0; Index
< End
&& ~*Ptr
& Mask
; Index
++)
230 if (++Count
>= NumberToFind
)
243 for (; Index
< End
&& *Ptr
& Mask
; Index
++)
257 if (OriginalHint
== 0)
260 /* Initialize the values for the beginning -> hint loop. */
261 HintIndex
= Index
= 0;
262 End
= OriginalHint
+ NumberToFind
- 1;
263 End
= End
> Size
? Size
: End
;
264 Ptr
= BitMapHeader
->Buffer
;
276 RtlFindClearBitsAndSet(PRTL_BITMAP BitMapHeader
,
282 Index
= RtlFindClearBits(BitMapHeader
,
285 if (Index
!= (ULONG
)-1)
287 RtlSetBits(BitMapHeader
,
300 RtlFindFirstRunClear(PRTL_BITMAP BitMapHeader
,
301 PULONG StartingIndex
)
309 Size
= BitMapHeader
->SizeOfBitMap
;
310 if (*StartingIndex
> Size
)
312 *StartingIndex
= (ULONG
)-1;
316 Index
= *StartingIndex
;
317 Ptr
= (PULONG
)BitMapHeader
->Buffer
+ (Index
/ 32);
318 Mask
= 1 << (Index
& 0x1F);
321 for (; Index
< Size
&& *Ptr
& Mask
; Index
++)
332 /* Return index of first clear bit */
335 *StartingIndex
= (ULONG
)-1;
340 *StartingIndex
= Index
;
343 /* Count clear bits */
344 for (Count
= 0; Index
< Size
&& ~*Ptr
& Mask
; Index
++)
364 RtlFindClearRuns(PRTL_BITMAP BitMapHeader
,
365 PRTL_BITMAP_RUN RunArray
,
366 ULONG SizeOfRunArray
,
367 BOOLEAN LocateLongestRuns
)
378 RtlFindLastBackwardRunClear(IN PRTL_BITMAP BitMapHeader
,
380 IN PULONG StartingRunIndex
)
391 RtlFindNextForwardRunClear(IN PRTL_BITMAP BitMapHeader
,
393 IN PULONG StartingRunIndex
)
404 RtlFindFirstRunSet(IN PRTL_BITMAP BitMapHeader
,
405 IN PULONG StartingIndex
)
413 Size
= BitMapHeader
->SizeOfBitMap
;
414 if (*StartingIndex
> Size
)
416 *StartingIndex
= (ULONG
)-1;
420 Index
= *StartingIndex
;
421 Ptr
= (PULONG
)BitMapHeader
->Buffer
+ (Index
/ 32);
422 Mask
= 1 << (Index
& 0x1F);
424 /* Skip clear bits */
425 for (; Index
< Size
&& ~*Ptr
& Mask
; Index
++)
436 /* Return index of first set bit */
439 *StartingIndex
= (ULONG
)-1;
444 *StartingIndex
= Index
;
448 for (Count
= 0; Index
< Size
&& *Ptr
& Mask
; Index
++)
468 RtlFindLongestRunClear(PRTL_BITMAP BitMapHeader
,
469 PULONG StartingIndex
)
480 Size
= BitMapHeader
->SizeOfBitMap
;
481 Ptr
= (PULONG
)BitMapHeader
->Buffer
;
487 /* Count clear bits */
488 for (Count
= 0; Index
< Size
&& ~*Ptr
& Mask
; Index
++)
501 for (; Index
< Size
&& *Ptr
& Mask
; Index
++)
519 if (StartingIndex
!= NULL
)
521 *StartingIndex
= Maxstart
;
532 RtlFindLongestRunSet(PRTL_BITMAP BitMapHeader
,
533 PULONG StartingIndex
)
544 Size
= BitMapHeader
->SizeOfBitMap
;
545 Ptr
= (PULONG
)BitMapHeader
->Buffer
;
552 for (Count
= 0; Index
< Size
&& *Ptr
& Mask
; Index
++)
564 /* Skip clear bits */
565 for (; Index
< Size
&& ~*Ptr
& Mask
; Index
++)
583 if (StartingIndex
!= NULL
)
585 *StartingIndex
= Maxstart
;
596 RtlFindSetBits(PRTL_BITMAP BitMapHeader
,
607 ULONG OriginalHint
= HintIndex
;
609 Size
= BitMapHeader
->SizeOfBitMap
;
610 if (NumberToFind
> Size
|| NumberToFind
== 0)
613 if (HintIndex
>= Size
)
616 /* Initialize the values to the hint location. */
618 Ptr
= BitMapHeader
->Buffer
+ (Index
/ 32);
619 Mask
= 1 << (Index
& 0x1F);
622 /* The outer loop does the magic of first searching from the
623 * hint to the bitmap end and then going again from beginning
624 * of the bitmap to the hint location.
626 for (Loop
= 0; Loop
< 2; Loop
++)
628 while (HintIndex
< End
)
631 for (Count
= 0; Index
< End
&& *Ptr
& Mask
; Index
++)
633 if (++Count
>= NumberToFind
)
645 /* Skip clear bits */
646 for (; Index
< End
&& ~*Ptr
& Mask
; Index
++)
661 if (OriginalHint
== 0)
664 /* Initialize the values for the beginning -> hint loop. */
665 HintIndex
= Index
= 0;
666 End
= OriginalHint
+ NumberToFind
- 1;
667 End
= End
> Size
? Size
: End
;
668 Ptr
= BitMapHeader
->Buffer
;
680 RtlFindSetBitsAndClear(PRTL_BITMAP BitMapHeader
,
686 Index
= RtlFindSetBits(BitMapHeader
,
689 if (Index
!= (ULONG
)-1)
691 RtlClearBits(BitMapHeader
,
704 RtlNumberOfClearBits(PRTL_BITMAP BitMapHeader
)
712 Size
= BitMapHeader
->SizeOfBitMap
;
713 Ptr
= (PULONG
)BitMapHeader
->Buffer
;
715 for (Mask
= 1, Index
= 0, Count
= 0; Index
< Size
; Index
++)
736 RtlNumberOfSetBits(PRTL_BITMAP BitMapHeader
)
744 Ptr
= (PULONG
)BitMapHeader
->Buffer
;
745 Size
= BitMapHeader
->SizeOfBitMap
;
746 for (Mask
= 1, Index
= 0, Count
= 0; Index
< Size
; Index
++)
767 * Note: According to the documentation, SizeOfBitmap is in bits, so the
768 * ROUND_UP(...) must be divided by the number of bits per byte here.
769 * The companion function, RtlClearAllBits, is exercised by the whole page
770 * allocator in npool.c which is how i came across this error.
773 RtlSetAllBits(IN OUT PRTL_BITMAP BitMapHeader
)
775 memset(BitMapHeader
->Buffer
,
777 ROUND_UP(BitMapHeader
->SizeOfBitMap
, 8) / 8);
785 RtlSetBit(PRTL_BITMAP BitMapHeader
,
790 if (BitNumber
>= BitMapHeader
->SizeOfBitMap
)
793 Ptr
= (PULONG
)BitMapHeader
->Buffer
+ (BitNumber
/ 32);
795 *Ptr
|= (1 << (BitNumber
% 32));
803 RtlSetBits(PRTL_BITMAP BitMapHeader
,
812 Size
= BitMapHeader
->SizeOfBitMap
;
813 if (StartingIndex
>= Size
|| NumberToSet
== 0)
816 ASSERT(StartingIndex
+ NumberToSet
<= Size
);
818 Ptr
= (PULONG
)BitMapHeader
->Buffer
+ (StartingIndex
/ 32);
821 /* Bit shift in current ulong */
822 Shift
= StartingIndex
& 0x1F;
824 /* Number of bits to change in current ulong */
825 Count
= (NumberToSet
> 32 - Shift
) ? 32 - Shift
: NumberToSet
;
828 *Ptr
++ |= MASK(Count
, Shift
);
829 NumberToSet
-= Count
;
830 StartingIndex
+= Count
;
839 RtlTestBit(PRTL_BITMAP BitMapHeader
,
844 if (BitNumber
>= BitMapHeader
->SizeOfBitMap
)
847 Ptr
= (PULONG
)BitMapHeader
->Buffer
+ (BitNumber
/ 32);
849 return (*Ptr
& (1 << (BitNumber
% 32)));