LinuxKPI: Add bitmap_intersects(), bitmap_from_arr32()

and bitmap_shift_right() functions to linux/bitmap.h

They perform calculation of two bitmaps intersection,
copying the contents of u32 array of bits to bitmap and
logical right shifting of the bits in a bitmap.

Sponsored by:	Serenity Cyber Security, LLC
Reviewed by:	manu
MFC after:	1 week
Differential Revision:	https://reviews.freebsd.org/D42812

(cherry picked from commit 5ae2e6f913fa1df5f3262255558b76af05409a09)
This commit is contained in:
Vladimir Kondratyev 2023-12-24 11:19:59 +03:00
parent cdceed0413
commit edeb8cfad0

View file

@ -264,6 +264,27 @@ bitmap_subset(const unsigned long *pa,
return (1);
}
static inline bool
bitmap_intersects(const unsigned long *pa, const unsigned long *pb,
unsigned size)
{
const unsigned end = BIT_WORD(size);
const unsigned tail = size & (BITS_PER_LONG - 1);
unsigned i;
for (i = 0; i != end; i++)
if (pa[i] & pb[i])
return (true);
if (tail) {
const unsigned long mask = BITMAP_LAST_WORD_MASK(tail);
if (pa[end] & pb[end] & mask)
return (true);
}
return (false);
}
static inline void
bitmap_complement(unsigned long *dst, const unsigned long *src,
const unsigned int size)
@ -306,6 +327,29 @@ bitmap_to_arr32(uint32_t *dst, const unsigned long *src, unsigned int size)
dst[end - 1] &= (uint32_t)(UINT_MAX >> (32 - (size % 32)));
}
static inline void
bitmap_from_arr32(unsigned long *dst, const uint32_t *src,
unsigned int size)
{
const unsigned int end = BIT_WORD(size);
const unsigned int tail = size & (BITS_PER_LONG - 1);
#ifdef __LP64__
const unsigned int end32 = howmany(size, 32);
unsigned int i = 0;
while (i < end32) {
dst[i++/2] = (unsigned long) *(src++);
if (i < end32)
dst[i++/2] |= ((unsigned long) *(src++)) << 32;
}
#else
bitmap_copy(dst, (unsigned long *)src, size);
#endif
if ((size % BITS_PER_LONG) != 0)
dst[end] &= BITMAP_LAST_WORD_MASK(tail);
}
static inline void
bitmap_or(unsigned long *dst, const unsigned long *src1,
const unsigned long *src2, const unsigned int size)
@ -350,6 +394,40 @@ bitmap_xor(unsigned long *dst, const unsigned long *src1,
dst[i] = src1[i] ^ src2[i];
}
static inline void
bitmap_shift_right(unsigned long *dst, const unsigned long *src,
unsigned int shift, unsigned int size)
{
const unsigned int end = BITS_TO_LONGS(size);
const unsigned int tail = size & (BITS_PER_LONG - 1);
const unsigned long mask = BITMAP_LAST_WORD_MASK(tail);
const unsigned int off = BIT_WORD(shift);
const unsigned int rem = shift & (BITS_PER_LONG - 1);
unsigned long left, right;
unsigned int i, srcpos;
for (i = 0, srcpos = off; srcpos < end; i++, srcpos++) {
right = src[srcpos];
left = 0;
if (srcpos == end - 1)
right &= mask;
if (rem != 0) {
right >>= rem;
if (srcpos + 1 < end) {
left = src[srcpos + 1];
if (srcpos + 1 == end - 1)
left &= mask;
left <<= (BITS_PER_LONG - rem);
}
}
dst[i] = left | right;
}
if (off != 0)
memset(dst + end - off, 0, off * sizeof(unsigned long));
}
static inline unsigned long *
bitmap_alloc(unsigned int size, gfp_t flags)
{