diff --git a/core/sync/extended.odin b/core/sync/extended.odin index 49d296c90..340244eb9 100644 --- a/core/sync/extended.odin +++ b/core/sync/extended.odin @@ -11,7 +11,7 @@ Wait_Group :: struct { cond: Cond, } -wait_group_add :: proc(wg: ^Wait_Group, delta: int) { +wait_group_add :: proc "contextless" (wg: ^Wait_Group, delta: int) { if delta == 0 { return } @@ -20,32 +20,32 @@ wait_group_add :: proc(wg: ^Wait_Group, delta: int) { atomic_add(&wg.counter, delta) if wg.counter < 0 { - panic("sync.Wait_Group negative counter") + _panic("sync.Wait_Group negative counter") } if wg.counter == 0 { cond_broadcast(&wg.cond) if wg.counter != 0 { - panic("sync.Wait_Group misuse: sync.wait_group_add called concurrently with sync.wait_group_wait") + _panic("sync.Wait_Group misuse: sync.wait_group_add called concurrently with sync.wait_group_wait") } } } -wait_group_done :: proc(wg: ^Wait_Group) { +wait_group_done :: proc "contextless" (wg: ^Wait_Group) { wait_group_add(wg, -1) } -wait_group_wait :: proc(wg: ^Wait_Group) { +wait_group_wait :: proc "contextless" (wg: ^Wait_Group) { guard(&wg.mutex) if wg.counter != 0 { cond_wait(&wg.cond, &wg.mutex) if wg.counter != 0 { - panic("sync.Wait_Group misuse: sync.wait_group_add called concurrently with sync.wait_group_wait") + _panic("sync.Wait_Group misuse: sync.wait_group_add called concurrently with sync.wait_group_wait") } } } -wait_group_wait_with_timeout :: proc(wg: ^Wait_Group, duration: time.Duration) -> bool { +wait_group_wait_with_timeout :: proc "contextless" (wg: ^Wait_Group, duration: time.Duration) -> bool { if duration <= 0 { return false } @@ -56,7 +56,7 @@ wait_group_wait_with_timeout :: proc(wg: ^Wait_Group, duration: time.Duration) - return false } if wg.counter != 0 { - panic("sync.Wait_Group misuse: sync.wait_group_add called concurrently with sync.wait_group_wait") + _panic("sync.Wait_Group misuse: sync.wait_group_add called concurrently with sync.wait_group_wait") } } return true @@ -76,7 +76,7 @@ Example: barrier := &sync.Barrier{} - main :: proc() { + main :: proc "contextless" () { fmt.println("Start") THREAD_COUNT :: 4 @@ -107,7 +107,7 @@ Barrier :: struct { thread_count: int, } -barrier_init :: proc(b: ^Barrier, thread_count: int) { +barrier_init :: proc "contextless" (b: ^Barrier, thread_count: int) { b.index = 0 b.generation_id = 0 b.thread_count = thread_count @@ -115,7 +115,7 @@ barrier_init :: proc(b: ^Barrier, thread_count: int) { // Block the current thread until all threads have rendezvoused // Barrier can be reused after all threads rendezvoused once, and can be used continuously -barrier_wait :: proc(b: ^Barrier) -> (is_leader: bool) { +barrier_wait :: proc "contextless" (b: ^Barrier) -> (is_leader: bool) { guard(&b.mutex) local_gen := b.generation_id b.index += 1 @@ -141,7 +141,7 @@ Auto_Reset_Event :: struct { sema: Sema, } -auto_reset_event_signal :: proc(e: ^Auto_Reset_Event) { +auto_reset_event_signal :: proc "contextless" (e: ^Auto_Reset_Event) { old_status := atomic_load_explicit(&e.status, .Relaxed) for { new_status := old_status + 1 if old_status < 1 else 1 @@ -155,7 +155,7 @@ auto_reset_event_signal :: proc(e: ^Auto_Reset_Event) { } } -auto_reset_event_wait :: proc(e: ^Auto_Reset_Event) { +auto_reset_event_wait :: proc "contextless" (e: ^Auto_Reset_Event) { old_status := atomic_sub_explicit(&e.status, 1, .Acquire) if old_status < 1 { sema_wait(&e.sema) @@ -169,18 +169,18 @@ Ticket_Mutex :: struct { serving: uint, } -ticket_mutex_lock :: #force_inline proc(m: ^Ticket_Mutex) { +ticket_mutex_lock :: #force_inline proc "contextless" (m: ^Ticket_Mutex) { ticket := atomic_add_explicit(&m.ticket, 1, .Relaxed) for ticket != atomic_load_explicit(&m.serving, .Acquire) { cpu_relax() } } -ticket_mutex_unlock :: #force_inline proc(m: ^Ticket_Mutex) { +ticket_mutex_unlock :: #force_inline proc "contextless" (m: ^Ticket_Mutex) { atomic_add_explicit(&m.serving, 1, .Relaxed) } @(deferred_in=ticket_mutex_unlock) -ticket_mutex_guard :: proc(m: ^Ticket_Mutex) -> bool { +ticket_mutex_guard :: proc "contextless" (m: ^Ticket_Mutex) -> bool { ticket_mutex_lock(m) return true } @@ -191,25 +191,25 @@ Benaphore :: struct { sema: Sema, } -benaphore_lock :: proc(b: ^Benaphore) { +benaphore_lock :: proc "contextless" (b: ^Benaphore) { if atomic_add_explicit(&b.counter, 1, .Acquire) > 1 { sema_wait(&b.sema) } } -benaphore_try_lock :: proc(b: ^Benaphore) -> bool { +benaphore_try_lock :: proc "contextless" (b: ^Benaphore) -> bool { v, _ := atomic_compare_exchange_strong_explicit(&b.counter, 0, 1, .Acquire, .Acquire) return v == 0 } -benaphore_unlock :: proc(b: ^Benaphore) { +benaphore_unlock :: proc "contextless" (b: ^Benaphore) { if atomic_sub_explicit(&b.counter, 1, .Release) > 0 { sema_post(&b.sema) } } @(deferred_in=benaphore_unlock) -benaphore_guard :: proc(m: ^Benaphore) -> bool { +benaphore_guard :: proc "contextless" (m: ^Benaphore) -> bool { benaphore_lock(m) return true } @@ -221,7 +221,7 @@ Recursive_Benaphore :: struct { sema: Sema, } -recursive_benaphore_lock :: proc(b: ^Recursive_Benaphore) { +recursive_benaphore_lock :: proc "contextless" (b: ^Recursive_Benaphore) { tid := current_thread_id() if atomic_add_explicit(&b.counter, 1, .Acquire) > 1 { if tid != b.owner { @@ -233,7 +233,7 @@ recursive_benaphore_lock :: proc(b: ^Recursive_Benaphore) { b.recursion += 1 } -recursive_benaphore_try_lock :: proc(b: ^Recursive_Benaphore) -> bool { +recursive_benaphore_try_lock :: proc "contextless" (b: ^Recursive_Benaphore) -> bool { tid := current_thread_id() if b.owner == tid { atomic_add_explicit(&b.counter, 1, .Acquire) @@ -248,9 +248,9 @@ recursive_benaphore_try_lock :: proc(b: ^Recursive_Benaphore) -> bool { return true } -recursive_benaphore_unlock :: proc(b: ^Recursive_Benaphore) { +recursive_benaphore_unlock :: proc "contextless" (b: ^Recursive_Benaphore) { tid := current_thread_id() - assert(tid == b.owner) + _assert(tid == b.owner, "tid != b.owner") b.recursion -= 1 recursion := b.recursion if recursion == 0 { @@ -265,7 +265,7 @@ recursive_benaphore_unlock :: proc(b: ^Recursive_Benaphore) { } @(deferred_in=recursive_benaphore_unlock) -recursive_benaphore_guard :: proc(m: ^Recursive_Benaphore) -> bool { +recursive_benaphore_guard :: proc "contextless" (m: ^Recursive_Benaphore) -> bool { recursive_benaphore_lock(m) return true } @@ -314,7 +314,7 @@ Parker :: struct { // Blocks the current thread until the token is made available. // // Assumes this is only called by the thread that owns the Parker. -park :: proc(p: ^Parker) { +park :: proc "contextless" (p: ^Parker) { EMPTY :: 0 NOTIFIED :: 1 PARKED :: max(u32) @@ -333,7 +333,7 @@ park :: proc(p: ^Parker) { // for a limited duration. // // Assumes this is only called by the thread that owns the Parker -park_with_timeout :: proc(p: ^Parker, duration: time.Duration) { +park_with_timeout :: proc "contextless" (p: ^Parker, duration: time.Duration) { EMPTY :: 0 NOTIFIED :: 1 PARKED :: max(u32) @@ -345,7 +345,7 @@ park_with_timeout :: proc(p: ^Parker, duration: time.Duration) { } // Automatically makes thee token available if it was not already. -unpark :: proc(p: ^Parker) { +unpark :: proc "contextless" (p: ^Parker) { EMPTY :: 0 NOTIFIED :: 1 PARKED :: max(Futex) diff --git a/core/sync/futex_darwin.odin b/core/sync/futex_darwin.odin index 1c118e75d..b85b15782 100644 --- a/core/sync/futex_darwin.odin +++ b/core/sync/futex_darwin.odin @@ -24,11 +24,11 @@ EINTR :: -4 EFAULT :: -14 ETIMEDOUT :: -60 -_futex_wait :: proc(f: ^Futex, expected: u32) -> bool { +_futex_wait :: proc "contextless" (f: ^Futex, expected: u32) -> bool { return _futex_wait_with_timeout(f, expected, 0) } -_futex_wait_with_timeout :: proc(f: ^Futex, expected: u32, duration: time.Duration) -> bool { +_futex_wait_with_timeout :: proc "contextless" (f: ^Futex, expected: u32, duration: time.Duration) -> bool { timeout_ns := u32(duration) * 1000 s := __ulock_wait(UL_COMPARE_AND_WAIT | ULF_NO_ERRNO, f, u64(expected), timeout_ns) @@ -41,13 +41,13 @@ _futex_wait_with_timeout :: proc(f: ^Futex, expected: u32, duration: time.Durati case ETIMEDOUT: return false case: - panic("futex_wait failure") + _panic("futex_wait failure") } return true } -_futex_signal :: proc(f: ^Futex) { +_futex_signal :: proc "contextless" (f: ^Futex) { loop: for { s := __ulock_wake(UL_COMPARE_AND_WAIT | ULF_NO_ERRNO, f, 0) if s >= 0 { @@ -59,12 +59,12 @@ _futex_signal :: proc(f: ^Futex) { case ENOENT: return case: - panic("futex_wake_single failure") + _panic("futex_wake_single failure") } } } -_futex_broadcast :: proc(f: ^Futex) { +_futex_broadcast :: proc "contextless" (f: ^Futex) { loop: for { s := __ulock_wake(UL_COMPARE_AND_WAIT | ULF_NO_ERRNO | ULF_WAKE_ALL, f, 0) if s >= 0 { @@ -76,7 +76,7 @@ _futex_broadcast :: proc(f: ^Futex) { case ENOENT: return case: - panic("futex_wake_all failure") + _panic("futex_wake_all failure") } } } diff --git a/core/sync/futex_freebsd.odin b/core/sync/futex_freebsd.odin index 07fba82a8..60b1d6e0d 100644 --- a/core/sync/futex_freebsd.odin +++ b/core/sync/futex_freebsd.odin @@ -17,7 +17,7 @@ foreign libc { __error :: proc "c" () -> ^c.int --- } -_futex_wait :: proc(f: ^Futex, expected: u32) -> bool { +_futex_wait :: proc "contextless" (f: ^Futex, expected: u32) -> bool { timeout := [2]i64{14400, 0} // 4 hours for { res := _umtx_op(f, UMTX_OP_WAIT, c.ulong(expected), nil, &timeout) @@ -30,12 +30,12 @@ _futex_wait :: proc(f: ^Futex, expected: u32) -> bool { continue } - panic("_futex_wait failure") + _panic("_futex_wait failure") } unreachable() } -_futex_wait_with_timeout :: proc(f: ^Futex, expected: u32, duration: time.Duration) -> bool { +_futex_wait_with_timeout :: proc "contextless" (f: ^Futex, expected: u32, duration: time.Duration) -> bool { if duration <= 0 { return false } @@ -51,21 +51,21 @@ _futex_wait_with_timeout :: proc(f: ^Futex, expected: u32, duration: time.Durati return false } - panic("_futex_wait_with_timeout failure") + _panic("_futex_wait_with_timeout failure") } -_futex_signal :: proc(f: ^Futex) { +_futex_signal :: proc "contextless" (f: ^Futex) { res := _umtx_op(f, UMTX_OP_WAKE, 1, nil, nil) if res == -1 { - panic("_futex_signal failure") + _panic("_futex_signal failure") } } -_futex_broadcast :: proc(f: ^Futex) { +_futex_broadcast :: proc "contextless" (f: ^Futex) { res := _umtx_op(f, UMTX_OP_WAKE, c.ulong(max(i32)), nil, nil) if res == -1 { - panic("_futex_broadcast failure") + _panic("_futex_broadcast failure") } } diff --git a/core/sync/futex_linux.odin b/core/sync/futex_linux.odin index c429a9d64..947d61cdf 100644 --- a/core/sync/futex_linux.odin +++ b/core/sync/futex_linux.odin @@ -21,20 +21,20 @@ EFAULT :: -14 EINVAL :: -22 ETIMEDOUT :: -110 -get_errno :: proc(r: int) -> int { +get_errno :: proc "contextless" (r: int) -> int { if -4096 < r && r < 0 { return r } return 0 } -internal_futex :: proc(f: ^Futex, op: c.int, val: u32, timeout: rawptr) -> int { +internal_futex :: proc "contextless" (f: ^Futex, op: c.int, val: u32, timeout: rawptr) -> int { code := int(intrinsics.syscall(unix.SYS_futex, uintptr(f), uintptr(op), uintptr(val), uintptr(timeout), 0, 0)) return get_errno(code) } -_futex_wait :: proc(f: ^Futex, expected: u32) -> bool { +_futex_wait :: proc "contextless" (f: ^Futex, expected: u32) -> bool { err := internal_futex(f, FUTEX_WAIT_PRIVATE | FUTEX_WAIT, expected, nil) switch err { case ESUCCESS, EINTR, EAGAIN, EINVAL: @@ -44,12 +44,12 @@ _futex_wait :: proc(f: ^Futex, expected: u32) -> bool { case EFAULT: fallthrough case: - panic("futex_wait failure") + _panic("futex_wait failure") } return true } -_futex_wait_with_timeout :: proc(f: ^Futex, expected: u32, duration: time.Duration) -> bool { +_futex_wait_with_timeout :: proc "contextless" (f: ^Futex, expected: u32, duration: time.Duration) -> bool { if duration <= 0 { return false } @@ -71,27 +71,27 @@ _futex_wait_with_timeout :: proc(f: ^Futex, expected: u32, duration: time.Durati case EFAULT: fallthrough case: - panic("futex_wait_with_timeout failure") + _panic("futex_wait_with_timeout failure") } return true } -_futex_signal :: proc(f: ^Futex) { +_futex_signal :: proc "contextless" (f: ^Futex) { err := internal_futex(f, FUTEX_WAKE_PRIVATE | FUTEX_WAKE, 1, nil) switch err { case ESUCCESS, EINVAL, EFAULT: // okay case: - panic("futex_wake_single failure") + _panic("futex_wake_single failure") } } -_futex_broadcast :: proc(f: ^Futex) { +_futex_broadcast :: proc "contextless" (f: ^Futex) { err := internal_futex(f, FUTEX_WAKE_PRIVATE | FUTEX_WAKE, u32(max(i32)), nil) switch err { case ESUCCESS, EINVAL, EFAULT: // okay case: - panic("_futex_wake_all failure") + _panic("_futex_wake_all failure") } } diff --git a/core/sync/futex_openbsd.odin b/core/sync/futex_openbsd.odin index 6ac9d3efb..e02221277 100644 --- a/core/sync/futex_openbsd.odin +++ b/core/sync/futex_openbsd.odin @@ -21,7 +21,7 @@ foreign libc { _unix_futex :: proc "c" (f: ^Futex, op: c.int, val: u32, timeout: rawptr) -> c.int --- } -_futex_wait :: proc(f: ^Futex, expected: u32) -> bool { +_futex_wait :: proc "contextless" (f: ^Futex, expected: u32) -> bool { res := _unix_futex(f, FUTEX_WAIT_PRIVATE, expected, nil) if res != -1 { @@ -32,10 +32,10 @@ _futex_wait :: proc(f: ^Futex, expected: u32) -> bool { return false } - panic("futex_wait failure") + _panic("futex_wait failure") } -_futex_wait_with_timeout :: proc(f: ^Futex, expected: u32, duration: time.Duration) -> bool { +_futex_wait_with_timeout :: proc "contextless" (f: ^Futex, expected: u32, duration: time.Duration) -> bool { if duration <= 0 { return false } @@ -58,21 +58,21 @@ _futex_wait_with_timeout :: proc(f: ^Futex, expected: u32, duration: time.Durati return false } - panic("futex_wait_with_timeout failure") + _panic("futex_wait_with_timeout failure") } -_futex_signal :: proc(f: ^Futex) { +_futex_signal :: proc "contextless" (f: ^Futex) { res := _unix_futex(f, FUTEX_WAKE_PRIVATE, 1, nil) if res == -1 { - panic("futex_wake_single failure") + _panic("futex_wake_single failure") } } -_futex_broadcast :: proc(f: ^Futex) { +_futex_broadcast :: proc "contextless" (f: ^Futex) { res := _unix_futex(f, FUTEX_WAKE_PRIVATE, u32(max(i32)), nil) if res == -1 { - panic("_futex_wake_all failure") + _panic("_futex_wake_all failure") } } diff --git a/core/sync/futex_wasm.odin b/core/sync/futex_wasm.odin index a32935143..621f4edaa 100644 --- a/core/sync/futex_wasm.odin +++ b/core/sync/futex_wasm.odin @@ -5,18 +5,18 @@ package sync import "core:intrinsics" import "core:time" -_futex_wait :: proc(f: ^Futex, expected: u32) -> bool { +_futex_wait :: proc "contextless" (f: ^Futex, expected: u32) -> bool { s := intrinsics.wasm_memory_atomic_wait32((^u32)(f), expected, -1) return s != 0 } -_futex_wait_with_timeout :: proc(f: ^Futex, expected: u32, duration: time.Duration) -> bool { +_futex_wait_with_timeout :: proc "contextless" (f: ^Futex, expected: u32, duration: time.Duration) -> bool { s := intrinsics.wasm_memory_atomic_wait32((^u32)(f), expected, i64(duration)) return s != 0 } -_futex_signal :: proc(f: ^Futex) { +_futex_signal :: proc "contextless" (f: ^Futex) { loop: for { s := intrinsics.wasm_memory_atomic_notify32((^u32)(f), 1) if s >= 1 { @@ -25,7 +25,7 @@ _futex_signal :: proc(f: ^Futex) { } } -_futex_broadcast :: proc(f: ^Futex) { +_futex_broadcast :: proc "contextless" (f: ^Futex) { loop: for { s := intrinsics.wasm_memory_atomic_notify32((^u32)(f), ~u32(0)) if s >= 0 { diff --git a/core/sync/futex_windows.odin b/core/sync/futex_windows.odin index ba6292742..8ddbef3ed 100644 --- a/core/sync/futex_windows.odin +++ b/core/sync/futex_windows.odin @@ -39,22 +39,22 @@ CustomWaitOnAddress :: proc "stdcall" (Address: rawptr, CompareAddress: rawptr, } -_futex_wait :: proc(f: ^Futex, expect: u32) -> bool { +_futex_wait :: proc "contextless" (f: ^Futex, expect: u32) -> bool { expect := expect return CustomWaitOnAddress(f, &expect, size_of(expect), nil) } -_futex_wait_with_timeout :: proc(f: ^Futex, expect: u32, duration: time.Duration) -> bool { +_futex_wait_with_timeout :: proc "contextless" (f: ^Futex, expect: u32, duration: time.Duration) -> bool { expect := expect // NOTE(bill): for some bizarre reason, this has be a negative number timeout := -i64(duration / 100) return CustomWaitOnAddress(f, &expect, size_of(expect), &timeout) } -_futex_signal :: proc(f: ^Futex) { +_futex_signal :: proc "contextless" (f: ^Futex) { WakeByAddressSingle(f) } -_futex_broadcast :: proc(f: ^Futex) { +_futex_broadcast :: proc "contextless" (f: ^Futex) { WakeByAddressAll(f) } \ No newline at end of file diff --git a/core/sync/primitives.odin b/core/sync/primitives.odin index bfbdc6f9b..00d7812a8 100644 --- a/core/sync/primitives.odin +++ b/core/sync/primitives.odin @@ -1,5 +1,6 @@ package sync +import "core:runtime" import "core:time" current_thread_id :: proc "contextless" () -> int { @@ -15,17 +16,17 @@ Mutex :: struct { } // mutex_lock locks m -mutex_lock :: proc(m: ^Mutex) { +mutex_lock :: proc "contextless" (m: ^Mutex) { _mutex_lock(m) } // mutex_unlock unlocks m -mutex_unlock :: proc(m: ^Mutex) { +mutex_unlock :: proc "contextless" (m: ^Mutex) { _mutex_unlock(m) } // mutex_try_lock tries to lock m, will return true on success, and false on failure -mutex_try_lock :: proc(m: ^Mutex) -> bool { +mutex_try_lock :: proc "contextless" (m: ^Mutex) -> bool { return _mutex_try_lock(m) } @@ -36,7 +37,7 @@ Example: } */ @(deferred_in=mutex_unlock) -mutex_guard :: proc(m: ^Mutex) -> bool { +mutex_guard :: proc "contextless" (m: ^Mutex) -> bool { mutex_lock(m) return true } @@ -52,32 +53,32 @@ RW_Mutex :: struct { // rw_mutex_lock locks rw for writing (with a single writer) // If the mutex is already locked for reading or writing, the mutex blocks until the mutex is available. -rw_mutex_lock :: proc(rw: ^RW_Mutex) { +rw_mutex_lock :: proc "contextless" (rw: ^RW_Mutex) { _rw_mutex_lock(rw) } // rw_mutex_unlock unlocks rw for writing (with a single writer) -rw_mutex_unlock :: proc(rw: ^RW_Mutex) { +rw_mutex_unlock :: proc "contextless" (rw: ^RW_Mutex) { _rw_mutex_unlock(rw) } // rw_mutex_try_lock tries to lock rw for writing (with a single writer) -rw_mutex_try_lock :: proc(rw: ^RW_Mutex) -> bool { +rw_mutex_try_lock :: proc "contextless" (rw: ^RW_Mutex) -> bool { return _rw_mutex_try_lock(rw) } // rw_mutex_shared_lock locks rw for reading (with arbitrary number of readers) -rw_mutex_shared_lock :: proc(rw: ^RW_Mutex) { +rw_mutex_shared_lock :: proc "contextless" (rw: ^RW_Mutex) { _rw_mutex_shared_lock(rw) } // rw_mutex_shared_unlock unlocks rw for reading (with arbitrary number of readers) -rw_mutex_shared_unlock :: proc(rw: ^RW_Mutex) { +rw_mutex_shared_unlock :: proc "contextless" (rw: ^RW_Mutex) { _rw_mutex_shared_unlock(rw) } // rw_mutex_try_shared_lock tries to lock rw for reading (with arbitrary number of readers) -rw_mutex_try_shared_lock :: proc(rw: ^RW_Mutex) -> bool { +rw_mutex_try_shared_lock :: proc "contextless" (rw: ^RW_Mutex) -> bool { return _rw_mutex_try_shared_lock(rw) } /* @@ -87,7 +88,7 @@ Example: } */ @(deferred_in=rw_mutex_unlock) -rw_mutex_guard :: proc(m: ^RW_Mutex) -> bool { +rw_mutex_guard :: proc "contextless" (m: ^RW_Mutex) -> bool { rw_mutex_lock(m) return true } @@ -99,7 +100,7 @@ Example: } */ @(deferred_in=rw_mutex_shared_unlock) -rw_mutex_shared_guard :: proc(m: ^RW_Mutex) -> bool { +rw_mutex_shared_guard :: proc "contextless" (m: ^RW_Mutex) -> bool { rw_mutex_shared_lock(m) return true } @@ -114,15 +115,15 @@ Recursive_Mutex :: struct { impl: _Recursive_Mutex, } -recursive_mutex_lock :: proc(m: ^Recursive_Mutex) { +recursive_mutex_lock :: proc "contextless" (m: ^Recursive_Mutex) { _recursive_mutex_lock(m) } -recursive_mutex_unlock :: proc(m: ^Recursive_Mutex) { +recursive_mutex_unlock :: proc "contextless" (m: ^Recursive_Mutex) { _recursive_mutex_unlock(m) } -recursive_mutex_try_lock :: proc(m: ^Recursive_Mutex) -> bool { +recursive_mutex_try_lock :: proc "contextless" (m: ^Recursive_Mutex) -> bool { return _recursive_mutex_try_lock(m) } @@ -133,7 +134,7 @@ Example: } */ @(deferred_in=recursive_mutex_unlock) -recursive_mutex_guard :: proc(m: ^Recursive_Mutex) -> bool { +recursive_mutex_guard :: proc "contextless" (m: ^Recursive_Mutex) -> bool { recursive_mutex_lock(m) return true } @@ -147,22 +148,22 @@ Cond :: struct { impl: _Cond, } -cond_wait :: proc(c: ^Cond, m: ^Mutex) { +cond_wait :: proc "contextless" (c: ^Cond, m: ^Mutex) { _cond_wait(c, m) } -cond_wait_with_timeout :: proc(c: ^Cond, m: ^Mutex, duration: time.Duration) -> bool { +cond_wait_with_timeout :: proc "contextless" (c: ^Cond, m: ^Mutex, duration: time.Duration) -> bool { if duration <= 0 { return false } return _cond_wait_with_timeout(c, m, duration) } -cond_signal :: proc(c: ^Cond) { +cond_signal :: proc "contextless" (c: ^Cond) { _cond_signal(c) } -cond_broadcast :: proc(c: ^Cond) { +cond_broadcast :: proc "contextless" (c: ^Cond) { _cond_broadcast(c) } @@ -175,15 +176,15 @@ Sema :: struct { impl: _Sema, } -sema_post :: proc(s: ^Sema, count := 1) { +sema_post :: proc "contextless" (s: ^Sema, count := 1) { _sema_post(s, count) } -sema_wait :: proc(s: ^Sema) { +sema_wait :: proc "contextless" (s: ^Sema) { _sema_wait(s) } -sema_wait_with_timeout :: proc(s: ^Sema, duration: time.Duration) -> bool { +sema_wait_with_timeout :: proc "contextless" (s: ^Sema, duration: time.Duration) -> bool { return _sema_wait_with_timeout(s, duration) } @@ -194,16 +195,16 @@ sema_wait_with_timeout :: proc(s: ^Sema, duration: time.Duration) -> bool { // An Futex must not be copied after first use Futex :: distinct u32 -futex_wait :: proc(f: ^Futex, expected: u32) { +futex_wait :: proc "contextless" (f: ^Futex, expected: u32) { if u32(atomic_load_explicit(f, .Acquire)) != expected { return } - assert(_futex_wait(f, expected), "futex_wait failure") + _assert(_futex_wait(f, expected), "futex_wait failure") } // returns true if the wait happened within the duration, false if it exceeded the time duration -futex_wait_with_timeout :: proc(f: ^Futex, expected: u32, duration: time.Duration) -> bool { +futex_wait_with_timeout :: proc "contextless" (f: ^Futex, expected: u32, duration: time.Duration) -> bool { if u32(atomic_load_explicit(f, .Acquire)) != expected { return true } @@ -214,10 +215,25 @@ futex_wait_with_timeout :: proc(f: ^Futex, expected: u32, duration: time.Duratio return _futex_wait_with_timeout(f, expected, duration) } -futex_signal :: proc(f: ^Futex) { +futex_signal :: proc "contextless" (f: ^Futex) { _futex_signal(f) } -futex_broadcast :: proc(f: ^Futex) { +futex_broadcast :: proc "contextless" (f: ^Futex) { _futex_broadcast(f) } + + +@(private) +_assert :: proc "contextless" (cond: bool, msg: string) { + if !cond { + _panic(msg) + } +} + +@(private) +_panic :: proc "contextless" (msg: string) -> ! { + runtime.print_string(msg) + runtime.print_byte('\n') + runtime.trap() +} \ No newline at end of file diff --git a/core/sync/primitives_atomic.odin b/core/sync/primitives_atomic.odin index a0f08c412..1abad5875 100644 --- a/core/sync/primitives_atomic.odin +++ b/core/sync/primitives_atomic.odin @@ -18,9 +18,9 @@ Atomic_Mutex :: struct { } // atomic_mutex_lock locks m -atomic_mutex_lock :: proc(m: ^Atomic_Mutex) { +atomic_mutex_lock :: proc "contextless" (m: ^Atomic_Mutex) { @(cold) - lock_slow :: proc(m: ^Atomic_Mutex, curr_state: Atomic_Mutex_State) { + lock_slow :: proc "contextless" (m: ^Atomic_Mutex, curr_state: Atomic_Mutex_State) { new_state := curr_state // Make a copy of it spin_lock: for spin in 0.. bool { +atomic_mutex_try_lock :: proc "contextless" (m: ^Atomic_Mutex) -> bool { _, ok := atomic_compare_exchange_strong_explicit(&m.state, .Unlocked, .Locked, .Acquire, .Consume) return ok } @@ -88,7 +88,7 @@ Example: } */ @(deferred_in=atomic_mutex_unlock) -atomic_mutex_guard :: proc(m: ^Atomic_Mutex) -> bool { +atomic_mutex_guard :: proc "contextless" (m: ^Atomic_Mutex) -> bool { atomic_mutex_lock(m) return true } @@ -117,7 +117,7 @@ Atomic_RW_Mutex :: struct { // atomic_rw_mutex_lock locks rw for writing (with a single writer) // If the mutex is already locked for reading or writing, the mutex blocks until the mutex is available. -atomic_rw_mutex_lock :: proc(rw: ^Atomic_RW_Mutex) { +atomic_rw_mutex_lock :: proc "contextless" (rw: ^Atomic_RW_Mutex) { _ = atomic_add(&rw.state, Atomic_RW_Mutex_State_Writer) atomic_mutex_lock(&rw.mutex) @@ -128,13 +128,13 @@ atomic_rw_mutex_lock :: proc(rw: ^Atomic_RW_Mutex) { } // atomic_rw_mutex_unlock unlocks rw for writing (with a single writer) -atomic_rw_mutex_unlock :: proc(rw: ^Atomic_RW_Mutex) { +atomic_rw_mutex_unlock :: proc "contextless" (rw: ^Atomic_RW_Mutex) { _ = atomic_and(&rw.state, ~Atomic_RW_Mutex_State_Is_Writing) atomic_mutex_unlock(&rw.mutex) } // atomic_rw_mutex_try_lock tries to lock rw for writing (with a single writer) -atomic_rw_mutex_try_lock :: proc(rw: ^Atomic_RW_Mutex) -> bool { +atomic_rw_mutex_try_lock :: proc "contextless" (rw: ^Atomic_RW_Mutex) -> bool { if atomic_mutex_try_lock(&rw.mutex) { state := atomic_load(&rw.state) if state & Atomic_RW_Mutex_State_Reader_Mask == 0 { @@ -148,7 +148,7 @@ atomic_rw_mutex_try_lock :: proc(rw: ^Atomic_RW_Mutex) -> bool { } // atomic_rw_mutex_shared_lock locks rw for reading (with arbitrary number of readers) -atomic_rw_mutex_shared_lock :: proc(rw: ^Atomic_RW_Mutex) { +atomic_rw_mutex_shared_lock :: proc "contextless" (rw: ^Atomic_RW_Mutex) { state := atomic_load(&rw.state) for state & (Atomic_RW_Mutex_State_Is_Writing|Atomic_RW_Mutex_State_Writer_Mask) == 0 { ok: bool @@ -164,7 +164,7 @@ atomic_rw_mutex_shared_lock :: proc(rw: ^Atomic_RW_Mutex) { } // atomic_rw_mutex_shared_unlock unlocks rw for reading (with arbitrary number of readers) -atomic_rw_mutex_shared_unlock :: proc(rw: ^Atomic_RW_Mutex) { +atomic_rw_mutex_shared_unlock :: proc "contextless" (rw: ^Atomic_RW_Mutex) { state := atomic_sub(&rw.state, Atomic_RW_Mutex_State_Reader) if (state & Atomic_RW_Mutex_State_Reader_Mask == Atomic_RW_Mutex_State_Reader) && @@ -174,7 +174,7 @@ atomic_rw_mutex_shared_unlock :: proc(rw: ^Atomic_RW_Mutex) { } // atomic_rw_mutex_try_shared_lock tries to lock rw for reading (with arbitrary number of readers) -atomic_rw_mutex_try_shared_lock :: proc(rw: ^Atomic_RW_Mutex) -> bool { +atomic_rw_mutex_try_shared_lock :: proc "contextless" (rw: ^Atomic_RW_Mutex) -> bool { state := atomic_load(&rw.state) if state & (Atomic_RW_Mutex_State_Is_Writing|Atomic_RW_Mutex_State_Writer_Mask) == 0 { _, ok := atomic_compare_exchange_strong(&rw.state, state, state + Atomic_RW_Mutex_State_Reader) @@ -198,7 +198,7 @@ Example: } */ @(deferred_in=atomic_rw_mutex_unlock) -atomic_rw_mutex_guard :: proc(m: ^Atomic_RW_Mutex) -> bool { +atomic_rw_mutex_guard :: proc "contextless" (m: ^Atomic_RW_Mutex) -> bool { atomic_rw_mutex_lock(m) return true } @@ -210,7 +210,7 @@ Example: } */ @(deferred_in=atomic_rw_mutex_shared_unlock) -atomic_rw_mutex_shared_guard :: proc(m: ^Atomic_RW_Mutex) -> bool { +atomic_rw_mutex_shared_guard :: proc "contextless" (m: ^Atomic_RW_Mutex) -> bool { atomic_rw_mutex_shared_lock(m) return true } @@ -228,7 +228,7 @@ Atomic_Recursive_Mutex :: struct { mutex: Mutex, } -atomic_recursive_mutex_lock :: proc(m: ^Atomic_Recursive_Mutex) { +atomic_recursive_mutex_lock :: proc "contextless" (m: ^Atomic_Recursive_Mutex) { tid := current_thread_id() if tid != m.owner { mutex_lock(&m.mutex) @@ -238,9 +238,9 @@ atomic_recursive_mutex_lock :: proc(m: ^Atomic_Recursive_Mutex) { m.recursion += 1 } -atomic_recursive_mutex_unlock :: proc(m: ^Atomic_Recursive_Mutex) { +atomic_recursive_mutex_unlock :: proc "contextless" (m: ^Atomic_Recursive_Mutex) { tid := current_thread_id() - assert(tid == m.owner) + _assert(tid == m.owner, "tid != m.owner") m.recursion -= 1 recursion := m.recursion if recursion == 0 { @@ -253,7 +253,7 @@ atomic_recursive_mutex_unlock :: proc(m: ^Atomic_Recursive_Mutex) { } -atomic_recursive_mutex_try_lock :: proc(m: ^Atomic_Recursive_Mutex) -> bool { +atomic_recursive_mutex_try_lock :: proc "contextless" (m: ^Atomic_Recursive_Mutex) -> bool { tid := current_thread_id() if m.owner == tid { return mutex_try_lock(&m.mutex) @@ -274,7 +274,7 @@ Example: } */ @(deferred_in=atomic_recursive_mutex_unlock) -atomic_recursive_mutex_guard :: proc(m: ^Atomic_Recursive_Mutex) -> bool { +atomic_recursive_mutex_guard :: proc "contextless" (m: ^Atomic_Recursive_Mutex) -> bool { atomic_recursive_mutex_lock(m) return true } @@ -289,7 +289,7 @@ Atomic_Cond :: struct { state: Futex, } -atomic_cond_wait :: proc(c: ^Atomic_Cond, m: ^Atomic_Mutex) { +atomic_cond_wait :: proc "contextless" (c: ^Atomic_Cond, m: ^Atomic_Mutex) { state := u32(atomic_load_explicit(&c.state, .Relaxed)) unlock(m) futex_wait(&c.state, state) @@ -297,7 +297,7 @@ atomic_cond_wait :: proc(c: ^Atomic_Cond, m: ^Atomic_Mutex) { } -atomic_cond_wait_with_timeout :: proc(c: ^Atomic_Cond, m: ^Atomic_Mutex, duration: time.Duration) -> (ok: bool) { +atomic_cond_wait_with_timeout :: proc "contextless" (c: ^Atomic_Cond, m: ^Atomic_Mutex, duration: time.Duration) -> (ok: bool) { state := u32(atomic_load_explicit(&c.state, .Relaxed)) unlock(m) ok = futex_wait_with_timeout(&c.state, state, duration) @@ -306,12 +306,12 @@ atomic_cond_wait_with_timeout :: proc(c: ^Atomic_Cond, m: ^Atomic_Mutex, duratio } -atomic_cond_signal :: proc(c: ^Atomic_Cond) { +atomic_cond_signal :: proc "contextless" (c: ^Atomic_Cond) { atomic_add_explicit(&c.state, 1, .Release) futex_signal(&c.state) } -atomic_cond_broadcast :: proc(c: ^Atomic_Cond) { +atomic_cond_broadcast :: proc "contextless" (c: ^Atomic_Cond) { atomic_add_explicit(&c.state, 1, .Release) futex_broadcast(&c.state) } @@ -324,7 +324,7 @@ Atomic_Sema :: struct { count: Futex, } -atomic_sema_post :: proc(s: ^Atomic_Sema, count := 1) { +atomic_sema_post :: proc "contextless" (s: ^Atomic_Sema, count := 1) { atomic_add_explicit(&s.count, Futex(count), .Release) if count == 1 { futex_signal(&s.count) @@ -333,7 +333,7 @@ atomic_sema_post :: proc(s: ^Atomic_Sema, count := 1) { } } -atomic_sema_wait :: proc(s: ^Atomic_Sema) { +atomic_sema_wait :: proc "contextless" (s: ^Atomic_Sema) { for { original_count := atomic_load_explicit(&s.count, .Relaxed) for original_count == 0 { @@ -346,7 +346,7 @@ atomic_sema_wait :: proc(s: ^Atomic_Sema) { } } -atomic_sema_wait_with_timeout :: proc(s: ^Atomic_Sema, duration: time.Duration) -> bool { +atomic_sema_wait_with_timeout :: proc "contextless" (s: ^Atomic_Sema, duration: time.Duration) -> bool { if duration <= 0 { return false } diff --git a/core/sync/primitives_internal.odin b/core/sync/primitives_internal.odin index ba17c2eb5..d613d821d 100644 --- a/core/sync/primitives_internal.odin +++ b/core/sync/primitives_internal.odin @@ -7,15 +7,15 @@ _Sema :: struct { atomic: Atomic_Sema, } -_sema_post :: proc(s: ^Sema, count := 1) { +_sema_post :: proc "contextless" (s: ^Sema, count := 1) { atomic_sema_post(&s.impl.atomic, count) } -_sema_wait :: proc(s: ^Sema) { +_sema_wait :: proc "contextless" (s: ^Sema) { atomic_sema_wait(&s.impl.atomic) } -_sema_wait_with_timeout :: proc(s: ^Sema, duration: time.Duration) -> bool { +_sema_wait_with_timeout :: proc "contextless" (s: ^Sema, duration: time.Duration) -> bool { return atomic_sema_wait_with_timeout(&s.impl.atomic, duration) } @@ -25,7 +25,7 @@ _Recursive_Mutex :: struct { recursion: i32, } -_recursive_mutex_lock :: proc(m: ^Recursive_Mutex) { +_recursive_mutex_lock :: proc "contextless" (m: ^Recursive_Mutex) { tid := Futex(current_thread_id()) for { prev_owner := atomic_compare_exchange_strong_explicit(&m.impl.owner, 0, tid, .Acquire, .Acquire) @@ -40,7 +40,7 @@ _recursive_mutex_lock :: proc(m: ^Recursive_Mutex) { } } -_recursive_mutex_unlock :: proc(m: ^Recursive_Mutex) { +_recursive_mutex_unlock :: proc "contextless" (m: ^Recursive_Mutex) { m.impl.recursion -= 1 if m.impl.recursion != 0 { return @@ -52,7 +52,7 @@ _recursive_mutex_unlock :: proc(m: ^Recursive_Mutex) { } -_recursive_mutex_try_lock :: proc(m: ^Recursive_Mutex) -> bool { +_recursive_mutex_try_lock :: proc "contextless" (m: ^Recursive_Mutex) -> bool { tid := Futex(current_thread_id()) prev_owner := atomic_compare_exchange_strong_explicit(&m.impl.owner, 0, tid, .Acquire, .Acquire) switch prev_owner { @@ -70,15 +70,15 @@ when ODIN_OS != .Windows { mutex: Atomic_Mutex, } - _mutex_lock :: proc(m: ^Mutex) { + _mutex_lock :: proc "contextless" (m: ^Mutex) { atomic_mutex_lock(&m.impl.mutex) } - _mutex_unlock :: proc(m: ^Mutex) { + _mutex_unlock :: proc "contextless" (m: ^Mutex) { atomic_mutex_unlock(&m.impl.mutex) } - _mutex_try_lock :: proc(m: ^Mutex) -> bool { + _mutex_try_lock :: proc "contextless" (m: ^Mutex) -> bool { return atomic_mutex_try_lock(&m.impl.mutex) } @@ -86,19 +86,19 @@ when ODIN_OS != .Windows { cond: Atomic_Cond, } - _cond_wait :: proc(c: ^Cond, m: ^Mutex) { + _cond_wait :: proc "contextless" (c: ^Cond, m: ^Mutex) { atomic_cond_wait(&c.impl.cond, &m.impl.mutex) } - _cond_wait_with_timeout :: proc(c: ^Cond, m: ^Mutex, duration: time.Duration) -> bool { + _cond_wait_with_timeout :: proc "contextless" (c: ^Cond, m: ^Mutex, duration: time.Duration) -> bool { return atomic_cond_wait_with_timeout(&c.impl.cond, &m.impl.mutex, duration) } - _cond_signal :: proc(c: ^Cond) { + _cond_signal :: proc "contextless" (c: ^Cond) { atomic_cond_signal(&c.impl.cond) } - _cond_broadcast :: proc(c: ^Cond) { + _cond_broadcast :: proc "contextless" (c: ^Cond) { atomic_cond_broadcast(&c.impl.cond) } @@ -107,27 +107,27 @@ when ODIN_OS != .Windows { mutex: Atomic_RW_Mutex, } - _rw_mutex_lock :: proc(rw: ^RW_Mutex) { + _rw_mutex_lock :: proc "contextless" (rw: ^RW_Mutex) { atomic_rw_mutex_lock(&rw.impl.mutex) } - _rw_mutex_unlock :: proc(rw: ^RW_Mutex) { + _rw_mutex_unlock :: proc "contextless" (rw: ^RW_Mutex) { atomic_rw_mutex_unlock(&rw.impl.mutex) } - _rw_mutex_try_lock :: proc(rw: ^RW_Mutex) -> bool { + _rw_mutex_try_lock :: proc "contextless" (rw: ^RW_Mutex) -> bool { return atomic_rw_mutex_try_lock(&rw.impl.mutex) } - _rw_mutex_shared_lock :: proc(rw: ^RW_Mutex) { + _rw_mutex_shared_lock :: proc "contextless" (rw: ^RW_Mutex) { atomic_rw_mutex_shared_lock(&rw.impl.mutex) } - _rw_mutex_shared_unlock :: proc(rw: ^RW_Mutex) { + _rw_mutex_shared_unlock :: proc "contextless" (rw: ^RW_Mutex) { atomic_rw_mutex_shared_unlock(&rw.impl.mutex) } - _rw_mutex_try_shared_lock :: proc(rw: ^RW_Mutex) -> bool { + _rw_mutex_try_shared_lock :: proc "contextless" (rw: ^RW_Mutex) -> bool { return atomic_rw_mutex_try_shared_lock(&rw.impl.mutex) } } \ No newline at end of file diff --git a/core/sync/primitives_windows.odin b/core/sync/primitives_windows.odin index 055167892..9f5bfc280 100644 --- a/core/sync/primitives_windows.odin +++ b/core/sync/primitives_windows.odin @@ -13,15 +13,15 @@ _Mutex :: struct { srwlock: win32.SRWLOCK, } -_mutex_lock :: proc(m: ^Mutex) { +_mutex_lock :: proc "contextless" (m: ^Mutex) { win32.AcquireSRWLockExclusive(&m.impl.srwlock) } -_mutex_unlock :: proc(m: ^Mutex) { +_mutex_unlock :: proc "contextless" (m: ^Mutex) { win32.ReleaseSRWLockExclusive(&m.impl.srwlock) } -_mutex_try_lock :: proc(m: ^Mutex) -> bool { +_mutex_try_lock :: proc "contextless" (m: ^Mutex) -> bool { return bool(win32.TryAcquireSRWLockExclusive(&m.impl.srwlock)) } @@ -29,27 +29,27 @@ _RW_Mutex :: struct { srwlock: win32.SRWLOCK, } -_rw_mutex_lock :: proc(rw: ^RW_Mutex) { +_rw_mutex_lock :: proc "contextless" (rw: ^RW_Mutex) { win32.AcquireSRWLockExclusive(&rw.impl.srwlock) } -_rw_mutex_unlock :: proc(rw: ^RW_Mutex) { +_rw_mutex_unlock :: proc "contextless" (rw: ^RW_Mutex) { win32.ReleaseSRWLockExclusive(&rw.impl.srwlock) } -_rw_mutex_try_lock :: proc(rw: ^RW_Mutex) -> bool { +_rw_mutex_try_lock :: proc "contextless" (rw: ^RW_Mutex) -> bool { return bool(win32.TryAcquireSRWLockExclusive(&rw.impl.srwlock)) } -_rw_mutex_shared_lock :: proc(rw: ^RW_Mutex) { +_rw_mutex_shared_lock :: proc "contextless" (rw: ^RW_Mutex) { win32.AcquireSRWLockShared(&rw.impl.srwlock) } -_rw_mutex_shared_unlock :: proc(rw: ^RW_Mutex) { +_rw_mutex_shared_unlock :: proc "contextless" (rw: ^RW_Mutex) { win32.ReleaseSRWLockShared(&rw.impl.srwlock) } -_rw_mutex_try_shared_lock :: proc(rw: ^RW_Mutex) -> bool { +_rw_mutex_try_shared_lock :: proc "contextless" (rw: ^RW_Mutex) -> bool { return bool(win32.TryAcquireSRWLockShared(&rw.impl.srwlock)) } @@ -58,22 +58,22 @@ _Cond :: struct { cond: win32.CONDITION_VARIABLE, } -_cond_wait :: proc(c: ^Cond, m: ^Mutex) { +_cond_wait :: proc "contextless" (c: ^Cond, m: ^Mutex) { _ = win32.SleepConditionVariableSRW(&c.impl.cond, &m.impl.srwlock, win32.INFINITE, 0) } -_cond_wait_with_timeout :: proc(c: ^Cond, m: ^Mutex, duration: time.Duration) -> bool { +_cond_wait_with_timeout :: proc "contextless" (c: ^Cond, m: ^Mutex, duration: time.Duration) -> bool { duration := u32(duration / time.Millisecond) ok := win32.SleepConditionVariableSRW(&c.impl.cond, &m.impl.srwlock, duration, 0) return bool(ok) } -_cond_signal :: proc(c: ^Cond) { +_cond_signal :: proc "contextless" (c: ^Cond) { win32.WakeConditionVariable(&c.impl.cond) } -_cond_broadcast :: proc(c: ^Cond) { +_cond_broadcast :: proc "contextless" (c: ^Cond) { win32.WakeAllConditionVariable(&c.impl.cond) }