[PATCH] ARM SMP: Add ARMv6 memory barriers
authorRussell King <rmk@dyn-67.arm.linux.org.uk>
Tue, 26 Jul 2005 18:44:26 +0000 (19:44 +0100)
committerRussell King <rmk+kernel@arm.linux.org.uk>
Tue, 26 Jul 2005 18:44:26 +0000 (19:44 +0100)
Convert explicit gcc asm-based memory barriers into smp_mb() calls.
These change between barrier() and the ARMv6 data memory barrier
instruction depending on whether ARMv6 SMP is enabled.

Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
include/asm-arm/bitops.h
include/asm-arm/locks.h
include/asm-arm/spinlock.h
include/asm-arm/system.h

index 4edd4dc40c5bcf991bb9cce6556f98b8de7b4afc..c1adc6b3e86d012139723b8d24e45e3ce720dcbe 100644 (file)
@@ -21,8 +21,8 @@
 
 #include <asm/system.h>
 
-#define smp_mb__before_clear_bit()     do { } while (0)
-#define smp_mb__after_clear_bit()      do { } while (0)
+#define smp_mb__before_clear_bit()     mb()
+#define smp_mb__after_clear_bit()      mb()
 
 /*
  * These functions are the basis of our bit ops.
index 9cb33fcc06c15e193086452b95c532085d52134e..f08dc844791301f91871506a1c2c50d1a0f27e03 100644 (file)
@@ -28,7 +28,8 @@
 "      blmi    " #fail                         \
        :                                       \
        : "r" (ptr), "I" (1)                    \
-       : "ip", "lr", "cc", "memory");          \
+       : "ip", "lr", "cc");                    \
+       smp_mb();                               \
        })
 
 #define __down_op_ret(ptr,fail)                        \
 "      mov     %0, ip"                         \
        : "=&r" (ret)                           \
        : "r" (ptr), "I" (1)                    \
-       : "ip", "lr", "cc", "memory");          \
+       : "ip", "lr", "cc");                    \
+       smp_mb();                               \
        ret;                                    \
        })
 
 #define __up_op(ptr,wake)                      \
        ({                                      \
+       smp_mb();                               \
        __asm__ __volatile__(                   \
        "@ up_op\n"                             \
 "1:    ldrex   lr, [%0]\n"                     \
@@ -66,7 +69,7 @@
 "      blle    " #wake                         \
        :                                       \
        : "r" (ptr), "I" (1)                    \
-       : "ip", "lr", "cc", "memory");          \
+       : "ip", "lr", "cc");                    \
        })
 
 /*
 "      blne    " #fail                         \
        :                                       \
        : "r" (ptr), "I" (RW_LOCK_BIAS)         \
-       : "ip", "lr", "cc", "memory");          \
+       : "ip", "lr", "cc");                    \
+       smp_mb();                               \
        })
 
 #define __up_op_write(ptr,wake)                        \
        ({                                      \
+       smp_mb();                               \
        __asm__ __volatile__(                   \
        "@ up_op_read\n"                        \
 "1:    ldrex   lr, [%0]\n"                     \
 "      blcs    " #wake                         \
        :                                       \
        : "r" (ptr), "I" (RW_LOCK_BIAS)         \
-       : "ip", "lr", "cc", "memory");          \
+       : "ip", "lr", "cc");                    \
        })
 
 #define __down_op_read(ptr,fail)               \
 
 #define __up_op_read(ptr,wake)                 \
        ({                                      \
+       smp_mb();                               \
        __asm__ __volatile__(                   \
        "@ up_op_read\n"                        \
 "1:    ldrex   lr, [%0]\n"                     \
 "      bleq    " #wake                         \
        :                                       \
        : "r" (ptr), "I" (1)                    \
-       : "ip", "lr", "cc", "memory");          \
+       : "ip", "lr", "cc");                    \
        })
 
 #else
 "      blmi    " #fail                         \
        :                                       \
        : "r" (ptr), "I" (1)                    \
-       : "ip", "lr", "cc", "memory");          \
+       : "ip", "lr", "cc");                    \
+       smp_mb();                               \
        })
 
 #define __down_op_ret(ptr,fail)                        \
 "      mov     %0, ip"                         \
        : "=&r" (ret)                           \
        : "r" (ptr), "I" (1)                    \
-       : "ip", "lr", "cc", "memory");          \
+       : "ip", "lr", "cc");                    \
+       smp_mb();                               \
        ret;                                    \
        })
 
 #define __up_op(ptr,wake)                      \
        ({                                      \
+       smp_mb();                               \
        __asm__ __volatile__(                   \
        "@ up_op\n"                             \
 "      mrs     ip, cpsr\n"                     \
 "      blle    " #wake                         \
        :                                       \
        : "r" (ptr), "I" (1)                    \
-       : "ip", "lr", "cc", "memory");          \
+       : "ip", "lr", "cc");                    \
        })
 
 /*
 "      blne    " #fail                         \
        :                                       \
        : "r" (ptr), "I" (RW_LOCK_BIAS)         \
-       : "ip", "lr", "cc", "memory");          \
+       : "ip", "lr", "cc");                    \
+       smp_mb();                               \
        })
 
 #define __up_op_write(ptr,wake)                        \
 "      blcs    " #wake                         \
        :                                       \
        : "r" (ptr), "I" (RW_LOCK_BIAS)         \
-       : "ip", "lr", "cc", "memory");          \
+       : "ip", "lr", "cc");                    \
+       smp_mb();                               \
        })
 
 #define __down_op_read(ptr,fail)               \
 
 #define __up_op_read(ptr,wake)                 \
        ({                                      \
+       smp_mb();                               \
        __asm__ __volatile__(                   \
        "@ up_op_read\n"                        \
 "      mrs     ip, cpsr\n"                     \
 "      bleq    " #wake                         \
        :                                       \
        : "r" (ptr), "I" (1)                    \
-       : "ip", "lr", "cc", "memory");          \
+       : "ip", "lr", "cc");                    \
        })
 
 #endif
index 9705d5eec94c69c2e795a7c130af164b09fe2434..1f906d09b6880f2ac04e9bb0dedf3dd0eafdafee 100644 (file)
@@ -8,9 +8,10 @@
 /*
  * ARMv6 Spin-locking.
  *
- * We (exclusively) read the old value, and decrement it.  If it
- * hits zero, we may have won the lock, so we try (exclusively)
- * storing it.
+ * We exclusively read the old value.  If it is zero, we may have
+ * won the lock, so we try exclusively storing it.  A memory barrier
+ * is required after we get a lock, and before we release it, because
+ * V6 CPUs are assumed to have weakly ordered memory.
  *
  * Unlocked value: 0
  * Locked value: 1
@@ -41,7 +42,9 @@ static inline void _raw_spin_lock(spinlock_t *lock)
 "      bne     1b"
        : "=&r" (tmp)
        : "r" (&lock->lock), "r" (1)
-       : "cc", "memory");
+       : "cc");
+
+       smp_mb();
 }
 
 static inline int _raw_spin_trylock(spinlock_t *lock)
@@ -54,18 +57,25 @@ static inline int _raw_spin_trylock(spinlock_t *lock)
 "      strexeq %0, %2, [%1]"
        : "=&r" (tmp)
        : "r" (&lock->lock), "r" (1)
-       : "cc", "memory");
-
-       return tmp == 0;
+       : "cc");
+
+       if (tmp == 0) {
+               smp_mb();
+               return 1;
+       } else {
+               return 0;
+       }
 }
 
 static inline void _raw_spin_unlock(spinlock_t *lock)
 {
+       smp_mb();
+
        __asm__ __volatile__(
 "      str     %1, [%0]"
        :
        : "r" (&lock->lock), "r" (0)
-       : "cc", "memory");
+       : "cc");
 }
 
 /*
@@ -98,7 +108,9 @@ static inline void _raw_write_lock(rwlock_t *rw)
 "      bne     1b"
        : "=&r" (tmp)
        : "r" (&rw->lock), "r" (0x80000000)
-       : "cc", "memory");
+       : "cc");
+
+       smp_mb();
 }
 
 static inline int _raw_write_trylock(rwlock_t *rw)
@@ -111,18 +123,25 @@ static inline int _raw_write_trylock(rwlock_t *rw)
 "      strexeq %0, %2, [%1]"
        : "=&r" (tmp)
        : "r" (&rw->lock), "r" (0x80000000)
-       : "cc", "memory");
-
-       return tmp == 0;
+       : "cc");
+
+       if (tmp == 0) {
+               smp_mb();
+               return 1;
+       } else {
+               return 0;
+       }
 }
 
 static inline void _raw_write_unlock(rwlock_t *rw)
 {
+       smp_mb();
+
        __asm__ __volatile__(
        "str    %1, [%0]"
        :
        : "r" (&rw->lock), "r" (0)
-       : "cc", "memory");
+       : "cc");
 }
 
 /*
@@ -149,13 +168,17 @@ static inline void _raw_read_lock(rwlock_t *rw)
 "      bmi     1b"
        : "=&r" (tmp), "=&r" (tmp2)
        : "r" (&rw->lock)
-       : "cc", "memory");
+       : "cc");
+
+       smp_mb();
 }
 
 static inline void _raw_read_unlock(rwlock_t *rw)
 {
        unsigned long tmp, tmp2;
 
+       smp_mb();
+
        __asm__ __volatile__(
 "1:    ldrex   %0, [%2]\n"
 "      sub     %0, %0, #1\n"
@@ -164,7 +187,7 @@ static inline void _raw_read_unlock(rwlock_t *rw)
 "      bne     1b"
        : "=&r" (tmp), "=&r" (tmp2)
        : "r" (&rw->lock)
-       : "cc", "memory");
+       : "cc");
 }
 
 #define _raw_read_trylock(lock) generic_raw_read_trylock(lock)
index 3f9c3626a73cc6bc4cddd47738979be95bb0d915..8efa4ebdcacb0c7f358f52a9e4f990e35a25d3d9 100644 (file)
@@ -139,7 +139,12 @@ extern unsigned int user_debug;
 #define vectors_high() (0)
 #endif
 
+#if __LINUX_ARM_ARCH__ >= 6
+#define mb() __asm__ __volatile__ ("mcr p15, 0, %0, c7, c10, 5" \
+                                   : : "r" (0) : "memory")
+#else
 #define mb() __asm__ __volatile__ ("" : : : "memory")
+#endif
 #define rmb() mb()
 #define wmb() mb()
 #define read_barrier_depends() do { } while(0)