Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/trunk]: src/sys/arch/arm/include Rather than having long complicated asm...



details:   https://anonhg.NetBSD.org/src/rev/bb9794cc6615
branches:  trunk
changeset: 794343:bb9794cc6615
user:      matt <matt%NetBSD.org@localhost>
date:      Wed Mar 12 17:55:02 2014 +0000

description:
Rather than having long complicated asm statements, use inlines for
ldrex/strex and let the compiler arrange the code how it wants.

diffstat:

 sys/arch/arm/include/lock.h |  191 +++++++++++++++++++++++--------------------
 1 files changed, 103 insertions(+), 88 deletions(-)

diffs (254 lines):

diff -r d2c082d6e374 -r bb9794cc6615 sys/arch/arm/include/lock.h
--- a/sys/arch/arm/include/lock.h       Wed Mar 12 17:49:13 2014 +0000
+++ b/sys/arch/arm/include/lock.h       Wed Mar 12 17:55:02 2014 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: lock.h,v 1.25 2013/08/18 04:31:08 matt Exp $   */
+/*     $NetBSD: lock.h,v 1.26 2014/03/12 17:55:02 matt Exp $   */
 
 /*-
  * Copyright (c) 2000, 2001 The NetBSD Foundation, Inc.
@@ -73,116 +73,115 @@
 #define        mb_memory       drain_writebuf          /* in cpufunc.h */
 #endif
 
-#if defined(_KERNEL)
-static __inline unsigned char
-__swp(__cpu_simple_lock_t __val, volatile __cpu_simple_lock_t *__ptr)
+#ifdef _ARM_ARCH_6
+static __inline unsigned int
+__arm_load_exclusive(__cpu_simple_lock_t *__alp)
 {
-#ifdef _ARM_ARCH_6
-       uint32_t __rv, __tmp;
-       if (sizeof(*__ptr) == 1) {
-               __asm volatile(
-                       "1:\t"
-                       "ldrexb\t%[__rv], [%[__ptr]]"                   "\n\t"
-                       "cmp\t%[__rv],%[__val]"                         "\n\t"
-#ifdef __thumb__
-                       "itt\tne"                                       "\n\t"
-#endif
-                       "strexbne\t%[__tmp], %[__val], [%[__ptr]]"      "\n\t"
-                       "cmpne\t%[__tmp], #0"                           "\n\t"
-                       "bne\t1b"                                       "\n\t"
-#ifdef _ARM_ARCH_7
-                       "dmb"
-#else
-                       "mcr\tp15, 0, %[__tmp], c7, c10, 5"
-#endif
-                   : [__rv] "=&r" (__rv), [__tmp] "=&r"(__tmp)
-                   : [__val] "r" (__val), [__ptr] "r" (__ptr) : "cc", "memory");
+       unsigned int __rv;
+       if (sizeof(*__alp) == 1) {
+               __asm __volatile("ldrexb\t%0,[%1]" : "=r"(__rv) : "r"(__alp));
        } else {
-               __asm volatile(
-                       "1:\t"
-                       "ldrex\t%[__rv], [%[__ptr]]"                    "\n\t"
-                       "cmp\t%[__rv],%[__val]"                         "\n\t"
-#ifdef __thumb__
-                       "itt\tne"                                       "\n\t"
-#endif
-                       "strexne\t%[__tmp], %[__val], [%[__ptr]]"       "\n\t"
-                       "cmpne\t%[__tmp], #0"                           "\n\t"
-                       "bne\t1b"                                       "\n\t"
-#ifdef _ARM_ARCH_7
-                       "nop"
-#else
-                       "mcr\tp15, 0, %[__tmp], c7, c10, 5"
-#endif
-                   : [__rv] "=&r" (__rv), [__tmp] "=&r"(__tmp)
-                   : [__val] "r" (__val), [__ptr] "r" (__ptr) : "cc", "memory");
+               __asm __volatile("ldrex\t%0,[%1]" : "=r"(__rv) : "r"(__alp));
        }
        return __rv;
-#else
+}
+
+/* returns 0 on success and 1 on failure */
+static __inline unsigned int
+__arm_store_exclusive(__cpu_simple_lock_t *__alp, unsigned int __val)
+{
+       unsigned int __rv;
+       if (sizeof(*__alp) == 1) {
+               __asm __volatile("strexb\t%0,%1,[%2]"
+                   : "=&r"(__rv) : "r"(__val), "r"(__alp) : "cc", "memory");
+       } else {
+               __asm __volatile("strex\t%0,%1,[%2]"
+                   : "=&r"(__rv) : "r"(__val), "r"(__alp) : "cc", "memory");
+       }
+       return __rv;
+}
+#elif defined(_KERNEL)
+static __inline unsigned char
+__swp(unsigned char __val, __cpu_simple_lock_t *__ptr)
+{
        uint32_t __val32;
-       __asm volatile("swpb %0, %1, [%2]"
+       __asm volatile("swpb    %0, %1, [%2]"
            : "=&r" (__val32) : "r" (__val), "r" (__ptr) : "memory");
        return __val32;
-#endif
 }
 #else
 /*
- * On Cortex-A9 (SMP), SWP no longer guarantees atomic results.  Thus we pad
- * out SWP so that when the A9 generates an undefined exception we can replace
+ * On MP Cortex, SWP no longer guarantees atomic results.  Thus we pad
+ * out SWP so that when the cpu generates an undefined exception we can replace
  * the SWP/MOV instructions with the right LDREX/STREX instructions.
  *
  * This is why we force the SWP into the template needed for LDREX/STREX
  * including the extra instructions and extra register for testing the result.
  */
 static __inline int
-__swp(int __val, volatile int *__ptr)
+__swp(int __val, __cpu_simple_lock_t *__ptr)
 {
-       int __rv, __tmp;
+       int __tmp;
        __asm volatile(
-               "1:\t"
-#ifdef _ARM_ARCH_6
-               "ldrex\t%[__rv], [%[__ptr]]"                    "\n\t"
-               "cmp\t%[__rv],%[__val]"                         "\n\t"
-#ifdef __thumb__
-               "it\tne"                                        "\n\t"
-#endif
-               "strexne\t%[__tmp], %[__val], [%[__ptr]]"       "\n\t"
+#if 1
+       "1:\t"  "swp    %[__rv], %[__val], [%[__ptr]]"
+       "\n\t"  "b      2f"
 #else
-               "swp\t%[__rv], %[__val], [%[__ptr]]"            "\n\t"
-               "mov\t%[__tmp], #0"                             "\n\t"
-               "cmp\t%[__rv],%[__val]"                         "\n\t"
+       "1:\t"  "ldrex  %[__rv],[%[__ptr]]"
+       "\n\t"  "strex  %[__tmp],%[__val],[%[__ptr]]"
 #endif
-               "cmpne\t%[__tmp], #0"                           "\n\t"
-               "bne\t1b"                                       "\n\t"
-#ifdef _ARM_ARCH_7
-               "dmb"
-#elif defined(_ARM_ARCH_6)
-               "mcr\tp15, 0, %[__tmp], c7, c10, 5"
-#else
-               "nop"
-#endif
-           : [__rv] "=&r" (__rv), [__tmp] "=&r"(__tmp)
+       "\n\t"  "cmp    %[__tmp],#0"
+       "\n\t"  "bne    1b"
+       "\n"    "2:"
+           : [__rv] "=&r" (__rv), [__tmp] "=&r" (__tmp__)
            : [__val] "r" (__val), [__ptr] "r" (__ptr) : "cc", "memory");
        return __rv;
 }
-#endif /* _KERNEL */
+#endif /* !_ARM_ARCH_6 */
+
+static inline void
+__arm_membar_producer(void)
+{
+#ifdef _ARM_ARCH_7
+               __asm __volatile("dsb");
+#elif defined(_ARM_ARCH_6)
+               __asm __volatile("mcr\tp15,0,%0,c7,c10,4" :: "r"(0));
+#endif
+}
+
+static inline void
+__arm_membar_consumer(void)
+{
+#ifdef _ARM_ARCH_7
+               __asm __volatile("dmb");
+#elif defined(_ARM_ARCH_6)
+               __asm __volatile("mcr\tp15,0,%0,c7,c10,5" :: "r"(0));
+#endif
+}
 
 static __inline void __unused
-__cpu_simple_lock_init(__cpu_simple_lock_t *alp)
+__cpu_simple_lock_init(__cpu_simple_lock_t *__alp)
 {
 
-       *alp = __SIMPLELOCK_UNLOCKED;
-#ifdef _ARM_ARCH_7
-       __asm __volatile("dsb");
-#endif
+       *__alp = __SIMPLELOCK_UNLOCKED;
+       __arm_membar_producer();
 }
 
 #if !defined(__thumb__) || defined(_ARM_ARCH_T2)
 static __inline void __unused
-__cpu_simple_lock(__cpu_simple_lock_t *alp)
+__cpu_simple_lock(__cpu_simple_lock_t *__alp)
 {
-
-       while (__swp(__SIMPLELOCK_LOCKED, alp) != __SIMPLELOCK_UNLOCKED)
+#ifdef _ARM_ARCH_6
+       __arm_membar_consumer();
+       do {
+               /* spin */
+       } while (__arm_load_exclusive(__alp) != __SIMPLELOCK_UNLOCKED
+                || __arm_store_exclusive(__alp, __SIMPLELOCK_LOCKED));
+       __arm_membar_producer();
+#else
+       while (__swp(__SIMPLELOCK_LOCKED, __alp) != __SIMPLELOCK_UNLOCKED)
                continue;
+#endif
 }
 #else
 void __cpu_simple_lock(__cpu_simple_lock_t *);
@@ -190,25 +189,41 @@
 
 #if !defined(__thumb__) || defined(_ARM_ARCH_T2)
 static __inline int __unused
-__cpu_simple_lock_try(__cpu_simple_lock_t *alp)
+__cpu_simple_lock_try(__cpu_simple_lock_t *__alp)
 {
-
-       return (__swp(__SIMPLELOCK_LOCKED, alp) == __SIMPLELOCK_UNLOCKED);
+#ifdef _ARM_ARCH_6
+       __arm_membar_consumer();
+       do {
+               if (__arm_load_exclusive(__alp) != __SIMPLELOCK_UNLOCKED) {
+                       return 0;
+               }
+       } while (__arm_store_exclusive(__alp, __SIMPLELOCK_LOCKED));
+       __arm_membar_producer();
+       return 1;
+#else
+       return (__swp(__SIMPLELOCK_LOCKED, __alp) == __SIMPLELOCK_UNLOCKED);
+#endif
 }
 #else
 int __cpu_simple_lock_try(__cpu_simple_lock_t *);
 #endif
 
 static __inline void __unused
-__cpu_simple_unlock(__cpu_simple_lock_t *alp)
+__cpu_simple_unlock(__cpu_simple_lock_t *__alp)
 {
 
-#ifdef _ARM_ARCH_7
-       __asm __volatile("dmb");
-#endif
-       *alp = __SIMPLELOCK_UNLOCKED;
-#ifdef _ARM_ARCH_7
-       __asm __volatile("dsb");
+#ifdef _ARM_ARCH_8
+       if (sizeof(*__alp) == 1) {
+               __asm __volatile("stab\t%0, [%1]"
+                   :: "r"(__SIMPLELOCK_UNLOCKED), "r"(__alp) : "memory");
+       } else {
+               __asm __volatile("sta\t%0, [%1]"
+                   :: "r"(__SIMPLELOCK_UNLOCKED), "r"(__alp) : "memory");
+       }
+#else
+       __arm_membar_consumer();
+       *__alp = __SIMPLELOCK_UNLOCKED;
+       __arm_membar_producer();
 #endif
 }
 



Home | Main Index | Thread Index | Old Index