From 4f2b9835f5f6966c5f11fe20f9f56855c54e4ce5 Mon Sep 17 00:00:00 2001 From: Rickard Andersson Date: Wed, 14 Jun 2023 22:13:36 +0300 Subject: [PATCH 1/8] feat(unix): add `poll` --- core/os/os_linux.odin | 36 +++++++++++++++++++++++++++++++ core/sys/unix/syscalls_linux.odin | 29 +++++++++++++++++++++++++ 2 files changed, 65 insertions(+) diff --git a/core/os/os_linux.odin b/core/os/os_linux.odin index 7a0a4b1dd..beb4acec5 100644 --- a/core/os/os_linux.odin +++ b/core/os/os_linux.odin @@ -432,6 +432,18 @@ AT_FDCWD :: ~uintptr(99) /* -100 */ AT_REMOVEDIR :: uintptr(0x200) AT_SYMLINK_NOFOLLOW :: uintptr(0x100) +pollfd :: struct { + fd: c.int, + events: c.short, + revents: c.short, +} + +nfds_t :: distinct c.uint + +sigset_t :: struct { + __val: [16]c.ulong, +} + foreign libc { @(link_name="__errno_location") __errno_location :: proc() -> ^int --- @@ -1087,3 +1099,27 @@ fcntl :: proc(fd: int, cmd: int, arg: int) -> (int, Errno) { } return result, ERROR_NONE } + +// select :: proc(nfds: int, readfds: ^fd_set, writefds: ^fd_set, exceptfds: ^fd_set, timeout: ^timeval) -> (int, Errno) { +// result := unix.sys_select(nfds, readfds, writefds, exceptfds, timeout) +// if result < 0 { +// return 0, _get_errno(result) +// } +// return result, ERROR_NONE +// } + +poll :: proc(fds: [^]pollfd, nfds: nfds_t, timeout: int) -> (int, Errno) { + result := unix.sys_poll(fds, uint(nfds), timeout) + if result < 0 { + return 0, _get_errno(result) + } + return result, ERROR_NONE +} + +ppoll :: proc(fds: [^]pollfd, nfds: nfds_t, timeout: ^unix.timespec, sigmask: ^sigset_t) -> (int, Errno) { + result := unix.sys_ppoll(fds, uint(nfds), timeout, sigmask, size_of(sigset_t)) + if result < 0 { + return 0, _get_errno(result) + } + return result, ERROR_NONE +} diff --git a/core/sys/unix/syscalls_linux.odin b/core/sys/unix/syscalls_linux.odin index abdcf0b92..54f8bcc25 100644 --- a/core/sys/unix/syscalls_linux.odin +++ b/core/sys/unix/syscalls_linux.odin @@ -1567,6 +1567,23 @@ MADV_HWPOISON :: 100 // pipe2 flags O_CLOEXEC :: 0o2000000 +// poll events +POLLIN :: 0x0001 +POLLPRI :: 0x0002 +POLLOUT :: 0x0004 +POLLERR :: 0x0008 +POLLHUP :: 0x0010 +POLLNVAL :: 0x0020 +POLLRDNORM :: 0x0040 +POLLRDBAND :: 0x0080 +POLLWRNORM :: 0x0100 +POLLWRBAND :: 0x0200 +POLLMSG :: 0x0400 +POLLREMOVE :: 0x1000 +POLLRDHUP :: 0x2000 +POLLFREE :: 0x4000 +POLL_BUSY_LOOP :: 0x8000 + // perf event data Perf_Sample :: struct #raw_union { period: u64, @@ -2057,6 +2074,18 @@ sys_fcntl :: proc "contextless" (fd: int, cmd: int, arg: int) -> int { return int(intrinsics.syscall(SYS_fcntl, uintptr(fd), uintptr(cmd), uintptr(arg))) } +sys_select :: proc "contextless" (nfds: int, readfds, writefds, exceptfds: rawptr, timeout: rawptr) -> int { + return int(intrinsics.syscall(SYS_select, uintptr(nfds), uintptr(readfds), uintptr(writefds), uintptr(exceptfds), uintptr(timeout))) +} + +sys_poll :: proc "contextless" (fds: rawptr, nfds: uint, timeout: int) -> int { + return int(intrinsics.syscall(SYS_poll, uintptr(fds), uintptr(nfds), uintptr(timeout))) +} + +sys_ppoll :: proc "contextless" (fds: rawptr, nfds: uint, timeout: rawptr, sigmask: rawptr, sigsetsize: uint) -> int { + return int(intrinsics.syscall(SYS_ppoll, uintptr(fds), uintptr(nfds), uintptr(timeout), uintptr(sigmask), uintptr(sigsetsize))) +} + get_errno :: proc "contextless" (res: int) -> i32 { if res < 0 && res > -4096 { return i32(-res) From 091c515fea784b639b4a907a2fff4a6c6eef53de Mon Sep 17 00:00:00 2001 From: Rickard Andersson Date: Wed, 14 Jun 2023 22:34:57 +0300 Subject: [PATCH 2/8] cleanup(os_linux): remove `select` --- core/os/os_linux.odin | 8 -------- 1 file changed, 8 deletions(-) diff --git a/core/os/os_linux.odin b/core/os/os_linux.odin index beb4acec5..70e842aa4 100644 --- a/core/os/os_linux.odin +++ b/core/os/os_linux.odin @@ -1100,14 +1100,6 @@ fcntl :: proc(fd: int, cmd: int, arg: int) -> (int, Errno) { return result, ERROR_NONE } -// select :: proc(nfds: int, readfds: ^fd_set, writefds: ^fd_set, exceptfds: ^fd_set, timeout: ^timeval) -> (int, Errno) { -// result := unix.sys_select(nfds, readfds, writefds, exceptfds, timeout) -// if result < 0 { -// return 0, _get_errno(result) -// } -// return result, ERROR_NONE -// } - poll :: proc(fds: [^]pollfd, nfds: nfds_t, timeout: int) -> (int, Errno) { result := unix.sys_poll(fds, uint(nfds), timeout) if result < 0 { From d6540d9077cbfe18f0d6804ec2a301c04758c820 Mon Sep 17 00:00:00 2001 From: Rickard Andersson Date: Wed, 14 Jun 2023 23:26:43 +0300 Subject: [PATCH 3/8] fix(os_linux): call `ppoll` instead on `arm64` --- core/os/os_linux.odin | 4 +--- core/sys/unix/syscalls_linux.odin | 17 ++++++++++++++++- 2 files changed, 17 insertions(+), 4 deletions(-) diff --git a/core/os/os_linux.odin b/core/os/os_linux.odin index 70e842aa4..3e5258af3 100644 --- a/core/os/os_linux.odin +++ b/core/os/os_linux.odin @@ -440,9 +440,7 @@ pollfd :: struct { nfds_t :: distinct c.uint -sigset_t :: struct { - __val: [16]c.ulong, -} +sigset_t :: distinct u64 foreign libc { @(link_name="__errno_location") __errno_location :: proc() -> ^int --- diff --git a/core/sys/unix/syscalls_linux.odin b/core/sys/unix/syscalls_linux.odin index 54f8bcc25..2e5bad153 100644 --- a/core/sys/unix/syscalls_linux.odin +++ b/core/sys/unix/syscalls_linux.odin @@ -2079,7 +2079,22 @@ sys_select :: proc "contextless" (nfds: int, readfds, writefds, exceptfds: rawpt } sys_poll :: proc "contextless" (fds: rawptr, nfds: uint, timeout: int) -> int { - return int(intrinsics.syscall(SYS_poll, uintptr(fds), uintptr(nfds), uintptr(timeout))) + // NOTE: specialcased here because `arm64` does not have `poll` + when ODIN_ARCH != .arm64 { + // redefined because we can't depend on the `unix` module here + timespec :: struct { + tv_sec: i64, + tv_nsec: i64, + } + seconds := i64(timeout / 1_000) + nanoseconds := i64((timeout % 1000) * 1_000_000) + timeout_spec := timespec{seconds, nanoseconds} + + return int(intrinsics.syscall(SYS_ppoll, uintptr(fds), uintptr(nfds), uintptr(&timeout_spec), uintptr(0), uintptr(8))) + } else { + return int(intrinsics.syscall(SYS_poll, uintptr(fds), uintptr(nfds), uintptr(timeout))) + } + } sys_ppoll :: proc "contextless" (fds: rawptr, nfds: uint, timeout: rawptr, sigmask: rawptr, sigsetsize: uint) -> int { From 003c470a4df12fe2e82b13fde532f95b2ac85637 Mon Sep 17 00:00:00 2001 From: Rickard Andersson Date: Wed, 14 Jun 2023 23:38:00 +0300 Subject: [PATCH 4/8] fix(os_linux): make `when` for `arm64` check correct order Also remove `sys_select` since we aren't using it anyway --- core/sys/unix/syscalls_linux.odin | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/core/sys/unix/syscalls_linux.odin b/core/sys/unix/syscalls_linux.odin index 2e5bad153..0accc9d53 100644 --- a/core/sys/unix/syscalls_linux.odin +++ b/core/sys/unix/syscalls_linux.odin @@ -2074,13 +2074,9 @@ sys_fcntl :: proc "contextless" (fd: int, cmd: int, arg: int) -> int { return int(intrinsics.syscall(SYS_fcntl, uintptr(fd), uintptr(cmd), uintptr(arg))) } -sys_select :: proc "contextless" (nfds: int, readfds, writefds, exceptfds: rawptr, timeout: rawptr) -> int { - return int(intrinsics.syscall(SYS_select, uintptr(nfds), uintptr(readfds), uintptr(writefds), uintptr(exceptfds), uintptr(timeout))) -} - sys_poll :: proc "contextless" (fds: rawptr, nfds: uint, timeout: int) -> int { // NOTE: specialcased here because `arm64` does not have `poll` - when ODIN_ARCH != .arm64 { + when ODIN_ARCH == .arm64 { // redefined because we can't depend on the `unix` module here timespec :: struct { tv_sec: i64, From 0036509f74592e6921e0dbb994e0df02e6d673ba Mon Sep 17 00:00:00 2001 From: Rickard Andersson Date: Wed, 14 Jun 2023 23:51:33 +0300 Subject: [PATCH 5/8] cleanup(os_linux/poll): use tabs everywhere :( --- core/sys/unix/syscalls_linux.odin | 23 +++++++++++------------ 1 file changed, 11 insertions(+), 12 deletions(-) diff --git a/core/sys/unix/syscalls_linux.odin b/core/sys/unix/syscalls_linux.odin index 0accc9d53..fdfc27187 100644 --- a/core/sys/unix/syscalls_linux.odin +++ b/core/sys/unix/syscalls_linux.odin @@ -2075,22 +2075,21 @@ sys_fcntl :: proc "contextless" (fd: int, cmd: int, arg: int) -> int { } sys_poll :: proc "contextless" (fds: rawptr, nfds: uint, timeout: int) -> int { - // NOTE: specialcased here because `arm64` does not have `poll` + // NOTE: specialcased here because `arm64` does not have `poll` when ODIN_ARCH == .arm64 { - // redefined because we can't depend on the `unix` module here - timespec :: struct { - tv_sec: i64, - tv_nsec: i64, - } - seconds := i64(timeout / 1_000) - nanoseconds := i64((timeout % 1000) * 1_000_000) - timeout_spec := timespec{seconds, nanoseconds} - + // redefined because we can't depend on the `unix` module here + timespec :: struct { + tv_sec: i64, + tv_nsec: i64, + } + seconds := i64(timeout / 1_000) + nanoseconds := i64((timeout % 1000) * 1_000_000) + timeout_spec := timespec{seconds, nanoseconds} + return int(intrinsics.syscall(SYS_ppoll, uintptr(fds), uintptr(nfds), uintptr(&timeout_spec), uintptr(0), uintptr(8))) } else { - return int(intrinsics.syscall(SYS_poll, uintptr(fds), uintptr(nfds), uintptr(timeout))) + return int(intrinsics.syscall(SYS_poll, uintptr(fds), uintptr(nfds), uintptr(timeout))) } - } sys_ppoll :: proc "contextless" (fds: rawptr, nfds: uint, timeout: rawptr, sigmask: rawptr, sigsetsize: uint) -> int { From a5ed5883c71282b2454e3e320fc7c8703b9fa952 Mon Sep 17 00:00:00 2001 From: Rickard Andersson Date: Wed, 14 Jun 2023 23:59:09 +0300 Subject: [PATCH 6/8] cleanup: more tabs --- core/os/os_linux.odin | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/core/os/os_linux.odin b/core/os/os_linux.odin index 3e5258af3..ff3ff700c 100644 --- a/core/os/os_linux.odin +++ b/core/os/os_linux.odin @@ -1099,17 +1099,17 @@ fcntl :: proc(fd: int, cmd: int, arg: int) -> (int, Errno) { } poll :: proc(fds: [^]pollfd, nfds: nfds_t, timeout: int) -> (int, Errno) { - result := unix.sys_poll(fds, uint(nfds), timeout) - if result < 0 { - return 0, _get_errno(result) - } - return result, ERROR_NONE + result := unix.sys_poll(fds, uint(nfds), timeout) + if result < 0 { + return 0, _get_errno(result) + } + return result, ERROR_NONE } ppoll :: proc(fds: [^]pollfd, nfds: nfds_t, timeout: ^unix.timespec, sigmask: ^sigset_t) -> (int, Errno) { - result := unix.sys_ppoll(fds, uint(nfds), timeout, sigmask, size_of(sigset_t)) - if result < 0 { - return 0, _get_errno(result) - } - return result, ERROR_NONE + result := unix.sys_ppoll(fds, uint(nfds), timeout, sigmask, size_of(sigset_t)) + if result < 0 { + return 0, _get_errno(result) + } + return result, ERROR_NONE } From dce57627c972276be8398ec0e2efcb7782b650d8 Mon Sep 17 00:00:00 2001 From: Rickard Andersson Date: Thu, 15 Jun 2023 08:54:42 +0300 Subject: [PATCH 7/8] fix: remove redefinition of `timespec` They are in the same package, so it's accessible anyway. --- core/sys/unix/syscalls_linux.odin | 5 ----- 1 file changed, 5 deletions(-) diff --git a/core/sys/unix/syscalls_linux.odin b/core/sys/unix/syscalls_linux.odin index fdfc27187..92b551041 100644 --- a/core/sys/unix/syscalls_linux.odin +++ b/core/sys/unix/syscalls_linux.odin @@ -2077,11 +2077,6 @@ sys_fcntl :: proc "contextless" (fd: int, cmd: int, arg: int) -> int { sys_poll :: proc "contextless" (fds: rawptr, nfds: uint, timeout: int) -> int { // NOTE: specialcased here because `arm64` does not have `poll` when ODIN_ARCH == .arm64 { - // redefined because we can't depend on the `unix` module here - timespec :: struct { - tv_sec: i64, - tv_nsec: i64, - } seconds := i64(timeout / 1_000) nanoseconds := i64((timeout % 1000) * 1_000_000) timeout_spec := timespec{seconds, nanoseconds} From 37469dc9c2eb2df30995599b80b234526c05f4d1 Mon Sep 17 00:00:00 2001 From: Rickard Andersson Date: Thu, 15 Jun 2023 16:10:00 +0300 Subject: [PATCH 8/8] fix(poll): make interface more odinary We take `fds` as a normal slice and get the length from it instead of bothering with a second parameter. --- core/os/os_linux.odin | 16 +++++++--------- core/sys/unix/syscalls_linux.odin | 2 +- 2 files changed, 8 insertions(+), 10 deletions(-) diff --git a/core/os/os_linux.odin b/core/os/os_linux.odin index ff3ff700c..e0b60fd36 100644 --- a/core/os/os_linux.odin +++ b/core/os/os_linux.odin @@ -433,13 +433,11 @@ AT_REMOVEDIR :: uintptr(0x200) AT_SYMLINK_NOFOLLOW :: uintptr(0x100) pollfd :: struct { - fd: c.int, - events: c.short, - revents: c.short, + fd: c.int, + events: c.short, + revents: c.short, } -nfds_t :: distinct c.uint - sigset_t :: distinct u64 foreign libc { @@ -1098,16 +1096,16 @@ fcntl :: proc(fd: int, cmd: int, arg: int) -> (int, Errno) { return result, ERROR_NONE } -poll :: proc(fds: [^]pollfd, nfds: nfds_t, timeout: int) -> (int, Errno) { - result := unix.sys_poll(fds, uint(nfds), timeout) +poll :: proc(fds: []pollfd, timeout: int) -> (int, Errno) { + result := unix.sys_poll(raw_data(fds), uint(len(fds)), timeout) if result < 0 { return 0, _get_errno(result) } return result, ERROR_NONE } -ppoll :: proc(fds: [^]pollfd, nfds: nfds_t, timeout: ^unix.timespec, sigmask: ^sigset_t) -> (int, Errno) { - result := unix.sys_ppoll(fds, uint(nfds), timeout, sigmask, size_of(sigset_t)) +ppoll :: proc(fds: []pollfd, timeout: ^unix.timespec, sigmask: ^sigset_t) -> (int, Errno) { + result := unix.sys_ppoll(raw_data(fds), uint(len(fds)), timeout, sigmask, size_of(sigset_t)) if result < 0 { return 0, _get_errno(result) } diff --git a/core/sys/unix/syscalls_linux.odin b/core/sys/unix/syscalls_linux.odin index 92b551041..3083c084b 100644 --- a/core/sys/unix/syscalls_linux.odin +++ b/core/sys/unix/syscalls_linux.odin @@ -2088,7 +2088,7 @@ sys_poll :: proc "contextless" (fds: rawptr, nfds: uint, timeout: int) -> int { } sys_ppoll :: proc "contextless" (fds: rawptr, nfds: uint, timeout: rawptr, sigmask: rawptr, sigsetsize: uint) -> int { - return int(intrinsics.syscall(SYS_ppoll, uintptr(fds), uintptr(nfds), uintptr(timeout), uintptr(sigmask), uintptr(sigsetsize))) + return int(intrinsics.syscall(SYS_ppoll, uintptr(fds), uintptr(nfds), uintptr(timeout), uintptr(sigmask), uintptr(sigsetsize))) } get_errno :: proc "contextless" (res: int) -> i32 {