aboutsummaryrefslogtreecommitdiff
path: root/core/thread
diff options
context:
space:
mode:
authorJeroen van Rijn <Kelimion@users.noreply.github.com>2022-05-11 13:43:29 +0200
committerJeroen van Rijn <Kelimion@users.noreply.github.com>2022-05-11 13:43:29 +0200
commit56e3b7cb7d96a467ace98ebdca11d2baeef0a8c0 (patch)
tree8740d8b97585389eaaf55def0a442fe75bd46584 /core/thread
parentae1f5d21816928c976b44fd562fa4745b1ee2223 (diff)
Fix join on *nix.
Diffstat (limited to 'core/thread')
-rw-r--r--core/thread/thread_unix.odin19
1 files changed, 14 insertions, 5 deletions
diff --git a/core/thread/thread_unix.odin b/core/thread/thread_unix.odin
index 8452df112..3897f6100 100644
--- a/core/thread/thread_unix.odin
+++ b/core/thread/thread_unix.odin
@@ -7,6 +7,8 @@ import "core:intrinsics"
import "core:sync"
import "core:sys/unix"
+CAS :: intrinsics.atomic_compare_exchange_strong
+
Thread_State :: enum u8 {
Started,
Joined,
@@ -98,7 +100,7 @@ _create :: proc(procedure: Thread_Proc, priority := Thread_Priority.Normal) -> ^
}
_start :: proc(t: ^Thread) {
- sync.guard(&t.mutex)
+ // sync.guard(&t.mutex)
t.flags += { .Started }
sync.signal(&t.cond)
}
@@ -108,15 +110,22 @@ _is_done :: proc(t: ^Thread) -> bool {
}
_join :: proc(t: ^Thread) {
- sync.guard(&t.mutex)
+ // sync.guard(&t.mutex)
- if .Joined in t.flags || unix.pthread_equal(unix.pthread_self(), t.unix_thread) {
+ if unix.pthread_equal(unix.pthread_self(), t.unix_thread) {
return
}
- unix.pthread_join(t.unix_thread, nil)
+ // Preserve other flags besides `.Joined`, like `.Started`.
+ unjoined := intrinsics.atomic_load(&t.flags) - {.Joined}
+ joined := unjoined + {.Joined}
- t.flags += { .Joined }
+ // Try to set `t.flags` from unjoined to joined. If it returns joined,
+ // it means the previous value had that flag set and we can return.
+ if res, ok := CAS(&t.flags, unjoined, joined); res == joined && !ok {
+ return
+ }
+ unix.pthread_join(t.unix_thread, nil)
}
_join_multiple :: proc(threads: ..^Thread) {