xref: /DragonOS/kernel/src/time/sleep.rs (revision 83ed0ebc293d5a10245089f627f52770fd5b9dd4)
1 use core::hint::spin_loop;
2 
3 use alloc::{boxed::Box, sync::Arc};
4 
5 use crate::{
6     arch::{sched::sched, CurrentIrqArch, CurrentTimeArch},
7     exception::InterruptArch,
8     include::bindings::bindings::{useconds_t, Cpu_tsc_freq},
9     process::ProcessManager,
10     syscall::SystemError,
11 };
12 
13 use super::{
14     timer::{next_n_us_timer_jiffies, Timer, WakeUpHelper},
15     TimeArch, TimeSpec,
16 };
17 
18 /// @brief 休眠指定时间(单位:纳秒)
19 ///
20 /// @param sleep_time 指定休眠的时间
21 ///
22 /// @return Ok(TimeSpec) 剩余休眠时间
23 ///
24 /// @return Err(SystemError) 错误码
25 pub fn nanosleep(sleep_time: TimeSpec) -> Result<TimeSpec, SystemError> {
26     if sleep_time.tv_nsec < 0 || sleep_time.tv_nsec >= 1000000000 {
27         return Err(SystemError::EINVAL);
28     }
29     // 对于小于500us的时间,使用spin/rdtsc来进行定时
30 
31     if sleep_time.tv_nsec < 500000 {
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 handler: Box<WakeUpHelper> = WakeUpHelper::new(ProcessManager::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     let irq_guard: crate::exception::IrqFlagsGuard =
52         unsafe { CurrentIrqArch::save_and_disable_irq() };
53     ProcessManager::mark_sleep(true).ok();
54     timer.activate();
55 
56     drop(irq_guard);
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 usleep(sleep_time: TimeSpec) -> Result<TimeSpec, SystemError> {
76     match nanosleep(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 usec 微秒
87 ///
88 /// @return Ok(i32) 0
89 ///
90 /// @return Err(SystemError) 错误码
91 #[no_mangle]
92 pub extern "C" fn rs_usleep(usec: useconds_t) -> i32 {
93     let sleep_time = TimeSpec {
94         tv_sec: (usec / 1000000) as i64,
95         tv_nsec: ((usec % 1000000) * 1000) as i64,
96     };
97     match usleep(sleep_time) {
98         Ok(_) => {
99             return 0;
100         }
101         Err(err) => {
102             return err.to_posix_errno();
103         }
104     };
105 }
106