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
17const TIMER_ABSTIME: i32 = 1;
19
20#[inline]
24pub fn current_time_ns() -> u64 {
25 crate::process::scheduler::ticks() * 10_000_000 }
27
28pub fn sys_clock_gettime(clock_id: u32, tp_ptr: u64) -> Result<u64, SyscallError> {
42 if tp_ptr == 0 {
43 return Err(SyscallError::Fault);
44 }
45
46 match clock_id {
49 CLOCK_MONOTONIC | CLOCK_REALTIME => {}
50 _ => return Err(SyscallError::InvalidArgument),
51 }
52
53 let now_ns = current_time_ns();
54 let ts = TimeSpec::from_nanos(now_ns);
55
56 let user = UserSliceReadWrite::new(tp_ptr, core::mem::size_of::<TimeSpec>())?;
57 user.write_val(&ts).map_err(|_| SyscallError::Fault)?;
58 Ok(0)
59}
60
61pub fn sys_nanosleep(req_ptr: u64, rem_ptr: u64) -> Result<u64, SyscallError> {
72 let req_slice = UserSliceRead::new(req_ptr, core::mem::size_of::<TimeSpec>() as usize)
74 .map_err(|_| SyscallError::Fault)?; let req = req_slice
77 .read_val::<TimeSpec>()
78 .map_err(|_| SyscallError::Fault)?;
79
80 if req.tv_sec < 0 || req.tv_nsec < 0 || req.tv_nsec >= 1_000_000_000 {
82 return Err(SyscallError::InvalidArgument); }
84
85 if req.tv_sec == 0 && req.tv_nsec == 0 {
87 yield_task();
88 return Ok(0);
89 }
90
91 let sleep_duration_ns = req.to_nanos();
92 let current_ns = current_time_ns();
93 let wake_deadline_ns = current_ns.saturating_add(sleep_duration_ns);
94
95 let task_id = current_task_id().ok_or_else(|| SyscallError::PermissionDenied)?; if let Some(task) = crate::process::get_task_by_id(task_id) {
100 task.wake_deadline_ns
101 .store(wake_deadline_ns, Ordering::Relaxed);
102 }
103
104 if let Some(task) = crate::process::get_task_by_id(task_id) {
110 let pending = task.pending_signals.get_mask();
111 let blocked = task.blocked_signals.get_mask();
112 let unblocked_pending = pending & !blocked;
113 if unblocked_pending != 0 {
114 task.wake_deadline_ns.store(0, Ordering::Relaxed);
116 return Err(SyscallError::Interrupted); }
118 }
119
120 loop {
121 block_current_task();
122
123 if let Some(task) = crate::process::get_task_by_id(task_id) {
124 let deadline = task.wake_deadline_ns.load(Ordering::Relaxed);
125 let now = current_time_ns();
126
127 if deadline == 0 || now >= deadline {
128 task.wake_deadline_ns.store(0, Ordering::Relaxed);
129 return Ok(0);
130 }
131
132 if crate::process::has_pending_signals() {
133 task.wake_deadline_ns.store(0, Ordering::Relaxed);
134 if rem_ptr != 0 {
135 let remaining_ns = deadline - now;
136 let remaining = TimeSpec::from_nanos(remaining_ns);
137 let rem_slice =
138 UserSliceReadWrite::new(rem_ptr, core::mem::size_of::<TimeSpec>() as usize)
139 .map_err(|_| SyscallError::Fault)?;
140 rem_slice
141 .write_val(&remaining)
142 .map_err(|_| SyscallError::Fault)?;
143 }
144 return Err(SyscallError::Interrupted);
145 }
146 } else {
147 return Err(SyscallError::Fault);
148 }
149 }
150}
151
152pub fn sys_clock_nanosleep(
171 clock_id: u32,
172 flags: i32,
173 req_ptr: u64,
174 rem_ptr: u64,
175) -> Result<u64, SyscallError> {
176 match clock_id {
178 CLOCK_MONOTONIC | CLOCK_REALTIME => {}
179 _ => return Err(SyscallError::InvalidArgument),
180 }
181
182 let req_slice = UserSliceRead::new(req_ptr, core::mem::size_of::<TimeSpec>() as usize)
184 .map_err(|_| SyscallError::Fault)?;
185
186 let req = req_slice
187 .read_val::<TimeSpec>()
188 .map_err(|_| SyscallError::Fault)?;
189
190 if req.tv_sec < 0 || req.tv_nsec < 0 || req.tv_nsec >= 1_000_000_000 {
192 return Err(SyscallError::InvalidArgument);
193 }
194
195 let current_ns = current_time_ns();
196
197 let wake_deadline_ns = if (flags & TIMER_ABSTIME) != 0 {
199 let deadline = req.to_nanos();
201 if deadline <= current_ns {
203 return Ok(0);
204 }
205 deadline
206 } else {
207 let sleep_duration_ns = req.to_nanos();
209
210 if sleep_duration_ns == 0 {
212 yield_task();
213 return Ok(0);
214 }
215
216 current_ns.saturating_add(sleep_duration_ns)
217 };
218
219 let task_id = current_task_id().ok_or_else(|| SyscallError::PermissionDenied)?;
221
222 if let Some(task) = crate::process::get_task_by_id(task_id) {
224 task.wake_deadline_ns
225 .store(wake_deadline_ns, Ordering::Relaxed);
226 }
227
228 if let Some(task) = crate::process::get_task_by_id(task_id) {
230 let pending = task.pending_signals.get_mask();
231 let blocked = task.blocked_signals.get_mask();
232 let unblocked_pending = pending & !blocked;
233 if unblocked_pending != 0 {
234 task.wake_deadline_ns.store(0, Ordering::Relaxed);
235 return Err(SyscallError::Interrupted);
236 }
237 }
238
239 loop {
240 block_current_task();
241
242 if let Some(task) = crate::process::get_task_by_id(task_id) {
243 let deadline = task.wake_deadline_ns.load(Ordering::Relaxed);
244 let now = current_time_ns();
245
246 if deadline == 0 || now >= deadline {
247 task.wake_deadline_ns.store(0, Ordering::Relaxed);
248 return Ok(0);
249 }
250
251 if crate::process::has_pending_signals() {
252 task.wake_deadline_ns.store(0, Ordering::Relaxed);
253
254 if (flags & TIMER_ABSTIME) == 0 && rem_ptr != 0 {
256 let remaining_ns = deadline - now;
257 let remaining = TimeSpec::from_nanos(remaining_ns);
258 let rem_slice =
259 UserSliceReadWrite::new(rem_ptr, core::mem::size_of::<TimeSpec>() as usize)
260 .map_err(|_| SyscallError::Fault)?;
261 rem_slice
262 .write_val(&remaining)
263 .map_err(|_| SyscallError::Fault)?;
264 }
265 return Err(SyscallError::Interrupted);
266 }
267 } else {
268 return Err(SyscallError::Fault);
269 }
270 }
271}