mirror of
https://github.com/Ed94/Odin.git
synced 2026-08-06 15:48:51 +00:00
Merge pull request #3701 from laytan/fix-thread-deadlock
Fix thread deadlock
This commit is contained in:
@@ -52,7 +52,7 @@ _futex_wait_with_timeout :: proc "contextless" (f: ^Futex, expected: u32, durati
|
|||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
timeout_ns := u32(duration) * 1000
|
timeout_ns := u32(duration)
|
||||||
s := __ulock_wait(UL_COMPARE_AND_WAIT | ULF_NO_ERRNO, f, u64(expected), timeout_ns)
|
s := __ulock_wait(UL_COMPARE_AND_WAIT | ULF_NO_ERRNO, f, u64(expected), timeout_ns)
|
||||||
if s >= 0 {
|
if s >= 0 {
|
||||||
return true
|
return true
|
||||||
|
|||||||
@@ -2,11 +2,11 @@
|
|||||||
// +private
|
// +private
|
||||||
package thread
|
package thread
|
||||||
|
|
||||||
import "base:intrinsics"
|
|
||||||
import "core:sync"
|
import "core:sync"
|
||||||
import "core:sys/unix"
|
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.
|
// NOTE(tetra): Aligned here because of core/unix/pthread_linux.odin/pthread_t.
|
||||||
// Also see core/sys/darwin/mach_darwin.odin/semaphore_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()
|
t.id = sync.current_thread_id()
|
||||||
|
|
||||||
for (.Started not_in t.flags) {
|
for (.Started not_in sync.atomic_load(&t.flags)) {
|
||||||
sync.wait(&t.cond, &t.mutex)
|
// 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
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -60,11 +62,11 @@ _create :: proc(procedure: Thread_Proc, priority: Thread_Priority) -> ^Thread {
|
|||||||
t.procedure(t)
|
t.procedure(t)
|
||||||
}
|
}
|
||||||
|
|
||||||
intrinsics.atomic_store(&t.flags, t.flags + { .Done })
|
sync.atomic_or(&t.flags, { .Done })
|
||||||
|
|
||||||
sync.unlock(&t.mutex)
|
sync.unlock(&t.mutex)
|
||||||
|
|
||||||
if .Self_Cleanup in t.flags {
|
if .Self_Cleanup in sync.atomic_load(&t.flags) {
|
||||||
t.unix_thread = {}
|
t.unix_thread = {}
|
||||||
// NOTE(ftphikari): It doesn't matter which context 'free' received, right?
|
// NOTE(ftphikari): It doesn't matter which context 'free' received, right?
|
||||||
context = {}
|
context = {}
|
||||||
@@ -122,13 +124,12 @@ _create :: proc(procedure: Thread_Proc, priority: Thread_Priority) -> ^Thread {
|
|||||||
}
|
}
|
||||||
|
|
||||||
_start :: proc(t: ^Thread) {
|
_start :: proc(t: ^Thread) {
|
||||||
// sync.guard(&t.mutex)
|
sync.atomic_or(&t.flags, { .Started })
|
||||||
t.flags += { .Started }
|
|
||||||
sync.signal(&t.cond)
|
sync.signal(&t.cond)
|
||||||
}
|
}
|
||||||
|
|
||||||
_is_done :: proc(t: ^Thread) -> bool {
|
_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) {
|
_join :: proc(t: ^Thread) {
|
||||||
@@ -139,7 +140,7 @@ _join :: proc(t: ^Thread) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Preserve other flags besides `.Joined`, like `.Started`.
|
// Preserve other flags besides `.Joined`, like `.Started`.
|
||||||
unjoined := intrinsics.atomic_load(&t.flags) - {.Joined}
|
unjoined := sync.atomic_load(&t.flags) - {.Joined}
|
||||||
joined := unjoined + {.Joined}
|
joined := unjoined + {.Joined}
|
||||||
|
|
||||||
// Try to set `t.flags` from unjoined to joined. If it returns joined,
|
// Try to set `t.flags` from unjoined to joined. If it returns joined,
|
||||||
|
|||||||
Reference in New Issue
Block a user