Index: sys/kern/subr_blist.c =================================================================== --- sys/kern/subr_blist.c +++ sys/kern/subr_blist.c @@ -170,6 +170,35 @@ } /* + * Use binary search to find the 1 bit in a u_daddr_t. + * Assumes that the argument has only one bit set. ffs(x) + * could be implemented as return (x==0? 0: 1+bitpos(x&-x)). + */ +static inline int +bitpos(u_daddr_t mask) +{ + int hi, lo, mid; + + switch (sizeof(u_daddr_t)) { +#ifdef HAVE_INLINE_FFSLL + case sizeof(long long): + return (ffsll(mask) - 1); +#endif + default: + lo = 0; + hi = BLIST_BMAP_RADIX; + while (lo + 1 < hi) { + mid = (lo + hi) >> 1; + if ((mask >> mid) != 0) + lo = mid; + else + hi = mid; + } + return (lo); + } +} + +/* * blist_create() - create a blist capable of handling up to the specified * number of blocks * @@ -355,13 +384,13 @@ * * This is the core of the allocator and is optimized for the * BLIST_BMAP_RADIX block allocation case. Otherwise, execution - * time is proportional to log2(count) + log2(BLIST_BMAP_RADIX). + * time is proportional to log2(count) + bitpos time. */ static daddr_t blst_leaf_alloc(blmeta_t *scan, daddr_t blk, int count, daddr_t cursor) { u_daddr_t mask; - int count1, hi, lo, mid, num_shifts, range1, range_ext; + int count1, lo, num_shifts, range1, range_ext; if (count == BLIST_BMAP_RADIX) { /* @@ -419,17 +448,10 @@ /* * The least significant set bit in mask marks the start of the first * available range of sufficient size. Clear all the bits but that one, - * and then perform a binary search to find its position. + * and find its position. */ mask &= -mask; - hi = BLIST_BMAP_RADIX - count1; - while (lo + 1 < hi) { - mid = (lo + hi) >> 1; - if ((mask >> mid) != 0) - lo = mid; - else - hi = mid; - } + lo = bitpos(mask); /* * Set in mask exactly the bits being allocated, and clear them from