summaryrefslogtreecommitdiffstats
path: root/tests/contrib/test_atomic.c
diff options
context:
space:
mode:
authorDavid Vašek <david.vasek@nic.cz>2024-05-05 11:12:39 +0200
committerDavid Vašek <david.vasek@nic.cz>2024-05-06 14:34:51 +0200
commit3f2f89ade100396c1a381d3f2cdf09582731c7e8 (patch)
treec2f2a3a4786d2b917bb2a9c6602494e33d51b157 /tests/contrib/test_atomic.c
parenttests/atomic: finish the thread early once an invalid value occurs (diff)
downloadknot-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.c23
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;
}