/** * __bitmap_shift_right - logical right shift of the bits in a bitmap * @dst : destination bitmap * @src : source bitmap * @shift : shift by this many bits * @nbits : bitmap size, in bits * * Shifting right (dividing) means moving bits in the MS -> LS bit * direction. Zeros are fed into the vacated MS positions and the * LS bits shifted off the bottom are lost. */ void __bitmap_shift_right(unsigned long *dst, const unsigned long *src, unsigned shift, unsigned nbits) { unsigned k, lim = BITS_TO_LONGS(nbits); unsigned off = shift/BITS_PER_LONG, rem = shift % BITS_PER_LONG; unsigned long mask = BITMAP_LAST_WORD_MASK(nbits); for (k = 0; off + k < lim; ++k) { unsigned long upper, lower; /* * If shift is not word aligned, take lower rem bits of * word above and make them the top rem bits of result. */ if (!rem || off + k + 1 >= lim) upper = 0; else { upper = src[off + k + 1]; if (off + k + 1 == lim - 1) upper &= mask; upper <<= (BITS_PER_LONG - rem); } lower = src[off + k]; if (off + k == lim - 1) lower &= mask; lower >>= rem; dst[k] = lower | upper; } if (off) memset(&dst[lim - off], 0, off*sizeof(unsigned long)); }
int bitmap_full(const unsigned long *src, unsigned int nbits) { if (small_const_nbits(nbits)) return ! (~(*src) & BITMAP_LAST_WORD_MASK(nbits)); return find_next_zero_bit(src, nbits, 0UL) == nbits; }
int __bitmap_weight(const unsigned long *bitmap, int bits) { int k, w = 0, lim = bits/BITS_PER_LONG; for (k = 0; k < lim; k++) w += hweight_long(bitmap[k]); if (bits % BITS_PER_LONG) w += hweight_long(bitmap[k] & BITMAP_LAST_WORD_MASK(bits)); return w; }
void slow_bitmap_complement(unsigned long *dst, const unsigned long *src, long bits) { long k, lim = bits/BITS_PER_LONG; for (k = 0; k < lim; ++k) { dst[k] = ~src[k]; } if (bits % BITS_PER_LONG) { dst[k] = ~src[k] & BITMAP_LAST_WORD_MASK(bits); } }
int __bitmap_equal(const unsigned long *bitmap1, const unsigned long *bitmap2, unsigned int bits) { unsigned int k, lim = bits/BITS_PER_LONG; for (k = 0; k < lim; ++k) if (bitmap1[k] != bitmap2[k]) return 0; if (bits % BITS_PER_LONG) if ((bitmap1[k] ^ bitmap2[k]) & BITMAP_LAST_WORD_MASK(bits)) return 0; return 1; }
unsigned long find_last_bit(const unsigned long *addr, unsigned long size) { if (size) { unsigned long val = BITMAP_LAST_WORD_MASK(size); unsigned long idx = (size-1) / BITS_PER_LONG; do { val &= addr[idx]; if (val) return idx * BITS_PER_LONG + __fls(val); val = ~0ul; } while (idx--); } return size; }
int slow_bitmap_empty(const unsigned long *bitmap, long bits) { long k, lim = bits/BITS_PER_LONG; for (k = 0; k < lim; ++k) { if (bitmap[k]) { return 0; } } if (bits % BITS_PER_LONG) { if (bitmap[k] & BITMAP_LAST_WORD_MASK(bits)) { return 0; } } return 1; }
int slow_bitmap_intersects(const unsigned long *bitmap1, const unsigned long *bitmap2, long bits) { long k, lim = bits/BITS_PER_LONG; for (k = 0; k < lim; ++k) { if (bitmap1[k] & bitmap2[k]) { return 1; } } if (bits % BITS_PER_LONG) { if ((bitmap1[k] & bitmap2[k]) & BITMAP_LAST_WORD_MASK(bits)) { return 1; } } return 0; }
bool bitmap_test_and_clear_atomic(unsigned long *map, long start, long nr) { unsigned long *p = map + BIT_WORD(start); const long size = start + nr; int bits_to_clear = BITS_PER_LONG - (start % BITS_PER_LONG); unsigned long mask_to_clear = BITMAP_FIRST_WORD_MASK(start); unsigned long dirty = 0; unsigned long old_bits; /* First word */ if (nr - bits_to_clear > 0) { old_bits = atomic_fetch_and(p, ~mask_to_clear); dirty |= old_bits & mask_to_clear; nr -= bits_to_clear; bits_to_clear = BITS_PER_LONG; mask_to_clear = ~0UL; p++; } /* Full words */ if (bits_to_clear == BITS_PER_LONG) { while (nr >= BITS_PER_LONG) { if (*p) { old_bits = atomic_xchg(p, 0); dirty |= old_bits; } nr -= BITS_PER_LONG; p++; } } /* Last word */ if (nr) { mask_to_clear &= BITMAP_LAST_WORD_MASK(size); old_bits = atomic_fetch_and(p, ~mask_to_clear); dirty |= old_bits & mask_to_clear; } else { if (!dirty) { smp_mb(); } } return dirty != 0; }
void bitmap_clear(unsigned long *map, unsigned int start, int len) { unsigned long *p = map + BIT_WORD(start); const unsigned int size = start + len; int bits_to_clear = BITS_PER_LONG - (start % BITS_PER_LONG); unsigned long mask_to_clear = BITMAP_FIRST_WORD_MASK(start); while (len - bits_to_clear >= 0) { *p &= ~mask_to_clear; len -= bits_to_clear; bits_to_clear = BITS_PER_LONG; mask_to_clear = ~0UL; p++; } if (len) { mask_to_clear &= BITMAP_LAST_WORD_MASK(size); *p &= ~mask_to_clear; } }
void bitmap_clear(unsigned long *map, long start, long nr) { unsigned long *p = map + BIT_WORD(start); const long size = start + nr; int bits_to_clear = BITS_PER_LONG - (start % BITS_PER_LONG); unsigned long mask_to_clear = BITMAP_FIRST_WORD_MASK(start); while (nr - bits_to_clear >= 0) { *p &= ~mask_to_clear; nr -= bits_to_clear; bits_to_clear = BITS_PER_LONG; mask_to_clear = ~0UL; p++; } if (nr) { mask_to_clear &= BITMAP_LAST_WORD_MASK(size); *p &= ~mask_to_clear; } }
void bitmap_set_atomic(unsigned long *map, long start, long nr) { unsigned long *p = map + BIT_WORD(start); const long size = start + nr; int bits_to_set = BITS_PER_LONG - (start % BITS_PER_LONG); unsigned long mask_to_set = BITMAP_FIRST_WORD_MASK(start); /* First word */ if (nr - bits_to_set > 0) { atomic_or(p, mask_to_set); nr -= bits_to_set; bits_to_set = BITS_PER_LONG; mask_to_set = ~0UL; p++; } /* Full words */ if (bits_to_set == BITS_PER_LONG) { while (nr >= BITS_PER_LONG) { *p = ~0UL; nr -= BITS_PER_LONG; p++; } } /* Last word */ if (nr) { mask_to_set &= BITMAP_LAST_WORD_MASK(size); atomic_or(p, mask_to_set); } else { /* If we avoided the full barrier in atomic_or(), issue a * barrier to account for the assignments in the while loop. */ smp_mb(); } }