142 lines
5.4 KiB
Rust
142 lines
5.4 KiB
Rust
use domain::process::MAX_THREADS_PER_PROCESS;
|
|
use platform::Platform;
|
|
|
|
use super::{SyscallOutcome, SyscallResult};
|
|
use crate::Kernel;
|
|
|
|
impl<P: Platform> Kernel<P> {
|
|
pub(crate) fn handle_spawn_thread(
|
|
&mut self,
|
|
pid: types::id::ProcessId,
|
|
entry: types::address::EntryPoint,
|
|
stack: types::address::StackPointer,
|
|
) -> SyscallOutcome {
|
|
use domain::scheduler::Scheduler;
|
|
use domain::thread::SavedContext;
|
|
|
|
let priority = types::bounded::Priority::DEFAULT;
|
|
let time_slice = types::time::TimeSlice::DEFAULT;
|
|
let context = SavedContext::with_entry_and_stack(entry, stack);
|
|
|
|
let tid = match self.threads.spawn_with_context(pid, priority, time_slice, None, context) {
|
|
Ok(t) => t,
|
|
Err(e) => return SyscallOutcome::Complete(SyscallResult::Error(e)),
|
|
};
|
|
|
|
if let Err(e) = self.processes.get_mut(pid).and_then(|p| p.add_thread(tid)) {
|
|
let _ = self.threads.destroy(tid);
|
|
return SyscallOutcome::Complete(SyscallResult::Error(e));
|
|
}
|
|
|
|
let core = self.platform.core_id();
|
|
self.scheduler.add(tid, priority, core);
|
|
SyscallOutcome::Complete(SyscallResult::Value(tid.raw() as usize))
|
|
}
|
|
|
|
pub(crate) fn handle_create_process(
|
|
&mut self,
|
|
caller_pid: types::id::ProcessId,
|
|
create_cap: types::bounded::CapSlot,
|
|
_image: types::address::DataRef,
|
|
) -> SyscallOutcome {
|
|
if let Err(e) = self.check_cap(caller_pid, create_cap, types::permission::Permission::Execute) {
|
|
return SyscallOutcome::Complete(SyscallResult::Error(e));
|
|
}
|
|
|
|
let new_pid = match self.processes.create(
|
|
domain::capability::CapabilityTable::new(),
|
|
None,
|
|
) {
|
|
Ok(p) => p,
|
|
Err(e) => return SyscallOutcome::Complete(SyscallResult::Error(e)),
|
|
};
|
|
|
|
self.process_memory[new_pid.raw() as usize] =
|
|
Some(domain::memory::process_memory::ProcessMemory::new(new_pid, domain::memory::process_memory::ProcessMemory::DEFAULT_PAGE_LIMIT));
|
|
|
|
match self.grant_cap(
|
|
caller_pid,
|
|
domain::resource::Resource::Process(new_pid),
|
|
types::permission::PermissionSet::empty()
|
|
.with(types::permission::Permission::Execute)
|
|
.with(types::permission::Permission::Read),
|
|
) {
|
|
Ok(slot) => SyscallOutcome::Complete(SyscallResult::Slot(slot)),
|
|
Err(e) => {
|
|
// Rollback: destroy orphaned process
|
|
let _ = self.processes.destroy(new_pid);
|
|
self.process_memory[new_pid.raw() as usize] = None;
|
|
SyscallOutcome::Complete(SyscallResult::Error(e))
|
|
}
|
|
}
|
|
}
|
|
|
|
pub(crate) fn handle_spawn_thread_in(
|
|
&mut self,
|
|
caller_pid: types::id::ProcessId,
|
|
process_cap: types::bounded::CapSlot,
|
|
entry: types::address::EntryPoint,
|
|
stack: types::address::StackPointer,
|
|
) -> SyscallOutcome {
|
|
use domain::scheduler::Scheduler;
|
|
use domain::thread::SavedContext;
|
|
|
|
let target_pid = match self.check_cap(
|
|
caller_pid,
|
|
process_cap,
|
|
types::permission::Permission::Execute,
|
|
) {
|
|
Ok(cap) => match cap.resource() {
|
|
domain::resource::Resource::Process(pid) => *pid,
|
|
_ => return SyscallOutcome::Complete(SyscallResult::Error(
|
|
domain::error::KernelError::PermissionDenied {
|
|
slot: process_cap,
|
|
needed: types::permission::Permission::Execute,
|
|
},
|
|
)),
|
|
},
|
|
Err(e) => return SyscallOutcome::Complete(SyscallResult::Error(e)),
|
|
};
|
|
|
|
let priority = types::bounded::Priority::DEFAULT;
|
|
let time_slice = types::time::TimeSlice::DEFAULT;
|
|
let context = SavedContext::with_entry_and_stack(entry, stack);
|
|
|
|
let tid = match self.threads.spawn_with_context(target_pid, priority, time_slice, None, context) {
|
|
Ok(t) => t,
|
|
Err(e) => return SyscallOutcome::Complete(SyscallResult::Error(e)),
|
|
};
|
|
|
|
if let Err(e) = self.processes.get_mut(target_pid).and_then(|p| p.add_thread(tid)) {
|
|
let _ = self.threads.destroy(tid);
|
|
return SyscallOutcome::Complete(SyscallResult::Error(e));
|
|
}
|
|
|
|
let core = self.platform.core_id();
|
|
self.scheduler.add(tid, priority, core);
|
|
SyscallOutcome::Complete(SyscallResult::Value(tid.raw() as usize))
|
|
}
|
|
|
|
pub(crate) fn handle_kill(
|
|
&mut self,
|
|
caller_pid: types::id::ProcessId,
|
|
process_cap: types::bounded::CapSlot,
|
|
) -> SyscallOutcome {
|
|
let target_pid = match self.check_cap(caller_pid, process_cap, types::permission::Permission::Execute) {
|
|
Ok(cap) => match cap.resource() {
|
|
domain::resource::Resource::Process(pid) => *pid,
|
|
_ => return SyscallOutcome::Complete(SyscallResult::Error(
|
|
domain::error::KernelError::PermissionDenied {
|
|
slot: process_cap,
|
|
needed: types::permission::Permission::Execute,
|
|
},
|
|
)),
|
|
},
|
|
Err(e) => return SyscallOutcome::Complete(SyscallResult::Error(e)),
|
|
};
|
|
|
|
self.destroy_process(target_pid);
|
|
SyscallOutcome::Complete(SyscallResult::Ok)
|
|
}
|
|
}
|