From 39f141df5ebf38599c20f1687551e45213463251 Mon Sep 17 00:00:00 2001 From: Jameson Nash Date: Sat, 9 Mar 2024 13:41:47 -0500 Subject: [PATCH] increase max atomic size to 16 on 64-bit platforms (#42268) --- src/Makefile | 2 +- src/datatype.c | 5 +++-- src/julia.h | 11 ++++++++--- test/intrinsics.jl | 2 +- 4 files changed, 13 insertions(+), 7 deletions(-) diff --git a/src/Makefile b/src/Makefile index ce81ff03cdd70..72895e9a8080c 100644 --- a/src/Makefile +++ b/src/Makefile @@ -26,7 +26,7 @@ endif JCFLAGS += -Wold-style-definition -Wstrict-prototypes -Wc++-compat ifeq ($(USECLANG),1) -FLAGS += -Wno-return-type-c-linkage +FLAGS += -Wno-return-type-c-linkage -Wno-atomic-alignment endif FLAGS += -DJL_BUILD_ARCH='"$(ARCH)"' diff --git a/src/datatype.c b/src/datatype.c index f9f7dec3d1b13..80668063bb8ba 100644 --- a/src/datatype.c +++ b/src/datatype.c @@ -8,6 +8,7 @@ #include #include #include +#include #include "julia.h" #include "julia_internal.h" #include "julia_assert.h" @@ -1012,7 +1013,7 @@ JL_DLLEXPORT int jl_is_foreign_type(jl_datatype_t *dt) #if MAX_POINTERATOMIC_SIZE >= 16 typedef struct _jl_uint128_t { - uint64_t a; + alignas(16) uint64_t a; uint64_t b; } jl_uint128_t; #endif @@ -1356,7 +1357,7 @@ JL_DLLEXPORT int jl_atomic_storeonce_bits(jl_datatype_t *dt, char *dst, const jl #endif #if MAX_POINTERATOMIC_SIZE >= 16 else if (nb <= 16) { - jl_uint128_t y128 = 0; + jl_uint128_t y128 = {0}; jl_uint128_t z128 = zext_read128(src, nb); while (1) { success = jl_atomic_cmpswap((_Atomic(jl_uint128_t)*)dst, &y128, z128); diff --git a/src/julia.h b/src/julia.h index 5c3a983367470..7d246d25cc767 100644 --- a/src/julia.h +++ b/src/julia.h @@ -46,11 +46,16 @@ #endif // Define the largest size (bytes) of a properly aligned object that the -// processor family and compiler typically supports without a lock -// (assumed to be at least a pointer size). Since C is bad at handling 16-byte -// types, we currently use 8 here as the default. +// processor family (MAX_ATOMIC_SIZE) and compiler (MAX_POINTERATOMIC_SIZE) +// typically supports without a lock (assumed to be at least a pointer size) +// with MAX_POINTERATOMIC_SIZE >= MAX_ATOMIC_SIZE. +#ifdef _P64 +#define MAX_ATOMIC_SIZE 16 +#define MAX_POINTERATOMIC_SIZE 16 +#else #define MAX_ATOMIC_SIZE 8 #define MAX_POINTERATOMIC_SIZE 8 +#endif #ifdef _P64 #define NWORDS(sz) (((sz)+7)>>3) diff --git a/test/intrinsics.jl b/test/intrinsics.jl index 8e4ab932f5eb6..6fbe4e5364354 100644 --- a/test/intrinsics.jl +++ b/test/intrinsics.jl @@ -220,7 +220,7 @@ for TT in (Int8, Int16, Int32, Int64, Int128, Int256, Int512, Complex{Int32}, Co @test_throws TypeError Core.Intrinsics.atomic_pointerreplace(p, T(10), S(3), :sequentially_consistent, :sequentially_consistent) end @test Core.Intrinsics.pointerref(p, 1, 1) === T(10) === r[] - if sizeof(r) > 8 + if sizeof(r) > 2*sizeof(Int) @test_throws ErrorException("atomic_pointerref: invalid pointer for atomic operation") unsafe_load(p, :sequentially_consistent) @test_throws ErrorException("atomic_pointerset: invalid pointer for atomic operation") unsafe_store!(p, T(1), :sequentially_consistent) @test_throws ErrorException("atomic_pointerswap: invalid pointer for atomic operation") unsafe_swap!(p, T(100), :sequentially_consistent)