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