mirror of
https://github.com/odin-lang/Odin.git
synced 2026-04-23 23:05:18 +00:00
kqueue: fix bsds, add user filter, add struct tests
This commit is contained in:
@@ -32,6 +32,7 @@ kevent :: proc(kq: KQ, change_list: []KEvent, event_list: []KEvent, timeout: ^po
|
||||
timeout,
|
||||
)
|
||||
if n_events == -1 {
|
||||
n_events = 0
|
||||
err = posix.errno()
|
||||
}
|
||||
return
|
||||
@@ -60,6 +61,7 @@ Filter :: enum _Filter_Backing {
|
||||
Proc = _FILTER_PROC, // Check for changes to the subject process.
|
||||
Signal = _FILTER_SIGNAL, // Check for signals delivered to the process.
|
||||
Timer = _FILTER_TIMER, // Timers.
|
||||
User = _FILTER_USER, // User events.
|
||||
}
|
||||
|
||||
RW_Flag :: enum u32 {
|
||||
@@ -82,18 +84,30 @@ 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.
|
||||
USeconds = log2(_NOTE_USECONDS), // Data is microseconds.
|
||||
Absolute = log2(_NOTE_ABSOLUTE), // Absolute timeout.
|
||||
}
|
||||
Timer_Flags :: bit_set[Timer_Flag; u32]
|
||||
|
||||
User_Flag :: enum u32 {
|
||||
Trigger = log2(0x01000000),
|
||||
FFAnd = log2(0x40000000),
|
||||
FFOr = log2(0x80000000),
|
||||
}
|
||||
User_Flags :: bit_set[User_Flag; u32]
|
||||
|
||||
USER_FLAGS_COPY :: User_Flags{.FFOr, .FFAnd}
|
||||
USER_FLAGS_CONTROL_MASK :: transmute(User_Flags)u32(0xc0000000)
|
||||
USER_FLAGS_MASK :: transmute(User_Flags)u32(0x00FFFFFF)
|
||||
|
||||
// Data is nanoseconds.
|
||||
TIMER_FLAGS_NSECONDS :: _TIMER_FLAGS_NSECONDS
|
||||
|
||||
when ODIN_OS == .Darwin {
|
||||
|
||||
_Filter_Backing :: distinct i16
|
||||
@@ -106,10 +120,14 @@ when ODIN_OS == .Darwin {
|
||||
_FILTER_PROC :: -5
|
||||
_FILTER_SIGNAL :: -6
|
||||
_FILTER_TIMER :: -7
|
||||
_FILTER_USER :: -10
|
||||
|
||||
_NOTE_USECONDS :: 0x00000002
|
||||
_NOTE_NSECONDS :: 0x00000004
|
||||
_NOTE_ABSOLUTE :: 0x00000008
|
||||
|
||||
_TIMER_FLAGS_NSECONDS :: Timer_Flags{Timer_Flag(log2(_NOTE_NSECONDS))}
|
||||
|
||||
KEvent :: struct #align(4) {
|
||||
// Value used to identify this event. The exact interpretation is determined by the attached filter.
|
||||
ident: uintptr,
|
||||
@@ -119,11 +137,12 @@ when ODIN_OS == .Darwin {
|
||||
flags: Flags,
|
||||
// Filter specific flags.
|
||||
fflags: struct #raw_union {
|
||||
rw: RW_Flags,
|
||||
vnode: VNode_Flags,
|
||||
fproc: Proc_Flags,
|
||||
rw: RW_Flags `raw_union_tag:"filter=.Read, filter=.Write"`,
|
||||
vnode: VNode_Flags `raw_union_tag:"filter=.VNode"`,
|
||||
fproc: Proc_Flags `raw_union_tag:"filter=.Proc"`,
|
||||
// vm: VM_Flags,
|
||||
timer: Timer_Flags,
|
||||
timer: Timer_Flags `raw_union_tag:"filter=.Timer"`,
|
||||
user: User_Flags `raw_union_tag:"filter=.User"`,
|
||||
},
|
||||
// Filter specific data.
|
||||
data: c.long /* intptr_t */,
|
||||
@@ -143,9 +162,13 @@ when ODIN_OS == .Darwin {
|
||||
_FILTER_PROC :: -5
|
||||
_FILTER_SIGNAL :: -6
|
||||
_FILTER_TIMER :: -7
|
||||
_FILTER_USER :: -11
|
||||
|
||||
_NOTE_NSECONDS :: 0x00000004
|
||||
_NOTE_ABSOLUTE :: 0x00000008
|
||||
_NOTE_USECONDS :: 0x00000004
|
||||
_NOTE_NSECONDS :: 0x00000008
|
||||
_NOTE_ABSOLUTE :: 0x00000010
|
||||
|
||||
_TIMER_FLAGS_NSECONDS :: Timer_Flags{Timer_Flag(log2(_NOTE_NSECONDS))}
|
||||
|
||||
KEvent :: struct {
|
||||
// Value used to identify this event. The exact interpretation is determined by the attached filter.
|
||||
@@ -156,11 +179,12 @@ when ODIN_OS == .Darwin {
|
||||
flags: Flags,
|
||||
// Filter specific flags.
|
||||
fflags: struct #raw_union {
|
||||
rw: RW_Flags,
|
||||
vnode: VNode_Flags,
|
||||
fproc: Proc_Flags,
|
||||
rw: RW_Flags `raw_union_tag:"filter=.Read, filter=.Write"`,
|
||||
vnode: VNode_Flags `raw_union_tag:"filter=.VNode"`,
|
||||
fproc: Proc_Flags `raw_union_tag:"filter=.Proc"`,
|
||||
// vm: VM_Flags,
|
||||
timer: Timer_Flags,
|
||||
timer: Timer_Flags `raw_union_tag:"filter=.Timer"`,
|
||||
user: User_Flags `raw_union_tag:"filter=.User"`,
|
||||
},
|
||||
// Filter specific data.
|
||||
data: i64,
|
||||
@@ -181,11 +205,14 @@ when ODIN_OS == .Darwin {
|
||||
_FILTER_PROC :: 4
|
||||
_FILTER_SIGNAL :: 5
|
||||
_FILTER_TIMER :: 6
|
||||
_FILTER_USER :: 8
|
||||
|
||||
_NOTE_NSECONDS :: 0x00000003
|
||||
_NOTE_USECONDS :: 0x00000002
|
||||
_NOTE_ABSOLUTE :: 0x00000010
|
||||
|
||||
KEvent :: struct #align(4) {
|
||||
_TIMER_FLAGS_NSECONDS :: Timer_Flags{.Seconds, .USeconds}
|
||||
|
||||
KEvent :: struct {
|
||||
// Value used to identify this event. The exact interpretation is determined by the attached filter.
|
||||
ident: uintptr,
|
||||
// Filter for event.
|
||||
@@ -194,18 +221,17 @@ when ODIN_OS == .Darwin {
|
||||
flags: Flags,
|
||||
// Filter specific flags.
|
||||
fflags: struct #raw_union {
|
||||
rw: RW_Flags,
|
||||
vnode: VNode_Flags,
|
||||
fproc: Proc_Flags,
|
||||
rw: RW_Flags `raw_union_tag:"filter=.Read, filter=.Write"`,
|
||||
vnode: VNode_Flags `raw_union_tag:"filter=.VNode"`,
|
||||
fproc: Proc_Flags `raw_union_tag:"filter=.Proc"`,
|
||||
// vm: VM_Flags,
|
||||
timer: Timer_Flags,
|
||||
timer: Timer_Flags `raw_union_tag:"filter=.Timer"`,
|
||||
user: User_Flags `raw_union_tag:"filter=.User"`,
|
||||
},
|
||||
// Filter specific data.
|
||||
data: i64,
|
||||
// Opaque user data passed through the kernel unchanged.
|
||||
udata: rawptr,
|
||||
// Extensions.
|
||||
ext: [4]u64,
|
||||
}
|
||||
} else when ODIN_OS == .OpenBSD {
|
||||
|
||||
@@ -219,10 +245,14 @@ when ODIN_OS == .Darwin {
|
||||
_FILTER_PROC :: -5
|
||||
_FILTER_SIGNAL :: -6
|
||||
_FILTER_TIMER :: -7
|
||||
_FILTER_USER :: -10
|
||||
|
||||
_NOTE_NSECONDS :: 0x00000003
|
||||
_NOTE_USECONDS :: 0x00000002
|
||||
_NOTE_NSECONDS :: 0x00000004
|
||||
_NOTE_ABSOLUTE :: 0x00000010
|
||||
|
||||
_TIMER_FLAGS_NSECONDS :: Timer_Flags{Timer_Flag(log2(_NOTE_NSECONDS))}
|
||||
|
||||
KEvent :: struct #align(4) {
|
||||
// Value used to identify this event. The exact interpretation is determined by the attached filter.
|
||||
ident: uintptr,
|
||||
@@ -232,11 +262,12 @@ when ODIN_OS == .Darwin {
|
||||
flags: Flags,
|
||||
// Filter specific flags.
|
||||
fflags: struct #raw_union {
|
||||
rw: RW_Flags,
|
||||
vnode: VNode_Flags,
|
||||
fproc: Proc_Flags,
|
||||
rw: RW_Flags `raw_union_tag:"filter=.Read, filter=.Write"`,
|
||||
vnode: VNode_Flags `raw_union_tag:"filter=.VNode"`,
|
||||
fproc: Proc_Flags `raw_union_tag:"filter=.Proc"`,
|
||||
// vm: VM_Flags,
|
||||
timer: Timer_Flags,
|
||||
timer: Timer_Flags `raw_union_tag:"filter=.Timer"`,
|
||||
user: User_Flags `raw_union_tag:"filter=.User"`,
|
||||
},
|
||||
// Filter specific data.
|
||||
data: i64,
|
||||
@@ -245,12 +276,20 @@ when ODIN_OS == .Darwin {
|
||||
}
|
||||
}
|
||||
|
||||
when ODIN_OS == .NetBSD {
|
||||
@(private)
|
||||
LKEVENT :: "__kevent50"
|
||||
} else {
|
||||
@(private)
|
||||
LKEVENT :: "kevent"
|
||||
}
|
||||
|
||||
@(private)
|
||||
log2 :: intrinsics.constant_log2
|
||||
|
||||
foreign lib {
|
||||
@(link_name="kqueue")
|
||||
_kqueue :: proc() -> KQ ---
|
||||
@(link_name="kevent")
|
||||
@(link_name=LKEVENT)
|
||||
_kevent :: proc(kq: KQ, change_list: [^]KEvent, n_changes: c.int, event_list: [^]KEvent, n_events: c.int, timeout: ^posix.timespec) -> c.int ---
|
||||
}
|
||||
|
||||
@@ -45,6 +45,7 @@ download_assets :: proc "contextless" () {
|
||||
@(require) import "sync"
|
||||
@(require) import "sync/chan"
|
||||
@(require) import "sys/posix"
|
||||
@(require) import "sys/kqueue"
|
||||
@(require) import "sys/windows"
|
||||
@(require) import "text/i18n"
|
||||
@(require) import "text/match"
|
||||
|
||||
56
tests/core/sys/kqueue/structs.odin
Normal file
56
tests/core/sys/kqueue/structs.odin
Normal file
@@ -0,0 +1,56 @@
|
||||
#+build darwin, freebsd, openbsd, netbsd
|
||||
package tests_core_sys_kqueue
|
||||
|
||||
import "core:strings"
|
||||
import "core:testing"
|
||||
import os "core:os/os2"
|
||||
|
||||
@(test)
|
||||
structs :: proc(t: ^testing.T) {
|
||||
{
|
||||
c_compiler := os.get_env("CC", context.temp_allocator)
|
||||
if c_compiler == "" {
|
||||
c_compiler = "clang"
|
||||
}
|
||||
|
||||
c_compilation, c_start_err := os.process_start({
|
||||
command = {c_compiler, #directory + "/structs/structs.c", "-o", #directory + "/structs/c_structs"},
|
||||
stdout = os.stdout,
|
||||
stderr = os.stderr,
|
||||
})
|
||||
testing.expect_value(t, c_start_err, nil)
|
||||
|
||||
o_compilation, o_start_err := os.process_start({
|
||||
command = {ODIN_ROOT + "/odin", "build", #directory + "/structs", "-out:" + #directory + "/structs/odin_structs"},
|
||||
stdout = os.stdout,
|
||||
stderr = os.stderr,
|
||||
})
|
||||
testing.expect_value(t, o_start_err, nil)
|
||||
|
||||
c_status, c_err := os.process_wait(c_compilation)
|
||||
testing.expect_value(t, c_err, nil)
|
||||
testing.expect_value(t, c_status.exit_code, 0)
|
||||
|
||||
o_status, o_err := os.process_wait(o_compilation)
|
||||
testing.expect_value(t, o_err, nil)
|
||||
testing.expect_value(t, o_status.exit_code, 0)
|
||||
}
|
||||
|
||||
c_status, c_stdout, c_stderr, c_err := os.process_exec({command={#directory + "/structs/c_structs"}}, context.temp_allocator)
|
||||
testing.expect_value(t, c_err, nil)
|
||||
testing.expect_value(t, c_status.exit_code, 0)
|
||||
testing.expect_value(t, string(c_stderr), "")
|
||||
|
||||
o_status, o_stdout, o_stderr, o_err := os.process_exec({command={#directory + "/structs/odin_structs"}}, context.temp_allocator)
|
||||
testing.expect_value(t, o_err, nil)
|
||||
testing.expect_value(t, o_status.exit_code, 0)
|
||||
testing.expect_value(t, string(o_stderr), "")
|
||||
|
||||
testing.expect(t, strings.trim_space(string(c_stdout)) != "")
|
||||
|
||||
testing.expect_value(
|
||||
t,
|
||||
strings.trim_space(string(o_stdout)),
|
||||
strings.trim_space(string(c_stdout)),
|
||||
)
|
||||
}
|
||||
63
tests/core/sys/kqueue/structs/structs.c
Normal file
63
tests/core/sys/kqueue/structs/structs.c
Normal file
@@ -0,0 +1,63 @@
|
||||
#include <stddef.h>
|
||||
#include <stdio.h>
|
||||
#include <sys/event.h>
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
printf("kevent %zu %zu\n", sizeof(struct kevent), _Alignof(struct kevent));
|
||||
printf("kevent.ident %zu\n", offsetof(struct kevent, ident));
|
||||
printf("kevent.filter %zu\n", offsetof(struct kevent, filter));
|
||||
printf("kevent.flags %zu\n", offsetof(struct kevent, flags));
|
||||
printf("kevent.fflags %zu\n", offsetof(struct kevent, fflags));
|
||||
printf("kevent.data %zu\n", offsetof(struct kevent, data));
|
||||
printf("kevent.udata %zu\n", offsetof(struct kevent, udata));
|
||||
|
||||
printf("EV_ADD %d\n", EV_ADD);
|
||||
printf("EV_DELETE %d\n", EV_DELETE);
|
||||
printf("EV_ENABLE %d\n", EV_ENABLE);
|
||||
printf("EV_DISABLE %d\n", EV_DISABLE);
|
||||
printf("EV_ONESHOT %d\n", EV_ONESHOT);
|
||||
printf("EV_CLEAR %d\n", EV_CLEAR);
|
||||
printf("EV_RECEIPT %d\n", EV_RECEIPT);
|
||||
printf("EV_DISPATCH %d\n", EV_DISPATCH);
|
||||
printf("EV_ERROR %d\n", EV_ERROR);
|
||||
printf("EV_EOF %d\n", EV_EOF);
|
||||
|
||||
printf("EVFILT_READ %d\n", EVFILT_READ);
|
||||
printf("EVFILT_WRITE %d\n", EVFILT_WRITE);
|
||||
printf("EVFILT_AIO %d\n", EVFILT_AIO);
|
||||
printf("EVFILT_VNODE %d\n", EVFILT_VNODE);
|
||||
printf("EVFILT_PROC %d\n", EVFILT_PROC);
|
||||
printf("EVFILT_SIGNAL %d\n", EVFILT_SIGNAL);
|
||||
printf("EVFILT_TIMER %d\n", EVFILT_TIMER);
|
||||
printf("EVFILT_USER %d\n", EVFILT_USER);
|
||||
|
||||
printf("NOTE_SECONDS %u\n", NOTE_SECONDS);
|
||||
printf("NOTE_USECONDS %u\n", NOTE_USECONDS);
|
||||
printf("NOTE_NSECONDS %u\n", NOTE_NSECONDS);
|
||||
#if defined(NOTE_ABSOLUTE)
|
||||
printf("NOTE_ABSOLUTE %u\n", NOTE_ABSOLUTE);
|
||||
#else
|
||||
printf("NOTE_ABSOLUTE %u\n", NOTE_ABSTIME);
|
||||
#endif
|
||||
|
||||
printf("NOTE_LOWAT %u\n", NOTE_LOWAT);
|
||||
|
||||
printf("NOTE_DELETE %u\n", NOTE_DELETE);
|
||||
printf("NOTE_WRITE %u\n", NOTE_WRITE);
|
||||
printf("NOTE_EXTEND %u\n", NOTE_EXTEND);
|
||||
printf("NOTE_ATTRIB %u\n", NOTE_ATTRIB);
|
||||
printf("NOTE_LINK %u\n", NOTE_LINK);
|
||||
printf("NOTE_RENAME %u\n", NOTE_RENAME);
|
||||
printf("NOTE_REVOKE %u\n", NOTE_REVOKE);
|
||||
|
||||
printf("NOTE_EXIT %u\n", NOTE_EXIT);
|
||||
printf("NOTE_FORK %u\n", NOTE_FORK);
|
||||
printf("NOTE_EXEC %u\n", NOTE_EXEC);
|
||||
|
||||
printf("NOTE_TRIGGER %u\n", NOTE_TRIGGER);
|
||||
printf("NOTE_FFAND %u\n", NOTE_FFAND);
|
||||
printf("NOTE_FFOR %u\n", NOTE_FFOR);
|
||||
printf("NOTE_FFCOPY %u\n", NOTE_FFCOPY);
|
||||
return 0;
|
||||
}
|
||||
58
tests/core/sys/kqueue/structs/structs.odin
Normal file
58
tests/core/sys/kqueue/structs/structs.odin
Normal file
@@ -0,0 +1,58 @@
|
||||
package main
|
||||
|
||||
import "core:fmt"
|
||||
import "core:sys/kqueue"
|
||||
|
||||
main :: proc() {
|
||||
fmt.println("kevent", size_of(kqueue.KEvent), align_of(kqueue.KEvent))
|
||||
fmt.println("kevent.ident", offset_of(kqueue.KEvent, ident))
|
||||
fmt.println("kevent.filter", offset_of(kqueue.KEvent, filter))
|
||||
fmt.println("kevent.flags", offset_of(kqueue.KEvent, flags))
|
||||
fmt.println("kevent.fflags", offset_of(kqueue.KEvent, fflags))
|
||||
fmt.println("kevent.data", offset_of(kqueue.KEvent, data))
|
||||
fmt.println("kevent.udata", offset_of(kqueue.KEvent, udata))
|
||||
|
||||
fmt.println("EV_ADD", transmute(kqueue._Flags_Backing)kqueue.Flags{.Add})
|
||||
fmt.println("EV_DELETE", transmute(kqueue._Flags_Backing)kqueue.Flags{.Delete})
|
||||
fmt.println("EV_ENABLE", transmute(kqueue._Flags_Backing)kqueue.Flags{.Enable})
|
||||
fmt.println("EV_DISABLE", transmute(kqueue._Flags_Backing)kqueue.Flags{.Disable})
|
||||
fmt.println("EV_ONESHOT", transmute(kqueue._Flags_Backing)kqueue.Flags{.One_Shot})
|
||||
fmt.println("EV_CLEAR", transmute(kqueue._Flags_Backing)kqueue.Flags{.Clear})
|
||||
fmt.println("EV_RECEIPT", transmute(kqueue._Flags_Backing)kqueue.Flags{.Receipt})
|
||||
fmt.println("EV_DISPATCH", transmute(kqueue._Flags_Backing)kqueue.Flags{.Dispatch})
|
||||
fmt.println("EV_ERROR", transmute(kqueue._Flags_Backing)kqueue.Flags{.Error})
|
||||
fmt.println("EV_EOF", transmute(kqueue._Flags_Backing)kqueue.Flags{.EOF})
|
||||
|
||||
fmt.println("EVFILT_READ", int(kqueue.Filter.Read))
|
||||
fmt.println("EVFILT_WRITE", int(kqueue.Filter.Write))
|
||||
fmt.println("EVFILT_AIO", int(kqueue.Filter.AIO))
|
||||
fmt.println("EVFILT_VNODE", int(kqueue.Filter.VNode))
|
||||
fmt.println("EVFILT_PROC", int(kqueue.Filter.Proc))
|
||||
fmt.println("EVFILT_SIGNAL", int(kqueue.Filter.Signal))
|
||||
fmt.println("EVFILT_TIMER", int(kqueue.Filter.Timer))
|
||||
fmt.println("EVFILT_USER", int(kqueue.Filter.User))
|
||||
|
||||
fmt.println("NOTE_SECONDS", transmute(u32)kqueue.Timer_Flags{.Seconds})
|
||||
fmt.println("NOTE_USECONDS", transmute(u32)kqueue.Timer_Flags{.USeconds})
|
||||
fmt.println("NOTE_NSECONDS", transmute(u32)kqueue.TIMER_FLAGS_NSECONDS)
|
||||
fmt.println("NOTE_ABSOLUTE", transmute(u32)kqueue.Timer_Flags{.Absolute})
|
||||
|
||||
fmt.println("NOTE_LOWAT", transmute(u32)kqueue.RW_Flags{.Low_Water_Mark})
|
||||
|
||||
fmt.println("NOTE_DELETE", transmute(u32)kqueue.VNode_Flags{.Delete})
|
||||
fmt.println("NOTE_WRITE", transmute(u32)kqueue.VNode_Flags{.Write})
|
||||
fmt.println("NOTE_EXTEND", transmute(u32)kqueue.VNode_Flags{.Extend})
|
||||
fmt.println("NOTE_ATTRIB", transmute(u32)kqueue.VNode_Flags{.Attrib})
|
||||
fmt.println("NOTE_LINK", transmute(u32)kqueue.VNode_Flags{.Link})
|
||||
fmt.println("NOTE_RENAME", transmute(u32)kqueue.VNode_Flags{.Rename})
|
||||
fmt.println("NOTE_REVOKE", transmute(u32)kqueue.VNode_Flags{.Revoke})
|
||||
|
||||
fmt.println("NOTE_EXIT", transmute(u32)kqueue.Proc_Flags{.Exit})
|
||||
fmt.println("NOTE_FORK", transmute(u32)kqueue.Proc_Flags{.Fork})
|
||||
fmt.println("NOTE_EXEC", transmute(u32)kqueue.Proc_Flags{.Exec})
|
||||
|
||||
fmt.println("NOTE_TRIGGER", transmute(u32)kqueue.User_Flags{.Trigger})
|
||||
fmt.println("NOTE_FFAND", transmute(u32)kqueue.User_Flags{.FFAnd})
|
||||
fmt.println("NOTE_FFOR", transmute(u32)kqueue.User_Flags{.FFOr})
|
||||
fmt.println("NOTE_FFCOPY", transmute(u32)kqueue.USER_FLAGS_COPY)
|
||||
}
|
||||
Reference in New Issue
Block a user