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