From 99167f6d66e509389c51732b763abd03a8187e56 Mon Sep 17 00:00:00 2001 From: Zach Brown Date: Wed, 27 Jul 2016 13:50:22 -0700 Subject: [PATCH] Expand little endian bitops functions We had the start of functions that operated on little endian bitmaps. This adds more operations and uses __packed to support unaligned bitmaps on platforms where unaligned accesses are a problem. Signed-off-by: Zach Brown --- utils/src/bitops.h | 64 +++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 61 insertions(+), 3 deletions(-) diff --git a/utils/src/bitops.h b/utils/src/bitops.h index 5ac429fc..abfa3755 100644 --- a/utils/src/bitops.h +++ b/utils/src/bitops.h @@ -1,6 +1,13 @@ #ifndef _BITOPS_H_ #define _BITOPS_H_ +/* + * Implement little endian bitmaps in terms of native longs. __packed + * is used to avoid unaligned accesses. + */ + +typedef unsigned long * __packed ulong_ptr; + #define BITS_PER_LONG (sizeof(long) * 8) #if __BYTE_ORDER == __LITTLE_ENDIAN #define BITOP_LE_SWIZZLE 0 @@ -8,13 +15,64 @@ #define BITOP_LE_SWIZZLE ((BITS_PER_LONG-1) & ~0x7) #endif -static inline void set_bit_le(int nr, void *addr) +static inline ulong_ptr nr_word(int nr, ulong_ptr longs) { - unsigned long *longs = addr; + return &longs[nr / BITS_PER_LONG]; +} + +static inline unsigned long nr_mask(int nr) +{ + return 1UL << (nr % BITS_PER_LONG); +} + +static inline int test_bit(int nr, ulong_ptr longs) +{ + return !!(*nr_word(nr, longs) & nr_mask(nr)); +} + +static inline void set_bit(int nr, ulong_ptr longs) +{ + *nr_word(nr, longs) |= nr_mask(nr); +} + +static inline void clear_bit(int nr, ulong_ptr longs) +{ + *nr_word(nr, longs) &= ~nr_mask(nr); +} + +static inline int test_bit_le(int nr, void *addr) +{ + return test_bit(nr ^ BITOP_LE_SWIZZLE, addr); +} + +static inline int test_and_set_bit_le(int nr, void *addr) +{ + int ret; nr ^= BITOP_LE_SWIZZLE; + ret = test_bit(nr, addr); + set_bit(nr, addr); + return ret; +} - longs[nr / BITS_PER_LONG] |= 1UL << (nr & (BITS_PER_LONG - 1)); +static inline void set_bit_le(int nr, void *addr) +{ + set_bit(nr ^ BITOP_LE_SWIZZLE, addr); +} + +static inline void clear_bit_le(int nr, void *addr) +{ + clear_bit(nr ^ BITOP_LE_SWIZZLE, addr); +} + +static inline int test_and_clear_bit_le(int nr, void *addr) +{ + int ret; + + nr ^= BITOP_LE_SWIZZLE; + ret = test_bit(nr, addr); + clear_bit(nr, addr); + return ret; } #endif