Skip to main content

relibc/header/sys_epoll/
mod.rs

1//! `sys/epoll.h` implementation.
2//!
3//! Non-POSIX, see <http://man7.org/linux/man-pages/man7/epoll.7.html>.
4
5use core::ptr;
6
7use crate::{
8    error::ResultExt,
9    header::bits_sigset_t::sigset_t,
10    platform::{
11        PalEpoll, Sys,
12        types::{c_int, c_uint, c_ulonglong, c_void},
13    },
14};
15
16/// Set the close-on-exec (`FD_CLOEXEC`) flag on the new file descriptor.
17#[cfg(target_os = "linux")]
18pub const EPOLL_CLOEXEC: c_int = 0x8_0000;
19
20/// Set the close-on-exec (`FD_CLOEXEC`) flag on the new file descriptor.
21#[cfg(target_os = "redox")]
22pub const EPOLL_CLOEXEC: c_int = 0x0100_0000;
23
24/// The associated file is available for read operations.
25pub const EPOLLIN: c_uint = 0x001;
26/// There is an exceptional condition on the file descriptor.
27pub const EPOLLPRI: c_uint = 0x002;
28/// The associated file is available for write operations.
29pub const EPOLLOUT: c_uint = 0x004;
30/// Error condition happened on the associated file descriptor.
31pub const EPOLLERR: c_uint = 0x008;
32/// Hang up happened onthe associated file descriptor.
33pub const EPOLLHUP: c_uint = 0x010;
34pub const EPOLLNVAL: c_uint = 0x020;
35pub const EPOLLRDNORM: c_uint = 0x040;
36pub const EPOLLRDBAND: c_uint = 0x080;
37pub const EPOLLWRNORM: c_uint = 0x100;
38pub const EPOLLWRBAND: c_uint = 0x200;
39pub const EPOLLMSG: c_uint = 0x400;
40/// Stream socket peer closed connection, or shut down writing half of
41/// connection.
42pub const EPOLLRDHUP: c_uint = 0x2000;
43/// Sets an exclusive wakeup mode for the epoll file descriptor that is being
44/// attached to the target file descriptor, `fd`.
45pub const EPOLLEXCLUSIVE: c_uint = 1 << 28;
46/// If `EPOLLONESHOT` and `EPOLLET` are clear and the process has the
47/// `CAP_BLOCK_SUSPEND` capability, ensure that the system does not enter
48/// "suspend" or "hibernate" while this event is pending or being processed.
49pub const EPOLLWAKEUP: c_uint = 1 << 29;
50/// Requests one-shot notification for the associated file descriptor.
51pub const EPOLLONESHOT: c_uint = 1 << 30;
52/// Requests edge-triggered notification for the associated file descriptor.
53pub const EPOLLET: c_uint = 1 << 31;
54
55/// Add an entry to the interest list of the epoll file descriptor, `epfd`.
56pub const EPOLL_CTL_ADD: c_int = 1;
57/// Remove (deregister) the target file descriptor `fd` from the interest list.
58pub const EPOLL_CTL_DEL: c_int = 2;
59/// Change the settings associated with `fd` in the interest list to the new
60/// settings specified in `event`.
61pub const EPOLL_CTL_MOD: c_int = 3;
62
63/// Non-POSIX, see <https://man7.org/linux/man-pages/man3/epoll_event.3type.html>.
64#[repr(C)]
65#[derive(Clone, Copy)]
66pub union epoll_data {
67    pub ptr: *mut c_void,
68    pub fd: c_int,
69    pub u32: c_uint,
70    pub u64: c_ulonglong,
71}
72impl Default for epoll_data {
73    fn default() -> Self {
74        Self { u64: 0 }
75    }
76}
77
78/// Non-POSIX, see <https://man7.org/linux/man-pages/man3/epoll_event.3type.html>.
79///
80/// Specifies data that the kernel should save and return when the
81/// corresponding file descriptor becomes ready.
82#[cfg(all(target_os = "redox", target_pointer_width = "64"))]
83#[repr(C)]
84#[derive(Clone, Copy, Default)]
85// This will match in size with syscall::Event (24 bytes on 64-bit
86// systems) on redox. The `Default` trait is here so we don't need to
87// worry about the padding when using this type.
88pub struct epoll_event {
89    /// Epoll events.
90    pub events: c_uint, // 4 bytes
91    // 4 automatic alignment bytes
92    /// User data variable.
93    pub data: epoll_data, // 8 bytes
94
95    pub _pad: c_ulonglong, // 8 bytes
96}
97
98/// Non-POSIX, see <https://man7.org/linux/man-pages/man3/epoll_event.3type.html>.
99///
100/// Specifies data that the kernel should save and return when the
101/// corresponding file descriptor becomes ready.
102#[cfg(not(all(target_os = "redox", target_pointer_width = "64")))]
103#[repr(C)]
104#[derive(Clone, Copy, Default)]
105pub struct epoll_event {
106    /// Epoll events.
107    pub events: c_uint,
108    /// User data variable.
109    pub data: epoll_data,
110}
111
112/// Non-POSIX, see <https://man7.org/linux/man-pages/man2/epoll_create.2.html>.
113///
114/// Creates a file descriptor referring to the new epoll instance.
115///
116/// Upon success, returns a file descriptor (a nonnegative integer). Upon
117/// error, `-1` is returned and errno set to indicate the error.
118///
119/// # Implementation
120/// The `_size` parameter is deliberately unused as it is no longer required.
121/// This function simply calls `epoll_create1`.
122#[unsafe(no_mangle)]
123pub extern "C" fn epoll_create(_size: c_int) -> c_int {
124    epoll_create1(0)
125}
126
127/// Non-POSIX, see <https://man7.org/linux/man-pages/man2/epoll_create1.2.html>.
128///
129/// Creates a file descriptor referring to the new epoll instance.
130///
131/// Upon success, returns a file descriptor (a nonnegative integer). Upon
132/// error, `-1` is returned and errno set to indicate the error.
133#[unsafe(no_mangle)]
134pub extern "C" fn epoll_create1(flags: c_int) -> c_int {
135    trace_expr!(
136        Sys::epoll_create1(flags).or_minus_one_errno(),
137        "epoll_create1({:#x})",
138        flags
139    )
140}
141
142/// Non-POSIX, see <https://man7.org/linux/man-pages/man2/epoll_ctl.2.html>.
143///
144/// Add, modify, or remove entries in the interest list of the epoll instance
145/// referred to by the file descriptor `epfd`.
146///
147/// Upon success, returns `0`. Upon error, returns `-1` and sets errno to
148/// indicate the error.
149#[unsafe(no_mangle)]
150pub unsafe extern "C" fn epoll_ctl(
151    epfd: c_int,
152    op: c_int,
153    fd: c_int,
154    event: *mut epoll_event,
155) -> c_int {
156    trace_expr!(
157        unsafe { Sys::epoll_ctl(epfd, op, fd, event) }
158            .map(|()| 0)
159            .or_minus_one_errno(),
160        "epoll_ctl({}, {}, {}, {:p})",
161        epfd,
162        op,
163        fd,
164        event
165    )
166}
167
168/// Non-POSIX, see <https://man7.org/linux/man-pages/man2/epoll_wait.2.html>.
169///
170/// Waits for events on the epoll instance referred to by the file descriptor
171/// `epdf`.
172///
173/// `timeout` represents the number of milliseconds this function call will
174/// block.
175///
176/// Will block until either:
177/// - a file descriptor delivers an event
178/// - the call is interrupted by a signal handler
179/// - the `timeout` expires
180///
181/// A `timeout` of `-1` will block indefinitely. A `timeout` of `0` will return
182/// immediately, even if no events are available.
183///
184/// Upon success, returns the number of file descriptors ready for the
185/// requested I/O operation, or `0` if no file descriptor became ready during
186/// the requested `timeout`. Upon failure, returns `-1` and sets errno to
187/// indicate the error.
188#[unsafe(no_mangle)]
189pub unsafe extern "C" fn epoll_wait(
190    epfd: c_int,
191    events: *mut epoll_event,
192    maxevents: c_int,
193    timeout: c_int,
194) -> c_int {
195    unsafe { epoll_pwait(epfd, events, maxevents, timeout, ptr::null()) }
196}
197
198/// Non-POSIX, see <https://man7.org/linux/man-pages/man2/epoll_wait.2.html>.
199///
200/// Allows an application to safely wait until either a file descriptor becomes
201/// ready or a signal is caught.
202///
203/// If `sigmask` is NULL, calling this function is equivalent to
204/// `epoll_wait()`.
205///
206/// Upon success, returns the number of file descriptors ready for the
207/// requested I/O operation, or `0` if no file descriptor became ready during
208/// the requested `timeout`. Upon failure, returns `-1` and sets errno to
209/// indicate the error.
210#[unsafe(no_mangle)]
211pub unsafe extern "C" fn epoll_pwait(
212    epfd: c_int,
213    events: *mut epoll_event,
214    maxevents: c_int,
215    timeout: c_int,
216    sigmask: *const sigset_t,
217) -> c_int {
218    trace_expr!(
219        unsafe { Sys::epoll_pwait(epfd, events, maxevents, timeout, sigmask) }
220            .map(|e| e as c_int)
221            .or_minus_one_errno(),
222        "epoll_pwait({}, {:p}, {}, {}, {:p})",
223        epfd,
224        events,
225        maxevents,
226        timeout,
227        sigmask
228    )
229}