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