diff --git a/ggml/src/ggml.c b/ggml/src/ggml.c index c3b462b3fe611a..e9ada3e4915524 100644 --- a/ggml/src/ggml.c +++ b/ggml/src/ggml.c @@ -3198,16 +3198,27 @@ static void ggml_barrier(struct ggml_threadpool * threadpool) { int passed_old = atomic_load_explicit(n_barrier_passed, memory_order_relaxed); - if (atomic_fetch_add(n_barrier, 1) == n_threads - 1) { + // All threads go through the full fence (memory barrier) operation once to ensure + // that all previos updates have completed. + // The rest of the reads and writes can be relaxed, but the thread sanitizer wants + // to see an explicit acquire / release sequence to declare all futher accesses + // as safe. + + #if defined(__has_feature) && __has_feature(thread_sanitizer) + #define passed_acquire memory_order_acquire + #define passed_release memory_order_release + #else + #define passed_acquire memory_order_relaxed + #define passed_release memory_order_relaxed + #endif + + if (atomic_fetch_add_explicit(n_barrier, 1, memory_order_seq_cst) == n_threads - 1) { // last thread - atomic_store(n_barrier, 0); - atomic_fetch_add_explicit(n_barrier_passed, 1, memory_order_relaxed); + atomic_store_explicit(n_barrier, 0, memory_order_relaxed); + atomic_fetch_add_explicit(n_barrier_passed, 1, passed_release); } else { // wait for other threads - while (true) { - if (atomic_load_explicit(n_barrier_passed, memory_order_relaxed) != passed_old) { - return; - } + while (atomic_load_explicit(n_barrier_passed, passed_acquire) == passed_old) { ggml_thread_cpu_relax(); } }