[PATCH] atomic: Reinstate HAVE_64B_ATOMICS configure check

Andreas K. Huettel dilfridge@gentoo.org
Wed Dec 17 00:10:11 GMT 2025


Am Dienstag, 16. Dezember 2025, 16:08:11 Mitteleuropäische Normalzeit schrieb Wilco Dijkstra:
> 
> Reinstate HAVE_64B_ATOMICS configure check that was reverted by commit
> 7fec8a5de6826ef9ae440238d698f0fe5a5fb372.  Rebase and add in cleanups
> in include/atomic.h that were omitted.

Maybe write a sentence or two why it now can be reinstated?

(because of code support in 3dd2cbfa35e0e6e0345633079bd5a83bb822c2d8 and 
runtime check in 83dd79dffbcdd0ad57bf5471fbc1a3fd1d4e7e9a ?)

> 
> Passes buildmanyglibc (with trivial fix for leon3).
> 
> OK for commit?
> 
> ---
> 
> diff --git a/config.h.in b/config.h.in
> index abc215850d00da8d8d101b699f13d996af8a60c1..2cd8c90eb663bd5d6b215ccd7ca5cfed6a683f47 100644
> --- a/config.h.in
> +++ b/config.h.in
> @@ -225,6 +225,9 @@
>  /* 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
> +
>  /*
>  
 */
>  
> diff --git a/configure b/configure
> index aa92a122b1818040976f097d2ebdf7270cf9734f..0cd2269859c972ef26037992d859310c51073628 100755
> --- 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}
> diff --git a/configure.ac b/configure.ac
> index ab355fa266ea498c1ea5029f41ad6063f7e7939d..3e4a601c01fc4a82f500edc143c2994b60971bff 100644
> --- a/configure.ac
> +++ b/configure.ac
> @@ -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
> diff --git a/include/atomic.h b/include/atomic.h
> index ed0dfbde3f98af4e9bb094c64c585d4b88891794..d7f9469ffe9d015007773b16227508700ce21a5f 100644
> --- a/include/atomic.h
> +++ b/include/atomic.h
> @@ -27,11 +27,6 @@
>     - 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);				      \
> @@ -121,55 +113,33 @@
>     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)
>  
> diff --git a/include/atomic_wide_counter.h b/include/atomic_wide_counter.h
> index 5b1979e6019499f891603168acf5152048ace331..106701c88a38b60410cb858ce03c60ffa05f969a 100644
> --- a/include/atomic_wide_counter.h
> +++ b/include/atomic_wide_counter.h
> @@ -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 */
> diff --git a/misc/atomic_wide_counter.c b/misc/atomic_wide_counter.c
> index 65f4288db29387ceb2801ee0edd5cc469854b058..7bdf4f0d2f9d22c267d5c3e037a8e6d76de1b00e 100644
> --- a/misc/atomic_wide_counter.c
> +++ b/misc/atomic_wide_counter.c
> @@ -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 */
> diff --git a/nptl/pthread_cond_common.c b/nptl/pthread_cond_common.c
> index de3580b56fdaeeb53e8146d5479dce5e5e1f663c..60bec96ee571f8416e3cc6b2c90d0f115aea8d5c 100644
> --- a/nptl/pthread_cond_common.c
> +++ b/nptl/pthread_cond_common.c
> @@ -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) /
> diff --git a/stdlib/setenv.h b/stdlib/setenv.h
> index aed97efd4e3a6deb66bdc56e59a64f2d0b4e67c1..07ac97b9061fdc57a394bb0f2bc93de541057b23 100644
> --- a/stdlib/setenv.h
> +++ b/stdlib/setenv.h
> @@ -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;
> diff --git a/sysdeps/alpha/atomic-machine.h b/sysdeps/alpha/atomic-machine.h
> index b7ce8c4726d0a6aa2ab770afc35924e5f1d6d51e..9aec23174881f2396be65aa9619742387b7ca726 100644
> --- a/sysdeps/alpha/atomic-machine.h
> +++ b/sysdeps/alpha/atomic-machine.h
> @@ -15,11 +15,6 @@
>     License along with the GNU C Library.  If not, see
>     <https://www.gnu.org/licenses/>.  */
>  
> -#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");
> -
> -#endif
> diff --git a/sysdeps/generic/atomic-machine.h b/sysdeps/generic/atomic-machine.h
> index ef72d9ba0d43994d94b9249b146de3519af0beac..9f8528c1f2a7943405d83296760bfe9c7a7d6a65 100644
> --- a/sysdeps/generic/atomic-machine.h
> +++ b/sysdeps/generic/atomic-machine.h
> @@ -34,16 +34,4 @@
>       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 */
> diff --git a/sysdeps/generic/atomic-sem_t.h b/sysdeps/generic/atomic-sem_t.h
> index 6205cc4f6b00d8d218eb6ef14356f9e064bbb2b6..a5d32cac001ae2a9e7ea7edf71f9698b1be2dff8 100644
> --- a/sysdeps/generic/atomic-sem_t.h
> +++ b/sysdeps/generic/atomic-sem_t.h
> @@ -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
> diff --git a/sysdeps/nptl/rseq-access.h b/sysdeps/nptl/rseq-access.h
> index 451cbf2743f32b2d22a586fe67fe99c06b0f5a40..17e7a68e0ba119cce18cfb672d58cc10529f76bc 100644
> --- a/sysdeps/nptl/rseq-access.h
> +++ b/sysdeps/nptl/rseq-access.h
> @@ -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			      \
> diff --git a/sysdeps/riscv/atomic-machine.h b/sysdeps/riscv/atomic-machine.h
> index e375c6665e978393654040044f096ece2ce3e592..b6494b3c83703b46c40e8a47e9011d96202dd770 100644
> --- a/sysdeps/riscv/atomic-machine.h
> +++ b/sysdeps/riscv/atomic-machine.h
> @@ -21,8 +21,6 @@
>  
>  #ifdef __riscv_atomic
>  
> -#include_next <atomic-machine.h>
> -
>  /* Miscellaneous.  */
>  
>  # define asm_amo(which, ordering, mem, value) ({ 		\
> diff --git a/sysdeps/sparc/atomic-machine.h b/sysdeps/sparc/atomic-machine.h
> index 2ffcbb2fcf3f3ed4b56c9b87556d48b69c2bad10..b8c1e96eb468a659f8cfab682f73894f42ddff76 100644
> --- a/sysdeps/sparc/atomic-machine.h
> +++ b/sysdeps/sparc/atomic-machine.h
> @@ -16,10 +16,8 @@
>     License along with the GNU C Library; if not, see
>     <https://www.gnu.org/licenses/>.  */
>  
> -#ifndef _SPARC_ATOMIC_MACHINE_H
> -#define _SPARC_ATOMIC_MACHINE_H	1
> -
> -#include_next <atomic-machine.h>
> +#ifndef _ATOMIC_MACHINE_H
> +#define _ATOMIC_MACHINE_H	1
>  
>  #ifdef __sparc_v9__
>  # define atomic_full_barrier() \
> diff --git a/sysdeps/unix/sysv/linux/sparc/sparc32/Makefile b/sysdeps/unix/sysv/linux/sparc/sparc32/Makefile
> index 167307cc78a95e86fa6f06ead1feb906980d361b..88b1383dbb5a203f33a61e66fda0606be1a1b1f2 100644
> --- a/sysdeps/unix/sysv/linux/sparc/sparc32/Makefile
> +++ b/sysdeps/unix/sysv/linux/sparc/sparc32/Makefile
> @@ -11,7 +11,7 @@ endif
>  
>  # When I get this to work, this is the right thing
>  ifeq ($(subdir),elf)
> -CFLAGS-rtld.c += -mcpu=v8
> +#CFLAGS-rtld.c += -mcpu=v8
>  #rtld-routines += dl-sysdepsparc
>  endif   # elf
>  
> diff --git a/sysdeps/x86/atomic-machine.h b/sysdeps/x86/atomic-machine.h
> index cfa6b62d323fb72b2be1e55e2ed2c2baf6431f00..0681f57987939ee44a6cfc2e2cee0c573435b1e2 100644
> --- a/sysdeps/x86/atomic-machine.h
> +++ b/sysdeps/x86/atomic-machine.h
> @@ -19,12 +19,6 @@
>  #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 */
> 
> 
> 


-- 
Andreas K. Hüttel
dilfridge@gentoo.org
Gentoo Linux developer
(council, toolchain, base-system, perl, libreoffice)
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 981 bytes
Desc: This is a digitally signed message part.
URL: <https://sourceware.org/pipermail/libc-alpha/attachments/20251217/a59ae3d7/attachment-0001.sig>


More information about the Libc-alpha mailing list