use domain::process::MAX_THREADS_PER_PROCESS; use platform::Platform; use super::{SyscallOutcome, SyscallResult}; use crate::Kernel; impl Kernel

{ 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) } }