aboutsummaryrefslogtreecommitdiff
path: root/src/threading.cpp
diff options
context:
space:
mode:
authorCourtney Strachan <courtney.strachan@gmail.com>2025-10-06 02:41:44 +0100
committerGitHub <noreply@github.com>2025-10-06 02:41:44 +0100
commit6de2d6e8ca687c989bbb7806e5cbe8d791e425bf (patch)
tree03a2e0a84c7c1530215f8e3f59a7f643b39b3677 /src/threading.cpp
parentdbbe96ae5c343f0e803de6ee508207a62571534f (diff)
parent0f97382fa3e46da80705c00dfe02f3deb9562e4f (diff)
Merge branch 'odin-lang:master' into master
Diffstat (limited to 'src/threading.cpp')
-rw-r--r--src/threading.cpp56
1 files changed, 51 insertions, 5 deletions
diff --git a/src/threading.cpp b/src/threading.cpp
index af8fd803c..84f09912d 100644
--- a/src/threading.cpp
+++ b/src/threading.cpp
@@ -195,7 +195,13 @@ gb_internal void mutex_lock(RecursiveMutex *m) {
// inside the lock
return;
}
- futex_wait(&m->owner, prev_owner);
+
+ // NOTE(lucas): we are doing spin lock since futex signal is expensive on OSX. The recursive locks are
+ // very short lived so we don't hit this mega often and I see no perform regression on windows (with
+ // a performance uplift on OSX).
+
+ //futex_wait(&m->owner, prev_owner);
+ yield_thread();
}
}
gb_internal bool mutex_try_lock(RecursiveMutex *m) {
@@ -216,7 +222,9 @@ gb_internal void mutex_unlock(RecursiveMutex *m) {
return;
}
m->owner.exchange(0, std::memory_order_release);
- futex_signal(&m->owner);
+ // NOTE(lucas): see comment about spin lock in mutex_lock above
+
+ // futex_signal(&m->owner);
// outside the lock
}
@@ -448,6 +456,44 @@ gb_internal void semaphore_wait(Semaphore *s) {
}
#endif
+static const int RWLOCK_WRITER = 1<<0;
+static const int RWLOCK_UPGRADED = 1<<1;
+static const int RWLOCK_READER = 1<<2;
+struct RWSpinLock {
+ Futex bits;
+};
+
+void rwlock_release_write(RWSpinLock *l) {
+ l->bits.fetch_and(~(RWLOCK_WRITER | RWLOCK_UPGRADED), std::memory_order_release);
+ futex_signal(&l->bits);
+}
+
+bool rwlock_try_acquire_upgrade(RWSpinLock *l) {
+ int value = l->bits.fetch_or(RWLOCK_UPGRADED, std::memory_order_acquire);
+ return (value & (RWLOCK_UPGRADED | RWLOCK_WRITER)) == 0;
+}
+
+void rwlock_acquire_upgrade(RWSpinLock *l) {
+ while (!rwlock_try_acquire_upgrade(l)) {
+ futex_wait(&l->bits, RWLOCK_UPGRADED | RWLOCK_WRITER);
+ }
+}
+void rwlock_release_upgrade(RWSpinLock *l) {
+ l->bits.fetch_add(-RWLOCK_UPGRADED, std::memory_order_acq_rel);
+}
+
+bool rwlock_try_release_upgrade_and_acquire_write(RWSpinLock *l) {
+ int expect = RWLOCK_UPGRADED;
+ return l->bits.compare_exchange_strong(expect, RWLOCK_WRITER, std::memory_order_acq_rel);
+}
+
+void rwlock_release_upgrade_and_acquire_write(RWSpinLock *l) {
+ while (!rwlock_try_release_upgrade_and_acquire_write(l)) {
+ futex_wait(&l->bits, RWLOCK_UPGRADED);
+ }
+}
+
+
struct Parker {
Futex state;
};
@@ -756,7 +802,7 @@ gb_internal void futex_signal(Futex *f) {
perror("Futex wake");
GB_PANIC("futex wake fail");
- } else if (ret == 1) {
+ } else {
return;
}
}
@@ -773,7 +819,7 @@ gb_internal void futex_broadcast(Futex *f) {
perror("Futex wake");
GB_PANIC("futex wake fail");
- } else if (ret == 1) {
+ } else {
return;
}
}
@@ -783,7 +829,7 @@ gb_internal void futex_wait(Futex *f, Footex val) {
for (;;) {
int ret = futex((volatile uint32_t *)f, FUTEX_WAIT | FUTEX_PRIVATE_FLAG, val, NULL, NULL);
if (ret == -1) {
- if (*f != val) {
+ if (errno == EAGAIN) {
return;
}