Skip site navigation (1)Skip section navigation (2)
Date:      Mon, 23 Apr 2018 17:00:15 +0000 (UTC)
From:      John Baldwin <jhb@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r332892 - head/sys/arm/include
Message-ID:  <201804231700.w3NH0FpG096149@repo.freebsd.org>

next in thread | raw e-mail | index | archive | help
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)



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201804231700.w3NH0FpG096149>