package libc // 7.26 Threads thrd_start_t :: proc "c" (rawptr) -> int; tss_dtor_t :: proc "c" (rawptr); when ODIN_OS == "windows" { foreign import libc { "system:libucrt.lib", "system:msvcprt.lib" } thrd_success :: 0; // _Thrd_success thrd_nomem :: 1; // _Thrd_nomem thrd_timedout :: 2; // _Thrd_timedout thrd_busy :: 3; // _Thrd_busy thrd_error :: 4; // _Thrd_error mtx_plain :: 1; // _Mtx_plain mtx_recursive :: 0x100; // _Mtx_recursive mtx_timed :: 4; // _Mtx_timed TSS_DTOR_ITERATIONS :: 4; // _TSS_DTOR_ITERATIONS_IMP once_flag :: distinct i8; // _Once_flag_imp_t thrd_t :: struct { _: rawptr, _: uint, } // _Thrd_t tss_t :: distinct int; // _Tss_imp_t cnd_t :: distinct rawptr; // _Cnd_imp_t mtx_t :: distinct rawptr; // _Mtx_imp_t // MSVCRT does not expose the C11 symbol names as what they are in C11 // because they held off implementing and C11 support for so // long that people started implementing their own. To prevent symbol // conflict with existing customers code they had to namespace them // differently. Thus we need to alias the correct symbol names with Odin's // link_name attribute. @(default_calling_convention="c") foreign libc { // 7.26.2 Initialization functions @(link_name="_Call_once") call_once :: proc(flag: ^once_flag, func: proc "c" ()) ---; // 7.26.3 Condition variable functions @(link_name="_Cnd_broadcast") cnd_broadcast :: proc(cond: ^cnd_t) -> int ---; @(link_name="_Cnd_destroy") cnd_destroy :: proc(cond: ^cnd_t) ---; @(link_name="_Cnd_init") cnd_init :: proc(cond: ^cnd_t) -> int ---; @(link_name="_Cnd_signal") cnd_signal :: proc(cond: ^cnd_t) -> int ---; @(link_name="_Cnd_timedwait") cnd_timedwait :: proc(cond: ^cnd_t, ts: ^timespec) -> int ---; @(link_name="_Cnd_wait") cnd_wait :: proc(cond: ^cnd_t, mtx: ^mtx_t) -> int ---; // 7.26.4 Mutex functions @(link_name="_Mtx_destroy") mtx_destroy :: proc(mtx: ^mtx_t) ---; @(link_name="_Mtx_init") mtx_init :: proc(mtx: ^mtx_t, type: int) -> int ---; @(link_name="_Mtx_lock") mtx_lock :: proc(mtx: ^mtx_t) -> int ---; @(link_name="_Mtx_timedlock") mtx_timedlock :: proc(mtx: ^mtx_t, ts: ^timespec) -> int ---; @(link_name="_Mtx_trylock") mtx_trylock :: proc(mtx: ^mtx_t) -> int ---; @(link_name="_Mtx_unlock") mtx_unlock :: proc(mtx: ^mtx_t) -> int ---; // 7.26.5 Thread functions @(link_name="_Thrd_create") thrd_create :: proc(thr: ^thrd_t, func: thrd_start_t, arg: rawptr) -> int ---; @(link_name="_Thrd_current") thrd_current :: proc() -> thrd_t ---; @(link_name="_Thrd_detach") thrd_detach :: proc(thr: thrd_t) -> int ---; @(link_name="_Thrd_equal") thrd_equal :: proc(lhs, rhs: thrd_t) -> int ---; @(link_name="_Thrd_exit") thrd_exit :: proc(res: int) -> ! ---; @(link_name="_Thrd_join") thrd_join :: proc(thr: thrd_t, res: ^int) -> int ---; @(link_name="_Thrd_sleep") thrd_sleep :: proc(duration, remaining: ^timespec) -> int ---; @(link_name="_Thrd_yield") thrd_yield :: proc() ---; // 7.26.6 Thread-specific storage functions @(link_name="_Tss_create") tss_create :: proc(key: ^tss_t, dtor: tss_dtor_t) -> int ---; @(link_name="_Tss_delete") tss_delete :: proc(key: tss_t) ---; @(link_name="_Tss_get") tss_get :: proc(key: tss_t) -> rawptr ---; @(link_name="_Tss_set") tss_set :: proc(key: tss_t, val: rawptr) -> int ---; } } // GLIBC and MUSL compatible constants and types. when ODIN_OS == "linux" { foreign import libc { "system:c", "system:pthread" } thrd_success :: 0; thrd_busy :: 1; thrd_error :: 2; thrd_nomem :: 3; thrd_timedout :: 4; mtx_plain :: 0; mtx_recursive :: 1; mtx_timed :: 2; TSS_DTOR_ITERATIONS :: 4; once_flag :: distinct int; thrd_t :: distinct ulong; tss_t :: distinct uint; cnd_t :: struct #raw_union { _: [12]int, _: [12 * size_of(int) / size_of(rawptr)]rawptr, }; mtx_t :: struct #raw_union { _: [10 when size_of(long) == 8 else 6]int, _: [5 when size_of(long) == 8 else 6]rawptr, }; @(default_calling_convention="c") foreign libc { // 7.26.2 Initialization functions call_once :: proc(flag: ^once_flag, func: proc "c" ()) ---; // 7.26.3 Condition variable functions cnd_broadcast :: proc(cond: ^cnd_t) -> int ---; cnd_destroy :: proc(cond: ^cnd_t) ---; cnd_init :: proc(cond: ^cnd_t) -> int ---; cnd_signal :: proc(cond: ^cnd_t) -> int ---; cnd_timedwait :: proc(cond: ^cnd_t, ts: ^timespec) -> int ---; cnd_wait :: proc(cond: ^cnd_t, mtx: ^mtx_t) -> int ---; // 7.26.4 Mutex functions mtx_destroy :: proc(mtx: ^mtx_t) ---; mtx_init :: proc(mtx: ^mtx_t, type: int) -> int ---; mtx_lock :: proc(mtx: ^mtx_t) -> int ---; mtx_timedlock :: proc(mtx: ^mtx_t, ts: ^timespec) -> int ---; mtx_trylock :: proc(mtx: ^mtx_t) -> int ---; mtx_unlock :: proc(mtx: ^mtx_t) -> int ---; // 7.26.5 Thread functions thrd_create :: proc(thr: ^thrd_t, func: thrd_start_t, arg: rawptr) -> int ---; thrd_current :: proc() -> thrd_t ---; thrd_detach :: proc(thr: thrd_t) -> int ---; thrd_equal :: proc(lhs, rhs: thrd_t) -> int ---; thrd_exit :: proc(res: int) -> ! ---; thrd_join :: proc(thr: thrd_t, res: ^int) -> int ---; thrd_sleep :: proc(duration, remaining: ^timespec) -> int ---; thrd_yield :: proc() ---; // 7.26.6 Thread-specific storage functions tss_create :: proc(key: ^tss_t, dtor: tss_dtor_t) -> int ---; tss_delete :: proc(key: tss_t) ---; tss_get :: proc(key: tss_t) -> rawptr ---; tss_set :: proc(key: tss_t, val: rawptr) -> int ---; } }