Author: jhb
Date: Mon Apr 23 17:00:15 2018
New Revision: 332892
URL: https://svnweb.freebsd.org/changeset/base/332892

Log:
  Implement 32-bit atomic_fcmpset() in userland for armv4/v5.
  
  - Add an implementation of atomic_fcmpset_32() using RAS for armv4/v5.
    This fixes recent world breakage due to use of atomic_fcmpset() in
    userland.
  - While here, be more careful to not expose wrapper macros for 64-bit
    atomic_*cmpset to userland for armv4/v5 as only 32-bit cmpset is
    implemented.
  
  This has been reviewed, but not runtime-tested, but should fix the arm.arm
  and arm.armeb worlds that have been broken for a while.
  
  Reviewed by:  imp
  MFC after:    1 month
  Differential Revision:        https://reviews.freebsd.org/D15147

Modified:
  head/sys/arm/include/atomic-v4.h

Modified: head/sys/arm/include/atomic-v4.h
==============================================================================
--- head/sys/arm/include/atomic-v4.h    Mon Apr 23 16:50:37 2018        
(r332891)
+++ head/sys/arm/include/atomic-v4.h    Mon Apr 23 17:00:15 2018        
(r332892)
@@ -321,6 +321,33 @@ atomic_cmpset_32(volatile u_int32_t *p, volatile u_int
        return (done);
 }
 
+static __inline int
+atomic_fcmpset_32(volatile u_int32_t *p, volatile u_int32_t *cmpval, volatile 
u_int32_t newval)
+{
+       int done, oldval, ras_start = ARM_RAS_START;
+
+       __asm __volatile("1:\n"
+           "adr        %1, 1b\n"
+           "str        %1, [%0]\n"
+           "adr        %1, 2f\n"
+           "str        %1, [%0, #4]\n"
+           "ldr        %1, [%2]\n"
+           "ldr        %5, [%3]\n"
+           "cmp        %1, %5\n"
+           "streq      %4, [%2]\n"
+           "2:\n"
+           "mov        %5, #0\n"
+           "str        %5, [%0]\n"
+           "mov        %5, #0xffffffff\n"
+           "str        %5, [%0, #4]\n"
+           "strne      %1, [%3]\n"
+           "moveq      %1, #1\n"
+           "movne      %1, #0\n"
+           : "+r" (ras_start), "=r" (done) ,"+r" (p)
+           , "+r" (cmpval), "+r" (newval), "+r" (oldval) : : "cc", "memory");
+       return (done);
+}
+
 static __inline uint32_t
 atomic_fetchadd_32(volatile uint32_t *p, uint32_t v)
 {
@@ -409,14 +436,18 @@ atomic_swap_32(volatile u_int32_t *p, u_int32_t v)
 
 #define atomic_fcmpset_rel_32  atomic_fcmpset_32
 #define atomic_fcmpset_acq_32  atomic_fcmpset_32
+#ifdef _KERNEL
 #define atomic_fcmpset_rel_64  atomic_fcmpset_64
 #define atomic_fcmpset_acq_64  atomic_fcmpset_64
+#endif
 #define atomic_fcmpset_acq_long        atomic_fcmpset_long
 #define atomic_fcmpset_rel_long        atomic_fcmpset_long
 #define atomic_cmpset_rel_32   atomic_cmpset_32
 #define atomic_cmpset_acq_32   atomic_cmpset_32
+#ifdef _KERNEL
 #define atomic_cmpset_rel_64   atomic_cmpset_64
 #define atomic_cmpset_acq_64   atomic_cmpset_64
+#endif
 #define atomic_set_rel_32      atomic_set_32
 #define atomic_set_acq_32      atomic_set_32
 #define atomic_clear_rel_32    atomic_clear_32
@@ -463,8 +494,6 @@ atomic_cmpset_long(volatile u_long *dst, u_long old, u
        return (atomic_cmpset_32((volatile uint32_t *)dst, old, newe));
 }
 
-#ifdef _KERNEL
-/* atomic_fcmpset_32 is only defined for the kernel */
 static __inline u_long
 atomic_fcmpset_long(volatile u_long *dst, u_long *old, u_long newe)
 {
@@ -472,7 +501,6 @@ atomic_fcmpset_long(volatile u_long *dst, u_long *old,
        return (atomic_fcmpset_32((volatile uint32_t *)dst,
            (uint32_t *)old, newe));
 }
-#endif
 
 static __inline u_long
 atomic_fetchadd_long(volatile u_long *p, u_long v)
_______________________________________________
svn-src-head@freebsd.org mailing list
https://lists.freebsd.org/mailman/listinfo/svn-src-head
To unsubscribe, send any mail to "svn-src-head-unsubscr...@freebsd.org"

Reply via email to