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