aboutsummaryrefslogtreecommitdiff
path: root/core/sys/kqueue
diff options
context:
space:
mode:
authorLaytan Laats <laytanlaats@hotmail.com>2024-08-22 23:00:01 +0200
committerLaytan Laats <laytanlaats@hotmail.com>2024-08-22 23:07:24 +0200
commita66520ba57a4d6376c757f64086dba831aae1294 (patch)
treeff56c70127fa9a3290881308ba2bcf87d07bf137 /core/sys/kqueue
parentb9043db434319dedd518dbab45e5cad9d0df486f (diff)
os2: process API for Darwin and most of it for BSDs
Diffstat (limited to 'core/sys/kqueue')
-rw-r--r--core/sys/kqueue/kqueue.odin256
1 files changed, 256 insertions, 0 deletions
diff --git a/core/sys/kqueue/kqueue.odin b/core/sys/kqueue/kqueue.odin
new file mode 100644
index 000000000..27d1ecaae
--- /dev/null
+++ b/core/sys/kqueue/kqueue.odin
@@ -0,0 +1,256 @@
+//+build darwin, netbsd, openbsd, freebsd
+package kqueue
+
+when ODIN_OS == .Darwin {
+ foreign import lib "system:System.framework"
+} else {
+ foreign import lib "system:c"
+}
+
+import "base:intrinsics"
+
+import "core:c"
+import "core:sys/posix"
+
+KQ :: posix.FD
+
+kqueue :: proc() -> (kq: KQ, err: posix.Errno) {
+ kq = _kqueue()
+ if kq == -1 {
+ err = posix.errno()
+ }
+ return
+}
+
+kevent :: proc(kq: KQ, change_list: []KEvent, event_list: []KEvent, timeout: ^posix.timespec) -> (n_events: c.int, err: posix.Errno) {
+ n_events = _kevent(
+ kq,
+ raw_data(change_list),
+ c.int(len(change_list)),
+ raw_data(event_list),
+ c.int(len(event_list)),
+ timeout,
+ )
+ if n_events == -1 {
+ err = posix.errno()
+ }
+ return
+}
+
+Flag :: enum _Flags_Backing {
+ Add = log2(0x0001), // Add event to kq (implies .Enable).
+ Delete = log2(0x0002), // Delete event from kq.
+ Enable = log2(0x0004), // Enable event.
+ Disable = log2(0x0008), // Disable event (not reported).
+ One_Shot = log2(0x0010), // Only report one occurrence.
+ Clear = log2(0x0020), // Clear event state after reporting.
+ Receipt = log2(0x0040), // Force immediate event output.
+ Dispatch = log2(0x0080), // Disable event after reporting.
+
+ Error = log2(0x4000), // Error, data contains errno.
+ EOF = log2(0x8000), // EOF detected.
+}
+Flags :: bit_set[Flag; _Flags_Backing]
+
+Filter :: enum _Filter_Backing {
+ Read = _FILTER_READ, // Check for read availability on the file descriptor.
+ Write = _FILTER_WRITE, // Check for write availability on the file descriptor.
+ AIO = _FILTER_AIO, // Attached to AIO requests.
+ VNode = _FILTER_VNODE, // Check for changes to the subject file.
+ Proc = _FILTER_PROC, // Check for changes to the subject process.
+ Signal = _FILTER_SIGNAL, // Check for signals delivered to the process.
+ Timer = _FILTER_TIMER, // Timers.
+}
+
+RW_Flag :: enum u32 {
+ Low_Water_Mark = log2(0x00000001),
+}
+RW_Flags :: bit_set[RW_Flag; u32]
+
+VNode_Flag :: enum u32 {
+ Delete = log2(0x00000001), // Deleted.
+ Write = log2(0x00000002), // Contents changed.
+ Extend = log2(0x00000004), // Size increased.
+ Attrib = log2(0x00000008), // Attributes changed.
+ Link = log2(0x00000010), // Link count changed.
+ Rename = log2(0x00000020), // Renamed.
+ Revoke = log2(0x00000040), // Access was revoked.
+}
+VNode_Flags :: bit_set[VNode_Flag; u32]
+
+Proc_Flag :: enum u32 {
+ Exit = log2(0x80000000), // Process exited.
+ Fork = log2(0x40000000), // Process forked.
+ Exec = log2(0x20000000), // Process exec'd.
+ Signal = log2(0x08000000), // Shared with `Filter.Signal`.
+}
+Proc_Flags :: bit_set[Proc_Flag; u32]
+
+Timer_Flag :: enum u32 {
+ Seconds = log2(0x00000001), // Data is seconds.
+ USeconds = log2(0x00000002), // Data is microseconds.
+ NSeconds = log2(_NOTE_NSECONDS), // Data is nanoseconds.
+ Absolute = log2(_NOTE_ABSOLUTE), // Absolute timeout.
+}
+Timer_Flags :: bit_set[Timer_Flag; u32]
+
+when ODIN_OS == .Darwin {
+
+ _Filter_Backing :: distinct i16
+ _Flags_Backing :: distinct u16
+
+ _FILTER_READ :: -1
+ _FILTER_WRITE :: -2
+ _FILTER_AIO :: -3
+ _FILTER_VNODE :: -4
+ _FILTER_PROC :: -5
+ _FILTER_SIGNAL :: -6
+ _FILTER_TIMER :: -7
+
+ _NOTE_NSECONDS :: 0x00000004
+ _NOTE_ABSOLUTE :: 0x00000008
+
+ KEvent :: struct #align(4) {
+ // Value used to identify this event. The exact interpretation is determined by the attached filter.
+ ident: uintptr,
+ // Filter for event.
+ filter: Filter,
+ // General flags.
+ flags: Flags,
+ // Filter specific flags.
+ fflags: struct #raw_union {
+ rw: RW_Flags,
+ vnode: VNode_Flags,
+ fproc: Proc_Flags,
+ // vm: VM_Flags,
+ timer: Timer_Flags,
+ },
+ // Filter specific data.
+ data: c.long /* intptr_t */,
+ // Opaque user data passed through the kernel unchanged.
+ udata: rawptr,
+ }
+
+} else when ODIN_OS == .FreeBSD {
+
+ _Filter_Backing :: distinct i16
+ _Flags_Backing :: distinct u16
+
+ _FILTER_READ :: -1
+ _FILTER_WRITE :: -2
+ _FILTER_AIO :: -3
+ _FILTER_VNODE :: -4
+ _FILTER_PROC :: -5
+ _FILTER_SIGNAL :: -6
+ _FILTER_TIMER :: -7
+
+ _NOTE_NSECONDS :: 0x00000004
+ _NOTE_ABSOLUTE :: 0x00000008
+
+ KEvent :: struct {
+ // Value used to identify this event. The exact interpretation is determined by the attached filter.
+ ident: uintptr,
+ // Filter for event.
+ filter: Filter,
+ // General flags.
+ flags: Flags,
+ // Filter specific flags.
+ fflags: struct #raw_union {
+ rw: RW_Flags,
+ vnode: VNode_Flags,
+ fproc: Proc_Flags,
+ // vm: VM_Flags,
+ timer: Timer_Flags,
+ },
+ // Filter specific data.
+ data: i64,
+ // Opaque user data passed through the kernel unchanged.
+ udata: rawptr,
+ // Extensions.
+ ext: [4]u64,
+ }
+} else when ODIN_OS == .NetBSD {
+
+ _Filter_Backing :: distinct u32
+ _Flags_Backing :: distinct u32
+
+ _FILTER_READ :: 0
+ _FILTER_WRITE :: 1
+ _FILTER_AIO :: 2
+ _FILTER_VNODE :: 3
+ _FILTER_PROC :: 4
+ _FILTER_SIGNAL :: 5
+ _FILTER_TIMER :: 6
+
+ _NOTE_NSECONDS :: 0x00000003
+ _NOTE_ABSOLUTE :: 0x00000010
+
+ KEvent :: struct #align(4) {
+ // Value used to identify this event. The exact interpretation is determined by the attached filter.
+ ident: uintptr,
+ // Filter for event.
+ filter: Filter,
+ // General flags.
+ flags: Flags,
+ // Filter specific flags.
+ fflags: struct #raw_union {
+ rw: RW_Flags,
+ vnode: VNode_Flags,
+ fproc: Proc_Flags,
+ // vm: VM_Flags,
+ timer: Timer_Flags,
+ },
+ // Filter specific data.
+ data: i64,
+ // Opaque user data passed through the kernel unchanged.
+ udata: rawptr,
+ // Extensions.
+ ext: [4]u64,
+ }
+} else when ODIN_OS == .OpenBSD {
+
+ _Filter_Backing :: distinct i16
+ _Flags_Backing :: distinct u16
+
+ _FILTER_READ :: -1
+ _FILTER_WRITE :: -2
+ _FILTER_AIO :: -3
+ _FILTER_VNODE :: -4
+ _FILTER_PROC :: -5
+ _FILTER_SIGNAL :: -6
+ _FILTER_TIMER :: -7
+
+ _NOTE_NSECONDS :: 0x00000003
+ _NOTE_ABSOLUTE :: 0x00000010
+
+ KEvent :: struct #align(4) {
+ // Value used to identify this event. The exact interpretation is determined by the attached filter.
+ ident: uintptr,
+ // Filter for event.
+ filter: Filter,
+ // General flags.
+ flags: Flags,
+ // Filter specific flags.
+ fflags: struct #raw_union {
+ rw: RW_Flags,
+ vnode: VNode_Flags,
+ fproc: Proc_Flags,
+ // vm: VM_Flags,
+ timer: Timer_Flags,
+ },
+ // Filter specific data.
+ data: i64,
+ // Opaque user data passed through the kernel unchanged.
+ udata: rawptr,
+ }
+}
+
+@(private)
+log2 :: intrinsics.constant_log2
+
+foreign lib {
+ @(link_name="kqueue")
+ _kqueue :: proc() -> KQ ---
+ @(link_name="kevent")
+ _kevent :: proc(kq: KQ, change_list: [^]KEvent, n_changes: c.int, event_list: [^]KEvent, n_events: c.int, timeout: ^posix.timespec) -> c.int ---
+}