/* Licensed under LGPLv2.1+ - see LICENSE file for details */ #include "config.h" #include #include #define BIT_ALIGN_DOWN(n) ((n) & ~(BITMAP_WORD_BITS - 1)) #define BIT_ALIGN_UP(n) BIT_ALIGN_DOWN((n) + BITMAP_WORD_BITS - 1) void bitmap_zero_range(bitmap *bmap, unsigned long n, unsigned long m) { unsigned long an = BIT_ALIGN_UP(n); unsigned long am = BIT_ALIGN_DOWN(m); bitmap_word headmask = -1ULL >> (n % BITMAP_WORD_BITS); bitmap_word tailmask = ~(-1ULL >> (m % BITMAP_WORD_BITS)); assert(m >= n); if (am < an) { BITMAP_WORD(bmap, n) &= ~bitmap_bswap(headmask & tailmask); return; } if (an > n) BITMAP_WORD(bmap, n) &= ~bitmap_bswap(headmask); if (am > an) memset(&BITMAP_WORD(bmap, an), 0, (am - an) / BITMAP_WORD_BITS * sizeof(bitmap_word)); if (m > am) BITMAP_WORD(bmap, m) &= ~bitmap_bswap(tailmask); } void bitmap_fill_range(bitmap *bmap, unsigned long n, unsigned long m) { unsigned long an = BIT_ALIGN_UP(n); unsigned long am = BIT_ALIGN_DOWN(m); bitmap_word headmask = -1ULL >> (n % BITMAP_WORD_BITS); bitmap_word tailmask = ~(-1ULL >> (m % BITMAP_WORD_BITS)); assert(m >= n); if (am < an) { BITMAP_WORD(bmap, n) |= bitmap_bswap(headmask & tailmask); return; } if (an > n) BITMAP_WORD(bmap, n) |= bitmap_bswap(headmask); if (am > an) memset(&BITMAP_WORD(bmap, an), 0xff, (am - an) / BITMAP_WORD_BITS * sizeof(bitmap_word)); if (m > am) BITMAP_WORD(bmap, m) |= bitmap_bswap(tailmask); } static int bitmap_clz(bitmap_word w) { #if HAVE_BUILTIN_CLZL return __builtin_clzl(w); #else int lz = 0; bitmap_word mask = 1UL << (BITMAP_WORD_BITS - 1); while (!(w & mask)) { lz++; mask >>= 1; } return lz; #endif } unsigned long bitmap_ffs(const bitmap *bmap, unsigned long n, unsigned long m) { unsigned long an = BIT_ALIGN_UP(n); unsigned long am = BIT_ALIGN_DOWN(m); bitmap_word headmask = -1ULL >> (n % BITMAP_WORD_BITS); bitmap_word tailmask = ~(-1ULL >> (m % BITMAP_WORD_BITS)); assert(m >= n); if (am < an) { bitmap_word w = bitmap_bswap(BITMAP_WORD(bmap, n)); w &= (headmask & tailmask); return w ? am + bitmap_clz(w) : m; } if (an > n) { bitmap_word w = bitmap_bswap(BITMAP_WORD(bmap, n)); w &= headmask; if (w) return BIT_ALIGN_DOWN(n) + bitmap_clz(w); } while (an < am) { bitmap_word w = bitmap_bswap(BITMAP_WORD(bmap, an)); if (w) return an + bitmap_clz(w); an += BITMAP_WORD_BITS; } if (m > am) { bitmap_word w = bitmap_bswap(BITMAP_WORD(bmap, m)); w &= tailmask; if (w) return am + bitmap_clz(w); } return m; }