123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119 |
- #+build linux, darwin, netbsd, openbsd, freebsd
- package posix
- import "base:intrinsics"
- import "core:c"
- when ODIN_OS == .Darwin {
- foreign import lib "system:System.framework"
- } 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 {
- suseconds_t :: distinct (c.int32_t when ODIN_OS == .Darwin || ODIN_OS == .NetBSD 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)
- 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))
- }
- }
|