[1/4] Add arch-specific configuration for C11 atomics support.
Commit Message
Patch 2/4 provides two ways to implement C11 atomics: Either using the
__atomic* builtins provided by GCC 4.7 and later, or based on the
existing glibc-specific atomic operations. This is a choice we best
make on a per-architecture basis, so I let each arch set
USE_ATOMIC_COMPILER_BUILTINS to true or false:
* True if either the existing atomic ops use the __atomic* builtins
anyway (aarch64, mips for some GCC versions) or on x86_64, where I have
tested this for pthread_once at least (and there are other things like
GCC's libitm that have been using the builtins and have been tested
quite well).
* False otherwise, even if GCC may provide __atomic builtins on such an
architecture. I think it is better to let the arch maintainer (or
anyone willing to test) make the decision to use the builtins.
I have not tested except on x86_64, but there for both true and false
for USE_ATOMIC_COMPILER_BUILTINS. I'd appreciate further testing on
other archs.
I believe that once we have some more testing including on archs with
weaker HW memory models (e.g., ARM or powerpc), we can commit this patch
even if we haven't tested on each arch. This is because most archs
don't use the builtins, and if they don't then this patch really relies
on the existing atomics to be correct. IOW, every arch with a correct
implementation of the current atomics should continue to work.
Also, this sets __HAVE_64B_ATOMICS if the particular arch supports 64b
atomic operations. This is useful for both the atomics implementation
as well as concurrent code that has different code paths for when 64b
atomics are available.
* sysdeps/aarch64/bits/atomic.h (__HAVE_64B_ATOMICS,
USE_ATOMIC_COMPILER_BUILTINS): Define.
* sysdeps/alpha/bits/atomic.h (__HAVE_64B_ATOMICS,
USE_ATOMIC_COMPILER_BUILTINS): Likewise.
* sysdeps/arm/bits/atomic.h (__HAVE_64B_ATOMICS,
USE_ATOMIC_COMPILER_BUILTINS): Likewise.
* sysdeps/i386/i486/atomic.h (__HAVE_64B_ATOMICS,
USE_ATOMIC_COMPILER_BUILTINS): Likewise.
* sysdeps/ia64/atomic.h (__HAVE_64B_ATOMICS,
USE_ATOMIC_COMPILER_BUILTINS): Likewise.
* sysdeps/m68k/coldfire/atomic.h (__HAVE_64B_ATOMICS,
USE_ATOMIC_COMPILER_BUILTINS): Likewise.
* sysdeps/m68k/m680x0/m68020/atomic.h (__HAVE_64B_ATOMICS,
USE_ATOMIC_COMPILER_BUILTINS): Likewise.
* sysdeps/microblaze/atomic.h (__HAVE_64B_ATOMICS,
USE_ATOMIC_COMPILER_BUILTINS): Likewise.
* sysdeps/mips/atomic.h (__HAVE_64B_ATOMICS,
USE_ATOMIC_COMPILER_BUILTINS): Likewise.
* sysdeps/powerpc/powerpc32/atomic.h (__HAVE_64B_ATOMICS,
USE_ATOMIC_COMPILER_BUILTINS): Likewise.
* sysdeps/powerpc/powerpc64/atomic.h (__HAVE_64B_ATOMICS,
USE_ATOMIC_COMPILER_BUILTINS): Likewise.
* sysdeps/s390/atomic.h (__HAVE_64B_ATOMICS,
USE_ATOMIC_COMPILER_BUILTINS): Likewise.
* sysdeps/sparc/sparc32/atomic.h (__HAVE_64B_ATOMICS,
USE_ATOMIC_COMPILER_BUILTINS): Likewise.
* sysdeps/sparc/sparc32/sparcv9/atomic.h (__HAVE_64B_ATOMICS,
USE_ATOMIC_COMPILER_BUILTINS): Likewise.
* sysdeps/sparc/sparc64/atomic.h (__HAVE_64B_ATOMICS,
USE_ATOMIC_COMPILER_BUILTINS): Likewise.
* sysdeps/tile/tilegx/atomic.h (__HAVE_64B_ATOMICS,
USE_ATOMIC_COMPILER_BUILTINS): Likewise.
* sysdeps/tile/tilepro/atomic.h (__HAVE_64B_ATOMICS,
USE_ATOMIC_COMPILER_BUILTINS): Likewise.
* sysdeps/unix/sysv/linux/hppa/bits/atomic.h (__HAVE_64B_ATOMICS,
USE_ATOMIC_COMPILER_BUILTINS): Likewise.
* sysdeps/unix/sysv/linux/m68k/coldfire/bits/atomic.h
(__HAVE_64B_ATOMICS, USE_ATOMIC_COMPILER_BUILTINS): Likewise.
* sysdeps/unix/sysv/linux/sh/bits/atomic.h (__HAVE_64B_ATOMICS,
USE_ATOMIC_COMPILER_BUILTINS): Likewise.
* sysdeps/x86_64/bits/atomic.h (__HAVE_64B_ATOMICS,
USE_ATOMIC_COMPILER_BUILTINS): Likewise.
Comments
Hi Torvald,
Patch looks ok in general, some comments regarding Changelog entry:
On 29-10-2014 19:39, Torvald Riegel wrote:
>
> * sysdeps/aarch64/bits/atomic.h (__HAVE_64B_ATOMICS,
> USE_ATOMIC_COMPILER_BUILTINS): Define.
> * sysdeps/alpha/bits/atomic.h (__HAVE_64B_ATOMICS,
> USE_ATOMIC_COMPILER_BUILTINS): Likewise.
> * sysdeps/arm/bits/atomic.h (__HAVE_64B_ATOMICS,
> USE_ATOMIC_COMPILER_BUILTINS): Likewise.
> * sysdeps/i386/i486/atomic.h (__HAVE_64B_ATOMICS,
> USE_ATOMIC_COMPILER_BUILTINS): Likewise.
I believe it should be sysdeps/i386/i486/bits/atomic.h. Same for other archs
as well (powerpc for instance).
> * sysdeps/ia64/atomic.h (__HAVE_64B_ATOMICS,
> USE_ATOMIC_COMPILER_BUILTINS): Likewise.
> * sysdeps/m68k/coldfire/atomic.h (__HAVE_64B_ATOMICS,
> USE_ATOMIC_COMPILER_BUILTINS): Likewise.
> * sysdeps/m68k/m680x0/m68020/atomic.h (__HAVE_64B_ATOMICS,
> USE_ATOMIC_COMPILER_BUILTINS): Likewise.
> * sysdeps/microblaze/atomic.h (__HAVE_64B_ATOMICS,
> USE_ATOMIC_COMPILER_BUILTINS): Likewise.
> * sysdeps/mips/atomic.h (__HAVE_64B_ATOMICS,
> USE_ATOMIC_COMPILER_BUILTINS): Likewise.
> * sysdeps/powerpc/powerpc32/atomic.h (__HAVE_64B_ATOMICS,
> USE_ATOMIC_COMPILER_BUILTINS): Likewise.
> * sysdeps/powerpc/powerpc64/atomic.h (__HAVE_64B_ATOMICS,
> USE_ATOMIC_COMPILER_BUILTINS): Likewise.
> * sysdeps/s390/atomic.h (__HAVE_64B_ATOMICS,
> USE_ATOMIC_COMPILER_BUILTINS): Likewise.
> * sysdeps/sparc/sparc32/atomic.h (__HAVE_64B_ATOMICS,
> USE_ATOMIC_COMPILER_BUILTINS): Likewise.
> * sysdeps/sparc/sparc32/sparcv9/atomic.h (__HAVE_64B_ATOMICS,
> USE_ATOMIC_COMPILER_BUILTINS): Likewise.
> * sysdeps/sparc/sparc64/atomic.h (__HAVE_64B_ATOMICS,
> USE_ATOMIC_COMPILER_BUILTINS): Likewise.
> * sysdeps/tile/tilegx/atomic.h (__HAVE_64B_ATOMICS,
> USE_ATOMIC_COMPILER_BUILTINS): Likewise.
> * sysdeps/tile/tilepro/atomic.h (__HAVE_64B_ATOMICS,
> USE_ATOMIC_COMPILER_BUILTINS): Likewise.
> * sysdeps/unix/sysv/linux/hppa/bits/atomic.h (__HAVE_64B_ATOMICS,
> USE_ATOMIC_COMPILER_BUILTINS): Likewise.
> * sysdeps/unix/sysv/linux/m68k/coldfire/bits/atomic.h
> (__HAVE_64B_ATOMICS, USE_ATOMIC_COMPILER_BUILTINS): Likewise.
> * sysdeps/unix/sysv/linux/sh/bits/atomic.h (__HAVE_64B_ATOMICS,
> USE_ATOMIC_COMPILER_BUILTINS): Likewise.
> * sysdeps/x86_64/bits/atomic.h (__HAVE_64B_ATOMICS,
> USE_ATOMIC_COMPILER_BUILTINS): Likewise.
commit 93952165df3000cc7dd8056ff87021f29a17b7ff
Author: Torvald Riegel <triegel@redhat.com>
Date: Sat Oct 18 01:02:59 2014 +0200
Add arch-specific configuration for C11 atomics support.
This sets __HAVE_64B_ATOMICS if provided. It also sets
USE_ATOMIC_COMPILER_BUILTINS to true if the existing atomic ops use the
__atomic* builtins (aarch64, mips partially) or if this has been
tested (x86_64); otherwise, this is set to false so that C11 atomics will
be based on the existing atomic operations.
@@ -36,6 +36,8 @@ typedef uintptr_t uatomicptr_t;
typedef intmax_t atomic_max_t;
typedef uintmax_t uatomic_max_t;
+#define __HAVE_64B_ATOMICS 1
+#define USE_ATOMIC_COMPILER_BUILTINS 1
/* Compare and exchange.
For all "bool" routines, we return FALSE if exchange succesful. */
@@ -42,6 +42,9 @@ typedef uintptr_t uatomicptr_t;
typedef intmax_t atomic_max_t;
typedef uintmax_t uatomic_max_t;
+#define __HAVE_64B_ATOMICS 1
+#define USE_ATOMIC_COMPILER_BUILTINS 0
+
#ifdef UP
# define __MB /* nothing */
@@ -33,6 +33,9 @@ typedef uintptr_t uatomicptr_t;
typedef intmax_t atomic_max_t;
typedef uintmax_t uatomic_max_t;
+#define __HAVE_64B_ATOMICS 0
+#define USE_ATOMIC_COMPILER_BUILTINS 0
+
void __arm_link_error (void);
#ifdef __GCC_HAVE_SYNC_COMPARE_AND_SWAP_4
@@ -54,6 +54,9 @@ typedef uintmax_t uatomic_max_t;
# endif
#endif
+#define __HAVE_64B_ATOMICS 0
+#define USE_ATOMIC_COMPILER_BUILTINS 0
+
#define atomic_compare_and_exchange_val_acq(mem, newval, oldval) \
__sync_val_compare_and_swap (mem, oldval, newval)
@@ -43,6 +43,9 @@ typedef uintptr_t uatomicptr_t;
typedef intmax_t atomic_max_t;
typedef uintmax_t uatomic_max_t;
+#define __HAVE_64B_ATOMICS 1
+#define USE_ATOMIC_COMPILER_BUILTINS 0
+
#define __arch_compare_and_exchange_bool_8_acq(mem, newval, oldval) \
(abort (), 0)
@@ -49,6 +49,10 @@ typedef uintptr_t uatomicptr_t;
typedef intmax_t atomic_max_t;
typedef uintmax_t uatomic_max_t;
+/* If we have just non-atomic operations, we can as well make them wide. */
+#define __HAVE_64B_ATOMICS 1
+#define USE_ATOMIC_COMPILER_BUILTINS 0
+
/* The only basic operation needed is compare and exchange. */
#define atomic_compare_and_exchange_val_acq(mem, newval, oldval) \
({ __typeof (mem) __gmemp = (mem); \
@@ -44,6 +44,9 @@ typedef uintptr_t uatomicptr_t;
typedef intmax_t atomic_max_t;
typedef uintmax_t uatomic_max_t;
+#define __HAVE_64B_ATOMICS 1
+#define USE_ATOMIC_COMPILER_BUILTINS 0
+
#define __arch_compare_and_exchange_val_8_acq(mem, newval, oldval) \
({ __typeof (*(mem)) __ret; \
__asm __volatile ("cas%.b %0,%2,%1" \
@@ -35,6 +35,9 @@ typedef uintptr_t uatomicptr_t;
typedef intmax_t atomic_max_t;
typedef uintmax_t uatomic_max_t;
+#define __HAVE_64B_ATOMICS 1
+#define USE_ATOMIC_COMPILER_BUILTINS 0
+
/* Microblaze does not have byte and halfword forms of load and reserve and
store conditional. So for microblaze we stub out the 8- and 16-bit forms. */
@@ -44,6 +44,12 @@ typedef uintmax_t uatomic_max_t;
#define MIPS_PUSH_MIPS2
#endif
+#if _MIPS_SIM == _ABIO32
+#define __HAVE_64B_ATOMICS 0
+#else
+#define __HAVE_64B_ATOMICS 1
+#endif
+
/* See the comments in <sys/asm.h> about the use of the sync instruction. */
#ifndef MIPS_SYNC
# define MIPS_SYNC sync
@@ -86,6 +92,8 @@ typedef uintmax_t uatomic_max_t;
have no assembly alternative available and want to avoid the __sync_*
builtins if at all possible. */
+#define USE_ATOMIC_COMPILER_BUILTINS 1
+
/* Compare and exchange.
For all "bool" routines, we return FALSE if exchange succesful. */
@@ -234,6 +242,8 @@ typedef uintmax_t uatomic_max_t;
/* This implementation using inline assembly will be removed once glibc
requires GCC 4.8 or later to build. */
+#define USE_ATOMIC_COMPILER_BUILTINS 0
+
/* Compare and exchange. For all of the "xxx" routines, we expect a
"__prev" and a "__cmp" variable to be provided by the enclosing scope,
in which values are returned. */
@@ -33,6 +33,9 @@
# define MUTEX_HINT_REL
#endif
+#define __HAVE_64B_ATOMICS 0
+#define USE_ATOMIC_COMPILER_BUILTINS 0
+
/*
* The 32-bit exchange_bool is different on powerpc64 because the subf
* does signed 64-bit arithmetic while the lwarx is 32-bit unsigned
@@ -33,6 +33,9 @@
# define MUTEX_HINT_REL
#endif
+#define __HAVE_64B_ATOMICS 1
+#define USE_ATOMIC_COMPILER_BUILTINS 0
+
/* The 32-bit exchange_bool is different on powerpc64 because the subf
does signed 64-bit arithmetic while the lwarx is 32-bit unsigned
(a load word and zero (high 32) form) load.
@@ -43,6 +43,8 @@ typedef uintptr_t uatomicptr_t;
typedef intmax_t atomic_max_t;
typedef uintmax_t uatomic_max_t;
+#define USE_ATOMIC_COMPILER_BUILTINS 0
+
#define __arch_compare_and_exchange_val_8_acq(mem, newval, oldval) \
(abort (), (__typeof (*mem)) 0)
@@ -59,6 +61,7 @@ typedef uintmax_t uatomic_max_t;
__archold; })
#ifdef __s390x__
+# define __HAVE_64B_ATOMICS 1
# define __arch_compare_and_exchange_val_64_acq(mem, newval, oldval) \
({ __typeof (mem) __archmem = (mem); \
__typeof (*mem) __archold = (oldval); \
@@ -67,6 +70,7 @@ typedef uintmax_t uatomic_max_t;
: "d" ((long) (newval)), "m" (*__archmem) : "cc", "memory" ); \
__archold; })
#else
+# define __HAVE_64B_ATOMICS 0
/* For 31 bit we do not really need 64-bit compare-and-exchange. We can
implement them by use of the csd instruction. The straightforward
implementation causes warnings so we skip the definition for now. */
@@ -47,6 +47,9 @@ typedef uintptr_t uatomicptr_t;
typedef intmax_t atomic_max_t;
typedef uintmax_t uatomic_max_t;
+#define __HAVE_64B_ATOMICS 0
+#define USE_ATOMIC_COMPILER_BUILTINS 0
+
/* We have no compare and swap, just test and set.
The following implementation contends on 64 global locks
@@ -44,6 +44,9 @@ typedef uintptr_t uatomicptr_t;
typedef intmax_t atomic_max_t;
typedef uintmax_t uatomic_max_t;
+#define __HAVE_64B_ATOMICS 0
+#define USE_ATOMIC_COMPILER_BUILTINS 0
+
#define __arch_compare_and_exchange_val_8_acq(mem, newval, oldval) \
(abort (), (__typeof (*mem)) 0)
@@ -44,6 +44,9 @@ typedef uintptr_t uatomicptr_t;
typedef intmax_t atomic_max_t;
typedef uintmax_t uatomic_max_t;
+#define __HAVE_64B_ATOMICS 1
+#define USE_ATOMIC_COMPILER_BUILTINS 0
+
#define __arch_compare_and_exchange_val_8_acq(mem, newval, oldval) \
(abort (), (__typeof (*mem)) 0)
@@ -21,6 +21,9 @@
#include <arch/spr_def.h>
+#define __HAVE_64B_ATOMICS 1
+#define USE_ATOMIC_COMPILER_BUILTINS 0
+
/* Pick appropriate 8- or 4-byte instruction. */
#define __atomic_update(mem, v, op) \
((__typeof (*(mem))) (__typeof (*(mem) - *(mem))) \
@@ -21,6 +21,9 @@
#include <asm/unistd.h>
+#define __HAVE_64B_ATOMICS 0
+#define USE_ATOMIC_COMPILER_BUILTINS 0
+
/* 32-bit integer compare-and-exchange. */
static __inline __attribute__ ((always_inline))
int __atomic_cmpxchg_32 (volatile int *mem, int newval, int oldval)
@@ -44,6 +44,9 @@ typedef uintptr_t uatomicptr_t;
typedef intmax_t atomic_max_t;
typedef uintmax_t uatomic_max_t;
+#define __HAVE_64B_ATOMICS 0
+#define USE_ATOMIC_COMPILER_BUILTINS 0
+
/* prev = *addr;
if (prev == old)
*addr = new;
@@ -36,6 +36,9 @@ typedef uintptr_t uatomicptr_t;
typedef intmax_t atomic_max_t;
typedef uintmax_t uatomic_max_t;
+#define __HAVE_64B_ATOMICS 0
+#define USE_ATOMIC_COMPILER_BUILTINS 0
+
/* The only basic operation needed is compare and exchange. */
/* For ColdFire we'll have to trap into the kernel mode anyway,
so trap from the library rather then from the kernel wrapper. */
@@ -44,6 +44,9 @@ typedef uintptr_t uatomicptr_t;
typedef intmax_t atomic_max_t;
typedef uintmax_t uatomic_max_t;
+#define __HAVE_64B_ATOMICS 0
+#define USE_ATOMIC_COMPILER_BUILTINS 0
+
/* SH kernel has implemented a gUSA ("g" User Space Atomicity) support
for the user space atomicity. The atomicity macros use this scheme.
@@ -55,6 +55,12 @@ typedef uintmax_t uatomic_max_t;
# endif
#endif
+#define __HAVE_64B_ATOMICS 1
+#if __GNUC_PREREQ (4, 7)
+#define USE_ATOMIC_COMPILER_BUILTINS 1
+#else
+#define USE_ATOMIC_COMPILER_BUILTINS 0
+#endif
#define atomic_compare_and_exchange_val_acq(mem, newval, oldval) \
__sync_val_compare_and_swap (mem, oldval, newval)