syscall.rs 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108
  1. use system_error::SystemError;
  2. use crate::{
  3. arch::ipc::signal::SigSet,
  4. filesystem::vfs::file::FileMode,
  5. ipc::signal::{restore_saved_sigmask, set_user_sigmask},
  6. mm::VirtAddr,
  7. syscall::{
  8. user_access::{UserBufferReader, UserBufferWriter},
  9. Syscall,
  10. },
  11. time::PosixTimeSpec,
  12. };
  13. use super::{EPollCtlOption, EPollEvent, EventPoll};
  14. impl Syscall {
  15. pub fn epoll_create(max_size: i32) -> Result<usize, SystemError> {
  16. if max_size < 0 {
  17. return Err(SystemError::EINVAL);
  18. }
  19. return EventPoll::create_epoll(FileMode::empty());
  20. }
  21. pub fn epoll_create1(flag: usize) -> Result<usize, SystemError> {
  22. let flags = FileMode::from_bits_truncate(flag as u32);
  23. let ret = EventPoll::create_epoll(flags);
  24. ret
  25. }
  26. pub fn epoll_wait(
  27. epfd: i32,
  28. events: VirtAddr,
  29. max_events: i32,
  30. timeout: i32,
  31. ) -> Result<usize, SystemError> {
  32. if max_events <= 0 || max_events as u32 > EventPoll::EP_MAX_EVENTS {
  33. return Err(SystemError::EINVAL);
  34. }
  35. let mut timespec = None;
  36. if timeout == 0 {
  37. timespec = Some(PosixTimeSpec::new(0, 0));
  38. }
  39. if timeout > 0 {
  40. let sec: i64 = timeout as i64 / 1000;
  41. let nsec: i64 = 1000000 * (timeout as i64 % 1000);
  42. timespec = Some(PosixTimeSpec::new(sec, nsec))
  43. }
  44. // 从用户传入的地址中拿到epoll_events
  45. let mut epds_writer = UserBufferWriter::new(
  46. events.as_ptr::<EPollEvent>(),
  47. max_events as usize * core::mem::size_of::<EPollEvent>(),
  48. true,
  49. )?;
  50. let epoll_events = epds_writer.buffer::<EPollEvent>(0)?;
  51. return EventPoll::epoll_wait(epfd, epoll_events, max_events, timespec);
  52. }
  53. pub fn epoll_ctl(epfd: i32, op: usize, fd: i32, event: VirtAddr) -> Result<usize, SystemError> {
  54. let op = EPollCtlOption::from_op_num(op)?;
  55. let mut epds = EPollEvent::default();
  56. if op != EPollCtlOption::Del {
  57. // 不为EpollCtlDel时不允许传入空指针
  58. if event.is_null() {
  59. return Err(SystemError::EFAULT);
  60. }
  61. // 还是一样的问题,C标准的epoll_event大小为12字节,而内核实现的epoll_event内存对齐后为16字节
  62. // 这样分别拷贝其实和整体拷贝差别不大,内核使用内存对其版本甚至可能提升性能
  63. let epds_reader = UserBufferReader::new(
  64. event.as_ptr::<EPollEvent>(),
  65. core::mem::size_of::<EPollEvent>(),
  66. true,
  67. )?;
  68. // 拷贝到内核
  69. epds_reader.copy_one_from_user(&mut epds, 0)?;
  70. }
  71. return EventPoll::epoll_ctl_with_epfd(epfd, op, fd, epds, false);
  72. }
  73. /// ## 在epoll_wait时屏蔽某些信号
  74. pub fn epoll_pwait(
  75. epfd: i32,
  76. epoll_event: VirtAddr,
  77. max_events: i32,
  78. timespec: i32,
  79. sigmask: &mut SigSet,
  80. ) -> Result<usize, SystemError> {
  81. // 设置屏蔽的信号
  82. set_user_sigmask(sigmask);
  83. let wait_ret = Self::epoll_wait(epfd, epoll_event, max_events, timespec);
  84. if wait_ret.is_err() && *wait_ret.as_ref().unwrap_err() != SystemError::EINTR {
  85. restore_saved_sigmask();
  86. }
  87. wait_ret
  88. }
  89. }