diff options
| author | Laytan Laats <laytanlaats@hotmail.com> | 2024-06-07 20:28:09 +0200 |
|---|---|---|
| committer | Laytan Laats <laytanlaats@hotmail.com> | 2024-06-07 20:28:09 +0200 |
| commit | 00dfff7ee06d8a691ba754232243689e4bfd8381 (patch) | |
| tree | 5865c08e1bdab33f734eed6bce07330cd40b0bd2 /core/thread | |
| parent | b35e72c82b53be5ae16b1a0923ae948183a32a8d (diff) | |
core/thread: fix a deadlock situation on unix
Diffstat (limited to 'core/thread')
| -rw-r--r-- | core/thread/thread_unix.odin | 23 |
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, |