Skip to content

Commit

Permalink
WIP: use Events type for kevent()
Browse files Browse the repository at this point in the history
  • Loading branch information
yorickpeterse committed Apr 5, 2024
1 parent bc88181 commit 022a8f4
Show file tree
Hide file tree
Showing 2 changed files with 49 additions and 9 deletions.
8 changes: 4 additions & 4 deletions examples/kq.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ fn main() -> std::io::Result<()> {
use rustix::{fd::AsRawFd, fs};

let kq = kqueue()?;
let mut out = Vec::with_capacity(10);
let mut buf: Events<10> = Events::new();

#[cfg(feature = "fs")]
let dir = fs::openat(
Expand Down Expand Up @@ -59,10 +59,11 @@ fn main() -> std::io::Result<()> {
eprintln!("Run with --features process to enable more!");
#[cfg(not(feature = "fs"))]
eprintln!("Run with --features fs to enable more!");
unsafe { kevent(&kq, &subs, &mut out, None) }?;

loop {
while let Some(e) = out.pop() {
let events = unsafe { kevent(&kq, &subs, &mut buf, None) }?;

for e in events {
match e.filter() {
#[cfg(feature = "process")]
EventFilter::Signal { signal, times } => {
Expand All @@ -79,7 +80,6 @@ fn main() -> std::io::Result<()> {
_ => eprintln!("Unknown event"),
}
}
unsafe { kevent(&kq, &[], &mut out, None) }?;
}
}

Expand Down
50 changes: 45 additions & 5 deletions src/event/kqueue.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ use backend::event::syscalls;

use alloc::vec::Vec;
use core::mem::{zeroed, MaybeUninit};
use core::slice::from_raw_parts;
use core::ptr::slice_from_raw_parts_mut;
use core::time::Duration;

/// A `kqueue` event for use with [`kevent`].
Expand Down Expand Up @@ -155,6 +155,39 @@ impl Event {
}
}

impl Default for Event {
fn default() -> Self {
Event {
inner: kevent_t {
..unsafe { zeroed() }
},
}
}
}

/// A buffer for storing [`Event`] values _produced_ by the [`kevent`] function.
pub struct Events<const N: usize> {
inner: [Event; N],
}

impl<const N: usize> Events<N> {
/// Returns a new buffer with enough space for `N` events.
///
/// # Examples
///
/// ```no_run
/// use rustix::event::kqueue::Events;
///
/// // Create a buffer that can hold up to 10 events.
/// let events: Events<10> = Events::new();
/// ```
pub fn new() -> Events<N> {
Events {
inner: [Event::default(); N],
}
}
}

/// Bottom 24 bits of a u32.
#[cfg(any(apple, freebsdlike))]
const EVFILT_USER_FLAGS: u32 = 0x00ff_ffff;
Expand Down Expand Up @@ -421,16 +454,23 @@ pub fn kqueue() -> io::Result<OwnedFd> {
/// [DragonFly BSD]: https://man.dragonflybsd.org/?command=kevent&section=2
pub unsafe fn kevent<'a, const N: usize>(
kqueue: impl AsFd,
changes: &[Event],
changelist: &[Event],
eventlist: &'a mut Events<N>,
timeout: Option<Duration>,
) -> io::Result<&'a [Event]> {
let timeout = timeout.map(|timeout| backend::c::timespec {
tv_sec: timeout.as_secs() as _,
tv_nsec: timeout.subsec_nanos() as _,
});

let mut out_slice: [MaybeUninit<Event>; N] = unsafe { MaybeUninit::uninit().assume_init() };
let out_slice =
slice_from_raw_parts_mut(eventlist.inner.as_mut_ptr().cast(), eventlist.inner.len());

syscalls::kevent(kqueue.as_fd(), changes, &mut out_slice, timeout.as_ref())
.map(|res| from_raw_parts(out_slice.as_ptr().cast(), res as usize))
syscalls::kevent(
kqueue.as_fd(),
changelist,
&mut *out_slice,
timeout.as_ref(),
)
.map(|res| &eventlist.inner[0..(res as usize)])
}

0 comments on commit 022a8f4

Please sign in to comment.