Fix data race in mju_getLogConfigPtr lazy init
The lazy init of log_config used a single atomic flag (env_checked) with a load-then-store pattern, allowing two threads to both enter the init path and concurrently write to the non-atomic log_config.topics field. Replace with a two-phase atomic init: an atomic exchange on env_init_claimed ensures exactly one thread enters the init, while env_init_done (with acquire/release semantics) signals completion and provides the happens-before edge that makes log_config writes visible to other threads. Also adds mj_atomic_exchange_bool to engine_crossplatform.h (both MSVC and GCC/Clang variants). PiperOrigin-RevId: 941202181 Change-Id: I59b6801c7b4b8b0e1647d82d2aeb534a90fb66fb
This commit is contained in:
committed by
Copybara-Service
parent
6e8a79c657
commit
bb80b55ae1
@@ -85,6 +85,20 @@
|
||||
__atomic_fetch_add(ptr, val, __ATOMIC_RELAXED)
|
||||
#endif
|
||||
|
||||
// Atomics helpers for mjtBool (1-byte _Bool) with acquire/release semantics.
|
||||
#if defined(_MSC_VER) && !defined(__clang__)
|
||||
#define mj_atomic_load_bool(ptr) \
|
||||
(mjtBool) _InterlockedCompareExchange8((volatile char*)(ptr), 0, 0)
|
||||
#define mj_atomic_store_bool(ptr, val) \
|
||||
(void)_InterlockedExchange8((volatile char*)(ptr), (char)(val))
|
||||
#define mj_atomic_exchange_bool(ptr, val) \
|
||||
(mjtBool) _InterlockedExchange8((volatile char*)(ptr), (char)(val))
|
||||
#else
|
||||
#define mj_atomic_load_bool(ptr) __atomic_load_n(ptr, __ATOMIC_ACQUIRE)
|
||||
#define mj_atomic_store_bool(ptr, val) __atomic_store_n(ptr, val, __ATOMIC_RELEASE)
|
||||
#define mj_atomic_exchange_bool(ptr, val) __atomic_exchange_n(ptr, val, __ATOMIC_ACQ_REL)
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
Reference in New Issue
Block a user