1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
|
#+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))
}
}
|