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