Commit: ba86ef9b9376f4680770a8c180235265ec1ff959
Parent: 8408acf219120932b5db273588d2542b87954356
Author: Randy Palamar
Date: Sun, 6 Apr 2025 17:53:22 -0600
core: use atomic_cas to ensure shared memory locks are transferred correctly
There was a moment of time between the load and inc that could
have caused a double increment on the lock giving an invalid state.
Diffstat:
3 files changed, 9 insertions(+), 10 deletions(-)
diff --git a/beamformer_work_queue.c b/beamformer_work_queue.c
@@ -57,8 +57,7 @@ try_wait_sync(i32 *sync, i32 timeout_ms, os_wait_on_value_fn *os_wait_on_value)
b32 result = 0;
for (;;) {
i32 current = atomic_load(sync);
- if (current) {
- atomic_inc(sync, -current);
+ if (current && atomic_cas(sync, ¤t, 0)) {
result = 1;
break;
} else if (!timeout_ms) {
diff --git a/intrinsics.c b/intrinsics.c
@@ -4,11 +4,13 @@
#define sqrt_f32(a) __builtin_sqrtf(a)
#define atan2_f32(y, x) __builtin_atan2f(y, x)
-#define atomic_store(ptr, n) __atomic_store_n(ptr, n, __ATOMIC_RELEASE)
-#define atomic_load(ptr) __atomic_load_n(ptr, __ATOMIC_ACQUIRE)
-#define atomic_and(ptr, n) __atomic_and_fetch(ptr, n, __ATOMIC_RELEASE)
-#define atomic_add(ptr, n) __atomic_add_fetch(ptr, n, __ATOMIC_RELEASE)
-#define atomic_inc(ptr, n) __atomic_fetch_add(ptr, n, __ATOMIC_ACQ_REL)
+#define atomic_store(ptr, n) __atomic_store_n(ptr, n, __ATOMIC_RELEASE)
+#define atomic_load(ptr) __atomic_load_n(ptr, __ATOMIC_ACQUIRE)
+#define atomic_swap(ptr, n) __atomic_exchange_n(ptr, n, __ATOMIC_RELEASE)
+#define atomic_and(ptr, n) __atomic_and_fetch(ptr, n, __ATOMIC_RELEASE)
+#define atomic_add(ptr, n) __atomic_add_fetch(ptr, n, __ATOMIC_RELEASE)
+#define atomic_inc(ptr, n) __atomic_fetch_add(ptr, n, __ATOMIC_ACQ_REL)
+#define atomic_cas(ptr, cptr, n) __atomic_compare_exchange_n(ptr, cptr, n, 0, __ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST)
static FORCE_INLINE u32
clz_u32(u32 a)
diff --git a/static.c b/static.c
@@ -256,10 +256,8 @@ static OS_THREAD_ENTRY_POINT_FN(compute_worker_thread_entry_point)
for (;;) {
for (;;) {
i32 current = atomic_load(&ctx->sync_variable);
- if (current) {
- atomic_inc(&ctx->sync_variable, -current);
+ if (current && atomic_swap(&ctx->sync_variable, 0) == current)
break;
- }
ctx->asleep = 1;
os_wait_on_value(&ctx->sync_variable, current, -1);