mirror of
https://github.com/versity/scoutfs.git
synced 2026-01-09 21:27:25 +00:00
We've had these in the past and we need them again for the block allocator item bitmaps. Signed-off-by: Zach Brown <zab@versity.com>
102 lines
1.9 KiB
C
102 lines
1.9 KiB
C
#ifndef _BITOPS_H_
|
|
#define _BITOPS_H_
|
|
|
|
#include "sparse.h"
|
|
|
|
/*
|
|
* Implement little endian bitmaps in terms of native longs. __packed
|
|
* is used to avoid unaligned accesses. These are neither atomic nor
|
|
* particularly efficient.
|
|
*/
|
|
|
|
#define BITS_PER_LONG (sizeof(long) * 8)
|
|
#if __BYTE_ORDER == __LITTLE_ENDIAN
|
|
#define BITOP_LE_SWIZZLE 0
|
|
#else
|
|
#define BITOP_LE_SWIZZLE ((BITS_PER_LONG-1) & ~0x7)
|
|
#endif
|
|
|
|
static inline unsigned long get_nr_word(int nr, void *addr)
|
|
{
|
|
unsigned long *longs = addr;
|
|
unsigned long ind = nr / BITS_PER_LONG;
|
|
unsigned long val;
|
|
|
|
memcpy(&val, &longs[ind], sizeof(val));
|
|
|
|
return val;
|
|
}
|
|
|
|
static inline void put_nr_word(int nr, void *addr, unsigned long val)
|
|
{
|
|
unsigned long *longs = addr;
|
|
unsigned long ind = nr / BITS_PER_LONG;
|
|
|
|
memcpy(&longs[ind], &val, sizeof(val));
|
|
}
|
|
|
|
static inline unsigned long nr_mask(int nr)
|
|
{
|
|
return 1UL << (nr % BITS_PER_LONG);
|
|
}
|
|
|
|
static inline int test_bit(int nr, void *addr)
|
|
{
|
|
unsigned long val = get_nr_word(nr, addr);
|
|
|
|
return !!(val & nr_mask(nr));
|
|
}
|
|
|
|
static inline void set_bit(int nr, void *addr)
|
|
{
|
|
unsigned long val = get_nr_word(nr, addr);
|
|
|
|
val |= nr_mask(nr);
|
|
put_nr_word(nr, addr, val);
|
|
}
|
|
|
|
static inline void clear_bit(int nr, void *addr)
|
|
{
|
|
unsigned long val = get_nr_word(nr, addr);
|
|
|
|
val &= ~nr_mask(nr);
|
|
put_nr_word(nr, addr, val);
|
|
}
|
|
|
|
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;
|
|
}
|
|
|
|
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
|