aboutsummaryrefslogtreecommitdiff
path: root/core/thread
diff options
context:
space:
mode:
authorLaytan Laats <laytanlaats@hotmail.com>2024-06-07 20:28:09 +0200
committerLaytan Laats <laytanlaats@hotmail.com>2024-06-07 20:28:09 +0200
commit00dfff7ee06d8a691ba754232243689e4bfd8381 (patch)
tree5865c08e1bdab33f734eed6bce07330cd40b0bd2 /core/thread
parentb35e72c82b53be5ae16b1a0923ae948183a32a8d (diff)
core/thread: fix a deadlock situation on unix
Diffstat (limited to 'core/thread')
-rw-r--r--core/thread/thread_unix.odin23
1 files changed, 12 insertions, 11 deletions
diff --git a/core/thread/thread_unix.odin b/core/thread/thread_unix.odin
index acc0e05cb..5291917da 100644
--- a/core/thread/thread_unix.odin
+++ b/core/thread/thread_unix.odin
@@ -2,11 +2,11 @@
// +private
package thread
-import "base:intrinsics"
import "core:sync"
import "core:sys/unix"
+import "core:time"
-CAS :: intrinsics.atomic_compare_exchange_strong
+CAS :: sync.atomic_compare_exchange_strong
// NOTE(tetra): Aligned here because of core/unix/pthread_linux.odin/pthread_t.
// Also see core/sys/darwin/mach_darwin.odin/semaphore_t.
@@ -32,11 +32,13 @@ _create :: proc(procedure: Thread_Proc, priority: Thread_Priority) -> ^Thread {
t.id = sync.current_thread_id()
- for (.Started not_in t.flags) {
- sync.wait(&t.cond, &t.mutex)
+ for (.Started not_in sync.atomic_load(&t.flags)) {
+ // HACK: use a timeout so in the event that the condition is signalled at THIS comment's exact point
+ // (after checking flags, before starting the wait) it gets itself out of that deadlock after a ms.
+ sync.wait_with_timeout(&t.cond, &t.mutex, time.Millisecond)
}
- if .Joined in t.flags {
+ if .Joined in sync.atomic_load(&t.flags) {
return nil
}
@@ -60,11 +62,11 @@ _create :: proc(procedure: Thread_Proc, priority: Thread_Priority) -> ^Thread {
t.procedure(t)
}
- intrinsics.atomic_store(&t.flags, t.flags + { .Done })
+ sync.atomic_or(&t.flags, { .Done })
sync.unlock(&t.mutex)
- if .Self_Cleanup in t.flags {
+ if .Self_Cleanup in sync.atomic_load(&t.flags) {
t.unix_thread = {}
// NOTE(ftphikari): It doesn't matter which context 'free' received, right?
context = {}
@@ -122,13 +124,12 @@ _create :: proc(procedure: Thread_Proc, priority: Thread_Priority) -> ^Thread {
}
_start :: proc(t: ^Thread) {
- // sync.guard(&t.mutex)
- t.flags += { .Started }
+ sync.atomic_or(&t.flags, { .Started })
sync.signal(&t.cond)
}
_is_done :: proc(t: ^Thread) -> bool {
- return .Done in intrinsics.atomic_load(&t.flags)
+ return .Done in sync.atomic_load(&t.flags)
}
_join :: proc(t: ^Thread) {
@@ -139,7 +140,7 @@ _join :: proc(t: ^Thread) {
}
// Preserve other flags besides `.Joined`, like `.Started`.
- unjoined := intrinsics.atomic_load(&t.flags) - {.Joined}
+ unjoined := sync.atomic_load(&t.flags) - {.Joined}
joined := unjoined + {.Joined}
// Try to set `t.flags` from unjoined to joined. If it returns joined,