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