summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--lib/frrcu.h2
-rw-r--r--lib/seqlock.c33
-rw-r--r--tests/lib/test_atomlist.c18
-rw-r--r--tests/lib/test_seqlock.c5
4 files changed, 46 insertions, 12 deletions
diff --git a/lib/frrcu.h b/lib/frrcu.h
index 9f07a69b52..81ab5528a9 100644
--- a/lib/frrcu.h
+++ b/lib/frrcu.h
@@ -156,7 +156,7 @@ extern void rcu_enqueue(struct rcu_head *head, const struct rcu_action *action);
#define rcu_call(func, ptr, field) \
do { \
typeof(ptr) _ptr = (ptr); \
- void (*fptype)(typeof(ptr)); \
+ void (*_fptype)(typeof(ptr)); \
struct rcu_head *_rcu_head = &_ptr->field; \
static const struct rcu_action _rcu_action = { \
.type = RCUA_CALL, \
diff --git a/lib/seqlock.c b/lib/seqlock.c
index 62ce316920..e74e6718bf 100644
--- a/lib/seqlock.c
+++ b/lib/seqlock.c
@@ -26,6 +26,39 @@
* OS specific synchronization wrappers *
****************************************/
+#ifndef __has_feature /* not available on old GCC */
+#define __has_feature(x) 0
+#endif
+
+#if (defined(__SANITIZE_THREAD__) || __has_feature(thread_sanitizer))
+/* TSAN really does not understand what is going on with the low-level
+ * futex/umtx calls. This leads to a whole bunch of warnings, a lot of which
+ * also have _extremely_ misleading text - since TSAN does not understand that
+ * there is in fact a synchronization primitive involved, it can end up pulling
+ * in completely unrelated things.
+ *
+ * What does work is the "unsupported platform" seqlock implementation based
+ * on a pthread mutex + condvar, since TSAN of course suppports these.
+ *
+ * It may be possible to also fix this with TSAN annotations (__tsan_acquire
+ * and __tsan_release), but using those (correctly) is not easy either, and
+ * for now just get things rolling.
+ */
+
+#ifdef HAVE_SYNC_LINUX_FUTEX
+#undef HAVE_SYNC_LINUX_FUTEX
+#endif
+
+#ifdef HAVE_SYNC_OPENBSD_FUTEX
+#undef HAVE_SYNC_OPENBSD_FUTEX
+#endif
+
+#ifdef HAVE_SYNC_UMTX_OP
+#undef HAVE_SYNC_UMTX_OP
+#endif
+
+#endif /* TSAN */
+
/*
* Linux: sys_futex()
*/
diff --git a/tests/lib/test_atomlist.c b/tests/lib/test_atomlist.c
index b50216cf92..afcfa98791 100644
--- a/tests/lib/test_atomlist.c
+++ b/tests/lib/test_atomlist.c
@@ -62,7 +62,7 @@ static struct asort_head shead;
static struct testthread {
pthread_t pt;
struct seqlock sqlo;
- size_t counter, nullops;
+ _Atomic size_t counter, nullops;
} thr[NTHREADS];
struct testrun {
@@ -97,10 +97,10 @@ static void trfunc_##name(unsigned int offset) \
{ \
size_t i = 0, n = 0;
-#define endtestrun \
- thr[offset].counter = i; \
- thr[offset].nullops = n; \
-}
+#define endtestrun \
+ atomic_store_explicit(&thr[offset].counter, i, memory_order_seq_cst); \
+ atomic_store_explicit(&thr[offset].nullops, n, memory_order_seq_cst); \
+ }
deftestrun(add, "add vs. add", 0, false)
for (; i < NITEM / NTHREADS; i++)
@@ -288,10 +288,10 @@ static void run_tr(struct testrun *tr)
sv = seqlock_bump(&sqlo) - SEQLOCK_INCR;
for (size_t i = 0; i < NTHREADS; i++) {
seqlock_wait(&thr[i].sqlo, seqlock_cur(&sqlo));
- s += thr[i].counter;
- n += thr[i].nullops;
- thr[i].counter = 0;
- thr[i].nullops = 0;
+ s += atomic_load_explicit(&thr[i].counter, memory_order_seq_cst);
+ n += atomic_load_explicit(&thr[i].nullops, memory_order_seq_cst);
+ atomic_store_explicit(&thr[i].counter, 0, memory_order_seq_cst);
+ atomic_store_explicit(&thr[i].nullops, 0, memory_order_seq_cst);
}
delta = monotime_since(&tv, NULL);
diff --git a/tests/lib/test_seqlock.c b/tests/lib/test_seqlock.c
index 288d4a8c25..937b3f34f5 100644
--- a/tests/lib/test_seqlock.c
+++ b/tests/lib/test_seqlock.c
@@ -82,11 +82,11 @@ int main(int argc, char **argv)
assert(seqlock_held(&sqlo));
assert(seqlock_cur(&sqlo) == 1);
- assert(seqlock_bump(&sqlo) == 1);
- assert(seqlock_cur(&sqlo) == 5);
assert(seqlock_bump(&sqlo) == 5);
+ assert(seqlock_cur(&sqlo) == 5);
assert(seqlock_bump(&sqlo) == 9);
assert(seqlock_bump(&sqlo) == 13);
+ assert(seqlock_bump(&sqlo) == 17);
assert(seqlock_cur(&sqlo) == 17);
assert(seqlock_held(&sqlo));
@@ -111,4 +111,5 @@ int main(int argc, char **argv)
writestr("main @release\n");
seqlock_release(&sqlo);
sleep(1);
+ pthread_join(thr1, NULL);
}