Files
Odin/core/sys/kqueue/kqueue.odin
Harold Brenes 219b0fe535 Replace system:System.framework imports with system:System
This makes the linker work for both macOS and iOS targets
2025-07-13 15:45:21 -04:00

257 lines
6.4 KiB
Odin

#+build darwin, netbsd, openbsd, freebsd
package kqueue
when ODIN_OS == .Darwin {
foreign import lib "system:System"
} 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 ---
}