strat9_kernel/syscall/
time.rs1use core::sync::atomic::Ordering;
4
5use crate::{
6 memory::userslice::{UserSliceRead, UserSliceReadWrite},
7 process::{block_current_task, current_task_id, yield_task},
8 syscall::error::SyscallError,
9};
10
11pub use strat9_abi::data::TimeSpec;
12
13pub const CLOCK_MONOTONIC: u32 = 1;
15pub const CLOCK_REALTIME: u32 = 0;
16
17#[inline]
21pub fn current_time_ns() -> u64 {
22 crate::process::scheduler::ticks() * 10_000_000 }
24
25pub fn sys_clock_gettime(clock_id: u32, tp_ptr: u64) -> Result<u64, SyscallError> {
39 if tp_ptr == 0 {
40 return Err(SyscallError::Fault);
41 }
42
43 match clock_id {
46 CLOCK_MONOTONIC | CLOCK_REALTIME => {}
47 _ => return Err(SyscallError::InvalidArgument),
48 }
49
50 let now_ns = current_time_ns();
51 let ts = TimeSpec::from_nanos(now_ns);
52
53 let user = UserSliceReadWrite::new(tp_ptr, core::mem::size_of::<TimeSpec>())?;
54 user.write_val(&ts).map_err(|_| SyscallError::Fault)?;
55 Ok(0)
56}
57
58pub fn sys_nanosleep(req_ptr: u64, rem_ptr: u64) -> Result<u64, SyscallError> {
69 let req_slice = UserSliceRead::new(req_ptr, core::mem::size_of::<TimeSpec>() as usize)
71 .map_err(|_| SyscallError::Fault)?; let req = req_slice
74 .read_val::<TimeSpec>()
75 .map_err(|_| SyscallError::Fault)?;
76
77 if req.tv_sec < 0 || req.tv_nsec < 0 || req.tv_nsec >= 1_000_000_000 {
79 return Err(SyscallError::InvalidArgument); }
81
82 if req.tv_sec == 0 && req.tv_nsec == 0 {
84 yield_task();
85 return Ok(0);
86 }
87
88 let sleep_duration_ns = req.to_nanos();
89 let current_ns = current_time_ns();
90 let wake_deadline_ns = current_ns.saturating_add(sleep_duration_ns);
91
92 let task_id = current_task_id().ok_or_else(|| SyscallError::PermissionDenied)?; if let Some(task) = crate::process::get_task_by_id(task_id) {
97 task.wake_deadline_ns
98 .store(wake_deadline_ns, Ordering::Relaxed);
99 }
100
101 if let Some(task) = crate::process::get_task_by_id(task_id) {
107 let pending = task.pending_signals.get_mask();
108 let blocked = task.blocked_signals.get_mask();
109 let unblocked_pending = pending & !blocked;
110 if unblocked_pending != 0 {
111 task.wake_deadline_ns.store(0, Ordering::Relaxed);
113 return Err(SyscallError::Interrupted); }
115 }
116
117 loop {
118 block_current_task();
119
120 if let Some(task) = crate::process::get_task_by_id(task_id) {
121 let deadline = task.wake_deadline_ns.load(Ordering::Relaxed);
122 let now = current_time_ns();
123
124 if deadline == 0 || now >= deadline {
125 task.wake_deadline_ns.store(0, Ordering::Relaxed);
126 return Ok(0);
127 }
128
129 if crate::process::has_pending_signals() {
130 task.wake_deadline_ns.store(0, Ordering::Relaxed);
131 if rem_ptr != 0 {
132 let remaining_ns = deadline - now;
133 let remaining = TimeSpec::from_nanos(remaining_ns);
134 let rem_slice =
135 UserSliceReadWrite::new(rem_ptr, core::mem::size_of::<TimeSpec>() as usize)
136 .map_err(|_| SyscallError::Fault)?;
137 rem_slice
138 .write_val(&remaining)
139 .map_err(|_| SyscallError::Fault)?;
140 }
141 return Err(SyscallError::Interrupted);
142 }
143 } else {
144 return Err(SyscallError::Fault);
145 }
146 }
147}