1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
/// Wait for an I/O event on an epoll file descriptor.
///
/// # Examples
///
/// ```
/// let epfd = unsafe { nc::epoll_create1(nc::EPOLL_CLOEXEC) };
/// assert!(epfd.is_ok());
/// let epfd = epfd.unwrap();
/// let mut fds: [i32; 2] = [0, 0];
/// let ret = unsafe { nc::pipe2(&mut fds, 0) };
/// assert!(ret.is_ok());
/// let mut event = nc::epoll_event_t::default();
/// event.events = nc::EPOLLIN | nc::EPOLLET;
/// event.data.fd = fds[0];
/// let ctl_ret = unsafe { nc::epoll_ctl(epfd, nc::EPOLL_CTL_ADD, fds[0], &mut event) };
/// assert!(ctl_ret.is_ok());
///
/// let msg = "Hello, Rust";
/// let ret = unsafe { nc::write(fds[1], msg.as_bytes()) };
/// assert!(ret.is_ok());
///
/// let mut events = [nc::epoll_event_t::default(); 4];
/// let timeout = 0;
/// let sigmask = nc::sigset_t::default();
/// let ret = unsafe {
/// nc::epoll_pwait2(
/// epfd,
/// &mut events,
/// None,
/// &sigmask,
/// )
/// };
/// assert!(ret.is_ok());
/// assert_eq!(ret, Ok(1));
///
/// for event in &events {
/// // Ready to read
/// if event.events == nc::EPOLLIN {
/// let ready_fd = unsafe { event.data.fd };
/// assert_eq!(ready_fd, fds[0]);
/// let mut buf = [0_u8; 64];
/// let ret = unsafe { nc::read(ready_fd, &mut buf) };
/// assert!(ret.is_ok());
/// let n_read = ret.unwrap() as usize;
/// assert_eq!(msg.as_bytes(), &buf[..n_read]);
/// }
/// }
///
/// let ret = unsafe { nc::close(fds[0]) };
/// assert!(ret.is_ok());
/// let ret = unsafe { nc::close(fds[1]) };
/// assert!(ret.is_ok());
/// let ret = unsafe { nc::close(epfd) };
/// assert!(ret.is_ok());
/// ```
pub unsafe fn epoll_pwait2(
epfd: i32,
events: &mut [epoll_event_t],
timeout: Option<×pec_t>,
sigmask: &sigset_t,
) -> Result<i32, Errno> {
let epfd = epfd as usize;
let events_ptr = events.as_mut_ptr() as usize;
let max_events = events.len();
let timeout_ptr = timeout.map_or(core::ptr::null::<timespec_t>() as usize, |timeout| {
timeout as *const timespec_t as usize
});
let sigmask_ptr = sigmask as *const sigset_t as usize;
let sigset_size = core::mem::size_of::<sigset_t>();
syscall6(
SYS_EPOLL_PWAIT2,
epfd,
events_ptr,
max_events,
timeout_ptr,
sigmask_ptr,
sigset_size,
)
.map(|ret| ret as i32)
}