summaryrefslogtreecommitdiff
path: root/include
diff options
context:
space:
mode:
Diffstat (limited to 'include')
-rw-r--r--include/asm-arm/bitops.h184
1 files changed, 94 insertions, 90 deletions
diff --git a/include/asm-arm/bitops.h b/include/asm-arm/bitops.h
index ee813c27ba3a..569c247bc7dc 100644
--- a/include/asm-arm/bitops.h
+++ b/include/asm-arm/bitops.h
@@ -5,7 +5,7 @@
* Big endian support: Copyright 2001, Nicolas Pitre
* reworked by rmk.
*
- * bit 0 is the LSB of addr; bit 32 is the LSB of (addr+1).
+ * bit 0 is the LSB of an "unsigned long" quantity.
*
* Please note that the code in this file should never be included
* from user space. Many of these are not implemented in assembler
@@ -26,34 +26,39 @@
/*
* These functions are the basis of our bit ops.
- * First, the atomic bitops.
*
- * The endian issue for these functions is handled by the macros below.
+ * First, the atomic bitops. These use native endian.
*/
-static inline void
-____atomic_set_bit_mask(unsigned int mask, volatile unsigned char *p)
+static inline void ____atomic_set_bit(unsigned int bit, unsigned long *p)
{
unsigned long flags;
+ unsigned long mask = 1UL << (bit & 31);
+
+ p += bit >> 5;
local_irq_save(flags);
*p |= mask;
local_irq_restore(flags);
}
-static inline void
-____atomic_clear_bit_mask(unsigned int mask, volatile unsigned char *p)
+static inline void ____atomic_clear_bit(unsigned int bit, unsigned long *p)
{
unsigned long flags;
+ unsigned long mask = 1UL << (bit & 31);
+
+ p += bit >> 5;
local_irq_save(flags);
*p &= ~mask;
local_irq_restore(flags);
}
-static inline void
-____atomic_change_bit_mask(unsigned int mask, volatile unsigned char *p)
+static inline void ____atomic_change_bit(unsigned int bit, unsigned long *p)
{
unsigned long flags;
+ unsigned long mask = 1UL << (bit & 31);
+
+ p += bit >> 5;
local_irq_save(flags);
*p ^= mask;
@@ -61,10 +66,13 @@ ____atomic_change_bit_mask(unsigned int mask, volatile unsigned char *p)
}
static inline int
-____atomic_test_and_set_bit_mask(unsigned int mask, volatile unsigned char *p)
+____atomic_test_and_set_bit(unsigned int bit, unsigned long *p)
{
unsigned long flags;
unsigned int res;
+ unsigned long mask = 1UL << (bit & 31);
+
+ p += bit >> 5;
local_irq_save(flags);
res = *p;
@@ -75,10 +83,13 @@ ____atomic_test_and_set_bit_mask(unsigned int mask, volatile unsigned char *p)
}
static inline int
-____atomic_test_and_clear_bit_mask(unsigned int mask, volatile unsigned char *p)
+____atomic_test_and_clear_bit(unsigned int bit, unsigned long *p)
{
unsigned long flags;
unsigned int res;
+ unsigned long mask = 1UL << (bit & 31);
+
+ p += bit >> 5;
local_irq_save(flags);
res = *p;
@@ -89,10 +100,13 @@ ____atomic_test_and_clear_bit_mask(unsigned int mask, volatile unsigned char *p)
}
static inline int
-____atomic_test_and_change_bit_mask(unsigned int mask, volatile unsigned char *p)
+____atomic_test_and_change_bit(unsigned int bit, unsigned long *p)
{
unsigned long flags;
unsigned int res;
+ unsigned long mask = 1UL << (bit & 31);
+
+ p += bit >> 5;
local_irq_save(flags);
res = *p;
@@ -103,61 +117,64 @@ ____atomic_test_and_change_bit_mask(unsigned int mask, volatile unsigned char *p
}
/*
- * Now the non-atomic variants. We let the compiler handle all optimisations
- * for these.
+ * Now the non-atomic variants. We let the compiler handle all
+ * optimisations for these. These are all _native_ endian.
*/
-static inline void ____nonatomic_set_bit(int nr, volatile void *p)
+static inline void __set_bit(int nr, volatile unsigned long *p)
{
- ((unsigned char *) p)[nr >> 3] |= (1U << (nr & 7));
+ p[nr >> 5] |= (1UL << (nr & 31));
}
-static inline void ____nonatomic_clear_bit(int nr, volatile void *p)
+static inline void __clear_bit(int nr, volatile unsigned long *p)
{
- ((unsigned char *) p)[nr >> 3] &= ~(1U << (nr & 7));
+ p[nr >> 5] &= ~(1UL << (nr & 31));
}
-static inline void ____nonatomic_change_bit(int nr, volatile void *p)
+static inline void __change_bit(int nr, volatile unsigned long *p)
{
- ((unsigned char *) p)[nr >> 3] ^= (1U << (nr & 7));
+ p[nr >> 5] ^= (1UL << (nr & 31));
}
-static inline int ____nonatomic_test_and_set_bit(int nr, volatile void *p)
+static inline int __test_and_set_bit(int nr, volatile unsigned long *p)
{
- unsigned int mask = 1 << (nr & 7);
- unsigned int oldval;
+ unsigned long oldval, mask = 1UL << (nr & 31);
- oldval = ((unsigned char *) p)[nr >> 3];
- ((unsigned char *) p)[nr >> 3] = oldval | mask;
+ p += nr >> 5;
+
+ oldval = *p;
+ *p = oldval | mask;
return oldval & mask;
}
-static inline int ____nonatomic_test_and_clear_bit(int nr, volatile void *p)
+static inline int __test_and_clear_bit(int nr, volatile unsigned long *p)
{
- unsigned int mask = 1 << (nr & 7);
- unsigned int oldval;
+ unsigned long oldval, mask = 1UL << (nr & 31);
+
+ p += nr >> 5;
- oldval = ((unsigned char *) p)[nr >> 3];
- ((unsigned char *) p)[nr >> 3] = oldval & ~mask;
+ oldval = *p;
+ *p = oldval & ~mask;
return oldval & mask;
}
-static inline int ____nonatomic_test_and_change_bit(int nr, volatile void *p)
+static inline int __test_and_change_bit(int nr, volatile unsigned long *p)
{
- unsigned int mask = 1 << (nr & 7);
- unsigned int oldval;
+ unsigned long oldval, mask = 1UL << (nr & 31);
- oldval = ((unsigned char *) p)[nr >> 3];
- ((unsigned char *) p)[nr >> 3] = oldval ^ mask;
+ p += nr >> 5;
+
+ oldval = *p;
+ *p = oldval ^ mask;
return oldval & mask;
}
/*
* This routine doesn't need to be atomic.
*/
-static inline int ____test_bit(int nr, const void * p)
+static inline int __test_bit(int nr, const unsigned long * p)
{
- return ((volatile unsigned char *) p)[nr >> 3] & (1U << (nr & 7));
-}
+ return p[nr >> 5] & (1UL << (nr & 31));
+}
/*
* A note about Endian-ness.
@@ -187,24 +204,24 @@ static inline int ____test_bit(int nr, const void * p)
/*
* Little endian assembly bitops. nr = 0 -> byte 0 bit 0.
*/
-extern void _set_bit_le(int nr, volatile void * p);
-extern void _clear_bit_le(int nr, volatile void * p);
-extern void _change_bit_le(int nr, volatile void * p);
-extern int _test_and_set_bit_le(int nr, volatile void * p);
-extern int _test_and_clear_bit_le(int nr, volatile void * p);
-extern int _test_and_change_bit_le(int nr, volatile void * p);
+extern void _set_bit_le(int nr, unsigned long * p);
+extern void _clear_bit_le(int nr, unsigned long * p);
+extern void _change_bit_le(int nr, unsigned long * p);
+extern int _test_and_set_bit_le(int nr, unsigned long * p);
+extern int _test_and_clear_bit_le(int nr, unsigned long * p);
+extern int _test_and_change_bit_le(int nr, unsigned long * p);
extern int _find_first_zero_bit_le(void * p, unsigned size);
extern int _find_next_zero_bit_le(void * p, int size, int offset);
/*
* Big endian assembly bitops. nr = 0 -> byte 3 bit 0.
*/
-extern void _set_bit_be(int nr, volatile void * p);
-extern void _clear_bit_be(int nr, volatile void * p);
-extern void _change_bit_be(int nr, volatile void * p);
-extern int _test_and_set_bit_be(int nr, volatile void * p);
-extern int _test_and_clear_bit_be(int nr, volatile void * p);
-extern int _test_and_change_bit_be(int nr, volatile void * p);
+extern void _set_bit_be(int nr, unsigned long * p);
+extern void _clear_bit_be(int nr, unsigned long * p);
+extern void _change_bit_be(int nr, unsigned long * p);
+extern int _test_and_set_bit_be(int nr, unsigned long * p);
+extern int _test_and_clear_bit_be(int nr, unsigned long * p);
+extern int _test_and_change_bit_be(int nr, unsigned long * p);
extern int _find_first_zero_bit_be(void * p, unsigned size);
extern int _find_next_zero_bit_be(void * p, int size, int offset);
@@ -214,22 +231,17 @@ extern int _find_next_zero_bit_be(void * p, int size, int offset);
*/
#define ATOMIC_BITOP_LE(name,nr,p) \
(__builtin_constant_p(nr) ? \
- ____atomic_##name##_mask(1 << ((nr) & 7), \
- ((unsigned char *)(p)) + ((nr) >> 3)) : \
+ ____atomic_##name(nr, p) : \
_##name##_le(nr,p))
#define ATOMIC_BITOP_BE(name,nr,p) \
(__builtin_constant_p(nr) ? \
- ____atomic_##name##_mask(1 << ((nr) & 7), \
- ((unsigned char *)(p)) + (((nr) >> 3) ^ 3)) : \
+ ____atomic_##name(nr, p) : \
_##name##_be(nr,p))
-#define NONATOMIC_BITOP_LE(name,nr,p) \
+#define NONATOMIC_BITOP(name,nr,p) \
(____nonatomic_##name(nr, p))
-#define NONATOMIC_BITOP_BE(name,nr,p) \
- (____nonatomic_##name(nr ^ 0x18, p))
-
#ifndef __ARMEB__
/*
* These are the little endian, atomic definitions.
@@ -240,20 +252,11 @@ extern int _find_next_zero_bit_be(void * p, int size, int offset);
#define test_and_set_bit(nr,p) ATOMIC_BITOP_LE(test_and_set_bit,nr,p)
#define test_and_clear_bit(nr,p) ATOMIC_BITOP_LE(test_and_clear_bit,nr,p)
#define test_and_change_bit(nr,p) ATOMIC_BITOP_LE(test_and_change_bit,nr,p)
-#define test_bit(nr,p) ____test_bit(nr,p)
+#define test_bit(nr,p) __test_bit(nr,p)
#define find_first_zero_bit(p,sz) _find_first_zero_bit_le(p,sz)
#define find_next_zero_bit(p,sz,off) _find_next_zero_bit_le(p,sz,off)
-/*
- * These are the little endian, non-atomic definitions.
- */
-#define __set_bit(nr,p) NONATOMIC_BITOP_LE(set_bit,nr,p)
-#define __clear_bit(nr,p) NONATOMIC_BITOP_LE(clear_bit,nr,p)
-#define __change_bit(nr,p) NONATOMIC_BITOP_LE(change_bit,nr,p)
-#define __test_and_set_bit(nr,p) NONATOMIC_BITOP_LE(test_and_set_bit,nr,p)
-#define __test_and_clear_bit(nr,p) NONATOMIC_BITOP_LE(test_and_clear_bit,nr,p)
-#define __test_and_change_bit(nr,p) NONATOMIC_BITOP_LE(test_and_change_bit,nr,p)
-#define __test_bit(nr,p) ____test_bit(nr,p)
+#define WORD_BITOFF_TO_LE(x) ((x))
#else
@@ -266,20 +269,11 @@ extern int _find_next_zero_bit_be(void * p, int size, int offset);
#define test_and_set_bit(nr,p) ATOMIC_BITOP_BE(test_and_set_bit,nr,p)
#define test_and_clear_bit(nr,p) ATOMIC_BITOP_BE(test_and_clear_bit,nr,p)
#define test_and_change_bit(nr,p) ATOMIC_BITOP_BE(test_and_change_bit,nr,p)
-#define test_bit(nr,p) ____test_bit((nr) ^ 0x18, p)
+#define test_bit(nr,p) __test_bit(nr,p)
#define find_first_zero_bit(p,sz) _find_first_zero_bit_be(p,sz)
#define find_next_zero_bit(p,sz,off) _find_next_zero_bit_be(p,sz,off)
-/*
- * These are the big endian, non-atomic definitions.
- */
-#define __set_bit(nr,p) NONATOMIC_BITOP_BE(set_bit,nr,p)
-#define __clear_bit(nr,p) NONATOMIC_BITOP_BE(clear_bit,nr,p)
-#define __change_bit(nr,p) NONATOMIC_BITOP_BE(change_bit,nr,p)
-#define __test_and_set_bit(nr,p) NONATOMIC_BITOP_BE(test_and_set_bit,nr,p)
-#define __test_and_clear_bit(nr,p) NONATOMIC_BITOP_BE(test_and_clear_bit,nr,p)
-#define __test_and_change_bit(nr,p) NONATOMIC_BITOP_BE(test_and_change_bit,nr,p)
-#define __test_bit(nr,p) ____test_bit((nr) ^ 0x18, p)
+#define WORD_BITOFF_TO_LE(x) ((x) ^ 0x18)
#endif
@@ -361,21 +355,31 @@ static inline int sched_find_first_bit(unsigned long *b)
* Ext2 is defined to use little-endian byte ordering.
* These do not need to be atomic.
*/
-#define ext2_set_bit(nr,p) NONATOMIC_BITOP_LE(test_and_set_bit,nr,p)
-#define ext2_clear_bit(nr,p) NONATOMIC_BITOP_LE(test_and_clear_bit,nr,p)
-#define ext2_test_bit(nr,p) __test_bit(nr,p)
-#define ext2_find_first_zero_bit(p,sz) _find_first_zero_bit_le(p,sz)
-#define ext2_find_next_zero_bit(p,sz,off) _find_next_zero_bit_le(p,sz,off)
+#define ext2_set_bit(nr,p) \
+ __test_and_set_bit(WORD_BITOFF_TO_LE(nr), (unsigned long *)(p))
+#define ext2_clear_bit(nr,p) \
+ __test_and_clear_bit(WORD_BITOFF_TO_LE(nr), (unsigned long *)(p))
+#define ext2_test_bit(nr,p) \
+ __test_bit(WORD_BITOFF_TO_LE(nr), (unsigned long *)(p))
+#define ext2_find_first_zero_bit(p,sz) \
+ _find_first_zero_bit_le(p,sz)
+#define ext2_find_next_zero_bit(p,sz,off) \
+ _find_next_zero_bit_le(p,sz,off)
/*
* Minix is defined to use little-endian byte ordering.
* These do not need to be atomic.
*/
-#define minix_set_bit(nr,p) NONATOMIC_BITOP_LE(set_bit,nr,p)
-#define minix_test_bit(nr,p) __test_bit(nr,p)
-#define minix_test_and_set_bit(nr,p) NONATOMIC_BITOP_LE(test_and_set_bit,nr,p)
-#define minix_test_and_clear_bit(nr,p) NONATOMIC_BITOP_LE(test_and_clear_bit,nr,p)
-#define minix_find_first_zero_bit(p,sz) _find_first_zero_bit_le(p,sz)
+#define minix_set_bit(nr,p) \
+ __set_bit(WORD_BITOFF_TO_LE(nr), (unsigned long *)(p))
+#define minix_test_bit(nr,p) \
+ __test_bit(WORD_BITOFF_TO_LE(nr), (unsigned long *)(p))
+#define minix_test_and_set_bit(nr,p) \
+ __test_and_set_bit(WORD_BITOFF_TO_LE(nr), (unsigned long *)(p))
+#define minix_test_and_clear_bit(nr,p) \
+ __test_and_clear_bit(WORD_BITOFF_TO_LE(nr), (unsigned long *)(p))
+#define minix_find_first_zero_bit(p,sz) \
+ _find_first_zero_bit_le(p,sz)
#endif /* __KERNEL__ */