Skip site navigation (1)Skip section navigation (2)
Date:      Wed, 16 May 2018 21:04:20 +0000 (UTC)
From:      John Baldwin <jhb@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-stable@freebsd.org, svn-src-stable-11@freebsd.org
Subject:   svn commit: r333687 - stable/11/sys/arm/include
Message-ID:  <201805162104.w4GL4Kmw029010@repo.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: jhb
Date: Wed May 16 21:04:19 2018
New Revision: 333687
URL: https://svnweb.freebsd.org/changeset/base/333687

Log:
  MFC 332891,332892: Fixes for atomic_*cmpset() on arm.
  
  332891:
  Fix some harmless type mismatches in the ARM atomic_cmpset implementations.
  
  The return value of atomic_cmpset() and atomic_fcmpset() is an int (which
  is really a bool) that has the values 0 or 1.  Some of the inlines were
  using the type being operated on (e.g. uint32_t) as either the return type
  of the function, or the type of a local 'ret' variable used to hold the
  return value.  Fix all of these to just use plain 'int'.  Due to C promotion
  rules and the fact that the value can only be 0 or 1, these should all be
  harmless.
  
  332892:
  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.
  
  Approved by:	re (kib)

Modified:
  stable/11/sys/arm/include/atomic-v4.h
  stable/11/sys/arm/include/atomic-v6.h
Directory Properties:
  stable/11/   (props changed)

Modified: stable/11/sys/arm/include/atomic-v4.h
==============================================================================
--- stable/11/sys/arm/include/atomic-v4.h	Wed May 16 21:03:22 2018	(r333686)
+++ stable/11/sys/arm/include/atomic-v4.h	Wed May 16 21:04:19 2018	(r333687)
@@ -115,7 +115,7 @@ atomic_clear_64(volatile uint64_t *address, uint64_t c
 static __inline int
 atomic_fcmpset_32(volatile u_int32_t *p, volatile u_int32_t *cmpval, volatile u_int32_t newval)
 {
-	u_int32_t ret;
+	int ret;
 
 	__with_interrupts_disabled(
 	 {
@@ -134,7 +134,7 @@ atomic_fcmpset_32(volatile u_int32_t *p, volatile u_in
 static __inline int
 atomic_fcmpset_64(volatile u_int64_t *p, volatile u_int64_t *cmpval, volatile u_int64_t newval)
 {
-	u_int64_t ret;
+	int ret;
 
 	__with_interrupts_disabled(
 	 {
@@ -149,7 +149,7 @@ atomic_fcmpset_64(volatile u_int64_t *p, volatile u_in
 	return (ret);
 }
 
-static __inline u_int32_t
+static __inline int
 atomic_cmpset_32(volatile u_int32_t *p, volatile u_int32_t cmpval, volatile u_int32_t newval)
 {
 	int ret;
@@ -166,7 +166,7 @@ atomic_cmpset_32(volatile u_int32_t *p, volatile u_int
 	return (ret);
 }
 
-static __inline u_int64_t
+static __inline int
 atomic_cmpset_64(volatile u_int64_t *p, volatile u_int64_t cmpval, volatile u_int64_t newval)
 {
 	int ret;
@@ -296,7 +296,7 @@ atomic_clear_32(volatile uint32_t *address, uint32_t c
 
 }
 
-static __inline u_int32_t
+static __inline int
 atomic_cmpset_32(volatile u_int32_t *p, volatile u_int32_t cmpval, volatile u_int32_t newval)
 {
 	int done, ras_start = ARM_RAS_START;
@@ -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)

Modified: stable/11/sys/arm/include/atomic-v6.h
==============================================================================
--- stable/11/sys/arm/include/atomic-v6.h	Wed May 16 21:03:22 2018	(r333686)
+++ stable/11/sys/arm/include/atomic-v6.h	Wed May 16 21:04:19 2018	(r333687)
@@ -209,7 +209,7 @@ atomic_fcmpset_32(volatile uint32_t *p, uint32_t *cmpv
 	return (!ret);
 }
 
-static __inline uint64_t
+static __inline int
 atomic_fcmpset_64(volatile uint64_t *p, uint64_t *cmpval, uint64_t newval)
 {
 	uint64_t tmp;
@@ -235,7 +235,7 @@ atomic_fcmpset_64(volatile uint64_t *p, uint64_t *cmpv
 	return (!ret);
 }
 
-static __inline u_long
+static __inline int
 atomic_fcmpset_long(volatile u_long *p, u_long *cmpval, u_long newval)
 {
 
@@ -243,38 +243,38 @@ atomic_fcmpset_long(volatile u_long *p, u_long *cmpval
 	    (uint32_t *)cmpval, newval));
 }
 
-static __inline uint64_t
+static __inline int
 atomic_fcmpset_acq_64(volatile uint64_t *p, uint64_t *cmpval, uint64_t newval)
 {
-	uint64_t ret;
+	int ret;
 
 	ret = atomic_fcmpset_64(p, cmpval, newval);
 	dmb();
 	return (ret);
 }
 
-static __inline u_long
+static __inline int
 atomic_fcmpset_acq_long(volatile u_long *p, u_long *cmpval, u_long newval)
 {
-	u_long ret;
+	int ret;
 
 	ret = atomic_fcmpset_long(p, cmpval, newval);
 	dmb();
 	return (ret);
 }
 
-static __inline uint32_t
+static __inline int
 atomic_fcmpset_acq_32(volatile uint32_t *p, uint32_t *cmpval, uint32_t newval)
 {
 
-	uint32_t ret;
+	int ret;
 
 	ret = atomic_fcmpset_32(p, cmpval, newval);
 	dmb();
 	return (ret);
 }
 
-static __inline uint32_t
+static __inline int
 atomic_fcmpset_rel_32(volatile uint32_t *p, uint32_t *cmpval, uint32_t newval)
 {
 
@@ -282,7 +282,7 @@ atomic_fcmpset_rel_32(volatile uint32_t *p, uint32_t *
 	return (atomic_fcmpset_32(p, cmpval, newval));
 }
 
-static __inline uint64_t
+static __inline int
 atomic_fcmpset_rel_64(volatile uint64_t *p, uint64_t *cmpval, uint64_t newval)
 {
 
@@ -290,7 +290,7 @@ atomic_fcmpset_rel_64(volatile uint64_t *p, uint64_t *
 	return (atomic_fcmpset_64(p, cmpval, newval));
 }
 
-static __inline u_long
+static __inline int
 atomic_fcmpset_rel_long(volatile u_long *p, u_long *cmpval, u_long newval)
 {
 
@@ -298,10 +298,10 @@ atomic_fcmpset_rel_long(volatile u_long *p, u_long *cm
 	return (atomic_fcmpset_long(p, cmpval, newval));
 }
 
-static __inline uint32_t
+static __inline int
 atomic_cmpset_32(volatile uint32_t *p, uint32_t cmpval, uint32_t newval)
 {
-	uint32_t ret;
+	int ret;
 
 	__asm __volatile(
 	    "1: ldrex	%0, [%1]	\n"
@@ -349,44 +349,44 @@ atomic_cmpset_64(volatile uint64_t *p, uint64_t cmpval
 	return (ret);
 }
 
-static __inline u_long
+static __inline int
 atomic_cmpset_long(volatile u_long *p, u_long cmpval, u_long newval)
 {
 
 	return (atomic_cmpset_32((volatile uint32_t *)p, cmpval, newval));
 }
 
-static __inline uint32_t
+static __inline int
 atomic_cmpset_acq_32(volatile uint32_t *p, uint32_t cmpval, uint32_t newval)
 {
-	uint32_t ret;
+	int ret;
 
 	ret = atomic_cmpset_32(p, cmpval, newval);
 	dmb();
 	return (ret);
 }
 
-static __inline uint64_t
+static __inline int
 atomic_cmpset_acq_64(volatile uint64_t *p, uint64_t cmpval, uint64_t newval)
 {
-	uint64_t ret;
+	int ret;
 
 	ret = atomic_cmpset_64(p, cmpval, newval);
 	dmb();
 	return (ret);
 }
 
-static __inline u_long
+static __inline int
 atomic_cmpset_acq_long(volatile u_long *p, u_long cmpval, u_long newval)
 {
-	u_long ret;
+	int ret;
 
 	ret = atomic_cmpset_long(p, cmpval, newval);
 	dmb();
 	return (ret);
 }
 
-static __inline uint32_t
+static __inline int
 atomic_cmpset_rel_32(volatile uint32_t *p, uint32_t cmpval, uint32_t newval)
 {
 
@@ -394,7 +394,7 @@ atomic_cmpset_rel_32(volatile uint32_t *p, uint32_t cm
 	return (atomic_cmpset_32(p, cmpval, newval));
 }
 
-static __inline uint64_t
+static __inline int
 atomic_cmpset_rel_64(volatile uint64_t *p, uint64_t cmpval, uint64_t newval)
 {
 
@@ -402,7 +402,7 @@ atomic_cmpset_rel_64(volatile uint64_t *p, uint64_t cm
 	return (atomic_cmpset_64(p, cmpval, newval));
 }
 
-static __inline u_long
+static __inline int
 atomic_cmpset_rel_long(volatile u_long *p, u_long cmpval, u_long newval)
 {
 



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