瀏覽代碼

Merge pull request #2591 from GoNZooo/g.add-poll-for-unix

feat(os_linux): add `poll` & `ppoll`
Jeroen van Rijn 2 年之前
父節點
當前提交
c1fb8eaf1a
共有 2 個文件被更改,包括 58 次插入0 次删除
  1. 24 0
      core/os/os_linux.odin
  2. 34 0
      core/sys/unix/syscalls_linux.odin

+ 24 - 0
core/os/os_linux.odin

@@ -432,6 +432,14 @@ 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,
+}
+
+sigset_t :: distinct u64
+
 foreign libc {
 	@(link_name="__errno_location") __errno_location    :: proc() -> ^int ---
 
@@ -1087,3 +1095,19 @@ fcntl :: proc(fd: int, cmd: int, arg: int) -> (int, Errno) {
 	}
 	return result, ERROR_NONE
 }
+
+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, 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)
+	}
+	return result, ERROR_NONE
+}

+ 34 - 0
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,23 @@ sys_fcntl :: proc "contextless" (fd: int, cmd: int, arg: int) -> int {
 	return int(intrinsics.syscall(SYS_fcntl, uintptr(fd), uintptr(cmd), uintptr(arg)))
 }
 
+sys_poll :: proc "contextless" (fds: rawptr, nfds: uint, timeout: int) -> int {
+	// NOTE: specialcased here because `arm64` does not have `poll`
+	when ODIN_ARCH == .arm64 {
+		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 {
+	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)