[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