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