Files
k-os/crates/kernel/src/syscall/simple.rs

95 lines
3.1 KiB
Rust

use platform::Platform;
use crate::{Kernel, SyscallOutcome, SyscallResult};
impl<P: Platform> Kernel<P> {
pub(crate) fn handle_get_time(&self) -> SyscallOutcome {
let ticks = self.platform.current_ticks();
SyscallOutcome::Complete(SyscallResult::Value(ticks.raw() as usize))
}
pub(crate) fn handle_get_process_id(&self, pid: types::id::ProcessId) -> SyscallOutcome {
SyscallOutcome::Complete(SyscallResult::Value(pid.raw() as usize))
}
pub(crate) fn handle_yield(&mut self, caller_tid: types::id::ThreadId) -> SyscallOutcome {
use domain::scheduler::Scheduler;
let core = self.platform.core_id();
let thread = match self.threads.get_mut(caller_tid) {
Ok(t) => t,
Err(e) => return SyscallOutcome::Complete(SyscallResult::Error(e)),
};
let priority = thread.priority();
if thread.preempt().is_err() {
return SyscallOutcome::Complete(SyscallResult::Ok);
}
self.scheduler.add(caller_tid, priority, core);
match self.scheduler.next(core) {
Some(next) if next != caller_tid => {
if self.threads.get_mut(next).and_then(|t| t.set_running(core)).is_ok() {
SyscallOutcome::SwitchTo(next)
} else {
let _ = self.threads.get_mut(caller_tid).map(|t| t.set_running(core));
SyscallOutcome::Complete(SyscallResult::Ok)
}
}
_ => {
let _ = self.threads.get_mut(caller_tid).map(|t| t.set_running(core));
SyscallOutcome::Complete(SyscallResult::Ok)
}
}
}
pub(crate) fn handle_exit(
&mut self,
_caller_tid: types::id::ThreadId,
pid: types::id::ProcessId,
) -> SyscallOutcome {
let thread_ids: [Option<types::id::ThreadId>; 4] = {
match self.processes.get(pid) {
Ok(p) => {
let mut ids = [None; 4];
for (i, tid) in p.thread_ids().enumerate() {
if i < 4 {
ids[i] = Some(tid);
}
}
ids
}
Err(_) => return SyscallOutcome::TerminateCaller,
}
};
self.cleanup_threads(&thread_ids);
let _ = self.processes.destroy(pid);
self.process_memory[pid.raw() as usize] = None;
SyscallOutcome::TerminateCaller
}
pub(crate) fn handle_exit_thread(
&mut self,
caller_tid: types::id::ThreadId,
pid: types::id::ProcessId,
) -> SyscallOutcome {
use domain::scheduler::Scheduler;
self.scheduler.remove(caller_tid);
let _ = self.threads.destroy(caller_tid);
if let Ok(process) = self.processes.get_mut(pid) {
process.remove_thread(caller_tid);
if process.thread_ids().count() == 0 {
let _ = self.processes.destroy(pid);
self.process_memory[pid.raw() as usize] = None;
}
}
SyscallOutcome::TerminateCaller
}
}