Browse Source

[sys/linux]: Add epoll syscalls

flysand7 1 year ago
parent
commit
03282c1234
3 changed files with 109 additions and 10 deletions
  1. 31 0
      core/sys/linux/bits.odin
  2. 61 10
      core/sys/linux/sys.odin
  3. 17 0
      core/sys/linux/types.odin

+ 31 - 0
core/sys/linux/bits.odin

@@ -1727,3 +1727,34 @@ Clock_Id :: enum {
 ITimer_Flags_Bits :: enum {
 ITimer_Flags_Bits :: enum {
 	ABSTIME = 1,
 	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,
+}

+ 61 - 10
core/sys/linux/sys.odin

@@ -2304,11 +2304,22 @@ futex :: proc {
 
 
 // TODO(flysand): lookup_dcookie
 // 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
 // TODO(flysand): remap_file_pages
 
 
@@ -2387,9 +2398,32 @@ exit_group :: proc "contextless" (code: i32) -> ! {
 	unreachable()
 	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.
 	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)
 	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
 // TODO(flysand): signalfd
 
 
@@ -2642,7 +2683,10 @@ utimensat :: proc "contextless" (dirfd: Fd, name: cstring, utimes: [^]Time_Spec,
 
 
 // TODO(flysand): eventfd2
 // 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`.
 	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): 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
 // TODO(flysand): mount_setattr
 
 

+ 17 - 0
core/sys/linux/types.odin

@@ -1220,3 +1220,20 @@ PTrace_Note_Type :: enum {
 	Flags for splice(2) and tee(2) syscalls.
 	Flags for splice(2) and tee(2) syscalls.
 */
 */
 Splice_Flags :: bit_set[Splice_Flags_Bits; u32]
 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,
+}