diff options
Diffstat (limited to 'ubifs-utils/common')
| -rw-r--r-- | ubifs-utils/common/bitops.c | 37 | ||||
| -rw-r--r-- | ubifs-utils/common/bitops.h | 152 | ||||
| -rw-r--r-- | ubifs-utils/common/defs.h | 36 | ||||
| -rw-r--r-- | ubifs-utils/common/lpt.c | 1 | 
4 files changed, 190 insertions, 36 deletions
| diff --git a/ubifs-utils/common/bitops.c b/ubifs-utils/common/bitops.c new file mode 100644 index 0000000..c82f1fa --- /dev/null +++ b/ubifs-utils/common/bitops.c @@ -0,0 +1,37 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Realizations of bit operations. + */ + +#include "bitops.h" +#include "defs.h" + +/* + * This is a common helper function for find_next_bit and + * find_next_zero_bit.  The difference is the "invert" argument, which + * is XORed with each fetched word before searching it for one bits. + */ +unsigned long _find_next_bit(const unsigned long *addr, +		unsigned long nbits, unsigned long start, unsigned long invert) +{ +	unsigned long tmp; + +	if (!nbits || start >= nbits) +		return nbits; + +	tmp = addr[start / BITS_PER_LONG] ^ invert; + +	/* Handle 1st word. */ +	tmp &= BITMAP_FIRST_WORD_MASK(start); +	start = round_down(start, BITS_PER_LONG); + +	while (!tmp) { +		start += BITS_PER_LONG; +		if (start >= nbits) +			return nbits; + +		tmp = addr[start / BITS_PER_LONG] ^ invert; +	} + +	return min(start + __ffs(tmp), nbits); +} diff --git a/ubifs-utils/common/bitops.h b/ubifs-utils/common/bitops.h new file mode 100644 index 0000000..3a2d3f8 --- /dev/null +++ b/ubifs-utils/common/bitops.h @@ -0,0 +1,152 @@ +#ifndef __BITOPS_H__ +#define __BITOPS_H__ + +/* + * Non-atomic bitops. + */ + +#include <stdbool.h> + +#define BITS_PER_LONG			__LONG_WIDTH__ +#define DIV_ROUND_UP(n, d)		(((n) + (d) - 1) / (d)) +#define BITS_TO_LONGS(nr)		DIV_ROUND_UP(nr, BITS_PER_LONG) + +#define BIT_MASK(nr)			(1UL << ((nr) % BITS_PER_LONG)) +#define BIT_WORD(nr)			((nr) / BITS_PER_LONG) +#define BITMAP_FIRST_WORD_MASK(start)	(~0UL << ((start) & (BITS_PER_LONG - 1))) + +static inline void __set_bit(int nr, volatile unsigned long *addr) +{ +	unsigned long mask = BIT_MASK(nr); +	unsigned long *p = ((unsigned long *)addr) + BIT_WORD(nr); + +	*p  |= mask; +} + +static inline void set_bit(int nr, volatile unsigned long *addr) +{ +	__set_bit(nr, addr); +} + +static inline void __clear_bit(int nr, volatile unsigned long *addr) +{ +	unsigned long mask = BIT_MASK(nr); +	unsigned long *p = ((unsigned long *)addr) + BIT_WORD(nr); + +	*p &= ~mask; +} + +static inline void clear_bit(int nr, volatile unsigned long *addr) +{ +	__clear_bit(nr, addr); +} + +static inline bool test_bit(int nr, const volatile unsigned long *addr) +{ +	unsigned long mask = BIT_MASK(nr); +	unsigned long *p = ((unsigned long *)addr) + BIT_WORD(nr); + +	return (*p & mask) != 0; +} + +/* Sets and returns original value of the bit */ +static inline int test_and_set_bit(int nr, volatile unsigned long *addr) +{ +	if (test_bit(nr, addr)) +		return 1; +	set_bit(nr, addr); +	return 0; +} + +/** + * fls - find last (most-significant) bit set + * @x: the word to search + * + * This is defined the same way as ffs. + * Note fls(0) = 0, fls(1) = 1, fls(0x80000000) = 32. + */ +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; +} + +/** + * __ffs - find first bit in word. + * @word: The word to search + * + * Undefined if no bit exists, so code should check against 0 first. + */ +static inline unsigned long __ffs(unsigned long word) +{ +	int num = 0; + +#if BITS_PER_LONG == 64 +	if ((word & 0xffffffff) == 0) { +		num += 32; +		word >>= 32; +	} +#endif +	if ((word & 0xffff) == 0) { +		num += 16; +		word >>= 16; +	} +	if ((word & 0xff) == 0) { +		num += 8; +		word >>= 8; +	} +	if ((word & 0xf) == 0) { +		num += 4; +		word >>= 4; +	} +	if ((word & 0x3) == 0) { +		num += 2; +		word >>= 2; +	} +	if ((word & 0x1) == 0) +		num += 1; +	return num; +} + +unsigned long _find_next_bit(const unsigned long *addr, +		unsigned long nbits, unsigned long start, unsigned long invert); + +/* + * Find the next set bit in a memory region. + */ +static inline unsigned long find_next_bit(const unsigned long *addr, +			unsigned long size, unsigned long offset) +{ +	return _find_next_bit(addr, size, offset, 0UL); +} + +static inline unsigned long find_next_zero_bit(const unsigned long *addr, +			unsigned long size, unsigned long offset) +{ +	return _find_next_bit(addr, size, offset, ~0UL); +} + +#endif diff --git a/ubifs-utils/common/defs.h b/ubifs-utils/common/defs.h index dd3b806..485c50c 100644 --- a/ubifs-utils/common/defs.h +++ b/ubifs-utils/common/defs.h @@ -28,42 +28,6 @@ enum { MKFS_PROGRAM_TYPE = 0 };  #define unlikely(x) (x) -/** - * fls - find last (most-significant) bit set - * @x: the word to search - * - * This is defined the same way as ffs. - * Note fls(0) = 0, fls(1) = 1, fls(0x80000000) = 32. - */ -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; -} -  #define do_div(n,base) ({ \  int __res; \  __res = ((unsigned long) n) % (unsigned) base; \ diff --git a/ubifs-utils/common/lpt.c b/ubifs-utils/common/lpt.c index d07f569..3c55f91 100644 --- a/ubifs-utils/common/lpt.c +++ b/ubifs-utils/common/lpt.c @@ -25,6 +25,7 @@  #endif  #include "lpt.h" +#include "bitops.h"  #include "defs.h"  #include "ubifs.h"  #include "crc16.h" | 
