Files
Odin/core/sys/posix/pthread.odin
2025-11-08 20:25:56 +01:00

670 lines
19 KiB
Odin

#+build linux, darwin, netbsd, openbsd, freebsd, haiku
package posix
import "core:c"
when ODIN_OS == .Darwin {
foreign import lib "system:System"
} else when ODIN_OS == .FreeBSD || ODIN_OS == .NetBSD || ODIN_OS == .Linux {
foreign import lib "system:pthread"
} else {
foreign import lib "system:c"
}
// pthread.h - threads
// NOTE: mutexes, rwlock, condition variables, once and barriers are left out in favour of `core:sync`.
foreign lib {
/*
Initializes a thread attributes object.
[[ More; https://pubs.opengroup.org/onlinepubs/9699919799/functions/pthread_attr_init.html ]]
*/
pthread_attr_init :: proc(attr: ^pthread_attr_t) -> Errno ---
/*
Destroys a thread attributes object.
[[ More; https://pubs.opengroup.org/onlinepubs/9699919799/functions/pthread_attr_init.html ]]
*/
pthread_attr_destroy :: proc(attr: ^pthread_attr_t) -> Errno ---
/*
The detachstate attribute controls whether the thread is created in a detached state.
If the thread is created detached, then use of the ID of the newly created thread is an error.
[[ More; https://pubs.opengroup.org/onlinepubs/9699919799/functions/pthread_attr_getdetachstate.html ]]
*/
pthread_attr_getdetachstate :: proc(attr: ^pthread_attr_t, detachstate: ^Detach_State) -> Errno ---
/*
The detachstate attribute controls whether the thread is created in a detached state.
If the thread is created detached, then use of the ID of the newly created thread is an error.
[[ More; https://pubs.opengroup.org/onlinepubs/9699919799/functions/pthread_attr_getdetachstate.html ]]
*/
pthread_attr_setdetachstate :: proc(attr: ^pthread_attr_t, detachstate: Detach_State) -> Errno ---
/*
The guardsize attribute controls the size of the guard area for the created thread's stack.
The guardsize attribute provides protection against overflow of the stack pointer.
If a thread's stack is created with guard protection, the implementation allocates extra memory
at the overflow end of the stack as a buffer against stack overflow of the stack pointer.
If an application overflows into this buffer an error shall result (possibly in a SIGSEGV signal being delivered to the thread).
[[ More; https://pubs.opengroup.org/onlinepubs/9699919799/functions/pthread_attr_setguardsize.html ]]
*/
pthread_attr_getguardsize :: proc(attr: ^pthread_attr_t, guardsize: ^c.size_t) -> Errno ---
/*
The guardsize attribute controls the size of the guard area for the created thread's stack.
The guardsize attribute provides protection against overflow of the stack pointer.
If a thread's stack is created with guard protection, the implementation allocates extra memory
at the overflow end of the stack as a buffer against stack overflow of the stack pointer.
If an application overflows into this buffer an error shall result (possibly in a SIGSEGV signal being delivered to the thread).
[[ More; https://pubs.opengroup.org/onlinepubs/9699919799/functions/pthread_attr_setguardsize.html ]]
*/
pthread_attr_setguardsize :: proc(attr: ^pthread_attr_t, guardsize: c.size_t) -> Errno ---
/*
When the attributes objects are used by pthread_create(), the inheritsched attribute determines
how the other scheduling attributes of the created thread shall be set.
[[ More; https://pubs.opengroup.org/onlinepubs/9699919799/functions/pthread_attr_setinheritsched.html ]]
*/
pthread_attr_getinheritsched :: proc(attr: ^pthread_attr_t, inheritsched: ^Inherit_Sched) -> Errno ---
/*
When the attributes objects are used by pthread_create(), the inheritsched attribute determines
how the other scheduling attributes of the created thread shall be set.
[[ More; https://pubs.opengroup.org/onlinepubs/9699919799/functions/pthread_attr_setinheritsched.html ]]
*/
pthread_attr_setinheritsched :: proc(attr: ^pthread_attr_t, inheritsched: Inherit_Sched) -> Errno ---
/*
Gets the scheduling param.
[[ More; https://pubs.opengroup.org/onlinepubs/9699919799/functions/pthread_attr_setschedparam.html ]]
*/
pthread_attr_getschedparam :: proc(attr: ^pthread_attr_t, param: ^sched_param) -> Errno ---
/*
Sets the scheduling param.
[[ More; https://pubs.opengroup.org/onlinepubs/9699919799/functions/pthread_attr_setschedparam.html ]]
*/
pthread_attr_setschedparam :: proc(attr: ^pthread_attr_t, param: ^sched_param) -> Errno ---
/*
Gets the scheduling poicy.
[[ More; https://pubs.opengroup.org/onlinepubs/9699919799/functions/pthread_attr_getschedpolicy.html ]]
*/
pthread_attr_getschedpolicy :: proc(attr: ^pthread_attr_t, policy: ^Sched_Policy) -> Errno ---
/*
Sets the scheduling poicy.
[[ More; https://pubs.opengroup.org/onlinepubs/9699919799/functions/pthread_attr_getschedpolicy.html ]]
*/
pthread_attr_setschedpolicy :: proc(attr: ^pthread_attr_t, policy: Sched_Policy) -> Errno ---
/*
Gets the contention scope.
[[ More; https://pubs.opengroup.org/onlinepubs/9699919799/functions/pthread_attr_getscope.html ]]
*/
pthread_attr_getscope :: proc(attr: ^pthread_attr_t, contentionscope: ^Thread_Scope) -> Errno ---
/*
Sets the contention scope.
[[ More; https://pubs.opengroup.org/onlinepubs/9699919799/functions/pthread_attr_getscope.html ]]
*/
pthread_attr_setscope :: proc(attr: ^pthread_attr_t, contentionscope: Thread_Scope) -> Errno ---
/*
Get the area of storage to be used for the created thread's stack.
[[ More; https://pubs.opengroup.org/onlinepubs/9699919799/functions/pthread_attr_getstack.html ]]
*/
pthread_attr_getstack :: proc(attr: ^pthread_attr_t, stackaddr: ^[^]byte, stacksize: ^c.size_t) -> Errno ---
/*
Specify the area of storage to be used for the created thread's stack.
[[ More; https://pubs.opengroup.org/onlinepubs/9699919799/functions/pthread_attr_getstack.html ]]
*/
pthread_attr_setstack :: proc(attr: ^pthread_attr_t, stackaddr: [^]byte, stacksize: c.size_t) -> Errno ---
/*
Gets the stack size.
[[ More; https://pubs.opengroup.org/onlinepubs/9699919799/functions/pthread_attr_getstacksize.html ]]
*/
pthread_attr_getstacksize :: proc(attr: ^pthread_attr_t, stacksize: ^c.size_t) -> Errno ---
/*
Sets the stack size.
[[ More; https://pubs.opengroup.org/onlinepubs/9699919799/functions/pthread_attr_getstacksize.html ]]
*/
pthread_attr_setstacksize :: proc(attr: ^pthread_attr_t, stacksize: c.size_t) -> Errno ---
/*
Register fork handlers to be called before and after fork().
[[ More; https://pubs.opengroup.org/onlinepubs/9699919799/functions/pthread_atfork.html ]]
*/
pthread_atfork :: proc(prepare: proc "c" (), parent: proc "c" (), child: proc "c" ()) -> Errno ---
/*
Cancel the execution of a thread.
[[ More; https://pubs.opengroup.org/onlinepubs/9699919799/functions/pthread_cancel.html ]]
*/
pthread_cancel :: proc(thread: pthread_t) -> Errno ---
/*
Creates a new thread with the given attributes.
[[ More; https://pubs.opengroup.org/onlinepubs/9699919799/functions/pthread_create.html ]]
*/
pthread_create :: proc(
thread: ^pthread_t,
attr: ^pthread_attr_t,
start_routine: proc "c" (arg: rawptr) -> rawptr,
arg: rawptr,
) -> Errno ---
/*
Indicate that storage for the thread can be reclaimed when the thread terminates.
[[ More; https://pubs.opengroup.org/onlinepubs/9699919799/functions/pthread_detach.html ]]
*/
pthread_detach :: proc(thread: pthread_t) -> Errno ---
/*
Compare thread IDs.
[[ More; https://pubs.opengroup.org/onlinepubs/9699919799/functions/pthread_equal.html ]]
*/
pthread_equal :: proc(t1: pthread_t, t2: pthread_t) -> b32 ---
/*
Terminates the calling thread and make the given value available to any successfull join calls.
[[ More; https://pubs.opengroup.org/onlinepubs/9699919799/functions/pthread_exit.html ]]
*/
pthread_exit :: proc(value_ptr: rawptr) -> ! ---
/*
Gets the current concurrency hint.
[[ More; https://pubs.opengroup.org/onlinepubs/9699919799/functions/pthread_getconcurrency.html ]]
*/
pthread_getconcurrency :: proc() -> c.int ---
/*
Sets the current desired concurrency hint.
[[ More; https://pubs.opengroup.org/onlinepubs/9699919799/functions/pthread_getconcurrency.html ]]
*/
pthread_setconcurrency :: proc(new_level: c.int) -> Errno ---
/*
Access a thread CPU-time clock.
[[ More; https://pubs.opengroup.org/onlinepubs/9699919799/functions/pthread_getcpuclockid.html ]]
*/
pthread_getcpuclockid :: proc(thread_id: pthread_t, clock_id: ^clockid_t) -> Errno ---
/*
Gets the scheduling policy and parameters.
[[ More; https://pubs.opengroup.org/onlinepubs/9699919799/functions/pthread_getschedparam.html ]]
*/
pthread_getschedparam :: proc(thread: pthread_t, policy: ^Sched_Policy, param: ^sched_param) -> Errno ---
/*
Sets the scheduling policy and parameters.
[[ More; https://pubs.opengroup.org/onlinepubs/9699919799/functions/pthread_getschedparam.html ]]
*/
pthread_setschedparam :: proc(thread: pthread_t, policy: Sched_Policy, param: ^sched_param) -> Errno ---
/*
Creates a thread-specific data key visible to all threads in the process.
[[ More; https://pubs.opengroup.org/onlinepubs/9699919799/functions/pthread_key_create.html ]]
*/
pthread_key_create :: proc(key: ^pthread_key_t, destructor: proc "c" (value: rawptr) = nil) -> Errno ---
/*
Deletes a thread-specific data key visible to all threads in the process.
[[ More; https://pubs.opengroup.org/onlinepubs/9699919799/functions/pthread_key_delete.html ]]
*/
pthread_key_delete :: proc(key: pthread_key_t) -> Errno ---
/*
Returns the value currently bound to the specified key on behalf of the calling thread.
[[ More; https://pubs.opengroup.org/onlinepubs/9699919799/functions/pthread_getspecific.html ]]
*/
pthread_getspecific :: proc(key: pthread_key_t) -> rawptr ---
/*
Sets the value currently bound to the specified key on behalf of the calling thread.
[[ More; https://pubs.opengroup.org/onlinepubs/9699919799/functions/pthread_getspecific.html ]]
*/
pthread_setspecific :: proc(key: pthread_key_t, value: rawptr) -> Errno ---
/*
Suspends execution of the calling thread until the target thread terminates.
Example:
ar: [10_000]i32
sb1 := ar[:5_000]
sb2 := ar[5_000:]
th1, th2: posix.pthread_t
posix.pthread_create(&th1, nil, incer, &sb1)
posix.pthread_create(&th2, nil, incer, &sb2)
posix.pthread_join(th1)
posix.pthread_join(th2)
incer :: proc "c" (arg: rawptr) -> rawptr {
sb := (^[]i32)(arg)
for &val in sb {
val += 1
}
return nil
}
[[ More; https://pubs.opengroup.org/onlinepubs/9699919799/functions/pthread_join.html ]]
*/
pthread_join :: proc(thread: pthread_t, value_ptr: ^rawptr = nil) -> Errno ---
/*
Get the calling thread ID.
[[ More; https://pubs.opengroup.org/onlinepubs/9699919799/functions/pthread_self.html ]]
*/
pthread_self :: proc() -> pthread_t ---
/*
Atomically set the calling thread's cancelability and return the previous value.
[[ More; https://pubs.opengroup.org/onlinepubs/9699919799/functions/pthread_setcancelstate.html ]]
*/
pthread_setcancelstate :: proc(state: Cancel_State, oldstate: ^Cancel_State) -> Errno ---
/*
Atomically set the calling thread's cancel type and return the previous value.
[[ More; https://pubs.opengroup.org/onlinepubs/9699919799/functions/pthread_setcancelstate.html ]]
*/
pthread_setcanceltype :: proc(type: Cancel_Type, oldtype: ^Cancel_Type) -> Errno ---
/*
Creates a cancellation point in the calling thread.
[[ More; https://pubs.opengroup.org/onlinepubs/9699919799/functions/pthread_testcancel.html ]]
*/
pthread_testcancel :: proc() ---
/*
Sets the scheduling priority for the thread given.
[[ More; https://pubs.opengroup.org/onlinepubs/9699919799/functions/pthread_setschedprio.html ]]
*/
pthread_setschedprio :: proc(thread: pthread_t, prio: c.int) -> Errno ---
}
Detach_State :: enum c.int {
// Causes all threads to be in the joinable state.
CREATE_JOINABLE = PTHREAD_CREATE_JOINABLE,
// Causes all threads to be in the detached state.
CREATE_DETACHED = PTHREAD_CREATE_DETACHED,
}
Inherit_Sched :: enum c.int {
// Threads inherit from the creating thread.
INHERIT_SCHED = PTHREAD_INHERIT_SCHED,
// Threads scheduling shall be set to the corresponding values from the attributes object.
EXPLICIT_SCHED = PTHREAD_EXPLICIT_SCHED,
}
Thread_Scope :: enum c.int {
// System scheduling contention scope.
SYSTEM = PTHREAD_SCOPE_SYSTEM,
// Process scheduling contention scope.
PROCESS = PTHREAD_SCOPE_PROCESS,
}
Cancel_State :: enum c.int {
// Cancel takes place at next cancellation point.
ENABLE = PTHREAD_CANCEL_ENABLE,
// Cancel postponed.
DISABLE = PTHREAD_CANCEL_DISABLE,
}
Cancel_Type :: enum c.int {
// Cancel waits until cancellation point.
DEFERRED = PTHREAD_CANCEL_DEFERRED,
// Cancel occurs immediately.
ASYNCHRONOUS = PTHREAD_CANCEL_ASYNCHRONOUS,
}
when ODIN_OS == .Darwin {
PTHREAD_CANCEL_ASYNCHRONOUS :: 0x00
PTHREAD_CANCEL_DEFERRED :: 0x02
PTHREAD_CANCEL_DISABLE :: 0x00
PTHREAD_CANCEL_ENABLE :: 0x01
// PTHREAD_CANCEL_ASYNCHRONOUS :: 1
// PTHREAD_CANCEL_DEFERRED :: 0
//
// PTHREAD_CANCEL_DISABLE :: 1
// PTHREAD_CANCEL_ENABLE :: 0
PTHREAD_CANCELED :: rawptr(uintptr(1))
PTHREAD_CREATE_DETACHED :: 2
PTHREAD_CREATE_JOINABLE :: 1
PTHREAD_EXPLICIT_SCHED :: 2
PTHREAD_INHERIT_SCHED :: 1
PTHREAD_PRIO_INHERIT :: 1
PTHREAD_PRIO_NONE :: 0
PTHREAD_PRIO_PROTECT :: 2
PTHREAD_PROCESS_SHARED :: 1
PTHREAD_PROCESS_PRIVATE :: 2
PTHREAD_SCOPE_PROCESS :: 2
PTHREAD_SCOPE_SYSTEM :: 1
pthread_t :: distinct rawptr
pthread_attr_t :: struct {
__sig: c.long,
__opaque: [56]c.char,
}
pthread_key_t :: distinct c.ulong
pthread_mutex_t :: struct {
__sig: c.long,
__opaque: [56]c.char,
}
pthread_cond_t :: struct {
__sig: c.long,
__opaque: [40]c.char,
}
sched_param :: struct {
sched_priority: c.int, /* [PSX] process or thread execution scheduling priority */
_: [4]c.char,
}
} else when ODIN_OS == .FreeBSD {
PTHREAD_CANCEL_ASYNCHRONOUS :: 0x02
PTHREAD_CANCEL_DEFERRED :: 0x00
PTHREAD_CANCEL_DISABLE :: 0x01
PTHREAD_CANCEL_ENABLE :: 0x00
PTHREAD_CANCELED :: rawptr(uintptr(1))
PTHREAD_CREATE_DETACHED :: 1
PTHREAD_CREATE_JOINABLE :: 0
PTHREAD_EXPLICIT_SCHED :: 0
PTHREAD_INHERIT_SCHED :: 4
PTHREAD_PRIO_INHERIT :: 1
PTHREAD_PRIO_NONE :: 0
PTHREAD_PRIO_PROTECT :: 2
PTHREAD_PROCESS_SHARED :: 1
PTHREAD_PROCESS_PRIVATE :: 0
PTHREAD_SCOPE_PROCESS :: 0
PTHREAD_SCOPE_SYSTEM :: 2
pthread_t :: distinct u64
pthread_attr_t :: struct #align(8) {
_: [8]byte,
}
pthread_key_t :: distinct c.int
pthread_mutex_t :: struct #align(8) {
_: [8]byte,
}
pthread_cond_t :: struct #align(8) {
_: [8]byte,
}
sched_param :: struct {
sched_priority: c.int, /* [PSX] process or thread execution scheduling priority */
}
} else when ODIN_OS == .NetBSD {
PTHREAD_CANCEL_ASYNCHRONOUS :: 1
PTHREAD_CANCEL_DEFERRED :: 0
PTHREAD_CANCEL_DISABLE :: 1
PTHREAD_CANCEL_ENABLE :: 0
PTHREAD_CANCELED :: rawptr(uintptr(1))
PTHREAD_CREATE_DETACHED :: 1
PTHREAD_CREATE_JOINABLE :: 0
PTHREAD_EXPLICIT_SCHED :: 1
PTHREAD_INHERIT_SCHED :: 0
PTHREAD_PRIO_INHERIT :: 1
PTHREAD_PRIO_NONE :: 0
PTHREAD_PRIO_PROTECT :: 2
PTHREAD_PROCESS_SHARED :: 1
PTHREAD_PROCESS_PRIVATE :: 0
PTHREAD_SCOPE_PROCESS :: 0
PTHREAD_SCOPE_SYSTEM :: 1
pthread_t :: distinct rawptr
pthread_attr_t :: struct {
pta_magic: c.uint,
pta_flags: c.int,
pta_private: rawptr,
}
pthread_key_t :: distinct c.int
pthread_cond_t :: struct #align(8) {
_: [40]byte,
}
pthread_mutex_t :: struct #align(8) {
_: [48]byte,
}
sched_param :: struct {
sched_priority: c.int, /* [PSX] process or thread execution scheduling priority */
}
} else when ODIN_OS == .OpenBSD {
PTHREAD_CANCEL_ASYNCHRONOUS :: 2
PTHREAD_CANCEL_DEFERRED :: 0
PTHREAD_CANCEL_DISABLE :: 1
PTHREAD_CANCEL_ENABLE :: 0
PTHREAD_CANCELED :: rawptr(uintptr(1))
PTHREAD_CREATE_DETACHED :: 0x1
PTHREAD_CREATE_JOINABLE :: 0
PTHREAD_EXPLICIT_SCHED :: 0
PTHREAD_INHERIT_SCHED :: 0x4
PTHREAD_PRIO_INHERIT :: 1
PTHREAD_PRIO_NONE :: 0
PTHREAD_PRIO_PROTECT :: 2
PTHREAD_PROCESS_SHARED :: 0
PTHREAD_PROCESS_PRIVATE :: 1
PTHREAD_SCOPE_PROCESS :: 0
PTHREAD_SCOPE_SYSTEM :: 0x2
pthread_t :: distinct rawptr
pthread_attr_t :: distinct rawptr
pthread_key_t :: distinct c.int
pthread_mutex_t :: distinct rawptr
pthread_cond_t :: distinct rawptr
sched_param :: struct {
sched_priority: c.int, /* [PSX] process or thread execution scheduling priority */
}
} else when ODIN_OS == .Haiku {
PTHREAD_CANCEL_ASYNCHRONOUS :: 2
PTHREAD_CANCEL_DEFERRED :: 0
PTHREAD_CANCEL_DISABLE :: 1
PTHREAD_CANCEL_ENABLE :: 0
PTHREAD_CANCELED :: rawptr(uintptr(1))
PTHREAD_CREATE_DETACHED :: 0x1
PTHREAD_CREATE_JOINABLE :: 0
PTHREAD_EXPLICIT_SCHED :: 0
PTHREAD_INHERIT_SCHED :: 0x4
PTHREAD_PRIO_INHERIT :: 1
PTHREAD_PRIO_NONE :: 0
PTHREAD_PRIO_PROTECT :: 2
PTHREAD_PROCESS_SHARED :: 1
PTHREAD_PROCESS_PRIVATE :: 0
PTHREAD_SCOPE_PROCESS :: 0
PTHREAD_SCOPE_SYSTEM :: 0x2
pthread_t :: distinct rawptr
pthread_attr_t :: distinct rawptr
pthread_key_t :: distinct c.int
pthread_mutex_t :: struct {
flags: u32,
lock: i32,
unused: i32,
owner: i32,
owner_count: i32,
}
pthread_cond_t :: struct {
flags: u32,
unused: i32,
mutex: ^pthread_mutex_t,
waiter_count: i32,
lock: i32,
}
sched_param :: struct {
sched_priority: c.int, /* [PSX] process or thread execution scheduling priority */
}
} else when ODIN_OS == .Linux {
PTHREAD_CANCEL_DEFERRED :: 0
PTHREAD_CANCEL_ASYNCHRONOUS :: 1
PTHREAD_CANCEL_ENABLE :: 0
PTHREAD_CANCEL_DISABLE :: 1
PTHREAD_CANCELED :: rawptr(~uintptr(0))
PTHREAD_CREATE_JOINABLE :: 0
PTHREAD_CREATE_DETACHED :: 1
PTHREAD_INHERIT_SCHED :: 0
PTHREAD_EXPLICIT_SCHED :: 1
PTHREAD_PRIO_NONE :: 0
PTHREAD_PRIO_INHERIT :: 1
PTHREAD_PRIO_PROTECT :: 2
PTHREAD_PROCESS_PRIVATE :: 0
PTHREAD_PROCESS_SHARED :: 1
PTHREAD_SCOPE_SYSTEM :: 0
PTHREAD_SCOPE_PROCESS :: 1
pthread_t :: distinct c.ulong
when ODIN_ARCH == .arm64 {
@(private)
__SIZEOF_PTHREAD_ATTR_T :: 64
} else {
@(private)
__SIZEOF_PTHREAD_ATTR_T :: 56
}
pthread_attr_t :: struct #raw_union {
__size: [__SIZEOF_PTHREAD_ATTR_T]c.char,
__align: c.long,
}
pthread_key_t :: distinct c.uint
pthread_cond_t :: struct {
__size: [40]c.char, // NOTE: may be smaller depending on libc or arch, but never larger.
__align: c.long,
}
pthread_mutex_t :: struct {
__size: [32]c.char, // NOTE: may be smaller depending on libc or arch, but never larger.
__align: c.long,
}
sched_param :: struct {
sched_priority: c.int, /* [PSX] process or thread execution scheduling priority */
// NOTE: may be smaller depending on libc or arch, but never larger.
__reserved1: c.int,
__reserved2: [4]c.long,
__reserved3: c.int,
}
}