diff options
author | Jaegeuk Kim <jaegeuk@kernel.org> | 2015-12-09 11:44:31 -0800 |
---|---|---|
committer | Greg Wallace <greg@gregtwallace.com> | 2016-01-19 22:02:20 -0500 |
commit | 3de0318a9a156f7b720a6b704c835b0c46240cc2 (patch) | |
tree | ea759307e3254d539fe992bf6e10eef5a02fd417 /lib | |
parent | 4cf9c57c6b52aabb38bde9f9c77652064c6937f1 (diff) | |
download | android_external_f2fs-tools-3de0318a9a156f7b720a6b704c835b0c46240cc2.tar.gz android_external_f2fs-tools-3de0318a9a156f7b720a6b704c835b0c46240cc2.tar.bz2 android_external_f2fs-tools-3de0318a9a156f7b720a6b704c835b0c46240cc2.zip |
libf2fs: enhance the bit operations
This patch modifies the existing bit operations.
Change-Id: Ib6c9ba77d5426b31ee31e0d811d45a85ac89cc57
Signed-off-by: Jaegeuk Kim <jaegeuk@kernel.org>
Diffstat (limited to 'lib')
-rw-r--r-- | lib/libf2fs.c | 104 |
1 files changed, 46 insertions, 58 deletions
diff --git a/lib/libf2fs.c b/lib/libf2fs.c index 8e10e6a..e80cae0 100644 --- a/lib/libf2fs.c +++ b/lib/libf2fs.c @@ -77,10 +77,10 @@ int get_bits_in_byte(unsigned char n) return bits_in_byte[n]; } -int set_bit(unsigned int nr,void * addr) +int set_bit(unsigned int nr, void *addr) { - int mask, retval; - unsigned char *ADDR = (unsigned char *) addr; + int mask, retval; + unsigned char *ADDR = (unsigned char *)addr; ADDR += nr >> 3; mask = 1 << ((nr & 0x07)); @@ -89,10 +89,10 @@ int set_bit(unsigned int nr,void * addr) return retval; } -int clear_bit(unsigned int nr, void * addr) +int clear_bit(unsigned int nr, void *addr) { - int mask, retval; - unsigned char *ADDR = (unsigned char *) addr; + int mask, retval; + unsigned char *ADDR = (unsigned char *)addr; ADDR += nr >> 3; mask = 1 << ((nr & 0x07)); @@ -101,7 +101,7 @@ int clear_bit(unsigned int nr, void * addr) return retval; } -int test_bit(unsigned int nr, const void * addr) +int test_bit(unsigned int nr, const void *addr) { const __u32 *p = (const __u32 *)addr; @@ -144,24 +144,10 @@ int f2fs_clear_bit(unsigned int nr, char *addr) return ret; } -static inline unsigned long __ffs(unsigned long word) +static inline unsigned long __ffs(unsigned char 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; @@ -175,43 +161,45 @@ static inline unsigned long __ffs(unsigned long word) return num; } -unsigned long find_next_bit(const unsigned long *addr, unsigned long size, - unsigned long offset) +/* Copied from linux/lib/find_bit.c */ +#define BITMAP_FIRST_BYTE_MASK(start) (0xff << ((start) & (BITS_PER_BYTE - 1))) + +static unsigned long _find_next_bit_le(const unsigned char *addr, + unsigned long nbits, unsigned long start, char invert) +{ + unsigned char tmp; + + if (!nbits || start >= nbits) + return nbits; + + tmp = addr[start / BITS_PER_BYTE] ^ invert; + + /* Handle 1st word. */ + tmp &= BITMAP_FIRST_BYTE_MASK(start); + start = round_down(start, BITS_PER_BYTE); + + while (!tmp) { + start += BITS_PER_BYTE; + if (start >= nbits) + return nbits; + + tmp = addr[start / BITS_PER_BYTE] ^ invert; + } + + return min(start + __ffs(tmp), nbits); +} + +unsigned long find_next_bit_le(const unsigned char *addr, unsigned long size, + unsigned long offset) +{ + return _find_next_bit_le(addr, size, offset, 0); +} + + +unsigned long find_next_zero_bit_le(const unsigned char *addr, + unsigned long size, unsigned long offset) { - const unsigned long *p = addr + BIT_WORD(offset); - unsigned long result = offset & ~(BITS_PER_LONG-1); - unsigned long tmp; - - if (offset >= size) - return size; - size -= result; - offset %= BITS_PER_LONG; - if (offset) { - tmp = *(p++); - tmp &= (~0UL << offset); - if (size < BITS_PER_LONG) - goto found_first; - if (tmp) - goto found_middle; - size -= BITS_PER_LONG; - result += BITS_PER_LONG; - } - while (size & ~(BITS_PER_LONG-1)) { - if ((tmp = *(p++))) - goto found_middle; - result += BITS_PER_LONG; - size -= BITS_PER_LONG; - } - if (!size) - return result; - tmp = *p; - -found_first: - tmp &= (~0UL >> (BITS_PER_LONG - size)); - if (tmp == 0UL) /* Are any bits set? */ - return result + size; /* Nope. */ -found_middle: - return result + __ffs(tmp); + return _find_next_bit_le(addr, size, offset, 0xff); } /* |