mod.rs 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213
  1. //! sys/select.h implementation
  2. use core::mem;
  3. use fs::File;
  4. use header::errno;
  5. use header::sys_epoll::{
  6. epoll_create1, EPOLL_CLOEXEC,
  7. epoll_ctl, EPOLL_CTL_ADD,
  8. epoll_wait,
  9. EPOLLIN, EPOLLOUT, EPOLLERR,
  10. epoll_data, epoll_event
  11. };
  12. use header::sys_time::timeval;
  13. use platform;
  14. use platform::types::*;
  15. // fd_set is also defined in C because cbindgen is incompatible with mem::size_of booo
  16. pub const FD_SETSIZE: usize = 1024;
  17. #[repr(C)]
  18. pub struct fd_set {
  19. pub fds_bits: [c_ulong; FD_SETSIZE / (8 * mem::size_of::<c_ulong>())],
  20. }
  21. impl fd_set {
  22. fn index(fd: c_int) -> usize {
  23. (fd as usize) / (8 * mem::size_of::<c_ulong>())
  24. }
  25. fn bitmask(fd: c_int) -> c_ulong {
  26. 1 << ((fd as usize) & (8 * mem::size_of::<c_ulong>() - 1)) as c_ulong
  27. }
  28. fn zero(&mut self) {
  29. for i in 0..self.fds_bits.len() {
  30. self.fds_bits[i] = 0;
  31. }
  32. }
  33. fn set(&mut self, fd: c_int) {
  34. self.fds_bits[Self::index(fd)] |= Self::bitmask(fd);
  35. }
  36. fn clr(&mut self, fd: c_int) {
  37. self.fds_bits[Self::index(fd)] &= !Self::bitmask(fd);
  38. }
  39. fn isset(&self, fd: c_int) -> bool {
  40. self.fds_bits[Self::index(fd)] & Self::bitmask(fd) > 0
  41. }
  42. }
  43. pub fn select_epoll(
  44. nfds: c_int,
  45. mut readfds: Option<&mut fd_set>,
  46. mut writefds: Option<&mut fd_set>,
  47. mut exceptfds: Option<&mut fd_set>,
  48. timeout: Option<&mut timeval>
  49. ) -> c_int {
  50. if nfds < 0 || nfds > FD_SETSIZE as i32 {
  51. unsafe { platform::errno = errno::EINVAL };
  52. return -1;
  53. };
  54. let ep = {
  55. let epfd = epoll_create1(EPOLL_CLOEXEC);
  56. if epfd < 0 {
  57. return -1;
  58. }
  59. File::new(epfd)
  60. };
  61. for fd in 0..nfds {
  62. if let Some(ref fd_set) = readfds {
  63. if fd_set.isset(fd) {
  64. let mut event = epoll_event {
  65. events: EPOLLIN,
  66. data: epoll_data {
  67. fd: fd,
  68. },
  69. };
  70. if epoll_ctl(*ep, EPOLL_CTL_ADD, fd, &mut event) < 0 {
  71. return -1;
  72. }
  73. }
  74. }
  75. if let Some(ref fd_set) = writefds {
  76. if fd_set.isset(fd) {
  77. let mut event = epoll_event {
  78. events: EPOLLOUT,
  79. data: epoll_data {
  80. fd: fd,
  81. },
  82. };
  83. if epoll_ctl(*ep, EPOLL_CTL_ADD, fd, &mut event) < 0 {
  84. return -1;
  85. }
  86. }
  87. }
  88. if let Some(ref fd_set) = exceptfds {
  89. if fd_set.isset(fd) {
  90. let mut event = epoll_event {
  91. events: EPOLLERR,
  92. data: epoll_data {
  93. fd: fd,
  94. },
  95. };
  96. if epoll_ctl(*ep, EPOLL_CTL_ADD, fd, &mut event) < 0 {
  97. return -1;
  98. }
  99. }
  100. }
  101. }
  102. let mut events: [epoll_event; 32] = unsafe { mem::zeroed() };
  103. let res = epoll_wait(
  104. *ep,
  105. events.as_mut_ptr(),
  106. events.len() as c_int,
  107. match timeout {
  108. Some(timeout) => {
  109. //TODO: Check for overflow
  110. ((timeout.tv_sec as c_int) * 1000) +
  111. ((timeout.tv_usec as c_int) / 1000)
  112. },
  113. None => -1
  114. }
  115. );
  116. if res < 0 {
  117. return -1;
  118. }
  119. if let Some(ref mut fd_set) = readfds {
  120. fd_set.zero();
  121. }
  122. if let Some(ref mut fd_set) = writefds {
  123. fd_set.zero();
  124. }
  125. if let Some(ref mut fd_set) = exceptfds {
  126. fd_set.zero();
  127. }
  128. let mut count = 0;
  129. for i in 0..res as usize {
  130. let event = &events[i];
  131. let fd = unsafe { event.data.fd };
  132. // TODO: Error status when fd does not match?
  133. if fd >= 0 && fd <= FD_SETSIZE as c_int {
  134. if event.events & EPOLLIN > 0 {
  135. if let Some(ref mut fd_set) = readfds {
  136. fd_set.set(fd);
  137. count += 1;
  138. }
  139. }
  140. if event.events & EPOLLOUT > 0 {
  141. if let Some(ref mut fd_set) = writefds {
  142. fd_set.set(fd);
  143. count += 1;
  144. }
  145. }
  146. if event.events & EPOLLERR > 0 {
  147. if let Some(ref mut fd_set) = exceptfds {
  148. fd_set.set(fd);
  149. count += 1;
  150. }
  151. }
  152. }
  153. }
  154. count
  155. }
  156. #[no_mangle]
  157. pub unsafe extern "C" fn select(
  158. nfds: c_int,
  159. readfds: *mut fd_set,
  160. writefds: *mut fd_set,
  161. exceptfds: *mut fd_set,
  162. timeout: *mut timeval,
  163. ) -> c_int {
  164. trace_expr!(
  165. select_epoll(
  166. nfds,
  167. if readfds.is_null() {
  168. None
  169. } else {
  170. Some(&mut *readfds)
  171. },
  172. if writefds.is_null() {
  173. None
  174. } else {
  175. Some(&mut *writefds)
  176. },
  177. if exceptfds.is_null() {
  178. None
  179. } else {
  180. Some(&mut *exceptfds)
  181. },
  182. if timeout.is_null() {
  183. None
  184. } else {
  185. Some(&mut *timeout)
  186. }
  187. ),
  188. "select({}, {:p}, {:p}, {:p}, {:p})",
  189. nfds,
  190. readfds,
  191. writefds,
  192. exceptfds,
  193. timeout
  194. )
  195. }