mirror of
https://github.com/Ed94/Odin.git
synced 2026-07-31 11:50:07 +00:00
Merge branch 'master' of https://github.com/odin-lang/Odin into more_dwmapi_bindings
This commit is contained in:
@@ -531,7 +531,7 @@ not_equal :: proc{not_equal_single, not_equal_array}
|
||||
|
||||
any :: proc(x: $A/[$N]bool) -> (out: bool) {
|
||||
for e in x {
|
||||
if x {
|
||||
if e {
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
@@ -23,16 +23,3 @@ make_any :: proc "contextless" (data: rawptr, id: typeid) -> any {
|
||||
}
|
||||
|
||||
raw_data :: builtin.raw_data
|
||||
|
||||
|
||||
Poly_Raw_Map_Entry :: struct($Key, $Value: typeid) {
|
||||
hash: uintptr,
|
||||
next: int,
|
||||
key: Key,
|
||||
value: Value,
|
||||
}
|
||||
|
||||
Poly_Raw_Map :: struct($Key, $Value: typeid) {
|
||||
hashes: []int,
|
||||
entries: [dynamic]Poly_Raw_Map_Entry(Key, Value),
|
||||
}
|
||||
@@ -333,7 +333,7 @@ foreign dl {
|
||||
@(link_name="dlerror") _unix_dlerror :: proc() -> cstring ---
|
||||
}
|
||||
|
||||
get_last_error :: proc() -> int {
|
||||
get_last_error :: proc "contextless" () -> int {
|
||||
return __error()^
|
||||
}
|
||||
|
||||
|
||||
@@ -303,7 +303,7 @@ is_path_separator :: proc(r: rune) -> bool {
|
||||
return r == '/'
|
||||
}
|
||||
|
||||
get_last_error :: proc() -> int {
|
||||
get_last_error :: proc "contextless" () -> int {
|
||||
return __errno_location()^
|
||||
}
|
||||
|
||||
|
||||
@@ -441,7 +441,7 @@ _get_errno :: proc(res: int) -> Errno {
|
||||
}
|
||||
|
||||
// get errno from libc
|
||||
get_last_error :: proc() -> int {
|
||||
get_last_error :: proc "contextless" () -> int {
|
||||
return __errno_location()^
|
||||
}
|
||||
|
||||
|
||||
@@ -294,7 +294,7 @@ is_path_separator :: proc(r: rune) -> bool {
|
||||
return r == '/'
|
||||
}
|
||||
|
||||
get_last_error :: proc() -> int {
|
||||
get_last_error :: proc "contextless" () -> int {
|
||||
return __errno()^
|
||||
}
|
||||
|
||||
|
||||
@@ -123,46 +123,17 @@ backing_type_kind :: proc(T: typeid) -> Type_Kind {
|
||||
}
|
||||
|
||||
|
||||
type_info_base :: proc(info: ^Type_Info) -> ^Type_Info {
|
||||
if info == nil { return nil }
|
||||
|
||||
base := info
|
||||
loop: for {
|
||||
#partial switch i in base.variant {
|
||||
case Type_Info_Named: base = i.base
|
||||
case: break loop
|
||||
}
|
||||
}
|
||||
return base
|
||||
}
|
||||
|
||||
|
||||
type_info_core :: proc(info: ^Type_Info) -> ^Type_Info {
|
||||
if info == nil { return nil }
|
||||
|
||||
base := info
|
||||
loop: for {
|
||||
#partial switch i in base.variant {
|
||||
case Type_Info_Named: base = i.base
|
||||
case Type_Info_Enum: base = i.base
|
||||
case: break loop
|
||||
}
|
||||
}
|
||||
return base
|
||||
}
|
||||
type_info_base :: runtime.type_info_base
|
||||
type_info_core :: runtime.type_info_core
|
||||
type_info_base_without_enum :: type_info_core
|
||||
|
||||
|
||||
typeid_base :: proc(id: typeid) -> typeid {
|
||||
ti := type_info_of(id)
|
||||
ti = type_info_base(ti)
|
||||
return ti.id
|
||||
when !ODIN_DISALLOW_RTTI {
|
||||
typeid_base :: runtime.typeid_base
|
||||
typeid_core :: runtime.typeid_core
|
||||
typeid_base_without_enum :: typeid_core
|
||||
}
|
||||
typeid_core :: proc(id: typeid) -> typeid {
|
||||
ti := type_info_base_without_enum(type_info_of(id))
|
||||
return ti.id
|
||||
}
|
||||
typeid_base_without_enum :: typeid_core
|
||||
|
||||
|
||||
any_base :: proc(v: any) -> any {
|
||||
v := v
|
||||
|
||||
@@ -615,7 +615,7 @@ shrink_dynamic_array :: proc(array: ^$T/[dynamic]$E, new_cap := -1, loc := #call
|
||||
old_size := a.cap * size_of(E)
|
||||
new_size := new_cap * size_of(E)
|
||||
|
||||
new_data, err := mem_resize(a.data, old_size, new_size, align_of(E), allocator, loc)
|
||||
new_data, err := mem_resize(a.data, old_size, new_size, align_of(E), a.allocator, loc)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
+1
-1
@@ -37,7 +37,7 @@ Map_Entry_Info :: struct($Key, $Value: typeid) {
|
||||
}
|
||||
|
||||
|
||||
map_entries :: proc(m: $M/map[$K]$V, allocator := context.allocator) -> (entries: []Map_Entry(K, V), err: runtime.Allocator) {
|
||||
map_entries :: proc(m: $M/map[$K]$V, allocator := context.allocator) -> (entries: []Map_Entry(K, V), err: runtime.Allocator_Error) {
|
||||
entries = make(type_of(entries), len(m), allocator) or_return
|
||||
i := 0
|
||||
for key, value in m {
|
||||
|
||||
+87
-30
@@ -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
|
||||
}
|
||||
@@ -282,7 +282,15 @@ Once :: struct {
|
||||
}
|
||||
|
||||
// once_do calls the procedure fn if and only if once_do is being called for the first for this instance of Once.
|
||||
once_do :: proc(o: ^Once, fn: proc()) {
|
||||
once_do :: proc{
|
||||
once_do_without_data,
|
||||
once_do_without_data_contextless,
|
||||
once_do_with_data,
|
||||
once_do_with_data_contextless,
|
||||
}
|
||||
|
||||
// once_do_without_data calls the procedure fn if and only if once_do_without_data is being called for the first for this instance of Once.
|
||||
once_do_without_data :: proc(o: ^Once, fn: proc()) {
|
||||
@(cold)
|
||||
do_slow :: proc(o: ^Once, fn: proc()) {
|
||||
guard(&o.m)
|
||||
@@ -292,12 +300,61 @@ once_do :: proc(o: ^Once, fn: proc()) {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if atomic_load_explicit(&o.done, .Acquire) == false {
|
||||
do_slow(o, fn)
|
||||
}
|
||||
}
|
||||
|
||||
// once_do_without_data calls the procedure fn if and only if once_do_without_data is being called for the first for this instance of Once.
|
||||
once_do_without_data_contextless :: proc(o: ^Once, fn: proc "contextless" ()) {
|
||||
@(cold)
|
||||
do_slow :: proc(o: ^Once, fn: proc "contextless" ()) {
|
||||
guard(&o.m)
|
||||
if !o.done {
|
||||
fn()
|
||||
atomic_store_explicit(&o.done, true, .Release)
|
||||
}
|
||||
}
|
||||
|
||||
if atomic_load_explicit(&o.done, .Acquire) == false {
|
||||
do_slow(o, fn)
|
||||
}
|
||||
}
|
||||
|
||||
// once_do_with_data calls the procedure fn if and only if once_do_with_data is being called for the first for this instance of Once.
|
||||
once_do_with_data :: proc(o: ^Once, fn: proc(data: rawptr), data: rawptr) {
|
||||
@(cold)
|
||||
do_slow :: proc(o: ^Once, fn: proc(data: rawptr), data: rawptr) {
|
||||
guard(&o.m)
|
||||
if !o.done {
|
||||
fn(data)
|
||||
atomic_store_explicit(&o.done, true, .Release)
|
||||
}
|
||||
}
|
||||
|
||||
if atomic_load_explicit(&o.done, .Acquire) == false {
|
||||
do_slow(o, fn, data)
|
||||
}
|
||||
}
|
||||
|
||||
// once_do_with_data_contextless calls the procedure fn if and only if once_do_with_data_contextless is being called for the first for this instance of Once.
|
||||
once_do_with_data_contextless :: proc "contextless" (o: ^Once, fn: proc "contextless" (data: rawptr), data: rawptr) {
|
||||
@(cold)
|
||||
do_slow :: proc "contextless" (o: ^Once, fn: proc "contextless" (data: rawptr), data: rawptr) {
|
||||
guard(&o.m)
|
||||
if !o.done {
|
||||
fn(data)
|
||||
atomic_store_explicit(&o.done, true, .Release)
|
||||
}
|
||||
}
|
||||
|
||||
if atomic_load_explicit(&o.done, .Acquire) == false {
|
||||
do_slow(o, fn, data)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
// A Parker is an associated token which is initially not present:
|
||||
@@ -314,7 +371,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 +390,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 +402,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)
|
||||
|
||||
@@ -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")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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")
|
||||
}
|
||||
}
|
||||
|
||||
+10
-10
@@ -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")
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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")
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
+44
-28
@@ -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()
|
||||
}
|
||||
@@ -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..<i32(100) {
|
||||
@@ -58,9 +58,9 @@ atomic_mutex_lock :: proc(m: ^Atomic_Mutex) {
|
||||
}
|
||||
|
||||
// atomic_mutex_unlock unlocks m
|
||||
atomic_mutex_unlock :: proc(m: ^Atomic_Mutex) {
|
||||
atomic_mutex_unlock :: proc "contextless" (m: ^Atomic_Mutex) {
|
||||
@(cold)
|
||||
unlock_slow :: proc(m: ^Atomic_Mutex) {
|
||||
unlock_slow :: proc "contextless" (m: ^Atomic_Mutex) {
|
||||
futex_signal((^Futex)(&m.state))
|
||||
}
|
||||
|
||||
@@ -76,7 +76,7 @@ atomic_mutex_unlock :: proc(m: ^Atomic_Mutex) {
|
||||
}
|
||||
|
||||
// atomic_mutex_try_lock tries to lock m, will return true on success, and false on failure
|
||||
atomic_mutex_try_lock :: proc(m: ^Atomic_Mutex) -> 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
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
}
|
||||
@@ -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)
|
||||
}
|
||||
|
||||
|
||||
@@ -62,6 +62,7 @@ foreign gdi32 {
|
||||
|
||||
SetPixelFormat :: proc(hdc: HDC, format: c_int, ppfd: ^PIXELFORMATDESCRIPTOR) -> BOOL ---
|
||||
ChoosePixelFormat :: proc(hdc: HDC, ppfd: ^PIXELFORMATDESCRIPTOR) -> c_int ---
|
||||
DescribePixelFormat :: proc(hdc: HDC, iPixelFormat: c_int, nBytes: UINT, ppfd: ^PIXELFORMATDESCRIPTOR) -> c_int ---
|
||||
SwapBuffers :: proc(HDC) -> BOOL ---
|
||||
|
||||
SetDCBrushColor :: proc(hdc: HDC, color: COLORREF) -> COLORREF ---
|
||||
|
||||
@@ -1554,6 +1554,25 @@ WA_INACTIVE :: 0
|
||||
WA_ACTIVE :: 1
|
||||
WA_CLICKACTIVE :: 2
|
||||
|
||||
// Struct pointed to by WM_GETMINMAXINFO lParam
|
||||
MINMAXINFO :: struct {
|
||||
ptReserved: POINT,
|
||||
ptMaxSize: POINT,
|
||||
ptMaxPosition: POINT,
|
||||
ptMinTrackSize: POINT,
|
||||
ptMaxTrackSize: POINT,
|
||||
}
|
||||
PMINMAXINFO :: ^MINMAXINFO
|
||||
LPMINMAXINFO :: PMINMAXINFO
|
||||
|
||||
MONITORINFO :: struct {
|
||||
cbSize: DWORD,
|
||||
rcMonitor: RECT,
|
||||
rcWork: RECT,
|
||||
dwFlags: DWORD,
|
||||
}
|
||||
LPMONITORINFO :: ^MONITORINFO
|
||||
|
||||
// SetWindowsHook() codes
|
||||
WH_MIN :: -1
|
||||
WH_MSGFILTER :: -1
|
||||
|
||||
@@ -100,6 +100,7 @@ foreign user32 {
|
||||
AdjustWindowRectExForDpi :: proc(lpRect: LPRECT, dwStyle: DWORD, bMenu: BOOL, dwExStyle: DWORD, dpi: UINT) -> BOOL ---
|
||||
|
||||
SystemParametersInfoW :: proc(uiAction, uiParam: UINT, pvParam: PVOID, fWinIni: UINT) -> BOOL ---
|
||||
GetMonitorInfoW :: proc(hMonitor: HMONITOR, lpmi: LPMONITORINFO) -> BOOL ---
|
||||
|
||||
GetWindowDC :: proc(hWnd: HWND) -> HDC ---
|
||||
GetDC :: proc(hWnd: HWND) -> HDC ---
|
||||
|
||||
Reference in New Issue
Block a user