14fda81ceSLoGin use core::hint::spin_loop; 2bacd691cSlogin 3bacd691cSlogin use alloc::{boxed::Box, sync::Arc}; 4*91e9d4abSLoGin use system_error::SystemError; 5bacd691cSlogin 6bacd691cSlogin use crate::{ 74fda81ceSLoGin arch::{sched::sched, CurrentIrqArch, CurrentTimeArch}, 8ab5c8ca4Slogin exception::InterruptArch, 9ab5c8ca4Slogin include::bindings::bindings::{useconds_t, Cpu_tsc_freq}, 101496ba7bSLoGin process::ProcessManager, 118612b6ceSLoGin time::timekeeping::getnstimeofday, 12bacd691cSlogin }; 13bacd691cSlogin 14bacd691cSlogin use super::{ 15bacd691cSlogin timer::{next_n_us_timer_jiffies, Timer, WakeUpHelper}, 164fda81ceSLoGin TimeArch, TimeSpec, 17bacd691cSlogin }; 18bacd691cSlogin 19bacd691cSlogin /// @brief 休眠指定时间(单位:纳秒) 20bacd691cSlogin /// 21bacd691cSlogin /// @param sleep_time 指定休眠的时间 22bacd691cSlogin /// 23bacd691cSlogin /// @return Ok(TimeSpec) 剩余休眠时间 24bacd691cSlogin /// 25bacd691cSlogin /// @return Err(SystemError) 错误码 26ab5c8ca4Slogin pub fn nanosleep(sleep_time: TimeSpec) -> Result<TimeSpec, SystemError> { 27bacd691cSlogin if sleep_time.tv_nsec < 0 || sleep_time.tv_nsec >= 1000000000 { 28bacd691cSlogin return Err(SystemError::EINVAL); 29bacd691cSlogin } 30bacd691cSlogin // 对于小于500us的时间,使用spin/rdtsc来进行定时 318612b6ceSLoGin if sleep_time.tv_nsec < 500000 && sleep_time.tv_sec == 0 { 324fda81ceSLoGin let expired_tsc: u64 = unsafe { 334fda81ceSLoGin CurrentTimeArch::get_cycles() as u64 344fda81ceSLoGin + (sleep_time.tv_nsec as u64 * Cpu_tsc_freq) / 1000000000 354fda81ceSLoGin }; 364fda81ceSLoGin while (CurrentTimeArch::get_cycles() as u64) < expired_tsc { 37bacd691cSlogin spin_loop() 38bacd691cSlogin } 39bacd691cSlogin return Ok(TimeSpec { 40bacd691cSlogin tv_sec: 0, 41bacd691cSlogin tv_nsec: 0, 42bacd691cSlogin }); 43bacd691cSlogin } 448612b6ceSLoGin 458612b6ceSLoGin let total_sleep_time_us: u64 = 468612b6ceSLoGin sleep_time.tv_sec as u64 * 1000000 + sleep_time.tv_nsec as u64 / 1000; 47bacd691cSlogin // 创建定时器 481496ba7bSLoGin let handler: Box<WakeUpHelper> = WakeUpHelper::new(ProcessManager::current_pcb()); 498612b6ceSLoGin let timer: Arc<Timer> = Timer::new(handler, next_n_us_timer_jiffies(total_sleep_time_us)); 50bacd691cSlogin 51ab5c8ca4Slogin let irq_guard: crate::exception::IrqFlagsGuard = 52ab5c8ca4Slogin unsafe { CurrentIrqArch::save_and_disable_irq() }; 531496ba7bSLoGin ProcessManager::mark_sleep(true).ok(); 548612b6ceSLoGin 558612b6ceSLoGin let start_time = getnstimeofday(); 56bacd691cSlogin timer.activate(); 571496ba7bSLoGin 58ab5c8ca4Slogin drop(irq_guard); 59bacd691cSlogin sched(); 60bacd691cSlogin 618612b6ceSLoGin let end_time = getnstimeofday(); 628612b6ceSLoGin // 返回正确的剩余时间 638612b6ceSLoGin let real_sleep_time = end_time - start_time; 648612b6ceSLoGin let rm_time: TimeSpec = (sleep_time - real_sleep_time.into()).into(); 65bacd691cSlogin 668612b6ceSLoGin return Ok(rm_time); 67bacd691cSlogin } 68bacd691cSlogin 69bacd691cSlogin /// @brief 休眠指定时间(单位:微秒) 70bacd691cSlogin /// 71bacd691cSlogin /// @param usec 微秒 72bacd691cSlogin /// 73bacd691cSlogin /// @return Ok(TimeSpec) 剩余休眠时间 74bacd691cSlogin /// 75bacd691cSlogin /// @return Err(SystemError) 错误码 76ab5c8ca4Slogin pub fn usleep(sleep_time: TimeSpec) -> Result<TimeSpec, SystemError> { 77ab5c8ca4Slogin match nanosleep(sleep_time) { 78bacd691cSlogin Ok(value) => return Ok(value), 79bacd691cSlogin Err(err) => return Err(err), 80bacd691cSlogin }; 81bacd691cSlogin } 82bacd691cSlogin 83bacd691cSlogin //===== 以下为提供给C的接口 ===== 84bacd691cSlogin 85bacd691cSlogin /// @brief 休眠指定时间(单位:微秒)(提供给C的接口) 86bacd691cSlogin /// 87bacd691cSlogin /// @param usec 微秒 88bacd691cSlogin /// 89bacd691cSlogin /// @return Ok(i32) 0 90bacd691cSlogin /// 91bacd691cSlogin /// @return Err(SystemError) 错误码 92bacd691cSlogin #[no_mangle] 93bacd691cSlogin pub extern "C" fn rs_usleep(usec: useconds_t) -> i32 { 94bacd691cSlogin let sleep_time = TimeSpec { 95bacd691cSlogin tv_sec: (usec / 1000000) as i64, 96bacd691cSlogin tv_nsec: ((usec % 1000000) * 1000) as i64, 97bacd691cSlogin }; 98ab5c8ca4Slogin match usleep(sleep_time) { 99bacd691cSlogin Ok(_) => { 100bacd691cSlogin return 0; 101bacd691cSlogin } 102bacd691cSlogin Err(err) => { 103bacd691cSlogin return err.to_posix_errno(); 104bacd691cSlogin } 105bacd691cSlogin }; 106bacd691cSlogin } 107