diff options
Diffstat (limited to 'contrib/timer-wheel/find_last_bit.c')
| -rw-r--r-- | contrib/timer-wheel/find_last_bit.c | 82 | 
1 files changed, 82 insertions, 0 deletions
diff --git a/contrib/timer-wheel/find_last_bit.c b/contrib/timer-wheel/find_last_bit.c new file mode 100644 index 00000000000..054e90a076f --- /dev/null +++ b/contrib/timer-wheel/find_last_bit.c @@ -0,0 +1,82 @@ +/* +  This program is free software; you can redistribute it and/or modify +  it under the terms of the GNU General Public License as published by +  the Free Software Foundation; either version 2 of the License, or +  (at your option) any later version. + +  This program is distributed in the hope that it will be useful, +  but WITHOUT ANY WARRANTY; without even the implied warranty of +  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the +  GNU General Public License for more details. + +  You should have received a copy of the GNU General Public License along +  with this program; if not, write to the Free Software Foundation, Inc., +  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +*/ + +/** + * @find_last_bit + * optimized implementation of find last bit in + */ + +#ifndef BITS_PER_LONG +#define BITS_PER_LONG 64 +#endif + +static inline int fls(int x) +{ +	int r = 32; + +	if (!x) +		return 0; +	if (!(x & 0xffff0000u)) { +		x <<= 16; +		r -= 16; +	} +	if (!(x & 0xff000000u)) { +		x <<= 8; +		r -= 8; +	} +	if (!(x & 0xf0000000u)) { +		x <<= 4; +		r -= 4; +	} +	if (!(x & 0xc0000000u)) { +		x <<= 2; +		r -= 2; +	} +	if (!(x & 0x80000000u)) { +		x <<= 1; +		r -= 1; +	} +	return r; +} + + +unsigned long gf_tw_find_last_bit(const unsigned long *addr, unsigned long size) +{ +	unsigned long words; +	unsigned long tmp; + +	/* Start at final word. */ +	words = size / BITS_PER_LONG; + +	/* Partial final word? */ +	if (size & (BITS_PER_LONG-1)) { +		tmp = (addr[words] & (~0UL >> (BITS_PER_LONG +					 - (size & (BITS_PER_LONG-1))))); +		if (tmp) +			goto found; +	} + +	while (words) { +		tmp = addr[--words]; +		if (tmp) { +found: +			return words * BITS_PER_LONG + fls(tmp); +		} +	} + +	/* Not found */ +	return size; +}  | 
