When bitpos can't be implemented with an inline ffs* instruction,

change the binary search so that it does not depend on a single bit
only being set in the bitmask. Use bitpos more generally, and avoid
some clearing of bits to accommodate its current behavior.

Approved by: kib (mentor)
Differential Revision: https://reviews.freebsd.org/D20237
This commit is contained in:
dougm 2019-05-11 09:09:10 +00:00
parent e2f91fb83d
commit 0ecc670646

View File

@ -192,30 +192,40 @@ bitrange(int n, int count)
/* /*
* Use binary search, or a faster method, to find the 1 bit in a u_daddr_t. * Find the first bit set in a u_daddr_t.
* Assumes that the argument has only one bit set.
*/ */
static inline int
generic_bitpos(u_daddr_t mask)
{
int hi, lo, mid;
lo = 0;
hi = BLIST_BMAP_RADIX;
while (lo + 1 < hi) {
mid = (lo + hi) >> 1;
if (mask & bitrange(0, mid))
hi = mid;
else
lo = mid;
}
return (lo);
}
static inline int static inline int
bitpos(u_daddr_t mask) bitpos(u_daddr_t mask)
{ {
int hi, lo, mid;
switch (sizeof(mask)) { switch (sizeof(mask)) {
#ifdef HAVE_INLINE_FFSLL #ifdef HAVE_INLINE_FFSLL
case sizeof(long long): case sizeof(long long):
return (ffsll(mask) - 1); return (ffsll(mask) - 1);
#endif
#ifdef HAVE_INLINE_FFS
case sizeof(int):
return (ffs(mask) - 1);
#endif #endif
default: default:
lo = 0; return (generic_bitpos(mask));
hi = BLIST_BMAP_RADIX;
while (lo + 1 < hi) {
mid = (lo + hi) >> 1;
if ((mask >> mid) != 0)
lo = mid;
else
hi = mid;
}
return (lo);
} }
} }
@ -532,7 +542,8 @@ blist_stats(blist_t bl, struct sbuf *s)
struct gap_stats gstats; struct gap_stats gstats;
struct gap_stats *stats = &gstats; struct gap_stats *stats = &gstats;
daddr_t i, nodes, radix; daddr_t i, nodes, radix;
u_daddr_t bit, diff, mask; u_daddr_t diff, mask;
int digit;
init_gap_stats(stats); init_gap_stats(stats);
nodes = 0; nodes = 0;
@ -570,9 +581,9 @@ blist_stats(blist_t bl, struct sbuf *s)
if (gap_stats_counting(stats)) if (gap_stats_counting(stats))
diff ^= 1; diff ^= 1;
while (diff != 0) { while (diff != 0) {
bit = diff & -diff; digit = bitpos(diff);
update_gap_stats(stats, i + bitpos(bit)); update_gap_stats(stats, i + digit);
diff ^= bit; diff ^= bitrange(digit, 1);
} }
} }
nodes += radix_to_skip(radix); nodes += radix_to_skip(radix);
@ -776,7 +787,7 @@ static daddr_t
blst_meta_alloc(blmeta_t *scan, daddr_t cursor, daddr_t count, u_daddr_t radix) blst_meta_alloc(blmeta_t *scan, daddr_t cursor, daddr_t count, u_daddr_t radix)
{ {
daddr_t blk, i, r, skip; daddr_t blk, i, r, skip;
u_daddr_t bit, mask; u_daddr_t mask;
bool scan_from_start; bool scan_from_start;
int digit; int digit;
@ -808,8 +819,7 @@ blst_meta_alloc(blmeta_t *scan, daddr_t cursor, daddr_t count, u_daddr_t radix)
* Examine the nonempty subtree associated with each bit set in mask. * Examine the nonempty subtree associated with each bit set in mask.
*/ */
do { do {
bit = mask & -mask; digit = bitpos(mask);
digit = bitpos(bit);
i = 1 + digit * skip; i = 1 + digit * skip;
if (count <= scan[i].bm_bighint) { if (count <= scan[i].bm_bighint) {
/* /*
@ -819,12 +829,12 @@ blst_meta_alloc(blmeta_t *scan, daddr_t cursor, daddr_t count, u_daddr_t radix)
count, radix); count, radix);
if (r != SWAPBLK_NONE) { if (r != SWAPBLK_NONE) {
if (scan[i].bm_bitmap == 0) if (scan[i].bm_bitmap == 0)
scan->bm_bitmap ^= bit; scan->bm_bitmap ^= bitrange(digit, 1);
return (r); return (r);
} }
} }
cursor = blk; cursor = blk;
} while ((mask ^= bit) != 0); } while ((mask ^= bitrange(digit, 1)) != 0);
/* /*
* We couldn't allocate count in this subtree. If the whole tree was * We couldn't allocate count in this subtree. If the whole tree was
@ -1019,7 +1029,7 @@ static void
blst_radix_print(blmeta_t *scan, daddr_t blk, daddr_t radix, int tab) blst_radix_print(blmeta_t *scan, daddr_t blk, daddr_t radix, int tab)
{ {
daddr_t skip; daddr_t skip;
u_daddr_t bit, mask; u_daddr_t mask;
int digit; int digit;
if (radix == BLIST_BMAP_RADIX) { if (radix == BLIST_BMAP_RADIX) {
@ -1051,11 +1061,10 @@ blst_radix_print(blmeta_t *scan, daddr_t blk, daddr_t radix, int tab)
mask = scan->bm_bitmap; mask = scan->bm_bitmap;
/* Examine the nonempty subtree associated with each bit set in mask */ /* Examine the nonempty subtree associated with each bit set in mask */
do { do {
bit = mask & -mask; digit = bitpos(mask);
digit = bitpos(bit);
blst_radix_print(&scan[1 + digit * skip], blk + digit * radix, blst_radix_print(&scan[1 + digit * skip], blk + digit * radix,
radix, tab); radix, tab);
} while ((mask ^= bit) != 0); } while ((mask ^= bitrange(digit, 1)) != 0);
tab -= 4; tab -= 4;
printf( printf(