poll.rs 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338
  1. use core::ffi::c_int;
  2. use crate::{
  3. arch::ipc::signal::SigSet,
  4. filesystem::epoll::{event_poll::EventPoll, EPollCtlOption, EPollEvent, EPollEventType},
  5. ipc::signal::{
  6. restore_saved_sigmask_unless, set_user_sigmask, RestartBlock, RestartBlockData, RestartFn,
  7. },
  8. mm::VirtAddr,
  9. process::ProcessManager,
  10. syscall::{
  11. user_access::{UserBufferReader, UserBufferWriter},
  12. Syscall,
  13. },
  14. time::{Duration, Instant, PosixTimeSpec},
  15. };
  16. use super::vfs::file::{File, FileMode};
  17. use alloc::sync::Arc;
  18. use system_error::SystemError;
  19. #[repr(C)]
  20. #[derive(Debug)]
  21. pub struct PollFd {
  22. pub fd: c_int,
  23. pub events: u16,
  24. pub revents: u16,
  25. }
  26. struct PollAdapter<'a> {
  27. ep_file: Arc<File>,
  28. poll_fds: &'a mut [PollFd],
  29. }
  30. impl<'a> PollAdapter<'a> {
  31. pub fn new(ep_file: Arc<File>, poll_fds: &'a mut [PollFd]) -> Self {
  32. Self { ep_file, poll_fds }
  33. }
  34. fn add_pollfds(&self) -> Result<(), SystemError> {
  35. for (i, pollfd) in self.poll_fds.iter().enumerate() {
  36. if pollfd.fd < 0 {
  37. continue;
  38. }
  39. let mut epoll_event = EPollEvent::default();
  40. let poll_flags = PollFlags::from_bits_truncate(pollfd.events);
  41. let ep_events: EPollEventType = poll_flags.into();
  42. epoll_event.set_events(ep_events.bits());
  43. epoll_event.set_data(i as u64);
  44. EventPoll::epoll_ctl_with_epfile(
  45. self.ep_file.clone(),
  46. EPollCtlOption::Add,
  47. pollfd.fd,
  48. epoll_event,
  49. false,
  50. )
  51. .map(|_| ())?;
  52. }
  53. Ok(())
  54. }
  55. fn poll_all_fds(&mut self, timeout: Option<Instant>) -> Result<usize, SystemError> {
  56. let mut epoll_events = vec![EPollEvent::default(); self.poll_fds.len()];
  57. let len = epoll_events.len() as i32;
  58. let remain_timeout = timeout.map(|t| {
  59. t.duration_since(Instant::now())
  60. .unwrap_or(Duration::ZERO)
  61. .into()
  62. });
  63. let events = EventPoll::epoll_wait_with_file(
  64. self.ep_file.clone(),
  65. &mut epoll_events,
  66. len,
  67. remain_timeout,
  68. )?;
  69. for event in epoll_events.iter() {
  70. let index = event.data() as usize;
  71. if index >= self.poll_fds.len() {
  72. log::warn!("poll_all_fds: Invalid index in epoll event: {}", index);
  73. continue;
  74. }
  75. self.poll_fds[index].revents = (event.events() & 0xffff) as u16;
  76. }
  77. Ok(events)
  78. }
  79. }
  80. impl Syscall {
  81. /// https://code.dragonos.org.cn/xref/linux-6.6.21/fs/select.c#1068
  82. #[inline(never)]
  83. pub fn poll(pollfd_ptr: usize, nfds: u32, timeout_ms: i32) -> Result<usize, SystemError> {
  84. let pollfd_ptr = VirtAddr::new(pollfd_ptr);
  85. let len = nfds as usize * core::mem::size_of::<PollFd>();
  86. let mut timeout: Option<Instant> = None;
  87. if timeout_ms >= 0 {
  88. timeout = poll_select_set_timeout(timeout_ms as u64);
  89. }
  90. let mut poll_fds_writer = UserBufferWriter::new(pollfd_ptr.as_ptr::<PollFd>(), len, true)?;
  91. let mut r = do_sys_poll(poll_fds_writer.buffer(0)?, timeout);
  92. if let Err(SystemError::ERESTARTNOHAND) = r {
  93. let restart_block_data = RestartBlockData::new_poll(pollfd_ptr, nfds, timeout);
  94. let restart_block = RestartBlock::new(&RestartFnPoll, restart_block_data);
  95. r = ProcessManager::current_pcb().set_restart_fn(Some(restart_block));
  96. }
  97. return r;
  98. }
  99. /// 参考 https://code.dragonos.org.cn/xref/linux-6.1.9/fs/select.c#1101
  100. #[inline(never)]
  101. pub fn ppoll(
  102. pollfd_ptr: usize,
  103. nfds: u32,
  104. timespec_ptr: usize,
  105. sigmask_ptr: usize,
  106. ) -> Result<usize, SystemError> {
  107. let mut timeout_ts: Option<Instant> = None;
  108. let mut sigmask: Option<SigSet> = None;
  109. let pollfd_ptr = VirtAddr::new(pollfd_ptr);
  110. let pollfds_len = nfds as usize * core::mem::size_of::<PollFd>();
  111. let mut poll_fds_writer =
  112. UserBufferWriter::new(pollfd_ptr.as_ptr::<PollFd>(), pollfds_len, true)?;
  113. let poll_fds = poll_fds_writer.buffer(0)?;
  114. if sigmask_ptr != 0 {
  115. let sigmask_reader =
  116. UserBufferReader::new(sigmask_ptr as *const SigSet, size_of::<SigSet>(), true)?;
  117. sigmask = Some(*sigmask_reader.read_one_from_user(0)?);
  118. }
  119. if timespec_ptr != 0 {
  120. let tsreader = UserBufferReader::new(
  121. timespec_ptr as *const PosixTimeSpec,
  122. size_of::<PosixTimeSpec>(),
  123. true,
  124. )?;
  125. let ts: PosixTimeSpec = *tsreader.read_one_from_user(0)?;
  126. let timeout_ms = ts.tv_sec * 1000 + ts.tv_nsec / 1_000_000;
  127. if timeout_ms >= 0 {
  128. timeout_ts =
  129. Some(poll_select_set_timeout(timeout_ms as u64).ok_or(SystemError::EINVAL)?);
  130. }
  131. }
  132. if let Some(mut sigmask) = sigmask {
  133. set_user_sigmask(&mut sigmask);
  134. }
  135. // log::debug!(
  136. // "ppoll: poll_fds: {:?}, nfds: {}, timeout_ts: {:?},sigmask: {:?}",
  137. // poll_fds,
  138. // nfds,
  139. // timeout_ts,
  140. // sigmask
  141. // );
  142. let r: Result<usize, SystemError> = do_sys_poll(poll_fds, timeout_ts);
  143. return poll_select_finish(timeout_ts, timespec_ptr, PollTimeType::TimeSpec, r);
  144. }
  145. }
  146. pub fn do_sys_poll(
  147. poll_fds: &mut [PollFd],
  148. timeout: Option<Instant>,
  149. ) -> Result<usize, SystemError> {
  150. let ep_file = EventPoll::create_epoll_file(FileMode::empty())?;
  151. let ep_file = Arc::new(ep_file);
  152. let mut adapter = PollAdapter::new(ep_file, poll_fds);
  153. adapter.add_pollfds()?;
  154. let nevents = adapter.poll_all_fds(timeout)?;
  155. Ok(nevents)
  156. }
  157. /// 计算超时的时刻
  158. pub fn poll_select_set_timeout(timeout_ms: u64) -> Option<Instant> {
  159. Some(Instant::now() + Duration::from_millis(timeout_ms))
  160. }
  161. /// 参考 https://code.dragonos.org.cn/xref/linux-6.1.9/fs/select.c#298
  162. fn poll_select_finish(
  163. end_time: Option<Instant>,
  164. user_time_ptr: usize,
  165. poll_time_type: PollTimeType,
  166. mut result: Result<usize, SystemError>,
  167. ) -> Result<usize, SystemError> {
  168. restore_saved_sigmask_unless(result == Err(SystemError::ERESTARTNOHAND));
  169. if user_time_ptr == 0 {
  170. return result;
  171. }
  172. // todo: 处理sticky timeouts
  173. if end_time.is_none() {
  174. return result;
  175. }
  176. let end_time = end_time.unwrap();
  177. // no update for zero timeout
  178. if end_time.total_millis() <= 0 {
  179. return result;
  180. }
  181. let ts = Instant::now();
  182. let duration = end_time.saturating_sub(ts);
  183. let rts: PosixTimeSpec = duration.into();
  184. match poll_time_type {
  185. PollTimeType::TimeSpec => {
  186. let mut tswriter = UserBufferWriter::new(
  187. user_time_ptr as *mut PosixTimeSpec,
  188. size_of::<PosixTimeSpec>(),
  189. true,
  190. )?;
  191. if tswriter.copy_one_to_user(&rts, 0).is_err() {
  192. return result;
  193. }
  194. }
  195. _ => todo!(),
  196. }
  197. if result == Err(SystemError::ERESTARTNOHAND) {
  198. result = result.map_err(|_| SystemError::EINTR);
  199. }
  200. return result;
  201. }
  202. #[allow(unused)]
  203. #[derive(Debug, Clone, Copy, PartialEq, Eq)]
  204. enum PollTimeType {
  205. TimeVal,
  206. OldTimeVal,
  207. TimeSpec,
  208. OldTimeSpec,
  209. }
  210. bitflags! {
  211. pub struct PollFlags: u16 {
  212. const POLLIN = 0x0001;
  213. const POLLPRI = 0x0002;
  214. const POLLOUT = 0x0004;
  215. const POLLERR = 0x0008;
  216. const POLLHUP = 0x0010;
  217. const POLLNVAL = 0x0020;
  218. const POLLRDNORM = 0x0040;
  219. const POLLRDBAND = 0x0080;
  220. const POLLWRNORM = 0x0100;
  221. const POLLWRBAND = 0x0200;
  222. const POLLMSG = 0x0400;
  223. const POLLREMOVE = 0x1000;
  224. const POLLRDHUP = 0x2000;
  225. const POLLFREE = 0x4000;
  226. const POLL_BUSY_LOOP = 0x8000;
  227. }
  228. }
  229. impl From<PollFlags> for EPollEventType {
  230. fn from(val: PollFlags) -> Self {
  231. let mut epoll_flags = EPollEventType::empty();
  232. if val.contains(PollFlags::POLLIN) {
  233. epoll_flags |= EPollEventType::EPOLLIN;
  234. }
  235. if val.contains(PollFlags::POLLPRI) {
  236. epoll_flags |= EPollEventType::EPOLLPRI;
  237. }
  238. if val.contains(PollFlags::POLLOUT) {
  239. epoll_flags |= EPollEventType::EPOLLOUT;
  240. }
  241. if val.contains(PollFlags::POLLERR) {
  242. epoll_flags |= EPollEventType::EPOLLERR;
  243. }
  244. if val.contains(PollFlags::POLLHUP) {
  245. epoll_flags |= EPollEventType::EPOLLHUP;
  246. }
  247. if val.contains(PollFlags::POLLNVAL) {
  248. epoll_flags |= EPollEventType::EPOLLNVAL;
  249. }
  250. if val.contains(PollFlags::POLLRDNORM) {
  251. epoll_flags |= EPollEventType::EPOLLRDNORM;
  252. }
  253. if val.contains(PollFlags::POLLRDBAND) {
  254. epoll_flags |= EPollEventType::EPOLLRDBAND;
  255. }
  256. if val.contains(PollFlags::POLLWRNORM) {
  257. epoll_flags |= EPollEventType::EPOLLWRNORM;
  258. }
  259. if val.contains(PollFlags::POLLWRBAND) {
  260. epoll_flags |= EPollEventType::EPOLLWRBAND;
  261. }
  262. if val.contains(PollFlags::POLLMSG) {
  263. epoll_flags |= EPollEventType::EPOLLMSG;
  264. }
  265. if val.contains(PollFlags::POLLRDHUP) {
  266. epoll_flags |= EPollEventType::EPOLLRDHUP;
  267. }
  268. if val.contains(PollFlags::POLLFREE) {
  269. epoll_flags |= EPollEventType::POLLFREE;
  270. }
  271. epoll_flags
  272. }
  273. }
  274. /// sys_poll的restart fn
  275. #[derive(Debug)]
  276. struct RestartFnPoll;
  277. impl RestartFn for RestartFnPoll {
  278. // 参考 https://code.dragonos.org.cn/xref/linux-6.6.21/fs/select.c#1047
  279. fn call(&self, data: &mut RestartBlockData) -> Result<usize, SystemError> {
  280. if let RestartBlockData::Poll(d) = data {
  281. let len = d.nfds as usize * core::mem::size_of::<PollFd>();
  282. let mut poll_fds_writer =
  283. UserBufferWriter::new(d.pollfd_ptr.as_ptr::<PollFd>(), len, true)?;
  284. let mut r = do_sys_poll(poll_fds_writer.buffer(0)?, d.timeout_instant);
  285. if let Err(SystemError::ERESTARTNOHAND) = r {
  286. let restart_block = RestartBlock::new(&RestartFnPoll, data.clone());
  287. r = ProcessManager::current_pcb().set_restart_fn(Some(restart_block));
  288. }
  289. return r;
  290. } else {
  291. panic!("RestartFnPoll called with wrong data type: {:?}", data);
  292. }
  293. }
  294. }