mirror of
https://github.com/odin-lang/Odin.git
synced 2025-12-28 17:04:34 +00:00
126 lines
3.4 KiB
Odin
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))
|
|
}
|
|
|
|
}
|