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