]> git.ipfire.org Git - thirdparty/glibc.git/commitdiff
atomic: Reinstate HAVE_64B_ATOMICS configure check
authorWilco Dijkstra <wilco.dijkstra@arm.com>
Mon, 15 Dec 2025 13:56:14 +0000 (13:56 +0000)
committerWilco Dijkstra <wilco.dijkstra@arm.com>
Wed, 17 Dec 2025 22:57:00 +0000 (22:57 +0000)
Reinstate HAVE_64B_ATOMICS configure check that was reverted by commit
7fec8a5de6826ef9ae440238d698f0fe5a5fb372 due to BZ #33632.  This was
fixed by 3dd2cbfa35e0e6e0345633079bd5a83bb822c2d8 by only allowing
64-bit atomics on sem_t if its type is 8-byte aligned.  Rebase and add
in cleanups in include/atomic.h that were omitted.

Fix an issue with sparcv8-linux-gnu-leon3 forcing -mcpu=v8 for rtld.c which
overrules -mcpu=leon3 and causes __atomic_always_lock_free (4, 0) to
incorrectly return 0 and trigger asserts in atomics.  Remove this as it
seems to be a workaround for an issue in 1997.

Reviewed-by: Adhemerval Zanella  <adhemerval.zanella@linaro.org>
16 files changed:
config.h.in
configure
configure.ac
include/atomic.h
include/atomic_wide_counter.h
misc/atomic_wide_counter.c
nptl/pthread_cond_common.c
stdlib/setenv.h
sysdeps/alpha/atomic-machine.h
sysdeps/generic/atomic-machine.h
sysdeps/generic/atomic-sem_t.h
sysdeps/nptl/rseq-access.h
sysdeps/riscv/atomic-machine.h
sysdeps/sparc/atomic-machine.h
sysdeps/unix/sysv/linux/sparc/sparc32/Makefile
sysdeps/x86/atomic-machine.h

index abc215850d00da8d8d101b699f13d996af8a60c1..2cd8c90eb663bd5d6b215ccd7ca5cfed6a683f47 100644 (file)
 /* Define if __builtin_fmod/__builtin_remainder is inlined on x86.  */
 #undef HAVE_X86_INLINE_FMOD
 
+/* Set to 1 if 64 bit atomics are supported.  */
+#undef HAVE_64B_ATOMICS
+
 /*
 \f */
 
index aa92a122b1818040976f097d2ebdf7270cf9734f..0cd2269859c972ef26037992d859310c51073628 100755 (executable)
--- a/configure
+++ b/configure
@@ -7679,6 +7679,48 @@ if test "$libc_cv_gcc_builtin_memset" = yes ; then
 
 fi
 
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for 64-bit atomic support" >&5
+printf %s "checking for 64-bit atomic support... " >&6; }
+if test ${libc_cv_gcc_has_64b_atomics+y}
+then :
+  printf %s "(cached) " >&6
+else case e in #(
+  e) cat > conftest.c <<\EOF
+typedef struct { long long t; } X;
+extern void has_64b_atomics(void);
+void f(void)
+{
+  X x;
+  /* Use address of structure with 64-bit type.  This avoids incorrect
+     implementations which return true even if long long is not 64-bit aligned.
+     This works on GCC and LLVM - other cases have bugs and they disagree.  */
+  _Static_assert (__atomic_always_lock_free (sizeof (x), &x), "no_64b_atomics");
+}
+EOF
+if { ac_try='${CC-cc} -O2 -S conftest.c'
+  { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_try\""; } >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; }; };
+then
+  libc_cv_gcc_has_64b_atomics=yes
+else
+  libc_cv_gcc_has_64b_atomics=no
+fi
+rm -f conftest*  ;;
+esac
+fi
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $libc_cv_gcc_has_64b_atomics" >&5
+printf "%s\n" "$libc_cv_gcc_has_64b_atomics" >&6; }
+if test "$libc_cv_gcc_has_64b_atomics" = yes; then
+  printf "%s\n" "#define HAVE_64B_ATOMICS 1" >>confdefs.h
+
+else
+  printf "%s\n" "#define HAVE_64B_ATOMICS 0" >>confdefs.h
+
+fi
+
 { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for compiler option to disable generation of FMA instructions" >&5
 printf %s "checking for compiler option to disable generation of FMA instructions... " >&6; }
 if test ${libc_cv_cc_nofma+y}
index ab355fa266ea498c1ea5029f41ad6063f7e7939d..3e4a601c01fc4a82f500edc143c2994b60971bff 100644 (file)
@@ -1485,6 +1485,33 @@ if test "$libc_cv_gcc_builtin_memset" = yes ; then
   AC_DEFINE(HAVE_BUILTIN_MEMSET)
 fi
 
+AC_CACHE_CHECK(for 64-bit atomic support, libc_cv_gcc_has_64b_atomics, [dnl
+cat > conftest.c <<\EOF
+typedef struct { long long t; } X;
+extern void has_64b_atomics(void);
+void f(void)
+{
+  X x;
+  /* Use address of structure with 64-bit type.  This avoids incorrect
+     implementations which return true even if long long is not 64-bit aligned.
+     This works on GCC and LLVM - other cases have bugs and they disagree.  */
+  _Static_assert (__atomic_always_lock_free (sizeof (x), &x), "no_64b_atomics");
+}
+EOF
+dnl
+if AC_TRY_COMMAND([${CC-cc} -O2 -S conftest.c]);
+then
+  libc_cv_gcc_has_64b_atomics=yes
+else
+  libc_cv_gcc_has_64b_atomics=no
+fi
+rm -f conftest* ])
+if test "$libc_cv_gcc_has_64b_atomics" = yes; then
+  AC_DEFINE(HAVE_64B_ATOMICS, 1)
+else
+  AC_DEFINE(HAVE_64B_ATOMICS, 0)
+fi
+
 dnl Determine how to disable generation of FMA instructions.
 AC_CACHE_CHECK([for compiler option to disable generation of FMA instructions],
               libc_cv_cc_nofma, [dnl
index ed0dfbde3f98af4e9bb094c64c585d4b88891794..d7f9469ffe9d015007773b16227508700ce21a5f 100644 (file)
    - support functions like barriers.  They also have the prefix
      "atomic_".
 
-   Architectures must provide a few lowlevel macros (the compare
-   and exchange definitions).  All others are optional.  They
-   should only be provided if the architecture has specific
-   support for the operation.
-
    As <atomic.h> macros are usually heavily nested and often use local
    variables to make sure side-effects are evaluated properly, use for
    macro local variables a per-macro unique prefix.  This file uses
@@ -42,7 +37,6 @@
 #include <atomic-machine.h>
 
 
-# undef atomic_compare_and_exchange_val_acq
 # define atomic_compare_and_exchange_val_acq(mem, newval, oldval) \
   ({                                                                         \
      __typeof (*(mem)) __atg3_old = (oldval);                                \
@@ -50,7 +44,6 @@
      __atg3_old;                                                             \
   })
 
-# undef atomic_compare_and_exchange_val_rel
 # define atomic_compare_and_exchange_val_rel(mem, newval, oldval)            \
   ({                                                                         \
      __typeof (*(mem)) __atg3_old = (oldval);                                \
@@ -58,7 +51,6 @@
      __atg3_old;                                                             \
   })
 
-# undef atomic_compare_and_exchange_bool_acq
 # define atomic_compare_and_exchange_bool_acq(mem, newval, oldval) \
   ({                                                                         \
      __typeof (*(mem)) __atg3_old = (oldval);                                \
    C11.  Usually, a function named atomic_OP_MO(args) is equivalent to C11's
    atomic_OP_explicit(args, memory_order_MO); exceptions noted below.  */
 
-/* We require 32b atomic operations; some archs also support 64b atomic
-   operations.  */
-void __atomic_link_error (void);
-# if USE_64B_ATOMICS == 1
-#  define __atomic_check_size(mem) \
-   if ((sizeof (*mem) != 4) && (sizeof (*mem) != 8))                         \
-     __atomic_link_error ();
-# else
-#  define __atomic_check_size(mem) \
-   if (sizeof (*mem) != 4)                                                   \
-     __atomic_link_error ();
-# endif
-/* We additionally provide 8b and 16b atomic loads and stores; we do not yet
-   need other atomic operations of such sizes, and restricting the support to
-   loads and stores makes this easier for archs that do not have native
-   support for atomic operations to less-than-word-sized data.  */
-# if USE_64B_ATOMICS == 1
-#  define __atomic_check_size_ls(mem) \
-   if ((sizeof (*mem) != 1) && (sizeof (*mem) != 2) && (sizeof (*mem) != 4)   \
-       && (sizeof (*mem) != 8))                                                      \
-     __atomic_link_error ();
-# else
-#  define __atomic_check_size_ls(mem) \
-   if ((sizeof (*mem) != 1) && (sizeof (*mem) != 2) && sizeof (*mem) != 4)    \
-     __atomic_link_error ();
-# endif
-
-# define atomic_thread_fence_acquire() \
-  __atomic_thread_fence (__ATOMIC_ACQUIRE)
-# define atomic_thread_fence_release() \
-  __atomic_thread_fence (__ATOMIC_RELEASE)
-# define atomic_thread_fence_seq_cst() \
-  __atomic_thread_fence (__ATOMIC_SEQ_CST)
+/* Check atomic operations are lock free.  Since this doesn't work correctly
+   on all targets (eg. if uint64_t is 4-byte aligned), use__HAVE_64B_ATOMICS
+   for 64-bit types.  */
+#define __atomic_check_size(mem) \
+  _Static_assert (__atomic_always_lock_free (sizeof (*(mem)), 0) &&          \
+                 !(sizeof (*(mem)) == 8 && HAVE_64B_ATOMICS == 0),           \
+                 "atomic not lock free!")
+
+#define atomic_thread_fence_acquire() __atomic_thread_fence (__ATOMIC_ACQUIRE)
+#define atomic_thread_fence_release() __atomic_thread_fence (__ATOMIC_RELEASE)
+#define atomic_thread_fence_seq_cst() __atomic_thread_fence (__ATOMIC_SEQ_CST)
 
 # define atomic_load_relaxed(mem) \
-  ({ __atomic_check_size_ls((mem));                                          \
+  ({ __atomic_check_size((mem));                                             \
      __atomic_load_n ((mem), __ATOMIC_RELAXED); })
 # define atomic_load_acquire(mem) \
-  ({ __atomic_check_size_ls((mem));                                          \
+  ({ __atomic_check_size((mem));                                             \
      __atomic_load_n ((mem), __ATOMIC_ACQUIRE); })
 
 # define atomic_store_relaxed(mem, val) \
   do {                                                                       \
-    __atomic_check_size_ls((mem));                                           \
+    __atomic_check_size((mem));                                                      \
     __atomic_store_n ((mem), (val), __ATOMIC_RELAXED);                       \
   } while (0)
 # define atomic_store_release(mem, val) \
   do {                                                                       \
-    __atomic_check_size_ls((mem));                                           \
+    __atomic_check_size((mem));                                                      \
     __atomic_store_n ((mem), (val), __ATOMIC_RELEASE);                       \
   } while (0)
 
index 5b1979e6019499f891603168acf5152048ace331..106701c88a38b60410cb858ce03c60ffa05f969a 100644 (file)
@@ -22,7 +22,7 @@
 #include <atomic.h>
 #include <bits/atomic_wide_counter.h>
 
-#if USE_64B_ATOMICS
+#if HAVE_64B_ATOMICS
 
 static inline uint64_t
 __atomic_wide_counter_load_relaxed (__atomic_wide_counter *c)
@@ -65,7 +65,7 @@ __atomic_wide_counter_fetch_xor_release (__atomic_wide_counter *c,
   return atomic_fetch_xor_release (&c->__value64, val);
 }
 
-#else /* !USE_64B_ATOMICS */
+#else /* !HAVE_64B_ATOMICS */
 
 uint64_t __atomic_wide_counter_load_relaxed (__atomic_wide_counter *c)
   attribute_hidden;
@@ -98,6 +98,6 @@ __atomic_wide_counter_add_relaxed (__atomic_wide_counter *c,
   __atomic_wide_counter_fetch_add_relaxed (c, val);
 }
 
-#endif /* !USE_64B_ATOMICS */
+#endif /* !HAVE_64B_ATOMICS */
 
 #endif /* _ATOMIC_WIDE_COUNTER_H */
index 65f4288db29387ceb2801ee0edd5cc469854b058..7bdf4f0d2f9d22c267d5c3e037a8e6d76de1b00e 100644 (file)
@@ -18,7 +18,7 @@
 
 #include <atomic_wide_counter.h>
 
-#if !USE_64B_ATOMICS
+#if !HAVE_64B_ATOMICS
 
 /* Values we add or xor are less than or equal to 1<<31, so we only
    have to make overflow-and-addition atomic wrt. to concurrent load
@@ -124,4 +124,4 @@ __atomic_wide_counter_load_relaxed (__atomic_wide_counter *c)
   return ((uint64_t) (h & ~((unsigned int) 1 << 31)) << 31) + l;
 }
 
-#endif /* !USE_64B_ATOMICS */
+#endif /* !HAVE_64B_ATOMICS */
index de3580b56fdaeeb53e8146d5479dce5e5e1f663c..60bec96ee571f8416e3cc6b2c90d0f115aea8d5c 100644 (file)
@@ -52,7 +52,7 @@ __condvar_add_g1_start_relaxed (pthread_cond_t *cond, unsigned int val)
   __atomic_wide_counter_add_relaxed (&cond->__data.__g1_start, val);
 }
 
-#if USE_64B_ATOMICS == 1
+#if HAVE_64B_ATOMICS == 1
 
 static inline uint64_t
 __condvar_fetch_xor_wseq_release (pthread_cond_t *cond, unsigned int val)
@@ -60,7 +60,7 @@ __condvar_fetch_xor_wseq_release (pthread_cond_t *cond, unsigned int val)
   return atomic_fetch_xor_release (&cond->__data.__wseq.__value64, val);
 }
 
-#else /* !USE_64B_ATOMICS */
+#else /* !HAVE_64B_ATOMICS */
 
 /* The xor operation needs to be an atomic read-modify-write.  The write
    itself is not an issue as it affects just the lower-order half but not bits
@@ -103,7 +103,7 @@ __condvar_fetch_xor_wseq_release (pthread_cond_t *cond, unsigned int val)
   return ((uint64_t) h << 31) + l2;
 }
 
-#endif /* !USE_64B_ATOMICS */
+#endif /* !HAVE_64B_ATOMICS */
 
 /* The lock that signalers use.  See pthread_cond_wait_common for uses.
    The lock is our normal three-state lock: not acquired (0) / acquired (1) /
index aed97efd4e3a6deb66bdc56e59a64f2d0b4e67c1..07ac97b9061fdc57a394bb0f2bc93de541057b23 100644 (file)
@@ -61,7 +61,7 @@ __environ_is_from_array_list (char **ep)
    but given that counter wrapround is probably impossible to hit
    (2**32 operations in unsetenv concurrently with getenv), using
    <atomic_wide_counter.h> seems unnecessary.  */
-#if USE_64B_ATOMICS
+#if HAVE_64B_ATOMICS
 typedef uint64_t environ_counter;
 #else
 typedef uint32_t environ_counter;
index b7ce8c4726d0a6aa2ab770afc35924e5f1d6d51e..df981d5881c5444c222922e2cbd97ea773481be5 100644 (file)
@@ -18,7 +18,7 @@
 #ifndef _ALPHA_ATOMIC_MACHINE_H
 #define _ALPHA_ATOMIC_MACHINE_H
 
-#include_next <atomic-machine.h>
+#include <stdint.h>
 
 #define atomic_write_barrier() __asm ("wmb" : : : "memory");
 
index ef72d9ba0d43994d94b9249b146de3519af0beac..9f8528c1f2a7943405d83296760bfe9c7a7d6a65 100644 (file)
      and adaptive mutexes to optimize spin-wait loops.
 */
 
-#include <bits/wordsize.h>
-
-/* NB: The NPTL semaphore code casts a sem_t to a new_sem and issues a 64-bit
-   atomic operation for USE_64B_ATOMICS.  However, the sem_t has 32-bit
-   alignment on 32-bit architectures, which prevents using 64-bit atomics even
-   if the ABI supports it.  */
-#if __WORDSIZE == 64
-# define USE_64B_ATOMICS 1
-#else
-# define USE_64B_ATOMICS 0
-#endif
-
 #endif /* atomic-machine.h */
index 6205cc4f6b00d8d218eb6ef14356f9e064bbb2b6..a5d32cac001ae2a9e7ea7edf71f9698b1be2dff8 100644 (file)
@@ -18,8 +18,8 @@
 #include <atomic-machine.h>
 #include <sem_t-align.h>
 
-#if USE_64B_ATOMICS && (SEM_T_ALIGN >= 8 \
-                       || defined HAVE_UNALIGNED_64B_ATOMICS)
+#if HAVE_64B_ATOMICS && (SEM_T_ALIGN >= 8 \
+                        || defined HAVE_UNALIGNED_64B_ATOMICS)
 # define USE_64B_ATOMICS_ON_SEM_T 1
 #else
 # define USE_64B_ATOMICS_ON_SEM_T 0
index 451cbf2743f32b2d22a586fe67fe99c06b0f5a40..17e7a68e0ba119cce18cfb672d58cc10529f76bc 100644 (file)
@@ -28,7 +28,7 @@
 
 /* Static assert for types that can't be loaded/stored atomically on the
    current architecture.  */
-#if USE_64B_ATOMICS
+#if HAVE_64B_ATOMICS
 #define __RSEQ_ASSERT_ATOMIC(member) \
    _Static_assert (sizeof (RSEQ_SELF()->member) == 1                         \
                   || sizeof (RSEQ_SELF()->member) == 4                       \
index e375c6665e978393654040044f096ece2ce3e592..b6494b3c83703b46c40e8a47e9011d96202dd770 100644 (file)
@@ -21,8 +21,6 @@
 
 #ifdef __riscv_atomic
 
-#include_next <atomic-machine.h>
-
 /* Miscellaneous.  */
 
 # define asm_amo(which, ordering, mem, value) ({               \
index 2ffcbb2fcf3f3ed4b56c9b87556d48b69c2bad10..92b3ebdf6e16447cd5035084e7e574cddf0ea456 100644 (file)
@@ -17,9 +17,7 @@
    <https://www.gnu.org/licenses/>.  */
 
 #ifndef _SPARC_ATOMIC_MACHINE_H
-#define _SPARC_ATOMIC_MACHINE_H        1
-
-#include_next <atomic-machine.h>
+#define _SPARC_ATOMIC_MACHINE_H
 
 #ifdef __sparc_v9__
 # define atomic_full_barrier() \
@@ -34,4 +32,4 @@ extern void __cpu_relax (void);
 # define atomic_spin_nop() __cpu_relax ()
 #endif
 
-#endif /* _ATOMIC_MACHINE_H  */
+#endif
index 167307cc78a95e86fa6f06ead1feb906980d361b..133704a57f3859057a984c104fb566fec50cdf30 100644 (file)
@@ -9,12 +9,6 @@ ifeq ($(subdir),stdlib)
 gen-as-const-headers += ucontext_i.sym
 endif
 
-# When I get this to work, this is the right thing
-ifeq ($(subdir),elf)
-CFLAGS-rtld.c += -mcpu=v8
-#rtld-routines += dl-sysdepsparc
-endif   # elf
-
 ifeq ($(subdir),math)
 # These 2 routines are normally in libgcc{.a,_s.so.1}.
 # However, sparc32 -mlong-double-128 libgcc relies on
index cfa6b62d323fb72b2be1e55e2ed2c2baf6431f00..0681f57987939ee44a6cfc2e2cee0c573435b1e2 100644 (file)
 #ifndef _X86_ATOMIC_MACHINE_H
 #define _X86_ATOMIC_MACHINE_H 1
 
-#ifdef __x86_64__
-# define USE_64B_ATOMICS               1
-#else
-# define USE_64B_ATOMICS               0
-#endif
-
 #define atomic_spin_nop() __asm ("pause")
 
 #endif /* atomic-machine.h */