95 lines
3.1 KiB
Rust
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
|
|
}
|
|
}
|