aboutsummaryrefslogtreecommitdiffstats
path: root/include
diff options
context:
space:
mode:
authorPaul Mackerras <paulus@samba.org>2004-08-22 22:34:28 -0700
committerLinus Torvalds <torvalds@ppc970.osdl.org>2004-08-22 22:34:28 -0700
commitec2a9baf62f237095013746da04580c5862e9087 (patch)
tree43f8b5ff2cef35b334b357ba4ad441c875ffa5fb /include
parente7af93879431242b5b49e48eff20d6734b80a6b7 (diff)
downloadhistory-ec2a9baf62f237095013746da04580c5862e9087.tar.gz
[PATCH] ppc64: better little-endian bitops
Below patch reuses the big-endian bitops for the little endian ones, and moves the ext2_{set,clear}_bit_atomic functions to be truly atomic instead of lock based. This requires that the bitmaps passed to the ext2_* bitop functions are 8-byte aligned. I have been assured that they will be 512-byte or 1024-byte aligned, and sparc and ppc32 also impose an alignment requirement on the bitmap. Signed-off-by: Olof Johansson <olof@austin.ibm.com> Signed-off-by: Paul Mackerras <paulus@samba.org> Signed-off-by: Andrew Morton <akpm@osdl.org> Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Diffstat (limited to 'include')
-rw-r--r--include/asm-ppc64/bitops.h88
1 files changed, 30 insertions, 58 deletions
diff --git a/include/asm-ppc64/bitops.h b/include/asm-ppc64/bitops.h
index 6d820e7ea7724b..a0f831224f96d1 100644
--- a/include/asm-ppc64/bitops.h
+++ b/include/asm-ppc64/bitops.h
@@ -22,6 +22,15 @@
* it will be a bad memory reference since we want to store in chunks
* of unsigned long (64 bits here) size.
*
+ * There are a few little-endian macros used mostly for filesystem bitmaps,
+ * these work on similar bit arrays layouts, but byte-oriented:
+ *
+ * |7...0|15...8|23...16|31...24|39...32|47...40|55...48|63...56|
+ *
+ * The main difference is that bit 3-5 in the bit number field needs to be
+ * reversed compared to the big-endian bit fields. This can be achieved
+ * by XOR with 0b111000 (0x38).
+ *
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version
@@ -306,71 +315,34 @@ static __inline__ int test_le_bit(unsigned long nr, __const__ unsigned long * ad
return (ADDR[nr >> 3] >> (nr & 7)) & 1;
}
+#define test_and_clear_le_bit(nr, addr) \
+ test_and_clear_bit((nr) ^ 0x38, (addr))
+#define test_and_set_le_bit(nr, addr) \
+ test_and_set_bit((nr) ^ 0x38, (addr))
+
/*
* non-atomic versions
*/
-static __inline__ void __set_le_bit(unsigned long nr, unsigned long *addr)
-{
- unsigned char *ADDR = (unsigned char *)addr;
-
- ADDR += nr >> 3;
- *ADDR |= 1 << (nr & 0x07);
-}
-
-static __inline__ void __clear_le_bit(unsigned long nr, unsigned long *addr)
-{
- unsigned char *ADDR = (unsigned char *)addr;
- ADDR += nr >> 3;
- *ADDR &= ~(1 << (nr & 0x07));
-}
-
-static __inline__ int __test_and_set_le_bit(unsigned long nr, unsigned long *addr)
-{
- int mask, retval;
- unsigned char *ADDR = (unsigned char *)addr;
-
- ADDR += nr >> 3;
- mask = 1 << (nr & 0x07);
- retval = (mask & *ADDR) != 0;
- *ADDR |= mask;
- return retval;
-}
-
-static __inline__ int __test_and_clear_le_bit(unsigned long nr, unsigned long *addr)
-{
- int mask, retval;
- unsigned char *ADDR = (unsigned char *)addr;
-
- ADDR += nr >> 3;
- mask = 1 << (nr & 0x07);
- retval = (mask & *ADDR) != 0;
- *ADDR &= ~mask;
- return retval;
-}
+#define __set_le_bit(nr, addr) \
+ __set_bit((nr) ^ 0x38, (addr))
+#define __clear_le_bit(nr, addr) \
+ __clear_bit((nr) ^ 0x38, (addr))
+#define __test_and_clear_le_bit(nr, addr) \
+ __test_and_clear_bit((nr) ^ 0x38, (addr))
+#define __test_and_set_le_bit(nr, addr) \
+ __test_and_set_bit((nr) ^ 0x38, (addr))
#define ext2_set_bit(nr,addr) \
- __test_and_set_le_bit((nr),(unsigned long*)addr)
+ __test_and_set_le_bit((nr), (unsigned long*)addr)
#define ext2_clear_bit(nr, addr) \
- __test_and_clear_le_bit((nr),(unsigned long*)addr)
-
-#define ext2_set_bit_atomic(lock, nr, addr) \
- ({ \
- int ret; \
- spin_lock(lock); \
- ret = ext2_set_bit((nr), (addr)); \
- spin_unlock(lock); \
- ret; \
- })
-
-#define ext2_clear_bit_atomic(lock, nr, addr) \
- ({ \
- int ret; \
- spin_lock(lock); \
- ret = ext2_clear_bit((nr), (addr)); \
- spin_unlock(lock); \
- ret; \
- })
+ __test_and_clear_le_bit((nr), (unsigned long*)addr)
+
+#define ext2_set_bit_atomic(lock, nr, addr) \
+ test_and_set_le_bit((nr), (unsigned long*)addr)
+#define ext2_clear_bit_atomic(lock, nr, addr) \
+ test_and_clear_le_bit((nr), (unsigned long*)addr)
+
#define ext2_test_bit(nr, addr) test_le_bit((nr),(unsigned long*)addr)
#define ext2_find_first_zero_bit(addr, size) \