1 //! poll implementation for Redox, following http://pubs.opengroup.org/onlinepubs/7908799/xsh/poll.h.html 2 3 use core::{mem, slice}; 4 5 use crate::unix::{ 6 fs::File, 7 header::sys_epoll::{ 8 epoll_ctl, epoll_data, epoll_event, epoll_wait, 9 EPOLL_CLOEXEC, EPOLL_CTL_ADD, 10 }, 11 }; 12 13 pub const POLLIN: ::c_short = 0x001; 14 pub const POLLPRI: ::c_short = 0x002; 15 pub const POLLOUT: ::c_short = 0x004; 16 pub const POLLERR: ::c_short = 0x008; 17 pub const POLLHUP: ::c_short = 0x010; 18 pub const POLLNVAL: ::c_short = 0x020; 19 pub const POLLRDNORM: ::c_short = 0x040; 20 pub const POLLRDBAND: ::c_short = 0x080; 21 pub const POLLWRNORM: ::c_short = 0x100; 22 pub const POLLWRBAND: ::c_short = 0x200; 23 24 pub type nfds_t = ::c_ulong; 25 26 #[repr(C)] 27 pub struct pollfd { 28 pub fd: ::c_int, 29 pub events: ::c_short, 30 pub revents: ::c_short, 31 } 32 33 pub fn poll_epoll(fds: &mut [pollfd], timeout: ::c_int) -> ::c_int { 34 let event_map = [ 35 (POLLIN, ::EPOLLIN), 36 (POLLPRI, ::EPOLLPRI), 37 (POLLOUT, ::EPOLLOUT), 38 (POLLERR, ::EPOLLERR), 39 (POLLHUP, ::EPOLLHUP), 40 (POLLNVAL, ::EPOLLNVAL), 41 (POLLRDNORM, ::EPOLLRDNORM), 42 (POLLWRNORM, ::EPOLLWRNORM), 43 (POLLRDBAND, ::EPOLLRDBAND), 44 (POLLWRBAND, ::EPOLLWRBAND), 45 ]; 46 47 let ep = { 48 let epfd = unsafe{::epoll_create1(EPOLL_CLOEXEC)}; 49 if epfd < 0 { 50 return -1; 51 } 52 File::new(epfd) 53 }; 54 55 for i in 0..fds.len() { 56 let mut pfd = &mut fds[i]; 57 58 let mut event = epoll_event { 59 events: 0, 60 data: epoll_data { u64: i as u64 }, 61 ..Default::default() 62 }; 63 64 for (p, ep) in event_map.iter() { 65 if pfd.events & p > 0 { 66 event.events |= ep; 67 } 68 } 69 70 pfd.revents = 0; 71 72 if unsafe{epoll_ctl(*ep, EPOLL_CTL_ADD, pfd.fd, &mut event)} < 0 { 73 return -1; 74 } 75 } 76 77 let mut events: [epoll_event; 32] = unsafe { mem::zeroed() }; 78 let res = epoll_wait(*ep, events.as_mut_ptr(), events.len() as ::c_int, timeout); 79 if res < 0 { 80 return -1; 81 } 82 83 for event in events.iter().take(res as usize) { 84 let pi = unsafe { event.data.u64 as usize }; 85 // TODO: Error status when fd does not match? 86 if let Some(pfd) = fds.get_mut(pi) { 87 for (p, ep) in event_map.iter() { 88 if event.events & ep > 0 { 89 pfd.revents |= p; 90 } 91 } 92 } 93 } 94 95 let mut count = 0; 96 for pfd in fds.iter() { 97 if pfd.revents > 0 { 98 count += 1; 99 } 100 } 101 count 102 } 103 104 #[no_mangle] 105 pub unsafe extern "C" fn poll(fds: *mut pollfd, nfds: nfds_t, timeout: ::c_int) -> ::c_int { 106 trace_expr!( 107 poll_epoll(slice::from_raw_parts_mut(fds, nfds as usize), timeout), 108 "poll({:p}, {}, {})", 109 fds, 110 nfds, 111 timeout 112 ) 113 } 114