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:
parent
e2f91fb83d
commit
0ecc670646
@ -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(
|
||||||
|
Loading…
Reference in New Issue
Block a user