From e5c2a4e4166a660a853406bc8ebb3cce244c4fc0 Mon Sep 17 00:00:00 2001 From: Nick Gasson Date: Sat, 5 Nov 2022 14:30:39 +0000 Subject: [PATCH] Use relaxed atomic operations for some work queue functions --- src/thread.c | 9 ++++++--- src/thread.h | 3 +++ test/workqbench.c | 2 +- 3 files changed, 10 insertions(+), 4 deletions(-) diff --git a/src/thread.c b/src/thread.c index 97cf614b..351882aa 100644 --- a/src/thread.c +++ b/src/thread.c @@ -513,16 +513,16 @@ void __scoped_unlock(nvc_lock_t **plock) static void push_bot(threadq_t *tq, const task_t *tasks, size_t count) { - const abp_idx_t bot = atomic_load(&tq->bot); + const abp_idx_t bot = relaxed_load(&tq->bot); assert(bot + count <= THREADQ_SIZE); memcpy(tq->deque + bot, tasks, count * sizeof(task_t)); - atomic_store(&tq->bot, bot + count); + store_release(&tq->bot, bot + count); } static bool pop_bot(threadq_t *tq, task_t *task) { - const abp_idx_t old_bot = atomic_load(&tq->bot); + const abp_idx_t old_bot = relaxed_load(&tq->bot); if (old_bot == 0) return false; @@ -547,6 +547,7 @@ static bool pop_bot(threadq_t *tq, task_t *task) return false; } +__attribute__((no_sanitize("thread"))) static bool pop_top(threadq_t *tq, task_t *task) { const abp_age_t old_age = { .bits = atomic_load(&tq->age.bits) }; @@ -555,6 +556,8 @@ static bool pop_top(threadq_t *tq, task_t *task) if (bot <= old_age.top) return false; + // This triggers a TSAN false-positive: we will never read from *task + // if the CAS fails below, so it's safe to ignore *task = tq->deque[old_age.top]; const abp_age_t new_age = { diff --git a/src/thread.h b/src/thread.h index 994e7e8c..c3158f04 100644 --- a/src/thread.h +++ b/src/thread.h @@ -39,6 +39,9 @@ #define relaxed_load(p) __atomic_load_n((p), __ATOMIC_RELAXED) #define relaxed_store(p, v) __atomic_store_n((p), (v), __ATOMIC_RELAXED) +#define store_release(p, v) __atomic_store_n((p), (v), __ATOMIC_RELEASE) +#define load_acquire(p) __atomic_load_n((p), __ATOMIC_ACQUIRE) + typedef struct _nvc_thread nvc_thread_t; void thread_init(void); diff --git a/test/workqbench.c b/test/workqbench.c index 6a6d3d0d..d4e8ab38 100644 --- a/test/workqbench.c +++ b/test/workqbench.c @@ -35,7 +35,7 @@ static void is_prime_cb(void *context, void *arg) { int n = (intptr_t)arg; - for (int i = 2; i < n / 2; i++) { + for (int i = 2; i <= n / 2; i++) { if (n % i == 0) { results[n] = 1; break; -- 2.39.2