aboutsummaryrefslogtreecommitdiff
path: root/core/sys/linux
diff options
context:
space:
mode:
authorflysand7 <yyakut.ac@gmail.com>2023-11-24 09:25:12 +1100
committerflysand7 <yyakut.ac@gmail.com>2023-11-24 09:39:36 +1100
commit03282c1234ea24e772c61fcb7b1b0a80245f78d8 (patch)
tree664333a09c03dfe99a348d7a1a43d594bf59f19b /core/sys/linux
parent4e145cf69c151a87ad2f2a1e34bf96cf2a70b52e (diff)
[sys/linux]: Add epoll syscalls
Diffstat (limited to 'core/sys/linux')
-rw-r--r--core/sys/linux/bits.odin31
-rw-r--r--core/sys/linux/sys.odin71
-rw-r--r--core/sys/linux/types.odin17
3 files changed, 109 insertions, 10 deletions
diff --git a/core/sys/linux/bits.odin b/core/sys/linux/bits.odin
index fa2470c78..946f32928 100644
--- a/core/sys/linux/bits.odin
+++ b/core/sys/linux/bits.odin
@@ -1727,3 +1727,34 @@ Clock_Id :: enum {
ITimer_Flags_Bits :: enum {
ABSTIME = 1,
}
+
+/*
+ Bits for epoll_create(2) flags.
+*/
+EPoll_Flags_Bits :: enum {
+ FDCLOEXEC = 19,
+}
+
+EPoll_Event_Kind :: enum u32 {
+ IN = 0x001,
+ PRI = 0x002,
+ OUT = 0x004,
+ RDNORM = 0x040,
+ RDBAND = 0x080,
+ WRNORM = 0x100,
+ WRBAND = 0x200,
+ MSG = 0x400,
+ ERR = 0x008,
+ HUP = 0x010,
+ RDHUP = 0x2000,
+ EXCLUSIVE = 1<<28,
+ WAKEUP = 1<<29,
+ ONESHOT = 1<<30,
+ ET = 1<<31,
+}
+
+EPoll_Ctl_Opcode :: enum i32 {
+ ADD = 1,
+ DEL = 2,
+ MOD = 3,
+}
diff --git a/core/sys/linux/sys.odin b/core/sys/linux/sys.odin
index 9ffca616c..d7aaed0b5 100644
--- a/core/sys/linux/sys.odin
+++ b/core/sys/linux/sys.odin
@@ -2304,11 +2304,22 @@ futex :: proc {
// TODO(flysand): lookup_dcookie
-// TODO(flysand): epoll_create
-
-// TODO(flysand): epoll_ctl_old
-
-// TODO(flysand): epoll_wait_old
+/*
+ Open an epoll file descriptor.
+
+ The `size` argument is ignored but must be greater than zero.
+
+ Available since Linux 2.6.
+*/
+epoll_create :: proc(size: i32 = 1) -> (Fd, Errno) {
+ when ODIN_ARCH != .arm64 {
+ ret := syscall(SYS_epoll_create)
+ return errno_unwrap(ret, Fd)
+ } else {
+ ret := syscall(SYS_epoll_create1, i32(0))
+ return errno_unwrap(ret, Fd)
+ }
+}
// TODO(flysand): remap_file_pages
@@ -2387,9 +2398,32 @@ exit_group :: proc "contextless" (code: i32) -> ! {
unreachable()
}
-// TODO(flysand): epoll_wait
+/*
+ Wait for an I/O event on an epoll file descriptor.
+
+ `timeout` is specified in milliseconds.
+
+ Available since Linux 2.6.
+*/
+epoll_wait :: proc(epfd: Fd, events: [^]EPoll_Event, count: i32, timeout: i32) -> (i32, Errno) {
+ when ODIN_ARCH != .arm64 {
+ ret := syscall(SYS_epoll_wait, epfd, events, count, timeout)
+ return errno_unwrap(ret, i32)
+ } else {
+ // Convert milliseconds to nanosecond timespec
+ ret := syscall(SYS_epoll_pwait, epfd, events, count, timeout, nil)
+ return errno_unwrap(ret, i32)
+ }
+}
-// TODO(flysand): epoll_ctl
+/*
+ Control interface for an epoll file descriptor.
+ Available since Linux 2.6.
+*/
+epoll_ctl :: proc(epfd: Fd, op: EPoll_Ctl_Opcode, fd: Fd, event: ^EPoll_Event) -> (Errno) {
+ ret := syscall(SYS_epoll_ctl, epfd, op, fd, event)
+ return Errno(-ret)
+}
/*
Send a signal to a specific thread in a thread group.
@@ -2622,7 +2656,14 @@ utimensat :: proc "contextless" (dirfd: Fd, name: cstring, utimes: [^]Time_Spec,
return Errno(-ret)
}
-// TODO(flysand): epoll_pwait
+/*
+ Wait for an I/O event on an epoll file descriptor.
+ Available since Linux 2.6.
+*/
+epoll_pwait :: proc(epfd: Fd, events: [^]EPoll_Event, count: i32, timeout: i32, sigmask: ^Sig_Set) -> (i32, Errno) {
+ ret := syscall(SYS_epoll_pwait, epfd, events, count, timeout, sigmask)
+ return errno_unwrap(ret, i32)
+}
// TODO(flysand): signalfd
@@ -2642,7 +2683,10 @@ utimensat :: proc "contextless" (dirfd: Fd, name: cstring, utimes: [^]Time_Spec,
// TODO(flysand): eventfd2
-// TODO(flysand): epoll_create1
+epoll_create1 :: proc(flags: EPoll_Flags) -> (Fd, Errno) {
+ ret := syscall(SYS_epoll_create1, transmute(i32) flags)
+ return errno_unwrap(ret, Fd)
+}
/*
Adjust an existing file descriptor to point to the same file as `old`.
@@ -2859,7 +2903,14 @@ faccessat2 :: proc "contextless" (dirfd: Fd, name: cstring, mode: Mode = F_OK, f
// TODO(flysand): process_madvise
-// TODO(flysand): epoll_pwait2
+/*
+ Wait for an I/O event on an epoll file descriptor.
+ Available since Linux 2.6.
+*/
+epoll_pwait2 :: proc(epfd: Fd, events: [^]EPoll_Event, count: i32, timeout: ^Time_Spec, sigmask: ^Sig_Set) -> (i32, Errno) {
+ ret := syscall(SYS_epoll_pwait2, epfd, events, count, timeout, sigmask)
+ return errno_unwrap(ret, i32)
+}
// TODO(flysand): mount_setattr
diff --git a/core/sys/linux/types.odin b/core/sys/linux/types.odin
index 997c9592b..22d698353 100644
--- a/core/sys/linux/types.odin
+++ b/core/sys/linux/types.odin
@@ -1220,3 +1220,20 @@ PTrace_Note_Type :: enum {
Flags for splice(2) and tee(2) syscalls.
*/
Splice_Flags :: bit_set[Splice_Flags_Bits; u32]
+
+/*
+ Flags for epoll_create(2) syscall.
+*/
+EPoll_Flags :: bit_set[EPoll_Flags_Bits; i32]
+
+EPoll_Data :: struct #raw_union {
+ ptr: rawptr,
+ fd: Fd,
+ u32: u32,
+ u64: u64,
+}
+
+EPoll_Event :: struct #packed {
+ events: EPoll_Event_Kind,
+ data: EPoll_Data,
+}