2
0

mod.rs 2.9 KB

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