sleep.rs 3.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106
  1. use core::hint::spin_loop;
  2. use alloc::{boxed::Box, sync::Arc};
  3. use crate::{
  4. arch::{sched::sched, CurrentIrqArch, CurrentTimeArch},
  5. exception::InterruptArch,
  6. include::bindings::bindings::{useconds_t, Cpu_tsc_freq},
  7. process::ProcessManager,
  8. syscall::SystemError,
  9. time::timekeeping::getnstimeofday,
  10. };
  11. use super::{
  12. timer::{next_n_us_timer_jiffies, Timer, WakeUpHelper},
  13. TimeArch, TimeSpec,
  14. };
  15. /// @brief 休眠指定时间(单位:纳秒)
  16. ///
  17. /// @param sleep_time 指定休眠的时间
  18. ///
  19. /// @return Ok(TimeSpec) 剩余休眠时间
  20. ///
  21. /// @return Err(SystemError) 错误码
  22. pub fn nanosleep(sleep_time: TimeSpec) -> Result<TimeSpec, SystemError> {
  23. if sleep_time.tv_nsec < 0 || sleep_time.tv_nsec >= 1000000000 {
  24. return Err(SystemError::EINVAL);
  25. }
  26. // 对于小于500us的时间,使用spin/rdtsc来进行定时
  27. if sleep_time.tv_nsec < 500000 && sleep_time.tv_sec == 0 {
  28. let expired_tsc: u64 = unsafe {
  29. CurrentTimeArch::get_cycles() as u64
  30. + (sleep_time.tv_nsec as u64 * Cpu_tsc_freq) / 1000000000
  31. };
  32. while (CurrentTimeArch::get_cycles() as u64) < expired_tsc {
  33. spin_loop()
  34. }
  35. return Ok(TimeSpec {
  36. tv_sec: 0,
  37. tv_nsec: 0,
  38. });
  39. }
  40. let total_sleep_time_us: u64 =
  41. sleep_time.tv_sec as u64 * 1000000 + sleep_time.tv_nsec as u64 / 1000;
  42. // 创建定时器
  43. let handler: Box<WakeUpHelper> = WakeUpHelper::new(ProcessManager::current_pcb());
  44. let timer: Arc<Timer> = Timer::new(handler, next_n_us_timer_jiffies(total_sleep_time_us));
  45. let irq_guard: crate::exception::IrqFlagsGuard =
  46. unsafe { CurrentIrqArch::save_and_disable_irq() };
  47. ProcessManager::mark_sleep(true).ok();
  48. let start_time = getnstimeofday();
  49. timer.activate();
  50. drop(irq_guard);
  51. sched();
  52. let end_time = getnstimeofday();
  53. // 返回正确的剩余时间
  54. let real_sleep_time = end_time - start_time;
  55. let rm_time: TimeSpec = (sleep_time - real_sleep_time.into()).into();
  56. return Ok(rm_time);
  57. }
  58. /// @brief 休眠指定时间(单位:微秒)
  59. ///
  60. /// @param usec 微秒
  61. ///
  62. /// @return Ok(TimeSpec) 剩余休眠时间
  63. ///
  64. /// @return Err(SystemError) 错误码
  65. pub fn usleep(sleep_time: TimeSpec) -> Result<TimeSpec, SystemError> {
  66. match nanosleep(sleep_time) {
  67. Ok(value) => return Ok(value),
  68. Err(err) => return Err(err),
  69. };
  70. }
  71. //===== 以下为提供给C的接口 =====
  72. /// @brief 休眠指定时间(单位:微秒)(提供给C的接口)
  73. ///
  74. /// @param usec 微秒
  75. ///
  76. /// @return Ok(i32) 0
  77. ///
  78. /// @return Err(SystemError) 错误码
  79. #[no_mangle]
  80. pub extern "C" fn rs_usleep(usec: useconds_t) -> i32 {
  81. let sleep_time = TimeSpec {
  82. tv_sec: (usec / 1000000) as i64,
  83. tv_nsec: ((usec % 1000000) * 1000) as i64,
  84. };
  85. match usleep(sleep_time) {
  86. Ok(_) => {
  87. return 0;
  88. }
  89. Err(err) => {
  90. return err.to_posix_errno();
  91. }
  92. };
  93. }