From 71c61c4b91f4974e87c88b14f8c49a774fb688c2 Mon Sep 17 00:00:00 2001 From: Daan Date: Thu, 6 Mar 2025 19:52:06 -0800 Subject: [PATCH] fix multi-threaded access in stats merging --- include/mimalloc/atomic.h | 5 +++++ src/stats.c | 12 ++++++------ 2 files changed, 11 insertions(+), 6 deletions(-) diff --git a/include/mimalloc/atomic.h b/include/mimalloc/atomic.h index dbd7160c..3f0bbc68 100644 --- a/include/mimalloc/atomic.h +++ b/include/mimalloc/atomic.h @@ -129,6 +129,11 @@ static inline intptr_t mi_atomic_subi(_Atomic(intptr_t)*p, intptr_t sub); static inline int64_t mi_atomic_addi64_relaxed(volatile int64_t* p, int64_t add) { return mi_atomic(fetch_add_explicit)((_Atomic(int64_t)*)p, add, mi_memory_order(relaxed)); } +static inline void mi_atomic_void_addi64_relaxed(volatile int64_t* p, int64_t add) { + if (add != 0) { + mi_atomic(fetch_add_explicit)((_Atomic(int64_t)*)p, add, mi_memory_order(relaxed)); + } +} static inline void mi_atomic_maxi64_relaxed(volatile int64_t* p, int64_t x) { int64_t current = mi_atomic_load_relaxed((_Atomic(int64_t)*)p); while (current < x && !mi_atomic_cas_weak_release((_Atomic(int64_t)*)p, ¤t, x)) { /* nothing */ }; diff --git a/src/stats.c b/src/stats.c index d9b26863..bce343f6 100644 --- a/src/stats.c +++ b/src/stats.c @@ -65,12 +65,12 @@ void _mi_stat_decrease(mi_stat_count_t* stat, size_t amount) { // must be thread safe as it is called from stats_merge static void mi_stat_count_add(mi_stat_count_t* stat, const mi_stat_count_t* src) { if (stat==src) return; - if (src->total!=0) { mi_atomic_addi64_relaxed(&stat->total, src->total); } - if (src->current!=0) { mi_atomic_addi64_relaxed(&stat->current, src->current); } - // peak scores do really not work across threads ... we use conservative max - if (src->peak > stat->peak) { - mi_atomic_maxi64_relaxed(&stat->peak, src->peak); // or: mi_atomic_addi64_relaxed( &stat->peak, src->peak); - } + mi_atomic_void_addi64_relaxed(&stat->total, src->total); + mi_atomic_void_addi64_relaxed(&stat->current, src->current); + // peak scores do really not work across threads .. we just add them + mi_atomic_void_addi64_relaxed( &stat->peak, src->peak); + // or, take the max? + // mi_atomic_maxi64_relaxed(&stat->peak, src->peak); } static void mi_stat_counter_add(mi_stat_counter_t* stat, const mi_stat_counter_t* src) {