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