1 //! libc syscalls supporting `rustix::event`.
2 
3 use crate::backend::c;
4 use crate::backend::conv::ret_c_int;
5 #[cfg(any(apple, netbsdlike, target_os = "dragonfly", target_os = "solaris"))]
6 use crate::backend::conv::ret_owned_fd;
7 use crate::event::PollFd;
8 #[cfg(any(linux_kernel, bsd, solarish, target_os = "espidf"))]
9 use crate::fd::OwnedFd;
10 use crate::io;
11 #[cfg(any(bsd, solarish))]
12 use {crate::backend::conv::borrowed_fd, crate::fd::BorrowedFd, core::mem::MaybeUninit};
13 #[cfg(solarish)]
14 use {
15     crate::backend::conv::ret, crate::event::port::Event, crate::utils::as_mut_ptr,
16     core::ptr::null_mut,
17 };
18 #[cfg(any(
19     linux_kernel,
20     target_os = "freebsd",
21     target_os = "illumos",
22     target_os = "espidf"
23 ))]
24 use {crate::backend::conv::ret_owned_fd, crate::event::EventfdFlags};
25 #[cfg(all(feature = "alloc", bsd))]
26 use {crate::event::kqueue::Event, crate::utils::as_ptr, core::ptr::null};
27 
28 #[cfg(any(
29     linux_kernel,
30     target_os = "freebsd",
31     target_os = "illumos",
32     target_os = "espidf"
33 ))]
eventfd(initval: u32, flags: EventfdFlags) -> io::Result<OwnedFd>34 pub(crate) fn eventfd(initval: u32, flags: EventfdFlags) -> io::Result<OwnedFd> {
35     #[cfg(linux_kernel)]
36     unsafe {
37         syscall! {
38             fn eventfd2(
39                 initval: c::c_uint,
40                 flags: c::c_int
41             ) via SYS_eventfd2 -> c::c_int
42         }
43         ret_owned_fd(eventfd2(initval, bitflags_bits!(flags)))
44     }
45 
46     // `eventfd` was added in FreeBSD 13, so it isn't available on FreeBSD 12.
47     #[cfg(target_os = "freebsd")]
48     unsafe {
49         weakcall! {
50             fn eventfd(
51                 initval: c::c_uint,
52                 flags: c::c_int
53             ) -> c::c_int
54         }
55         ret_owned_fd(eventfd(initval, bitflags_bits!(flags)))
56     }
57 
58     #[cfg(any(target_os = "illumos", target_os = "espidf"))]
59     unsafe {
60         ret_owned_fd(c::eventfd(initval, bitflags_bits!(flags)))
61     }
62 }
63 
64 #[cfg(all(feature = "alloc", bsd))]
kqueue() -> io::Result<OwnedFd>65 pub(crate) fn kqueue() -> io::Result<OwnedFd> {
66     unsafe { ret_owned_fd(c::kqueue()) }
67 }
68 
69 #[cfg(all(feature = "alloc", bsd))]
kevent( kq: BorrowedFd<'_>, changelist: &[Event], eventlist: &mut [MaybeUninit<Event>], timeout: Option<&c::timespec>, ) -> io::Result<c::c_int>70 pub(crate) unsafe fn kevent(
71     kq: BorrowedFd<'_>,
72     changelist: &[Event],
73     eventlist: &mut [MaybeUninit<Event>],
74     timeout: Option<&c::timespec>,
75 ) -> io::Result<c::c_int> {
76     ret_c_int(c::kevent(
77         borrowed_fd(kq),
78         changelist.as_ptr().cast(),
79         changelist
80             .len()
81             .try_into()
82             .map_err(|_| io::Errno::OVERFLOW)?,
83         eventlist.as_mut_ptr().cast(),
84         eventlist
85             .len()
86             .try_into()
87             .map_err(|_| io::Errno::OVERFLOW)?,
88         timeout.map_or(null(), as_ptr),
89     ))
90 }
91 
92 #[inline]
poll(fds: &mut [PollFd<'_>], timeout: c::c_int) -> io::Result<usize>93 pub(crate) fn poll(fds: &mut [PollFd<'_>], timeout: c::c_int) -> io::Result<usize> {
94     let nfds = fds
95         .len()
96         .try_into()
97         .map_err(|_convert_err| io::Errno::INVAL)?;
98 
99     ret_c_int(unsafe { c::poll(fds.as_mut_ptr().cast(), nfds, timeout) })
100         .map(|nready| nready as usize)
101 }
102 
103 #[cfg(solarish)]
port_create() -> io::Result<OwnedFd>104 pub(crate) fn port_create() -> io::Result<OwnedFd> {
105     unsafe { ret_owned_fd(c::port_create()) }
106 }
107 
108 #[cfg(solarish)]
port_associate( port: BorrowedFd<'_>, source: c::c_int, object: c::uintptr_t, events: c::c_int, user: *mut c::c_void, ) -> io::Result<()>109 pub(crate) unsafe fn port_associate(
110     port: BorrowedFd<'_>,
111     source: c::c_int,
112     object: c::uintptr_t,
113     events: c::c_int,
114     user: *mut c::c_void,
115 ) -> io::Result<()> {
116     ret(c::port_associate(
117         borrowed_fd(port),
118         source,
119         object,
120         events,
121         user,
122     ))
123 }
124 
125 #[cfg(solarish)]
port_dissociate( port: BorrowedFd<'_>, source: c::c_int, object: c::uintptr_t, ) -> io::Result<()>126 pub(crate) unsafe fn port_dissociate(
127     port: BorrowedFd<'_>,
128     source: c::c_int,
129     object: c::uintptr_t,
130 ) -> io::Result<()> {
131     ret(c::port_dissociate(borrowed_fd(port), source, object))
132 }
133 
134 #[cfg(solarish)]
port_get( port: BorrowedFd<'_>, timeout: Option<&mut c::timespec>, ) -> io::Result<Event>135 pub(crate) fn port_get(
136     port: BorrowedFd<'_>,
137     timeout: Option<&mut c::timespec>,
138 ) -> io::Result<Event> {
139     let mut event = MaybeUninit::<c::port_event>::uninit();
140     let timeout = timeout.map_or(null_mut(), as_mut_ptr);
141 
142     unsafe {
143         ret(c::port_get(borrowed_fd(port), event.as_mut_ptr(), timeout))?;
144     }
145 
146     // If we're done, initialize the event and return it.
147     Ok(Event(unsafe { event.assume_init() }))
148 }
149 
150 #[cfg(all(feature = "alloc", solarish))]
port_getn( port: BorrowedFd<'_>, timeout: Option<&mut c::timespec>, events: &mut Vec<Event>, mut nget: u32, ) -> io::Result<()>151 pub(crate) fn port_getn(
152     port: BorrowedFd<'_>,
153     timeout: Option<&mut c::timespec>,
154     events: &mut Vec<Event>,
155     mut nget: u32,
156 ) -> io::Result<()> {
157     let timeout = timeout.map_or(null_mut(), as_mut_ptr);
158     unsafe {
159         ret(c::port_getn(
160             borrowed_fd(port),
161             events.as_mut_ptr().cast(),
162             events.len().try_into().unwrap(),
163             &mut nget,
164             timeout,
165         ))?;
166     }
167 
168     // Update the vector length.
169     unsafe {
170         events.set_len(nget.try_into().unwrap());
171     }
172 
173     Ok(())
174 }
175 
176 #[cfg(solarish)]
port_send( port: BorrowedFd<'_>, events: c::c_int, userdata: *mut c::c_void, ) -> io::Result<()>177 pub(crate) fn port_send(
178     port: BorrowedFd<'_>,
179     events: c::c_int,
180     userdata: *mut c::c_void,
181 ) -> io::Result<()> {
182     unsafe { ret(c::port_send(borrowed_fd(port), events, userdata)) }
183 }
184 
185 #[cfg(not(any(windows, target_os = "redox", target_os = "wasi")))]
pause()186 pub(crate) fn pause() {
187     let r = unsafe { libc::pause() };
188     let errno = libc_errno::errno().0;
189     debug_assert_eq!(r, -1);
190     debug_assert_eq!(errno, libc::EINTR);
191 }
192