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