Files
Odin/core/sys/posix/sys_select.odin
Harold Brenes 219b0fe535 Replace system:System.framework imports with system:System
This makes the linker work for both macOS and iOS targets
2025-07-13 15:45:21 -04:00

126 lines
3.4 KiB
Odin

#+build linux, darwin, netbsd, openbsd, freebsd, haiku
package posix
import "base:intrinsics"
import "core:c"
when ODIN_OS == .Darwin {
foreign import lib "system:System"
} else {
foreign import lib "system:c"
}
// sys/select.h - select types
foreign lib {
/*
Examines the file descriptor sets to see whether some of their descriptors are ready for writing,
or have an exceptional condition pending, respectively.
Returns: -1 (setting errno) on failure, total amount of bits set in the bit masks otherwise
[[ More; https://pubs.opengroup.org/onlinepubs/9699919799/functions/pselect.html ]]
*/
@(link_name=LPSELECT)
pselect :: proc(
nfds: c.int,
readfds: ^fd_set,
writefds: ^fd_set,
errorfds: ^fd_set,
timeout: ^timespec,
sigmask: ^sigset_t,
) -> c.int ---
/*
Equivalent to pselect() except a more specific timeout resolution (nanoseconds),
does not have a signal mask, and may modify the timeout.
[[ More; https://pubs.opengroup.org/onlinepubs/9699919799/functions/pselect.html ]]
*/
@(link_name=LSELECT)
select :: proc(
nfds: c.int,
readfds: ^fd_set,
writefds: ^fd_set,
errorfds: ^fd_set,
timeout: ^timeval,
) -> c.int ---
}
when ODIN_OS == .NetBSD {
LPSELECT :: "__pselect50"
LSELECT :: "__select50"
} else {
LPSELECT :: "pselect"
LSELECT :: "select"
}
when ODIN_OS == .Darwin || ODIN_OS == .FreeBSD || ODIN_OS == .NetBSD || ODIN_OS == .OpenBSD || ODIN_OS == .Linux || ODIN_OS == .Haiku {
suseconds_t :: distinct (c.int32_t when ODIN_OS == .Darwin || ODIN_OS == .NetBSD || ODIN_OS == .Haiku else c.long)
timeval :: struct {
tv_sec: time_t, /* [PSX] seconds */
tv_usec: suseconds_t, /* [PSX] microseconds */
}
// Maximum number of file descriptors in the fd_set structure.
FD_SETSIZE :: #config(POSIX_FD_SETSIZE, 256 when ODIN_OS == .NetBSD else 1024)
@(private)
__NFDBITS :: size_of(c.int32_t) * 8
// NOTE: this seems correct for FreeBSD but they do use a set backed by the long type themselves (thus the align change).
@(private)
ALIGN :: align_of(c.long) when ODIN_OS == .FreeBSD || ODIN_OS == .Linux else align_of(c.int32_t)
when ODIN_OS == .Haiku {
fd_set :: struct #align(ALIGN) {
fds_bits: [(FD_SETSIZE + (__NFDBITS - 1)) / __NFDBITS]c.int32_t,
}
} else {
fd_set :: struct #align(ALIGN) {
fds_bits: [(FD_SETSIZE / __NFDBITS) when (FD_SETSIZE % __NFDBITS) == 0 else (FD_SETSIZE / __NFDBITS) + 1]c.int32_t,
}
}
@(private)
__check_fd_set :: #force_inline proc "contextless" (_a: FD, _b: rawptr) -> bool {
if _a < 0 {
set_errno(.EINVAL)
}
if _a >= FD_SETSIZE {
set_errno(.EINVAL)
}
return true
}
FD_CLR :: #force_inline proc "contextless" (_fd: FD, _p: ^fd_set) {
if __check_fd_set(_fd, _p) {
_p.fds_bits[cast(c.ulong)_fd / __NFDBITS] &= ~cast(c.int32_t)((cast(c.ulong)1) << (cast(c.ulong)_fd % __NFDBITS))
}
}
FD_ISSET :: #force_inline proc "contextless" (_fd: FD, _p: ^fd_set) -> bool {
if __check_fd_set(_fd, _p) {
return bool(_p.fds_bits[cast(c.ulong)_fd / __NFDBITS] & cast(c.int32_t)((cast(c.ulong)1) << (cast(c.ulong)_fd % __NFDBITS)))
}
return false
}
FD_SET :: #force_inline proc "contextless" (_fd: FD, _p: ^fd_set) {
if __check_fd_set(_fd, _p) {
_p.fds_bits[cast(c.ulong)_fd / __NFDBITS] |= cast(c.int32_t)((cast(c.ulong)1) << (cast(c.ulong)_fd % __NFDBITS))
}
}
FD_ZERO :: #force_inline proc "contextless" (_p: ^fd_set) {
intrinsics.mem_zero(_p, size_of(fd_set))
}
}