xref: /aosp_15_r20/external/crosvm/base/src/sys/macos/kqueue.rs (revision bb4ee6a4ae7042d18b07a98463b9c8b875e44b39)
1*bb4ee6a4SAndroid Build Coastguard Worker // Copyright 2024 The ChromiumOS Authors
2*bb4ee6a4SAndroid Build Coastguard Worker // Use of this source code is governed by a BSD-style license that can be
3*bb4ee6a4SAndroid Build Coastguard Worker // found in the LICENSE file.
4*bb4ee6a4SAndroid Build Coastguard Worker 
5*bb4ee6a4SAndroid Build Coastguard Worker use std::ptr;
6*bb4ee6a4SAndroid Build Coastguard Worker use std::time::Duration;
7*bb4ee6a4SAndroid Build Coastguard Worker 
8*bb4ee6a4SAndroid Build Coastguard Worker use crate::descriptor::AsRawDescriptor;
9*bb4ee6a4SAndroid Build Coastguard Worker use crate::descriptor::FromRawDescriptor;
10*bb4ee6a4SAndroid Build Coastguard Worker use crate::errno::errno_result;
11*bb4ee6a4SAndroid Build Coastguard Worker use crate::errno::Error;
12*bb4ee6a4SAndroid Build Coastguard Worker use crate::errno::Result;
13*bb4ee6a4SAndroid Build Coastguard Worker use crate::sys::unix::RawDescriptor;
14*bb4ee6a4SAndroid Build Coastguard Worker use crate::unix::duration_to_timespec;
15*bb4ee6a4SAndroid Build Coastguard Worker use crate::unix::set_descriptor_cloexec;
16*bb4ee6a4SAndroid Build Coastguard Worker use crate::SafeDescriptor;
17*bb4ee6a4SAndroid Build Coastguard Worker 
18*bb4ee6a4SAndroid Build Coastguard Worker #[derive(Debug, PartialEq, Eq, serde::Serialize, serde::Deserialize)]
19*bb4ee6a4SAndroid Build Coastguard Worker pub(in crate::sys::macos) struct Kqueue {
20*bb4ee6a4SAndroid Build Coastguard Worker     queue: SafeDescriptor,
21*bb4ee6a4SAndroid Build Coastguard Worker }
22*bb4ee6a4SAndroid Build Coastguard Worker 
23*bb4ee6a4SAndroid Build Coastguard Worker // Only accepts the subset of parameters we actually use
make_kevent(filter: i16, flags: u16, fflags: u32) -> libc::kevent64_s24*bb4ee6a4SAndroid Build Coastguard Worker pub(in crate::sys::macos) fn make_kevent(filter: i16, flags: u16, fflags: u32) -> libc::kevent64_s {
25*bb4ee6a4SAndroid Build Coastguard Worker     libc::kevent64_s {
26*bb4ee6a4SAndroid Build Coastguard Worker         ident: 0, /* hopefully not global? */
27*bb4ee6a4SAndroid Build Coastguard Worker         filter,
28*bb4ee6a4SAndroid Build Coastguard Worker         flags,
29*bb4ee6a4SAndroid Build Coastguard Worker         fflags,
30*bb4ee6a4SAndroid Build Coastguard Worker         data: 0,
31*bb4ee6a4SAndroid Build Coastguard Worker         udata: 0,
32*bb4ee6a4SAndroid Build Coastguard Worker         ext: [0, 0],
33*bb4ee6a4SAndroid Build Coastguard Worker     }
34*bb4ee6a4SAndroid Build Coastguard Worker }
35*bb4ee6a4SAndroid Build Coastguard Worker 
36*bb4ee6a4SAndroid Build Coastguard Worker impl Kqueue {
new() -> Result<Kqueue>37*bb4ee6a4SAndroid Build Coastguard Worker     pub(in crate::sys::macos) fn new() -> Result<Kqueue> {
38*bb4ee6a4SAndroid Build Coastguard Worker         // SAFETY: Trivially safe
39*bb4ee6a4SAndroid Build Coastguard Worker         let raw_queue = unsafe { libc::kqueue() };
40*bb4ee6a4SAndroid Build Coastguard Worker         if raw_queue < 0 {
41*bb4ee6a4SAndroid Build Coastguard Worker             return crate::errno::errno_result();
42*bb4ee6a4SAndroid Build Coastguard Worker         }
43*bb4ee6a4SAndroid Build Coastguard Worker         // SAFETY: Tested whether it was a valid file descriptor
44*bb4ee6a4SAndroid Build Coastguard Worker         let queue = unsafe { SafeDescriptor::from_raw_descriptor(raw_queue) };
45*bb4ee6a4SAndroid Build Coastguard Worker         set_descriptor_cloexec(&queue)?;
46*bb4ee6a4SAndroid Build Coastguard Worker         Ok(Kqueue { queue })
47*bb4ee6a4SAndroid Build Coastguard Worker     }
48*bb4ee6a4SAndroid Build Coastguard Worker 
kevent<'a>( &self, changelist: &[libc::kevent64_s], eventlist: &'a mut [libc::kevent64_s], timeout: Option<Duration>, ) -> Result<&'a mut [libc::kevent64_s]>49*bb4ee6a4SAndroid Build Coastguard Worker     pub(in crate::sys::macos) fn kevent<'a>(
50*bb4ee6a4SAndroid Build Coastguard Worker         &self,
51*bb4ee6a4SAndroid Build Coastguard Worker         changelist: &[libc::kevent64_s],
52*bb4ee6a4SAndroid Build Coastguard Worker         eventlist: &'a mut [libc::kevent64_s],
53*bb4ee6a4SAndroid Build Coastguard Worker         timeout: Option<Duration>,
54*bb4ee6a4SAndroid Build Coastguard Worker     ) -> Result<&'a mut [libc::kevent64_s]> {
55*bb4ee6a4SAndroid Build Coastguard Worker         let timespec = timeout.map(duration_to_timespec);
56*bb4ee6a4SAndroid Build Coastguard Worker         // SAFETY: `queue` is a valid kqueue, `changelist` and `eventlist` are supplied with lengths
57*bb4ee6a4SAndroid Build Coastguard Worker         // based on valid slices
58*bb4ee6a4SAndroid Build Coastguard Worker         let res = unsafe {
59*bb4ee6a4SAndroid Build Coastguard Worker             libc::kevent64(
60*bb4ee6a4SAndroid Build Coastguard Worker                 self.queue.as_raw_descriptor(),
61*bb4ee6a4SAndroid Build Coastguard Worker                 changelist.as_ptr(),
62*bb4ee6a4SAndroid Build Coastguard Worker                 changelist.len() as i32,
63*bb4ee6a4SAndroid Build Coastguard Worker                 eventlist.as_mut_ptr(),
64*bb4ee6a4SAndroid Build Coastguard Worker                 eventlist.len() as i32,
65*bb4ee6a4SAndroid Build Coastguard Worker                 0,
66*bb4ee6a4SAndroid Build Coastguard Worker                 if let Some(timeout) = timespec {
67*bb4ee6a4SAndroid Build Coastguard Worker                     &timeout
68*bb4ee6a4SAndroid Build Coastguard Worker                 } else {
69*bb4ee6a4SAndroid Build Coastguard Worker                     ptr::null()
70*bb4ee6a4SAndroid Build Coastguard Worker                 },
71*bb4ee6a4SAndroid Build Coastguard Worker             )
72*bb4ee6a4SAndroid Build Coastguard Worker         };
73*bb4ee6a4SAndroid Build Coastguard Worker         if res < 0 {
74*bb4ee6a4SAndroid Build Coastguard Worker             return errno_result();
75*bb4ee6a4SAndroid Build Coastguard Worker         }
76*bb4ee6a4SAndroid Build Coastguard Worker         let returned_events = eventlist.split_at_mut(res as usize).0;
77*bb4ee6a4SAndroid Build Coastguard Worker         for event in returned_events.iter() {
78*bb4ee6a4SAndroid Build Coastguard Worker             if event.flags & libc::EV_ERROR != 0 {
79*bb4ee6a4SAndroid Build Coastguard Worker                 return Err(Error::new(event.data));
80*bb4ee6a4SAndroid Build Coastguard Worker             }
81*bb4ee6a4SAndroid Build Coastguard Worker         }
82*bb4ee6a4SAndroid Build Coastguard Worker         Ok(returned_events)
83*bb4ee6a4SAndroid Build Coastguard Worker     }
84*bb4ee6a4SAndroid Build Coastguard Worker 
try_clone(&self) -> Result<Kqueue>85*bb4ee6a4SAndroid Build Coastguard Worker     pub(in crate::sys::macos) fn try_clone(&self) -> Result<Kqueue> {
86*bb4ee6a4SAndroid Build Coastguard Worker         self.queue.try_clone().map(|queue| Kqueue { queue })
87*bb4ee6a4SAndroid Build Coastguard Worker     }
88*bb4ee6a4SAndroid Build Coastguard Worker }
89*bb4ee6a4SAndroid Build Coastguard Worker 
90*bb4ee6a4SAndroid Build Coastguard Worker impl crate::AsRawDescriptor for Kqueue {
as_raw_descriptor(&self) -> RawDescriptor91*bb4ee6a4SAndroid Build Coastguard Worker     fn as_raw_descriptor(&self) -> RawDescriptor {
92*bb4ee6a4SAndroid Build Coastguard Worker         self.queue.as_raw_descriptor()
93*bb4ee6a4SAndroid Build Coastguard Worker     }
94*bb4ee6a4SAndroid Build Coastguard Worker }
95*bb4ee6a4SAndroid Build Coastguard Worker 
96*bb4ee6a4SAndroid Build Coastguard Worker impl crate::FromRawDescriptor for Kqueue {
from_raw_descriptor(descriptor: RawDescriptor) -> Self97*bb4ee6a4SAndroid Build Coastguard Worker     unsafe fn from_raw_descriptor(descriptor: RawDescriptor) -> Self {
98*bb4ee6a4SAndroid Build Coastguard Worker         Kqueue {
99*bb4ee6a4SAndroid Build Coastguard Worker             queue: SafeDescriptor::from_raw_descriptor(descriptor),
100*bb4ee6a4SAndroid Build Coastguard Worker         }
101*bb4ee6a4SAndroid Build Coastguard Worker     }
102*bb4ee6a4SAndroid Build Coastguard Worker }
103*bb4ee6a4SAndroid Build Coastguard Worker 
104*bb4ee6a4SAndroid Build Coastguard Worker impl crate::IntoRawDescriptor for Kqueue {
into_raw_descriptor(self) -> RawDescriptor105*bb4ee6a4SAndroid Build Coastguard Worker     fn into_raw_descriptor(self) -> RawDescriptor {
106*bb4ee6a4SAndroid Build Coastguard Worker         self.queue.into_raw_descriptor()
107*bb4ee6a4SAndroid Build Coastguard Worker     }
108*bb4ee6a4SAndroid Build Coastguard Worker }
109*bb4ee6a4SAndroid Build Coastguard Worker 
110*bb4ee6a4SAndroid Build Coastguard Worker impl From<Kqueue> for crate::SafeDescriptor {
from(queue: Kqueue) -> Self111*bb4ee6a4SAndroid Build Coastguard Worker     fn from(queue: Kqueue) -> Self {
112*bb4ee6a4SAndroid Build Coastguard Worker         queue.queue
113*bb4ee6a4SAndroid Build Coastguard Worker     }
114*bb4ee6a4SAndroid Build Coastguard Worker }
115*bb4ee6a4SAndroid Build Coastguard Worker 
116*bb4ee6a4SAndroid Build Coastguard Worker impl From<SafeDescriptor> for Kqueue {
from(queue: SafeDescriptor) -> Self117*bb4ee6a4SAndroid Build Coastguard Worker     fn from(queue: SafeDescriptor) -> Self {
118*bb4ee6a4SAndroid Build Coastguard Worker         Kqueue { queue }
119*bb4ee6a4SAndroid Build Coastguard Worker     }
120*bb4ee6a4SAndroid Build Coastguard Worker }
121