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