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