Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions rumur/resources/header.c
Original file line number Diff line number Diff line change
Expand Up @@ -2462,6 +2462,7 @@ static dword_t atomic_read(dword_t *p) {
* ¹ https://gcc.gnu.org/bugzilla/show_bug.cgi?id=104688
*/
#ifdef __x86_64__
#ifndef __ILP32__
#ifdef __SSE2__
#ifdef __GCC_HAVE_SYNC_COMPARE_AND_SWAP_16
#ifdef __has_include
Expand All @@ -2488,6 +2489,7 @@ static dword_t atomic_read(dword_t *p) {
#endif
#endif
#endif
#endif

#if defined(__x86_64__) || defined(__i386__) || \
(defined(__aarch64__) && defined(__GNUC__) && !defined(__clang__))
Expand Down Expand Up @@ -2522,6 +2524,7 @@ static void atomic_write(dword_t *p, dword_t v) {
* ¹ https://gcc.gnu.org/bugzilla/show_bug.cgi?id=104688
*/
#ifdef __x86_64__
#ifndef __ILP32__
#ifdef __SSE2__
#ifdef __GCC_HAVE_SYNC_COMPARE_AND_SWAP_16
#ifdef __has_include
Expand Down Expand Up @@ -2549,6 +2552,7 @@ static void atomic_write(dword_t *p, dword_t v) {
#endif
#endif
#endif
#endif

#if defined(__x86_64__) || defined(__i386__) || \
(defined(__aarch64__) && defined(__GNUC__) && !defined(__clang__))
Expand Down
77 changes: 77 additions & 0 deletions rumur/src/rumur-run
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,14 @@ def needs_libatomic():

// replicate what is in ../resources/header.c

#ifdef __x86_64__
#ifdef __has_include
#if __has_include(<immintrin.h>)
#include <immintrin.h>
#endif
#endif
#endif

#define THREADS 2

#if __SIZEOF_POINTER__ <= 4
Expand All @@ -117,6 +125,40 @@ static dword_t atomic_read(dword_t *p) {
return *p;
}

/* 128-bit AVX loads are atomic.¹ So use that when possible.
*
* ¹ https://gcc.gnu.org/bugzilla/show_bug.cgi?id=104688
*/
#ifdef __x86_64__
#ifndef __ILP32__
#ifdef __SSE2__
#ifdef __GCC_HAVE_SYNC_COMPARE_AND_SWAP_16
#ifdef __has_include
#if __has_include(<immintrin.h>)
#ifdef __has_feature
/* TSan (falsely, I believe) considers a 128-bit load on a shared variable to
* be a data race
*/
#if !__has_feature(thread_sanitizer)
/* This is the only reliable way I have found of emitting a MOVDQA/MOVAPS.
* Surprisingly the Intel intrinsics for these do not reliably lower to the
* instruction they claim to, and inline assembly results in inefficient
* surrounding logic.
*/
{
typedef __m128i __attribute__((may_alias)) avx128_t;
volatile const avx128_t *const ptr = (const avx128_t *)p;
return (dword_t)*ptr;
}
#endif
#endif
#endif
#endif
#endif
#endif
#endif
#endif

#if defined(__x86_64__) || defined(__i386__) || \
(defined(__aarch64__) && defined(__GNUC__) && !defined(__clang__))
/* x86-64: MOV is not guaranteed to be atomic on 128-bit naturally aligned
Expand Down Expand Up @@ -145,6 +187,41 @@ static void atomic_write(dword_t *p, dword_t v) {
return;
}

/* 128-bit AVX stores are atomic.¹ So use that when possible.
*
* ¹ https://gcc.gnu.org/bugzilla/show_bug.cgi?id=104688
*/
#ifdef __x86_64__
#ifndef __ILP32__
#ifdef __SSE2__
#ifdef __GCC_HAVE_SYNC_COMPARE_AND_SWAP_16
#ifdef __has_include
#if __has_include(<immintrin.h>)
#ifdef __has_feature
/* TSan (falsely, I believe) considers a 128-bit store on a shared variable to
* be a data race
*/
#if !__has_feature(thread_sanitizer)
/* This is the only reliable way I have found of emitting a MOVDQA/MOVAPS.
* Surprisingly the Intel intrinsics for these do not reliably lower to the
* instruction they claim to, and inline assembly results in inefficient
* surrounding logic.
*/
{
typedef __m128i __attribute__((may_alias)) avx128_t;
volatile avx128_t *const ptr = (avx128_t *)p;
*ptr = (__m128i)v;
return;
}
#endif
#endif
#endif
#endif
#endif
#endif
#endif
#endif

#if defined(__x86_64__) || defined(__i386__) || \
(defined(__aarch64__) && defined(__GNUC__) && !defined(__clang__))
/* As explained above, we need some extra gymnastics to avoid a call to
Expand Down
77 changes: 77 additions & 0 deletions tests/tests.py
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,14 @@ def needs_libatomic():

// replicate what is in ../rumur/resources/header.c

#ifdef __x86_64__
#ifdef __has_include
#if __has_include(<immintrin.h>)
#include <immintrin.h>
#endif
#endif
#endif

#define THREADS 2

#if __SIZEOF_POINTER__ <= 4
Expand All @@ -146,6 +154,40 @@ def needs_libatomic():
return *p;
}

/* 128-bit AVX loads are atomic.¹ So use that when possible.
*
* ¹ https://gcc.gnu.org/bugzilla/show_bug.cgi?id=104688
*/
#ifdef __x86_64__
#ifndef __ILP32__
#ifdef __SSE2__
#ifdef __GCC_HAVE_SYNC_COMPARE_AND_SWAP_16
#ifdef __has_include
#if __has_include(<immintrin.h>)
#ifdef __has_feature
/* TSan (falsely, I believe) considers a 128-bit load on a shared variable to
* be a data race
*/
#if !__has_feature(thread_sanitizer)
/* This is the only reliable way I have found of emitting a MOVDQA/MOVAPS.
* Surprisingly the Intel intrinsics for these do not reliably lower to the
* instruction they claim to, and inline assembly results in inefficient
* surrounding logic.
*/
{
typedef __m128i __attribute__((may_alias)) avx128_t;
volatile const avx128_t *const ptr = (const avx128_t *)p;
return (dword_t)*ptr;
}
#endif
#endif
#endif
#endif
#endif
#endif
#endif
#endif

#if defined(__x86_64__) || defined(__i386__) || \\
(defined(__aarch64__) && defined(__GNUC__) && !defined(__clang__))
/* x86-64: MOV is not guaranteed to be atomic on 128-bit naturally aligned
Expand Down Expand Up @@ -174,6 +216,41 @@ def needs_libatomic():
return;
}

/* 128-bit AVX stores are atomic.¹ So use that when possible.
*
* ¹ https://gcc.gnu.org/bugzilla/show_bug.cgi?id=104688
*/
#ifdef __x86_64__
#ifndef __ILP32__
#ifdef __SSE2__
#ifdef __GCC_HAVE_SYNC_COMPARE_AND_SWAP_16
#ifdef __has_include
#if __has_include(<immintrin.h>)
#ifdef __has_feature
/* TSan (falsely, I believe) considers a 128-bit store on a shared variable to
* be a data race
*/
#if !__has_feature(thread_sanitizer)
/* This is the only reliable way I have found of emitting a MOVDQA/MOVAPS.
* Surprisingly the Intel intrinsics for these do not reliably lower to the
* instruction they claim to, and inline assembly results in inefficient
* surrounding logic.
*/
{
typedef __m128i __attribute__((may_alias)) avx128_t;
volatile avx128_t *const ptr = (avx128_t *)p;
*ptr = (__m128i)v;
return;
}
#endif
#endif
#endif
#endif
#endif
#endif
#endif
#endif

#if defined(__x86_64__) || defined(__i386__) || \\
(defined(__aarch64__) && defined(__GNUC__) && !defined(__clang__))
/* As explained above, we need some extra gymnastics to avoid a call to
Expand Down
Loading