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