1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
//! # KEvent
//! Generates kevent syscalls from a tasks functionality
use libc::c_void;
use std::{mem, ptr, time::Duration};
use crate::{constants::KEVENT_COUNT, modules::event_desc::EventDesc};
/// Generates kevent syscalls and passes back their ID
pub(crate) struct KEvent;
impl KEvent {
/// Registers a new `kevent` with the kernel
#[inline(always)]
pub(crate) unsafe fn register(
id: i32,
kevent_id: usize,
data: libc::intptr_t,
udata: *mut c_void,
desc: EventDesc,
) -> i32 {
let event_c = create(kevent_id, data, udata, desc);
unsafe {
libc::kevent(
id, // kqueue id
&event_c, // Events to register
1, // Number of events to register
ptr::null_mut(),
0,
ptr::null(),
)
}
}
/// Waits for events, giving up after `timeout`
///
/// ## Returns
/// How many events landed, or zero if the time ran out
#[inline(always)]
pub(crate) unsafe fn listen_for(
id: i32,
event_list: &mut [libc::kevent; KEVENT_COUNT],
timeout: Duration,
) -> i32 {
let spec = libc::timespec {
tv_sec: timeout.as_secs().min(libc::time_t::MAX as u64) as libc::time_t,
tv_nsec: timeout.subsec_nanos() as libc::c_long,
};
unsafe {
libc::kevent(
id,
ptr::null(),
0,
event_list.as_mut_ptr(),
event_list.len() as i32,
&spec,
)
}
}
#[inline(always)]
pub(crate) unsafe fn listen(id: i32, event_list: &mut [libc::kevent; KEVENT_COUNT]) -> i32 {
unsafe {
libc::kevent(
id,
ptr::null(),
0,
event_list.as_mut_ptr(),
event_list.len() as i32,
ptr::null(),
)
}
}
}
/// Creates the eventlist at compile time
#[inline(always)]
pub(crate) const fn eventlist() -> [libc::kevent; KEVENT_COUNT] {
unsafe { mem::zeroed() }
}
/// Creates a `kevent`
///
/// `data` is whatever the filter takes, such as a timer's
/// duration
#[inline(always)]
fn create(id: usize, data: libc::intptr_t, udata: *mut c_void, desc: EventDesc) -> libc::kevent {
libc::kevent {
ident: id, // Timer id, is unique across threads so it's fine
filter: desc.filter,
flags: desc.flags,
fflags: desc.fflags,
data, // The sleep duration in ns
udata, // Thread handle as *mut c_void
}
}