diff options
author | David Vašek <david.vasek@nic.cz> | 2024-05-05 11:12:39 +0200 |
---|---|---|
committer | David Vašek <david.vasek@nic.cz> | 2024-05-06 14:34:51 +0200 |
commit | 3f2f89ade100396c1a381d3f2cdf09582731c7e8 (patch) | |
tree | c2f2a3a4786d2b917bb2a9c6602494e33d51b157 /tests/contrib/test_atomic.c | |
parent | tests/atomic: finish the thread early once an invalid value occurs (diff) | |
download | knot-3f2f89ade100396c1a381d3f2cdf09582731c7e8.tar.xz knot-3f2f89ade100396c1a381d3f2cdf09582731c7e8.zip |
tests/atomic: workaround for a GCC optimization bug on i386
With -O1 and higher, the test of atomic_exchange_explicit() doesn't work right for 64-bit variables
on i386 (and possibly other 32-bit architectures). It seems that atomic_exchange_explicit() doesn't
exchange 64-bit values properly when it's used in a loop and GCC compiler optimization is turned
on. As a workaround, we are testing ATOMIC_XCHG on a pointer size of the given architecture.
It isn't sure yet, if atomic_exchange_explicit() is safe for 64-bit variables with GCC on i386 when
not used in a loop. Therefore, ATOMIC_XCHG should not be used on general 64-bit variables until
this GCC bug is solved.
Clang and gcc -O0 don't seem to be affected by this issue.
Diffstat (limited to 'tests/contrib/test_atomic.c')
-rw-r--r-- | tests/contrib/test_atomic.c | 23 |
1 files changed, 13 insertions, 10 deletions
diff --git a/tests/contrib/test_atomic.c b/tests/contrib/test_atomic.c index 4ba93c822..c5b81dfb3 100644 --- a/tests/contrib/test_atomic.c +++ b/tests/contrib/test_atomic.c @@ -27,10 +27,13 @@ #define CYCLES3 100000 #define UPPER 0xffffffff00000000 #define LOWER 0x00000000ffffffff +#define UPPER_PTR ((void *) UPPER) +#define LOWER_PTR ((void *) LOWER) static volatile knot_atomic_uint64_t counter_add = 0; static volatile knot_atomic_uint64_t counter_sub = 0; static volatile knot_atomic_uint64_t atomic_var; +static volatile knot_atomic_ptr_t atomic_var2; static int errors = 0; static int uppers = 0; static int lowers = 0; @@ -67,10 +70,10 @@ static int thread_set(struct dthread *thread) static int thread_xchg(struct dthread *thread) { - u_int64_t val = (dt_get_id(thread) % 2) ? UPPER : LOWER; + void *val = (dt_get_id(thread) % 2) ? UPPER_PTR : LOWER_PTR; pthread_mutex_lock(&mx); - if (val == UPPER) { + if (val == UPPER_PTR) { uppers++; } else { lowers++; @@ -78,8 +81,8 @@ static int thread_xchg(struct dthread *thread) pthread_mutex_unlock(&mx); for (int i = 0; i < CYCLES3; i++) { - val = ATOMIC_XCHG(atomic_var, val); - if (val != UPPER && val != LOWER) { + val = ATOMIC_XCHG(atomic_var2, val); + if (val != UPPER_PTR && val != LOWER_PTR) { // Non-atomic counter, won't be accurate! // However, it's sufficient for fault detection. errors++; @@ -88,9 +91,9 @@ static int thread_xchg(struct dthread *thread) } pthread_mutex_lock(&mx); - if (val == UPPER) { + if (val == UPPER_PTR) { uppers_count++; - } else if (val == LOWER) { + } else if (val == LOWER_PTR) { lowers_count++; }; pthread_mutex_unlock(&mx); @@ -132,7 +135,7 @@ int main(int argc, char *argv[]) is_int(0, errors, "atomicity of ATOMIC_SET / ATOMIC_GET"); // Test for atomicity of ATOMIC_XCHG. - atomic_var = UPPER; + atomic_var2 = UPPER_PTR; uppers++; errors = 0; @@ -143,17 +146,17 @@ int main(int argc, char *argv[]) dt_delete(&unit); pthread_mutex_destroy(&mx); - if (atomic_var == UPPER) { + if (atomic_var2 == UPPER_PTR) { uppers_count++; - } else if (atomic_var == LOWER) { + } else if (atomic_var2 == LOWER_PTR) { lowers_count++; } else { errors++; } is_int(0, errors, "set/get atomicity of ATOMIC_XCHG"); - is_int(lowers, lowers_count, "atomicity of ATOMIC_XCHG"); is_int(uppers, uppers_count, "atomicity of ATOMIC_XCHG"); + is_int(lowers, lowers_count, "atomicity of ATOMIC_XCHG"); return 0; } |