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