]> git.hungrycats.org Git - linux/commitdiff
[PATCH] ppc64: better little-endian bitops
authorPaul Mackerras <paulus@samba.org>
Mon, 23 Aug 2004 05:34:28 +0000 (22:34 -0700)
committerLinus Torvalds <torvalds@ppc970.osdl.org>
Mon, 23 Aug 2004 05:34:28 +0000 (22:34 -0700)
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>
include/asm-ppc64/bitops.h

index 6d820e7ea7724b474f397d3923e9579ca2c9f5e1..a0f831224f96d176336e19ab26e1094891e7aee5 100644 (file)
  * 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) \