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