xref: /DragonOS/kernel/src/time/sleep.rs (revision c757940bd61b0125e037a59eb77565e42470201b)
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