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
13unsafe impl crate::memory::userslice::UserPod for TimeSpec {}
17
18pub const CLOCK_MONOTONIC: u32 = 1;
20pub const CLOCK_REALTIME: u32 = 0;
21
22const TIMER_ABSTIME: i32 = 1;
24
25#[inline]
29pub fn current_time_ns() -> u64 {
30 crate::process::scheduler::ticks() * 10_000_000 }
32
33pub fn sys_clock_gettime(clock_id: u32, tp_ptr: u64) -> Result<u64, SyscallError> {
47 if tp_ptr == 0 {
48 return Err(SyscallError::Fault);
49 }
50
51 match clock_id {
54 CLOCK_MONOTONIC | CLOCK_REALTIME => {}
55 _ => return Err(SyscallError::InvalidArgument),
56 }
57
58 let now_ns = current_time_ns();
59 let ts = TimeSpec::from_nanos(now_ns);
60
61 let user = UserSliceReadWrite::new(tp_ptr, core::mem::size_of::<TimeSpec>())?;
62 user.write_val(&ts).map_err(|_| SyscallError::Fault)?;
63 Ok(0)
64}
65
66pub fn sys_nanosleep(req_ptr: u64, rem_ptr: u64) -> Result<u64, SyscallError> {
77 let req_slice = UserSliceRead::new(req_ptr, core::mem::size_of::<TimeSpec>() as usize)
79 .map_err(|_| SyscallError::Fault)?; let req = req_slice
82 .read_val::<TimeSpec>()
83 .map_err(|_| SyscallError::Fault)?;
84
85 if req.tv_sec < 0 || req.tv_nsec < 0 || req.tv_nsec >= 1_000_000_000 {
87 return Err(SyscallError::InvalidArgument); }
89
90 if req.tv_sec == 0 && req.tv_nsec == 0 {
92 yield_task();
93 return Ok(0);
94 }
95
96 let sleep_duration_ns = req.to_nanos();
97 let current_ns = current_time_ns();
98 let wake_deadline_ns = current_ns.saturating_add(sleep_duration_ns);
99
100 let task_id = current_task_id().ok_or_else(|| SyscallError::PermissionDenied)?; if let Some(task) = crate::process::get_task_by_id(task_id) {
105 task.wake_deadline_ns
106 .store(wake_deadline_ns, Ordering::Relaxed);
107 }
108
109 if let Some(task) = crate::process::get_task_by_id(task_id) {
115 let pending = task.pending_signals.get_mask();
116 let blocked = task.blocked_signals.get_mask();
117 let unblocked_pending = pending & !blocked;
118 if unblocked_pending != 0 {
119 task.wake_deadline_ns.store(0, Ordering::Relaxed);
121 return Err(SyscallError::Interrupted); }
123 }
124
125 loop {
126 block_current_task();
127
128 if let Some(task) = crate::process::get_task_by_id(task_id) {
129 let deadline = task.wake_deadline_ns.load(Ordering::Relaxed);
130 let now = current_time_ns();
131
132 if deadline == 0 || now >= deadline {
133 task.wake_deadline_ns.store(0, Ordering::Relaxed);
134 return Ok(0);
135 }
136
137 if crate::process::has_pending_signals() {
138 task.wake_deadline_ns.store(0, Ordering::Relaxed);
139 if rem_ptr != 0 {
140 let remaining_ns = deadline - now;
141 let remaining = TimeSpec::from_nanos(remaining_ns);
142 let rem_slice =
143 UserSliceReadWrite::new(rem_ptr, core::mem::size_of::<TimeSpec>() as usize)
144 .map_err(|_| SyscallError::Fault)?;
145 rem_slice
146 .write_val(&remaining)
147 .map_err(|_| SyscallError::Fault)?;
148 }
149 return Err(SyscallError::Interrupted);
150 }
151 } else {
152 return Err(SyscallError::Fault);
153 }
154 }
155}
156
157pub fn sys_clock_nanosleep(
176 clock_id: u32,
177 flags: i32,
178 req_ptr: u64,
179 rem_ptr: u64,
180) -> Result<u64, SyscallError> {
181 match clock_id {
183 CLOCK_MONOTONIC | CLOCK_REALTIME => {}
184 _ => return Err(SyscallError::InvalidArgument),
185 }
186
187 let req_slice = UserSliceRead::new(req_ptr, core::mem::size_of::<TimeSpec>() as usize)
189 .map_err(|_| SyscallError::Fault)?;
190
191 let req = req_slice
192 .read_val::<TimeSpec>()
193 .map_err(|_| SyscallError::Fault)?;
194
195 if req.tv_sec < 0 || req.tv_nsec < 0 || req.tv_nsec >= 1_000_000_000 {
197 return Err(SyscallError::InvalidArgument);
198 }
199
200 let current_ns = current_time_ns();
201
202 let wake_deadline_ns = if (flags & TIMER_ABSTIME) != 0 {
204 let deadline = req.to_nanos();
206 if deadline <= current_ns {
208 return Ok(0);
209 }
210 deadline
211 } else {
212 let sleep_duration_ns = req.to_nanos();
214
215 if sleep_duration_ns == 0 {
217 yield_task();
218 return Ok(0);
219 }
220
221 current_ns.saturating_add(sleep_duration_ns)
222 };
223
224 let task_id = current_task_id().ok_or_else(|| SyscallError::PermissionDenied)?;
226
227 if let Some(task) = crate::process::get_task_by_id(task_id) {
229 task.wake_deadline_ns
230 .store(wake_deadline_ns, Ordering::Relaxed);
231 }
232
233 if let Some(task) = crate::process::get_task_by_id(task_id) {
235 let pending = task.pending_signals.get_mask();
236 let blocked = task.blocked_signals.get_mask();
237 let unblocked_pending = pending & !blocked;
238 if unblocked_pending != 0 {
239 task.wake_deadline_ns.store(0, Ordering::Relaxed);
240 return Err(SyscallError::Interrupted);
241 }
242 }
243
244 loop {
245 block_current_task();
246
247 if let Some(task) = crate::process::get_task_by_id(task_id) {
248 let deadline = task.wake_deadline_ns.load(Ordering::Relaxed);
249 let now = current_time_ns();
250
251 if deadline == 0 || now >= deadline {
252 task.wake_deadline_ns.store(0, Ordering::Relaxed);
253 return Ok(0);
254 }
255
256 if crate::process::has_pending_signals() {
257 task.wake_deadline_ns.store(0, Ordering::Relaxed);
258
259 if (flags & TIMER_ABSTIME) == 0 && rem_ptr != 0 {
261 let remaining_ns = deadline - now;
262 let remaining = TimeSpec::from_nanos(remaining_ns);
263 let rem_slice =
264 UserSliceReadWrite::new(rem_ptr, core::mem::size_of::<TimeSpec>() as usize)
265 .map_err(|_| SyscallError::Fault)?;
266 rem_slice
267 .write_val(&remaining)
268 .map_err(|_| SyscallError::Fault)?;
269 }
270 return Err(SyscallError::Interrupted);
271 }
272 } else {
273 return Err(SyscallError::Fault);
274 }
275 }
276}