diff options
| author | gingerBill <bill@gingerbill.org> | 2021-04-11 18:25:56 +0100 |
|---|---|---|
| committer | gingerBill <bill@gingerbill.org> | 2021-04-11 18:25:56 +0100 |
| commit | 1156bd9dd05becd536feeed90f8d33dc4cc30078 (patch) | |
| tree | b34def1f8566b43cd9d53db8e1def5632100d498 /core/thread | |
| parent | 52c193316b3dec24ae78b6790134840536af406f (diff) | |
Remove thread stuff from sync2; Cleanup package thread
Diffstat (limited to 'core/thread')
| -rw-r--r-- | core/thread/thread.odin | 69 | ||||
| -rw-r--r-- | core/thread/thread_unix.odin | 58 | ||||
| -rw-r--r-- | core/thread/thread_windows.odin | 31 |
3 files changed, 79 insertions, 79 deletions
diff --git a/core/thread/thread.odin b/core/thread/thread.odin index 51fb116e3..fce35b124 100644 --- a/core/thread/thread.odin +++ b/core/thread/thread.odin @@ -26,6 +26,46 @@ Thread :: struct { #assert(size_of(Thread{}.user_index) == size_of(uintptr)); +Thread_Priority :: enum { + Normal, + Low, + High, +} + +create :: proc(procedure: Thread_Proc, priority := Thread_Priority.Normal) -> ^Thread { + return _create(procedure, priority); +} +destroy :: proc(thread: ^Thread) { + _destroy(thread); +} + +start :: proc(thread: ^Thread) { + _start(thread); +} + +is_done :: proc(thread: ^Thread) -> bool { + return _is_done(thread); +} + + +join :: proc(thread: ^Thread) { + _join(thread); +} + + +join_mulitple :: proc(threads: ..^Thread) { + _join_multiple(..threads); +} + +terminate :: proc(thread: ^Thread, exit_code: int) { + _terminate(thread, exit_code); +} + +yield :: proc() { + _yield(); +} + + run :: proc(fn: proc(), init_context: Maybe(runtime.Context) = nil, priority := Thread_Priority.Normal) { thread_proc :: proc(t: ^Thread) { @@ -39,7 +79,6 @@ run :: proc(fn: proc(), init_context: Maybe(runtime.Context) = nil, priority := start(t); } - run_with_data :: proc(data: rawptr, fn: proc(data: rawptr), init_context: Maybe(runtime.Context) = nil, priority := Thread_Priority.Normal) { thread_proc :: proc(t: ^Thread) { fn := cast(proc(rawptr))t.data; @@ -152,31 +191,3 @@ create_and_start :: proc(fn: Thread_Proc, init_context: Maybe(runtime.Context) = start(t); return t; } - - -Once :: struct { - m: sync.Blocking_Mutex, - done: bool, -} -once_init :: proc(o: ^Once) { - sync.blocking_mutex_init(&o.m); - intrinsics.atomic_store_rel(&o.done, false); -} -once_destroy :: proc(o: ^Once) { - sync.blocking_mutex_destroy(&o.m); -} - -once_do :: proc(o: ^Once, fn: proc()) { - if intrinsics.atomic_load(&o.done) == false { - _once_do_slow(o, fn); - } -} - -_once_do_slow :: proc(o: ^Once, fn: proc()) { - sync.blocking_mutex_lock(&o.m); - defer sync.blocking_mutex_unlock(&o.m); - if !o.done { - fn(); - intrinsics.atomic_store_rel(&o.done, true); - } -} diff --git a/core/thread/thread_unix.odin b/core/thread/thread_unix.odin index d87291c0e..139c323bd 100644 --- a/core/thread/thread_unix.odin +++ b/core/thread/thread_unix.odin @@ -1,9 +1,10 @@ // +build linux, darwin, freebsd -package thread; +// +private +package thread import "core:runtime" import "core:intrinsics" -import "core:sync" +import sync "core:sync/sync2" import "core:sys/unix" // NOTE(tetra): Aligned here because of core/unix/pthread_linux.odin/pthread_t. @@ -19,7 +20,7 @@ Thread_Os_Specific :: struct #align 16 { // in a suspended state, we have it wait on this gate, which we // signal to start it. // destroyed after thread is started. - start_gate: sync.Condition, + start_gate: sync.Cond, start_mutex: sync.Mutex, // if true, the thread has been started and the start_gate has been destroyed. @@ -31,25 +32,16 @@ Thread_Os_Specific :: struct #align 16 { // See the comment in `join`. already_joined: bool, } - -Thread_Priority :: enum { - Normal, - Low, - High, -} - // // Creates a thread which will run the given procedure. // It then waits for `start` to be called. // -create :: proc(procedure: Thread_Proc, priority := Thread_Priority.Normal) -> ^Thread { +_create :: proc(procedure: Thread_Proc, priority := Thread_Priority.Normal) -> ^Thread { __linux_thread_entry_proc :: proc "c" (t: rawptr) -> rawptr { context = runtime.default_context(); t := (^Thread)(t); - sync.condition_wait_for(&t.start_gate); - sync.condition_destroy(&t.start_gate); - sync.mutex_destroy(&t.start_mutex); + sync.cond_wait(&t.start_gate, &t.start_mutex); t.start_gate = {}; t.start_mutex = {}; @@ -67,7 +59,7 @@ create :: proc(procedure: Thread_Proc, priority := Thread_Priority.Normal) -> ^T } } - sync.atomic_store(&t.done, true, .Sequentially_Consistent); + intrinsics.atomic_store(&t.done, true); return nil; } @@ -104,8 +96,6 @@ create :: proc(procedure: Thread_Proc, priority := Thread_Priority.Normal) -> ^T res = unix.pthread_attr_setschedparam(&attrs, ¶ms); assert(res == 0); - sync.mutex_init(&thread.start_mutex); - sync.condition_init(&thread.start_gate, &thread.start_mutex); if unix.pthread_create(&thread.unix_thread, &attrs, __linux_thread_entry_proc, thread) != 0 { free(thread, thread.creation_allocator); return nil; @@ -115,18 +105,18 @@ create :: proc(procedure: Thread_Proc, priority := Thread_Priority.Normal) -> ^T return thread; } -start :: proc(t: ^Thread) { - if sync.atomic_swap(&t.started, true, .Sequentially_Consistent) { +_start :: proc(t: ^Thread) { + if intrinsics.atomic_xchg(&t.started, true) { return; } - sync.condition_signal(&t.start_gate); + sync.cond_signal(&t.start_gate); } -is_done :: proc(t: ^Thread) -> bool { - return sync.atomic_load(&t.done, .Sequentially_Consistent); +_is_done :: proc(t: ^Thread) -> bool { + return intrinsics.atomic_load(&t.done); } -join :: proc(t: ^Thread) { +_join :: proc(t: ^Thread) { if unix.pthread_equal(unix.pthread_self(), t.unix_thread) { return; } @@ -138,9 +128,9 @@ join :: proc(t: ^Thread) { // See note on `already_joined` field. // TODO(tetra): I'm not sure if we should do this, or panic, since I'm not // sure it makes sense to need to join from multiple threads? - if sync.atomic_swap(&t.already_joined, true, .Sequentially_Consistent) { + if intrinsics.atomic_xchg(&t.already_joined, true) { for { - if sync.atomic_load(&t.done, .Sequentially_Consistent) { + if intrinsics.atomic_load(&t.done) { return; } intrinsics.cpu_relax(); @@ -152,31 +142,35 @@ join :: proc(t: ^Thread) { // We do this instead because I don't know if there is a danger // that you may join a different thread from the one you called join on, // if the thread handle is reused. - if sync.atomic_load(&t.done, .Sequentially_Consistent) { + if intrinsics.atomic_load(&t.done) { return; } ret_val: rawptr; _ = unix.pthread_join(t.unix_thread, &ret_val); - if !sync.atomic_load(&t.done, .Sequentially_Consistent) { + if !intrinsics.atomic_load(&t.done) { panic("thread not done after join"); } } -join_multiple :: proc(threads: ..^Thread) { +_join_multiple :: proc(threads: ..^Thread) { for t in threads { - join(t); + _join(t); } } -destroy :: proc(t: ^Thread) { - join(t); +_destroy :: proc(t: ^Thread) { + _join(t); t.unix_thread = {}; free(t, t.creation_allocator); } -yield :: proc() { +_terminate :: proc(t: ^Thread, exit_code: int) { + // TODO(bill) +} + +_yield :: proc() { unix.sched_yield(); } diff --git a/core/thread/thread_windows.odin b/core/thread/thread_windows.odin index 27a14c7f6..b44ec8f36 100644 --- a/core/thread/thread_windows.odin +++ b/core/thread/thread_windows.odin @@ -1,3 +1,5 @@ +//+build windows +//+private package thread import "core:runtime" @@ -10,20 +12,13 @@ Thread_Os_Specific :: struct { done: bool, // see note in `is_done` } - -Thread_Priority :: enum { - Normal, - Low, - High, -} - _thread_priority_map := [Thread_Priority]i32{ .Normal = 0, .Low = -2, .High = +2, }; -create :: proc(procedure: Thread_Proc, priority := Thread_Priority.Normal) -> ^Thread { +_create :: proc(procedure: Thread_Proc, priority := Thread_Priority.Normal) -> ^Thread { win32_thread_id: win32.DWORD; __windows_thread_entry_proc :: proc "stdcall" (t_: rawptr) -> win32.DWORD { @@ -70,18 +65,18 @@ create :: proc(procedure: Thread_Proc, priority := Thread_Priority.Normal) -> ^T return thread; } -start :: proc(using thread: ^Thread) { - win32.ResumeThread(win32_thread); +_start :: proc(thread: ^Thread) { + win32.ResumeThread(thread.win32_thread); } -is_done :: proc(using thread: ^Thread) -> bool { +_is_done :: proc(using thread: ^Thread) -> bool { // NOTE(tetra, 2019-10-31): Apparently using wait_for_single_object and // checking if it didn't time out immediately, is not good enough, // so we do it this way instead. return sync.atomic_load(&done, .Sequentially_Consistent); } -join :: proc(using thread: ^Thread) { +_join :: proc(using thread: ^Thread) { if win32_thread != win32.INVALID_HANDLE { win32.WaitForSingleObject(win32_thread, win32.INFINITE); win32.CloseHandle(win32_thread); @@ -89,7 +84,7 @@ join :: proc(using thread: ^Thread) { } } -join_multiple :: proc(threads: ..^Thread) { +_join_multiple :: proc(threads: ..^Thread) { MAXIMUM_WAIT_OBJECTS :: 64; handles: [MAXIMUM_WAIT_OBJECTS]win32.HANDLE; @@ -113,16 +108,16 @@ join_multiple :: proc(threads: ..^Thread) { } } -destroy :: proc(thread: ^Thread) { - join(thread); +_destroy :: proc(thread: ^Thread) { + _join(thread); free(thread, thread.creation_allocator); } -terminate :: proc(using thread : ^Thread, exit_code: u32) { - win32.TerminateThread(win32_thread, exit_code); +_terminate :: proc(using thread : ^Thread, exit_code: int) { + win32.TerminateThread(win32_thread, u32(exit_code)); } -yield :: proc() { +_yield :: proc() { win32.SwitchToThread(); } |