mirror of
https://github.com/Ed94/Odin.git
synced 2026-07-21 23:12:03 -07:00
Strip semicolons in core which were missing
This commit is contained in:
@@ -9,13 +9,13 @@ import "core:intrinsics"
|
||||
foreign import pthread "System.framework"
|
||||
|
||||
_current_thread_id :: proc "contextless" () -> int {
|
||||
tid: u64;
|
||||
tid: u64
|
||||
// NOTE(Oskar): available from OSX 10.6 and iOS 3.2.
|
||||
// For older versions there is `syscall(SYS_thread_selfid)`, but not really
|
||||
// the same thing apparently.
|
||||
foreign pthread { pthread_threadid_np :: proc "c" (rawptr, ^u64) -> c.int ---; }
|
||||
pthread_threadid_np(nil, &tid);
|
||||
return int(tid);
|
||||
foreign pthread { pthread_threadid_np :: proc "c" (rawptr, ^u64) -> c.int --- }
|
||||
pthread_threadid_np(nil, &tid)
|
||||
return int(tid)
|
||||
}
|
||||
|
||||
foreign {
|
||||
@@ -26,38 +26,38 @@ foreign {
|
||||
}
|
||||
|
||||
_atomic_try_wait_slow :: proc(ptr: ^u32, val: u32) {
|
||||
history: uint = 10;
|
||||
history: uint = 10
|
||||
for {
|
||||
// Exponential wait
|
||||
_darwin_usleep(history >> 2);
|
||||
history += history >> 2;
|
||||
_darwin_usleep(history >> 2)
|
||||
history += history >> 2
|
||||
if history > (1 << 10) {
|
||||
history = 1 << 10;
|
||||
history = 1 << 10
|
||||
}
|
||||
|
||||
if atomic_load(ptr) != val {
|
||||
break;
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
_atomic_wait :: proc(ptr: ^u32, val: u32) {
|
||||
if intrinsics.expect(atomic_load(ptr) != val, true) {
|
||||
return;
|
||||
return
|
||||
}
|
||||
for i in 0..<16 {
|
||||
if atomic_load(ptr) != val {
|
||||
return;
|
||||
return
|
||||
}
|
||||
if i < 12 {
|
||||
intrinsics.cpu_relax();
|
||||
intrinsics.cpu_relax()
|
||||
} else {
|
||||
_darwin_sched_yield();
|
||||
_darwin_sched_yield()
|
||||
}
|
||||
}
|
||||
|
||||
for val == atomic_load(ptr) {
|
||||
_atomic_try_wait_slow(ptr, val);
|
||||
_atomic_try_wait_slow(ptr, val)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -73,7 +73,7 @@ _mutex_unlock :: proc(m: ^Mutex) {
|
||||
}
|
||||
|
||||
_mutex_try_lock :: proc(m: ^Mutex) -> bool {
|
||||
return false;
|
||||
return false
|
||||
}
|
||||
|
||||
_RW_Mutex :: struct {
|
||||
@@ -86,7 +86,7 @@ _rw_mutex_unlock :: proc(rw: ^RW_Mutex) {
|
||||
}
|
||||
|
||||
_rw_mutex_try_lock :: proc(rw: ^RW_Mutex) -> bool {
|
||||
return false;
|
||||
return false
|
||||
}
|
||||
|
||||
_rw_mutex_shared_lock :: proc(rw: ^RW_Mutex) {
|
||||
@@ -96,7 +96,7 @@ _rw_mutex_shared_unlock :: proc(rw: ^RW_Mutex) {
|
||||
}
|
||||
|
||||
_rw_mutex_try_shared_lock :: proc(rw: ^RW_Mutex) -> bool {
|
||||
return false;
|
||||
return false
|
||||
}
|
||||
|
||||
|
||||
@@ -110,7 +110,7 @@ _recursive_mutex_unlock :: proc(m: ^Recursive_Mutex) {
|
||||
}
|
||||
|
||||
_recursive_mutex_try_lock :: proc(m: ^Recursive_Mutex) -> bool {
|
||||
return false;
|
||||
return false
|
||||
}
|
||||
|
||||
|
||||
@@ -123,7 +123,7 @@ _cond_wait :: proc(c: ^Cond, m: ^Mutex) {
|
||||
}
|
||||
|
||||
_cond_wait_with_timeout :: proc(c: ^Cond, m: ^Mutex, timeout: time.Duration) -> bool {
|
||||
return false;
|
||||
return false
|
||||
}
|
||||
|
||||
_cond_signal :: proc(c: ^Cond) {
|
||||
|
||||
@@ -10,6 +10,6 @@ _current_thread_id :: proc "contextless" () -> int {
|
||||
syscall :: proc(number: i32, #c_vararg args: ..any) -> i32 ---
|
||||
}
|
||||
|
||||
SYS_GETTID :: 186;
|
||||
return int(syscall(SYS_GETTID));
|
||||
SYS_GETTID :: 186
|
||||
return int(syscall(SYS_GETTID))
|
||||
}
|
||||
|
||||
@@ -18,30 +18,30 @@ _Mutex :: struct {
|
||||
}
|
||||
|
||||
_mutex_lock :: proc(m: ^Mutex) {
|
||||
err := unix.pthread_mutex_lock(&m.impl.pthread_mutex);
|
||||
assert(err == 0);
|
||||
err := unix.pthread_mutex_lock(&m.impl.pthread_mutex)
|
||||
assert(err == 0)
|
||||
}
|
||||
|
||||
_mutex_unlock :: proc(m: ^Mutex) {
|
||||
err := unix.pthread_mutex_unlock(&m.impl.pthread_mutex);
|
||||
assert(err == 0);
|
||||
err := unix.pthread_mutex_unlock(&m.impl.pthread_mutex)
|
||||
assert(err == 0)
|
||||
}
|
||||
|
||||
_mutex_try_lock :: proc(m: ^Mutex) -> bool {
|
||||
err := unix.pthread_mutex_trylock(&m.impl.pthread_mutex);
|
||||
return err == 0;
|
||||
err := unix.pthread_mutex_trylock(&m.impl.pthread_mutex)
|
||||
return err == 0
|
||||
}
|
||||
|
||||
|
||||
|
||||
RW_Mutex_State :: distinct uint;
|
||||
RW_Mutex_State_Half_Width :: size_of(RW_Mutex_State)*8/2;
|
||||
RW_Mutex_State_Is_Writing :: RW_Mutex_State(1);
|
||||
RW_Mutex_State_Writer :: RW_Mutex_State(1)<<1;
|
||||
RW_Mutex_State_Reader :: RW_Mutex_State(1)<<RW_Mutex_State_Half_Width;
|
||||
RW_Mutex_State :: distinct uint
|
||||
RW_Mutex_State_Half_Width :: size_of(RW_Mutex_State)*8/2
|
||||
RW_Mutex_State_Is_Writing :: RW_Mutex_State(1)
|
||||
RW_Mutex_State_Writer :: RW_Mutex_State(1)<<1
|
||||
RW_Mutex_State_Reader :: RW_Mutex_State(1)<<RW_Mutex_State_Half_Width
|
||||
|
||||
RW_Mutex_State_Writer_Mask :: RW_Mutex_State(1<<(RW_Mutex_State_Half_Width-1) - 1) << 1;
|
||||
RW_Mutex_State_Reader_Mask :: RW_Mutex_State(1<<(RW_Mutex_State_Half_Width-1) - 1) << RW_Mutex_State_Half_Width;
|
||||
RW_Mutex_State_Writer_Mask :: RW_Mutex_State(1<<(RW_Mutex_State_Half_Width-1) - 1) << 1
|
||||
RW_Mutex_State_Reader_Mask :: RW_Mutex_State(1<<(RW_Mutex_State_Half_Width-1) - 1) << RW_Mutex_State_Half_Width
|
||||
|
||||
|
||||
_RW_Mutex :: struct {
|
||||
@@ -53,72 +53,72 @@ _RW_Mutex :: struct {
|
||||
}
|
||||
|
||||
_rw_mutex_lock :: proc(rw: ^RW_Mutex) {
|
||||
_ = atomic_add(&rw.impl.state, RW_Mutex_State_Writer);
|
||||
mutex_lock(&rw.impl.mutex);
|
||||
_ = atomic_add(&rw.impl.state, RW_Mutex_State_Writer)
|
||||
mutex_lock(&rw.impl.mutex)
|
||||
|
||||
state := atomic_or(&rw.impl.state, RW_Mutex_State_Writer);
|
||||
state := atomic_or(&rw.impl.state, RW_Mutex_State_Writer)
|
||||
if state & RW_Mutex_State_Reader_Mask != 0 {
|
||||
sema_wait(&rw.impl.sema);
|
||||
sema_wait(&rw.impl.sema)
|
||||
}
|
||||
}
|
||||
|
||||
_rw_mutex_unlock :: proc(rw: ^RW_Mutex) {
|
||||
_ = atomic_and(&rw.impl.state, ~RW_Mutex_State_Is_Writing);
|
||||
mutex_unlock(&rw.impl.mutex);
|
||||
_ = atomic_and(&rw.impl.state, ~RW_Mutex_State_Is_Writing)
|
||||
mutex_unlock(&rw.impl.mutex)
|
||||
}
|
||||
|
||||
_rw_mutex_try_lock :: proc(rw: ^RW_Mutex) -> bool {
|
||||
if mutex_try_lock(&rw.impl.mutex) {
|
||||
state := atomic_load(&rw.impl.state);
|
||||
state := atomic_load(&rw.impl.state)
|
||||
if state & RW_Mutex_State_Reader_Mask == 0 {
|
||||
_ = atomic_or(&rw.impl.state, RW_Mutex_State_Is_Writing);
|
||||
return true;
|
||||
_ = atomic_or(&rw.impl.state, RW_Mutex_State_Is_Writing)
|
||||
return true
|
||||
}
|
||||
|
||||
mutex_unlock(&rw.impl.mutex);
|
||||
mutex_unlock(&rw.impl.mutex)
|
||||
}
|
||||
return false;
|
||||
return false
|
||||
}
|
||||
|
||||
_rw_mutex_shared_lock :: proc(rw: ^RW_Mutex) {
|
||||
state := atomic_load(&rw.impl.state);
|
||||
state := atomic_load(&rw.impl.state)
|
||||
for state & (RW_Mutex_State_Is_Writing|RW_Mutex_State_Writer_Mask) == 0 {
|
||||
ok: bool;
|
||||
state, ok = atomic_compare_exchange_weak(&rw.impl.state, state, state + RW_Mutex_State_Reader);
|
||||
ok: bool
|
||||
state, ok = atomic_compare_exchange_weak(&rw.impl.state, state, state + RW_Mutex_State_Reader)
|
||||
if ok {
|
||||
return;
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
mutex_lock(&rw.impl.mutex);
|
||||
_ = atomic_add(&rw.impl.state, RW_Mutex_State_Reader);
|
||||
mutex_unlock(&rw.impl.mutex);
|
||||
mutex_lock(&rw.impl.mutex)
|
||||
_ = atomic_add(&rw.impl.state, RW_Mutex_State_Reader)
|
||||
mutex_unlock(&rw.impl.mutex)
|
||||
}
|
||||
|
||||
_rw_mutex_shared_unlock :: proc(rw: ^RW_Mutex) {
|
||||
state := atomic_sub(&rw.impl.state, RW_Mutex_State_Reader);
|
||||
state := atomic_sub(&rw.impl.state, RW_Mutex_State_Reader)
|
||||
|
||||
if (state & RW_Mutex_State_Reader_Mask == RW_Mutex_State_Reader) &&
|
||||
(state & RW_Mutex_State_Is_Writing != 0) {
|
||||
sema_post(&rw.impl.sema);
|
||||
sema_post(&rw.impl.sema)
|
||||
}
|
||||
}
|
||||
|
||||
_rw_mutex_try_shared_lock :: proc(rw: ^RW_Mutex) -> bool {
|
||||
state := atomic_load(&rw.impl.state);
|
||||
state := atomic_load(&rw.impl.state)
|
||||
if state & (RW_Mutex_State_Is_Writing|RW_Mutex_State_Writer_Mask) == 0 {
|
||||
_, ok := atomic_compare_exchange_strong(&rw.impl.state, state, state + RW_Mutex_State_Reader);
|
||||
_, ok := atomic_compare_exchange_strong(&rw.impl.state, state, state + RW_Mutex_State_Reader)
|
||||
if ok {
|
||||
return true;
|
||||
return true
|
||||
}
|
||||
}
|
||||
if mutex_try_lock(&rw.impl.mutex) {
|
||||
_ = atomic_add(&rw.impl.state, RW_Mutex_State_Reader);
|
||||
mutex_unlock(&rw.impl.mutex);
|
||||
return true;
|
||||
_ = atomic_add(&rw.impl.state, RW_Mutex_State_Reader)
|
||||
mutex_unlock(&rw.impl.mutex)
|
||||
return true
|
||||
}
|
||||
|
||||
return false;
|
||||
return false
|
||||
}
|
||||
|
||||
|
||||
@@ -129,42 +129,42 @@ _Recursive_Mutex :: struct {
|
||||
}
|
||||
|
||||
_recursive_mutex_lock :: proc(m: ^Recursive_Mutex) {
|
||||
tid := _current_thread_id();
|
||||
tid := _current_thread_id()
|
||||
if tid != m.impl.owner {
|
||||
mutex_lock(&m.impl.mutex);
|
||||
mutex_lock(&m.impl.mutex)
|
||||
}
|
||||
// inside the lock
|
||||
m.impl.owner = tid;
|
||||
m.impl.recursion += 1;
|
||||
m.impl.owner = tid
|
||||
m.impl.recursion += 1
|
||||
}
|
||||
|
||||
_recursive_mutex_unlock :: proc(m: ^Recursive_Mutex) {
|
||||
tid := _current_thread_id();
|
||||
assert(tid == m.impl.owner);
|
||||
m.impl.recursion -= 1;
|
||||
recursion := m.impl.recursion;
|
||||
tid := _current_thread_id()
|
||||
assert(tid == m.impl.owner)
|
||||
m.impl.recursion -= 1
|
||||
recursion := m.impl.recursion
|
||||
if recursion == 0 {
|
||||
m.impl.owner = 0;
|
||||
m.impl.owner = 0
|
||||
}
|
||||
if recursion == 0 {
|
||||
mutex_unlock(&m.impl.mutex);
|
||||
mutex_unlock(&m.impl.mutex)
|
||||
}
|
||||
// outside the lock
|
||||
|
||||
}
|
||||
|
||||
_recursive_mutex_try_lock :: proc(m: ^Recursive_Mutex) -> bool {
|
||||
tid := _current_thread_id();
|
||||
tid := _current_thread_id()
|
||||
if m.impl.owner == tid {
|
||||
return mutex_try_lock(&m.impl.mutex);
|
||||
return mutex_try_lock(&m.impl.mutex)
|
||||
}
|
||||
if !mutex_try_lock(&m.impl.mutex) {
|
||||
return false;
|
||||
return false
|
||||
}
|
||||
// inside the lock
|
||||
m.impl.owner = tid;
|
||||
m.impl.recursion += 1;
|
||||
return true;
|
||||
m.impl.owner = tid
|
||||
m.impl.recursion += 1
|
||||
return true
|
||||
}
|
||||
|
||||
|
||||
@@ -173,29 +173,29 @@ _Cond :: struct {
|
||||
}
|
||||
|
||||
_cond_wait :: proc(c: ^Cond, m: ^Mutex) {
|
||||
err := unix.pthread_cond_wait(&c.impl.pthread_cond, &m.impl.pthread_mutex);
|
||||
assert(err == 0);
|
||||
err := unix.pthread_cond_wait(&c.impl.pthread_cond, &m.impl.pthread_mutex)
|
||||
assert(err == 0)
|
||||
}
|
||||
|
||||
_cond_wait_with_timeout :: proc(c: ^Cond, m: ^Mutex, timeout: time.Duration) -> bool {
|
||||
ns := time.duration_nanoseconds(timeout);
|
||||
ns := time.duration_nanoseconds(timeout)
|
||||
timeout_timespec := &time.TimeSpec{
|
||||
tv_sec = ns / 1e9,
|
||||
tv_nsec = ns % 1e9,
|
||||
};
|
||||
err := unix.pthread_cond_timedwait(&c.impl.pthread_cond, &m.impl.pthread_mutex, timeout_timespec);
|
||||
}
|
||||
err := unix.pthread_cond_timedwait(&c.impl.pthread_cond, &m.impl.pthread_mutex, timeout_timespec)
|
||||
// TODO(bill):
|
||||
return err == 0;
|
||||
return err == 0
|
||||
}
|
||||
|
||||
_cond_signal :: proc(c: ^Cond) {
|
||||
err := unix.pthread_cond_signal(&c.impl.pthread_cond);
|
||||
assert(err == 0);
|
||||
err := unix.pthread_cond_signal(&c.impl.pthread_cond)
|
||||
assert(err == 0)
|
||||
}
|
||||
|
||||
_cond_broadcast :: proc(c: ^Cond) {
|
||||
err := unix.pthread_cond_broadcast(&c.impl.pthread_cond);
|
||||
assert(err == 0);
|
||||
err := unix.pthread_cond_broadcast(&c.impl.pthread_cond)
|
||||
assert(err == 0)
|
||||
}
|
||||
|
||||
_Sema :: struct {
|
||||
@@ -205,25 +205,25 @@ _Sema :: struct {
|
||||
}
|
||||
|
||||
_sema_wait :: proc(s: ^Sema) {
|
||||
mutex_lock(&s.impl.mutex);
|
||||
defer mutex_unlock(&s.impl.mutex);
|
||||
mutex_lock(&s.impl.mutex)
|
||||
defer mutex_unlock(&s.impl.mutex)
|
||||
|
||||
for s.impl.count == 0 {
|
||||
cond_wait(&s.impl.cond, &s.impl.mutex);
|
||||
cond_wait(&s.impl.cond, &s.impl.mutex)
|
||||
}
|
||||
|
||||
s.impl.count -= 1;
|
||||
s.impl.count -= 1
|
||||
if s.impl.count > 0 {
|
||||
cond_signal(&s.impl.cond);
|
||||
cond_signal(&s.impl.cond)
|
||||
}
|
||||
}
|
||||
|
||||
_sema_post :: proc(s: ^Sema, count := 1) {
|
||||
mutex_lock(&s.impl.mutex);
|
||||
defer mutex_unlock(&s.impl.mutex);
|
||||
mutex_lock(&s.impl.mutex)
|
||||
defer mutex_unlock(&s.impl.mutex)
|
||||
|
||||
s.impl.count += count;
|
||||
cond_signal(&s.impl.cond);
|
||||
s.impl.count += count
|
||||
cond_signal(&s.impl.cond)
|
||||
}
|
||||
|
||||
|
||||
|
||||
+15
-15
@@ -7,13 +7,13 @@ import "core:c"
|
||||
foreign import pthread "System.framework"
|
||||
|
||||
current_thread_id :: proc "contextless" () -> int {
|
||||
tid: u64;
|
||||
tid: u64
|
||||
// NOTE(Oskar): available from OSX 10.6 and iOS 3.2.
|
||||
// For older versions there is `syscall(SYS_thread_selfid)`, but not really
|
||||
// the same thing apparently.
|
||||
foreign pthread { pthread_threadid_np :: proc "c" (rawptr, ^u64) -> c.int ---; }
|
||||
pthread_threadid_np(nil, &tid);
|
||||
return int(tid);
|
||||
foreign pthread { pthread_threadid_np :: proc "c" (rawptr, ^u64) -> c.int --- }
|
||||
pthread_threadid_np(nil, &tid)
|
||||
return int(tid)
|
||||
}
|
||||
|
||||
|
||||
@@ -28,27 +28,27 @@ Semaphore :: struct #align 16 {
|
||||
// See core/sys/unix/pthread_linux.odin/pthread_t.
|
||||
|
||||
semaphore_init :: proc(s: ^Semaphore, initial_count := 0) {
|
||||
ct := darwin.mach_task_self();
|
||||
res := darwin.semaphore_create(ct, &s.handle, 0, c.int(initial_count));
|
||||
assert(res == 0);
|
||||
ct := darwin.mach_task_self()
|
||||
res := darwin.semaphore_create(ct, &s.handle, 0, c.int(initial_count))
|
||||
assert(res == 0)
|
||||
}
|
||||
|
||||
semaphore_destroy :: proc(s: ^Semaphore) {
|
||||
ct := darwin.mach_task_self();
|
||||
res := darwin.semaphore_destroy(ct, s.handle);
|
||||
assert(res == 0);
|
||||
s.handle = {};
|
||||
ct := darwin.mach_task_self()
|
||||
res := darwin.semaphore_destroy(ct, s.handle)
|
||||
assert(res == 0)
|
||||
s.handle = {}
|
||||
}
|
||||
|
||||
semaphore_post :: proc(s: ^Semaphore, count := 1) {
|
||||
// NOTE: SPEED: If there's one syscall to do this, we should use it instead of the loop.
|
||||
for in 0..<count {
|
||||
res := darwin.semaphore_signal(s.handle);
|
||||
assert(res == 0);
|
||||
res := darwin.semaphore_signal(s.handle)
|
||||
assert(res == 0)
|
||||
}
|
||||
}
|
||||
|
||||
semaphore_wait_for :: proc(s: ^Semaphore) {
|
||||
res := darwin.semaphore_wait(s.handle);
|
||||
assert(res == 0);
|
||||
res := darwin.semaphore_wait(s.handle)
|
||||
assert(res == 0)
|
||||
}
|
||||
|
||||
@@ -4,8 +4,8 @@ import "core:sys/unix"
|
||||
import "core:intrinsics"
|
||||
|
||||
current_thread_id :: proc "contextless" () -> int {
|
||||
SYS_GETTID :: 186;
|
||||
return int(intrinsics.syscall(SYS_GETTID));
|
||||
SYS_GETTID :: 186
|
||||
return int(intrinsics.syscall(SYS_GETTID))
|
||||
}
|
||||
|
||||
|
||||
@@ -18,21 +18,21 @@ Semaphore :: struct #align 16 {
|
||||
}
|
||||
|
||||
semaphore_init :: proc(s: ^Semaphore, initial_count := 0) {
|
||||
assert(unix.sem_init(&s.handle, 0, u32(initial_count)) == 0);
|
||||
assert(unix.sem_init(&s.handle, 0, u32(initial_count)) == 0)
|
||||
}
|
||||
|
||||
semaphore_destroy :: proc(s: ^Semaphore) {
|
||||
assert(unix.sem_destroy(&s.handle) == 0);
|
||||
s.handle = {};
|
||||
assert(unix.sem_destroy(&s.handle) == 0)
|
||||
s.handle = {}
|
||||
}
|
||||
|
||||
semaphore_post :: proc(s: ^Semaphore, count := 1) {
|
||||
// NOTE: SPEED: If there's one syscall to do this, we should use it instead of the loop.
|
||||
for in 0..<count {
|
||||
assert(unix.sem_post(&s.handle) == 0);
|
||||
assert(unix.sem_post(&s.handle) == 0)
|
||||
}
|
||||
}
|
||||
|
||||
semaphore_wait_for :: proc(s: ^Semaphore) {
|
||||
assert(unix.sem_wait(&s.handle) == 0);
|
||||
assert(unix.sem_wait(&s.handle) == 0)
|
||||
}
|
||||
|
||||
+72
-72
@@ -12,30 +12,30 @@ Mutex :: struct {
|
||||
|
||||
mutex_init :: proc(m: ^Mutex) {
|
||||
// NOTE(tetra, 2019-11-01): POSIX OOM if we cannot init the attrs or the mutex.
|
||||
attrs: unix.pthread_mutexattr_t;
|
||||
assert(unix.pthread_mutexattr_init(&attrs) == 0);
|
||||
defer unix.pthread_mutexattr_destroy(&attrs); // ignores destruction error
|
||||
unix.pthread_mutexattr_settype(&attrs, unix.PTHREAD_MUTEX_RECURSIVE);
|
||||
attrs: unix.pthread_mutexattr_t
|
||||
assert(unix.pthread_mutexattr_init(&attrs) == 0)
|
||||
defer unix.pthread_mutexattr_destroy(&attrs) // ignores destruction error
|
||||
unix.pthread_mutexattr_settype(&attrs, unix.PTHREAD_MUTEX_RECURSIVE)
|
||||
|
||||
assert(unix.pthread_mutex_init(&m.handle, &attrs) == 0);
|
||||
assert(unix.pthread_mutex_init(&m.handle, &attrs) == 0)
|
||||
}
|
||||
|
||||
mutex_destroy :: proc(m: ^Mutex) {
|
||||
assert(unix.pthread_mutex_destroy(&m.handle) == 0);
|
||||
m.handle = {};
|
||||
assert(unix.pthread_mutex_destroy(&m.handle) == 0)
|
||||
m.handle = {}
|
||||
}
|
||||
|
||||
mutex_lock :: proc(m: ^Mutex) {
|
||||
assert(unix.pthread_mutex_lock(&m.handle) == 0);
|
||||
assert(unix.pthread_mutex_lock(&m.handle) == 0)
|
||||
}
|
||||
|
||||
// Returns false if someone else holds the lock.
|
||||
mutex_try_lock :: proc(m: ^Mutex) -> bool {
|
||||
return unix.pthread_mutex_trylock(&m.handle) == 0;
|
||||
return unix.pthread_mutex_trylock(&m.handle) == 0
|
||||
}
|
||||
|
||||
mutex_unlock :: proc(m: ^Mutex) {
|
||||
assert(unix.pthread_mutex_unlock(&m.handle) == 0);
|
||||
assert(unix.pthread_mutex_unlock(&m.handle) == 0)
|
||||
}
|
||||
|
||||
|
||||
@@ -46,29 +46,29 @@ Blocking_Mutex :: struct {
|
||||
|
||||
blocking_mutex_init :: proc(m: ^Blocking_Mutex) {
|
||||
// NOTE(tetra, 2019-11-01): POSIX OOM if we cannot init the attrs or the mutex.
|
||||
attrs: unix.pthread_mutexattr_t;
|
||||
assert(unix.pthread_mutexattr_init(&attrs) == 0);
|
||||
defer unix.pthread_mutexattr_destroy(&attrs); // ignores destruction error
|
||||
attrs: unix.pthread_mutexattr_t
|
||||
assert(unix.pthread_mutexattr_init(&attrs) == 0)
|
||||
defer unix.pthread_mutexattr_destroy(&attrs) // ignores destruction error
|
||||
|
||||
assert(unix.pthread_mutex_init(&m.handle, &attrs) == 0);
|
||||
assert(unix.pthread_mutex_init(&m.handle, &attrs) == 0)
|
||||
}
|
||||
|
||||
blocking_mutex_destroy :: proc(m: ^Blocking_Mutex) {
|
||||
assert(unix.pthread_mutex_destroy(&m.handle) == 0);
|
||||
m.handle = {};
|
||||
assert(unix.pthread_mutex_destroy(&m.handle) == 0)
|
||||
m.handle = {}
|
||||
}
|
||||
|
||||
blocking_mutex_lock :: proc(m: ^Blocking_Mutex) {
|
||||
assert(unix.pthread_mutex_lock(&m.handle) == 0);
|
||||
assert(unix.pthread_mutex_lock(&m.handle) == 0)
|
||||
}
|
||||
|
||||
// Returns false if someone else holds the lock.
|
||||
blocking_mutex_try_lock :: proc(m: ^Blocking_Mutex) -> bool {
|
||||
return unix.pthread_mutex_trylock(&m.handle) == 0;
|
||||
return unix.pthread_mutex_trylock(&m.handle) == 0
|
||||
}
|
||||
|
||||
blocking_mutex_unlock :: proc(m: ^Blocking_Mutex) {
|
||||
assert(unix.pthread_mutex_unlock(&m.handle) == 0);
|
||||
assert(unix.pthread_mutex_unlock(&m.handle) == 0)
|
||||
}
|
||||
|
||||
|
||||
@@ -90,42 +90,42 @@ Condition :: struct {
|
||||
|
||||
condition_init :: proc(c: ^Condition, mutex: Condition_Mutex_Ptr) -> bool {
|
||||
// NOTE(tetra, 2019-11-01): POSIX OOM if we cannot init the attrs or the condition.
|
||||
attrs: unix.pthread_condattr_t;
|
||||
attrs: unix.pthread_condattr_t
|
||||
if unix.pthread_condattr_init(&attrs) != 0 {
|
||||
return false;
|
||||
return false
|
||||
}
|
||||
defer unix.pthread_condattr_destroy(&attrs); // ignores destruction error
|
||||
defer unix.pthread_condattr_destroy(&attrs) // ignores destruction error
|
||||
|
||||
c.flag = false;
|
||||
c.mutex = mutex;
|
||||
return unix.pthread_cond_init(&c.handle, &attrs) == 0;
|
||||
c.flag = false
|
||||
c.mutex = mutex
|
||||
return unix.pthread_cond_init(&c.handle, &attrs) == 0
|
||||
}
|
||||
|
||||
condition_destroy :: proc(c: ^Condition) {
|
||||
assert(unix.pthread_cond_destroy(&c.handle) == 0);
|
||||
c.handle = {};
|
||||
assert(unix.pthread_cond_destroy(&c.handle) == 0)
|
||||
c.handle = {}
|
||||
}
|
||||
|
||||
// Awaken exactly one thread who is waiting on the condition
|
||||
condition_signal :: proc(c: ^Condition) -> bool {
|
||||
switch m in c.mutex {
|
||||
case ^Mutex:
|
||||
mutex_lock(m);
|
||||
defer mutex_unlock(m);
|
||||
atomic_swap(&c.flag, true, .Sequentially_Consistent);
|
||||
return unix.pthread_cond_signal(&c.handle) == 0;
|
||||
mutex_lock(m)
|
||||
defer mutex_unlock(m)
|
||||
atomic_swap(&c.flag, true, .Sequentially_Consistent)
|
||||
return unix.pthread_cond_signal(&c.handle) == 0
|
||||
case ^Blocking_Mutex:
|
||||
blocking_mutex_lock(m);
|
||||
defer blocking_mutex_unlock(m);
|
||||
atomic_swap(&c.flag, true, .Sequentially_Consistent);
|
||||
return unix.pthread_cond_signal(&c.handle) == 0;
|
||||
blocking_mutex_lock(m)
|
||||
defer blocking_mutex_unlock(m)
|
||||
atomic_swap(&c.flag, true, .Sequentially_Consistent)
|
||||
return unix.pthread_cond_signal(&c.handle) == 0
|
||||
}
|
||||
return false;
|
||||
return false
|
||||
}
|
||||
|
||||
// Awaken all threads who are waiting on the condition
|
||||
condition_broadcast :: proc(c: ^Condition) -> bool {
|
||||
return unix.pthread_cond_broadcast(&c.handle) == 0;
|
||||
return unix.pthread_cond_broadcast(&c.handle) == 0
|
||||
}
|
||||
|
||||
// Wait for the condition to be signalled.
|
||||
@@ -134,48 +134,48 @@ condition_broadcast :: proc(c: ^Condition) -> bool {
|
||||
condition_wait_for :: proc(c: ^Condition) -> bool {
|
||||
switch m in c.mutex {
|
||||
case ^Mutex:
|
||||
mutex_lock(m);
|
||||
defer mutex_unlock(m);
|
||||
mutex_lock(m)
|
||||
defer mutex_unlock(m)
|
||||
// NOTE(tetra): If a thread comes by and steals the flag immediately after the signal occurs,
|
||||
// the thread that gets signalled and wakes up, discovers that the flag was taken and goes
|
||||
// back to sleep.
|
||||
// Though this overall behavior is the most sane, there may be a better way to do this that means that
|
||||
// the first thread to wait, gets the flag first.
|
||||
if atomic_swap(&c.flag, false, .Sequentially_Consistent) {
|
||||
return true;
|
||||
return true
|
||||
}
|
||||
for {
|
||||
if unix.pthread_cond_wait(&c.handle, &m.handle) != 0 {
|
||||
return false;
|
||||
return false
|
||||
}
|
||||
if atomic_swap(&c.flag, false, .Sequentially_Consistent) {
|
||||
return true;
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false;
|
||||
return false
|
||||
|
||||
case ^Blocking_Mutex:
|
||||
blocking_mutex_lock(m);
|
||||
defer blocking_mutex_unlock(m);
|
||||
blocking_mutex_lock(m)
|
||||
defer blocking_mutex_unlock(m)
|
||||
// NOTE(tetra): If a thread comes by and steals the flag immediately after the signal occurs,
|
||||
// the thread that gets signalled and wakes up, discovers that the flag was taken and goes
|
||||
// back to sleep.
|
||||
// Though this overall behavior is the most sane, there may be a better way to do this that means that
|
||||
// the first thread to wait, gets the flag first.
|
||||
if atomic_swap(&c.flag, false, .Sequentially_Consistent) {
|
||||
return true;
|
||||
return true
|
||||
}
|
||||
for {
|
||||
if unix.pthread_cond_wait(&c.handle, &m.handle) != 0 {
|
||||
return false;
|
||||
return false
|
||||
}
|
||||
if atomic_swap(&c.flag, false, .Sequentially_Consistent) {
|
||||
return true;
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false;
|
||||
return false
|
||||
}
|
||||
return false;
|
||||
return false
|
||||
}
|
||||
|
||||
// Wait for the condition to be signalled.
|
||||
@@ -184,65 +184,65 @@ condition_wait_for :: proc(c: ^Condition) -> bool {
|
||||
condition_wait_for_timeout :: proc(c: ^Condition, duration: time.Duration) -> bool {
|
||||
switch m in c.mutex {
|
||||
case ^Mutex:
|
||||
mutex_lock(m);
|
||||
defer mutex_unlock(m);
|
||||
mutex_lock(m)
|
||||
defer mutex_unlock(m)
|
||||
// NOTE(tetra): If a thread comes by and steals the flag immediately after the signal occurs,
|
||||
// the thread that gets signalled and wakes up, discovers that the flag was taken and goes
|
||||
// back to sleep.
|
||||
// Though this overall behavior is the most sane, there may be a better way to do this that means that
|
||||
// the first thread to wait, gets the flag first.
|
||||
if atomic_swap(&c.flag, false, .Sequentially_Consistent) {
|
||||
return true;
|
||||
return true
|
||||
}
|
||||
|
||||
ns := time.duration_nanoseconds(duration);
|
||||
timeout: time.TimeSpec;
|
||||
timeout.tv_sec = ns / 1e9;
|
||||
timeout.tv_nsec = ns % 1e9;
|
||||
ns := time.duration_nanoseconds(duration)
|
||||
timeout: time.TimeSpec
|
||||
timeout.tv_sec = ns / 1e9
|
||||
timeout.tv_nsec = ns % 1e9
|
||||
|
||||
for {
|
||||
if unix.pthread_cond_timedwait(&c.handle, &m.handle, &timeout) != 0 {
|
||||
return false;
|
||||
return false
|
||||
}
|
||||
if atomic_swap(&c.flag, false, .Sequentially_Consistent) {
|
||||
return true;
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false;
|
||||
return false
|
||||
|
||||
case ^Blocking_Mutex:
|
||||
blocking_mutex_lock(m);
|
||||
defer blocking_mutex_unlock(m);
|
||||
blocking_mutex_lock(m)
|
||||
defer blocking_mutex_unlock(m)
|
||||
// NOTE(tetra): If a thread comes by and steals the flag immediately after the signal occurs,
|
||||
// the thread that gets signalled and wakes up, discovers that the flag was taken and goes
|
||||
// back to sleep.
|
||||
// Though this overall behavior is the most sane, there may be a better way to do this that means that
|
||||
// the first thread to wait, gets the flag first.
|
||||
if atomic_swap(&c.flag, false, .Sequentially_Consistent) {
|
||||
return true;
|
||||
return true
|
||||
}
|
||||
|
||||
ns := time.duration_nanoseconds(duration);
|
||||
ns := time.duration_nanoseconds(duration)
|
||||
|
||||
timeout: time.TimeSpec;
|
||||
timeout.tv_sec = ns / 1e9;
|
||||
timeout.tv_nsec = ns % 1e9;
|
||||
timeout: time.TimeSpec
|
||||
timeout.tv_sec = ns / 1e9
|
||||
timeout.tv_nsec = ns % 1e9
|
||||
|
||||
for {
|
||||
if unix.pthread_cond_timedwait(&c.handle, &m.handle, &timeout) != 0 {
|
||||
return false;
|
||||
return false
|
||||
}
|
||||
if atomic_swap(&c.flag, false, .Sequentially_Consistent) {
|
||||
return true;
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false;
|
||||
return false
|
||||
}
|
||||
return false;
|
||||
return false
|
||||
}
|
||||
|
||||
|
||||
|
||||
thread_yield :: proc() {
|
||||
unix.sched_yield();
|
||||
unix.sched_yield()
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user