@@ -14,14 +14,21 @@ use std::os::fd::{AsFd, BorrowedFd};
1414use std::os::unix::io::{AsRawFd, FromRawFd, OwnedFd};
1515use std::ptr;
1616
17- /// A kernel event queue. Used to notify a process of various asynchronous
18- /// events.
17+ /// An event for use with [`Kqueue::kevent`].
1918#[repr(C)]
2019#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
2120pub struct KEvent {
2221 kevent: libc::kevent,
2322}
2423
24+ /// An event for use with [`Kqueue::kevent64`].
25+ #[cfg(apple_targets)]
26+ #[repr(transparent)]
27+ #[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
28+ pub struct KEvent64 {
29+ kevent: libc::kevent64_s,
30+ }
31+
2532/// A kernel event queue.
2633///
2734/// Used by the kernel to notify the process of various types of asynchronous
@@ -89,6 +96,33 @@ impl Kqueue {
8996 };
9097 Errno::result(res).map(|r| r as usize)
9198 }
99+
100+ /// Like [`kevent`](Kqueue::kevent), but uses [`KEvent64`].
101+ #[cfg(apple_targets)]
102+ pub fn kevent64(
103+ &self,
104+ changelist: &[KEvent64],
105+ eventlist: &mut [KEvent64],
106+ flags: Kevent64Flags,
107+ timeout_opt: Option<timespec>,
108+ ) -> Result<usize> {
109+ let res = unsafe {
110+ libc::kevent64(
111+ self.0.as_raw_fd(),
112+ changelist.as_ptr().cast(),
113+ changelist.len() as c_int,
114+ eventlist.as_mut_ptr().cast(),
115+ eventlist.len() as c_int,
116+ flags.bits(),
117+ if let Some(ref timeout) = timeout_opt {
118+ timeout as *const timespec
119+ } else {
120+ ptr::null()
121+ },
122+ )
123+ };
124+ Errno::result(res).map(|r| r as usize)
125+ }
92126}
93127
94128#[cfg(target_os = "netbsd")]
@@ -328,6 +362,17 @@ libc_bitflags!(
328362 }
329363);
330364
365+ #[cfg(apple_targets)]
366+ libc_bitflags! {
367+ /// Flags for [`Kqueue::kevent64`].
368+ pub struct Kevent64Flags: libc::c_uint {
369+ /// Return immediately even if there are no events to return.
370+ KEVENT_FLAG_IMMEDIATE;
371+ /// Only return error events from the changelist.
372+ KEVENT_FLAG_ERROR_EVENTS;
373+ }
374+ }
375+
331376#[allow(missing_docs)]
332377#[deprecated(since = "0.27.0", note = "Use KEvent::new instead")]
333378pub fn kqueue() -> Result<Kqueue> {
@@ -401,6 +446,75 @@ impl KEvent {
401446 }
402447}
403448
449+ #[cfg(apple_targets)]
450+ const _: () = {
451+ fn _assert_send<T: Send>() {}
452+ fn _assert() {
453+ _assert_send::<KEvent64>();
454+ }
455+ };
456+
457+ #[cfg(apple_targets)]
458+ impl KEvent64 {
459+ /// Construct a new `KEvent64`.
460+ pub fn new(
461+ ident: u64,
462+ filter: EventFilter,
463+ flags: EvFlags,
464+ fflags: FilterFlag,
465+ data: i64,
466+ udata: u64,
467+ ext: [u64; 2],
468+ ) -> KEvent64 {
469+ KEvent64 {
470+ kevent: libc::kevent64_s {
471+ ident,
472+ filter: filter as type_of_event_filter,
473+ flags: flags.bits(),
474+ fflags: fflags.bits(),
475+ data,
476+ udata,
477+ ext,
478+ },
479+ }
480+ }
481+
482+ /// Value used to identify this event.
483+ pub fn ident(&self) -> u64 {
484+ self.kevent.ident
485+ }
486+
487+ /// Identifies the kernel filter used to process this event.
488+ pub fn filter(&self) -> Result<EventFilter> {
489+ self.kevent.filter.try_into()
490+ }
491+
492+ /// Event flags.
493+ pub fn flags(&self) -> EvFlags {
494+ EvFlags::from_bits_retain(self.kevent.flags)
495+ }
496+
497+ /// Filter-specific flags.
498+ pub fn fflags(&self) -> FilterFlag {
499+ FilterFlag::from_bits_retain(self.kevent.fflags)
500+ }
501+
502+ /// Filter-specific data value.
503+ pub fn data(&self) -> i64 {
504+ self.kevent.data
505+ }
506+
507+ /// Opaque user-defined value passed through the kernel unchanged.
508+ pub fn udata(&self) -> u64 {
509+ self.kevent.udata
510+ }
511+
512+ /// Filter-specific extension data.
513+ pub fn ext(&self) -> [u64; 2] {
514+ self.kevent.ext
515+ }
516+ }
517+
404518#[allow(missing_docs)]
405519#[deprecated(since = "0.27.0", note = "Use Kqueue::kevent instead")]
406520pub fn kevent(
0 commit comments