refactor(kernel): move SyscallOutcome/Result to syscall module, move test helpers to tests module

This commit is contained in:
2026-10-18 00:39:28 +02:00
parent 38ebb6002b
commit 2c4a9dbadc
8 changed files with 118 additions and 115 deletions

View File

@@ -3,6 +3,8 @@
pub mod interrupt; pub mod interrupt;
pub mod syscall; pub mod syscall;
pub use syscall::{SyscallOutcome, SyscallResult};
#[cfg(test)] #[cfg(test)]
#[path = "tests/mod.rs"] #[path = "tests/mod.rs"]
mod tests; mod tests;
@@ -33,22 +35,6 @@ use types::{
time::TimeSlice, time::TimeSlice,
}; };
pub enum SyscallOutcome {
Complete(SyscallResult),
BlockCaller(domain::thread::BlockReason),
SwitchTo(ThreadId),
TerminateCaller,
}
pub enum SyscallResult {
Ok,
Value(usize),
Slot(CapSlot),
Message(Message),
WakeReason(domain::syscall::WakeReason),
Error(KernelError),
}
pub struct Kernel<P: Platform> { pub struct Kernel<P: Platform> {
platform: P, platform: P,
processes: ProcessTable, processes: ProcessTable,
@@ -117,6 +103,14 @@ impl<P: Platform> Kernel<P> {
self.pending_results[thread.raw() as usize].as_ref() self.pending_results[thread.raw() as usize].as_ref()
} }
pub fn free_page_count(&self) -> usize {
self.page_pool.free_count()
}
pub fn process_exists(&self, pid: ProcessId) -> bool {
self.processes.get(pid).is_ok()
}
fn caller(&self) -> Result<(ThreadId, ProcessId), KernelError> { fn caller(&self) -> Result<(ThreadId, ProcessId), KernelError> {
let core = self.platform.core_id(); let core = self.platform.core_id();
let tid = self.scheduler.current(core) let tid = self.scheduler.current(core)
@@ -128,14 +122,6 @@ impl<P: Platform> Kernel<P> {
} }
} }
pub fn free_page_count(&self) -> usize {
self.page_pool.free_count()
}
pub fn process_exists(&self, pid: ProcessId) -> bool {
self.processes.get(pid).is_ok()
}
pub(crate) fn cleanup_threads(&mut self, thread_ids: &[Option<ThreadId>; 4]) { pub(crate) fn cleanup_threads(&mut self, thread_ids: &[Option<ThreadId>; 4]) {
use domain::scheduler::Scheduler; use domain::scheduler::Scheduler;
for slot in thread_ids { for slot in thread_ids {
@@ -184,82 +170,4 @@ impl<P: Platform> Kernel<P> {
let cap = Capability::new(resource, permissions, Generation::initial()); let cap = Capability::new(resource, permissions, Generation::initial());
self.processes.get_mut(to)?.capabilities_mut().insert(cap) self.processes.get_mut(to)?.capabilities_mut().insert(cap)
} }
#[cfg(test)]
pub fn spawn_thread_for_test(
&mut self,
pid: ProcessId,
priority: Priority,
time_slice: TimeSlice,
) -> ThreadId {
use domain::scheduler::Scheduler;
let tid = self.threads.spawn(pid, priority, time_slice, None).expect("spawn");
let _ = self.processes.get_mut(pid).map(|p| p.add_thread(tid));
let core = self.platform.core_id();
self.scheduler.add(tid, priority, core);
tid
}
#[cfg(test)]
pub fn register_irq_for_test(&mut self, irq: types::id::IrqId, thread: ThreadId) {
let _ = self.irqs.register(irq, thread);
}
#[cfg(test)]
pub fn block_thread_for_test(
&mut self,
tid: ThreadId,
reason: domain::thread::BlockReason,
) {
use domain::scheduler::Scheduler;
let core = self.platform.core_id();
if let Ok(t) = self.threads.get_mut(tid) {
if matches!(t.state(), ThreadState::Ready) {
let _ = t.set_running(core);
}
let _ = t.block(reason);
}
self.scheduler.remove(tid);
}
#[cfg(test)]
pub fn switch_to_thread_for_test(&mut self, tid: ThreadId) {
use domain::scheduler::Scheduler;
let core = self.platform.core_id();
if let Some(current) = self.scheduler.current(core) {
if current == tid {
return;
}
if let Ok(t) = self.threads.get_mut(current) {
if matches!(t.state(), ThreadState::Running(_)) {
let priority = t.priority();
let _ = t.preempt();
self.scheduler.add(current, priority, core);
}
}
}
if let Ok(t) = self.threads.get(tid) {
if matches!(t.state(), ThreadState::Ready) {
self.scheduler.next(core);
let _ = self.threads.get_mut(tid).map(|t| t.set_running(core));
}
}
}
#[cfg(test)]
pub fn create_endpoint_for_test(&mut self) -> types::id::EndpointId {
self.endpoints.create().expect("create endpoint")
}
#[cfg(test)]
pub fn grant_cap_for_test(
&mut self,
pid: ProcessId,
resource: Resource,
permissions: PermissionSet,
) -> CapSlot {
self.grant_cap(pid, resource, permissions).expect("grant cap")
}
} }

View File

@@ -1,6 +1,7 @@
use platform::Platform; use platform::Platform;
use crate::{Kernel, SyscallOutcome, SyscallResult}; use super::{SyscallOutcome, SyscallResult};
use crate::Kernel;
impl<P: Platform> Kernel<P> { impl<P: Platform> Kernel<P> {
pub(crate) fn handle_delegate( pub(crate) fn handle_delegate(

View File

@@ -1,6 +1,7 @@
use platform::Platform; use platform::Platform;
use crate::{Kernel, SyscallOutcome, SyscallResult}; use super::{SyscallOutcome, SyscallResult};
use crate::Kernel;
impl<P: Platform> Kernel<P> { impl<P: Platform> Kernel<P> {
pub(crate) fn handle_send( pub(crate) fn handle_send(

View File

@@ -1,6 +1,7 @@
use platform::Platform; use platform::Platform;
use crate::{Kernel, SyscallOutcome, SyscallResult}; use super::{SyscallOutcome, SyscallResult};
use crate::Kernel;
impl<P: Platform> Kernel<P> { impl<P: Platform> Kernel<P> {
pub(crate) fn handle_spawn_thread( pub(crate) fn handle_spawn_thread(

View File

@@ -1,6 +1,7 @@
use platform::Platform; use platform::Platform;
use crate::{Kernel, SyscallOutcome, SyscallResult}; use super::{SyscallOutcome, SyscallResult};
use crate::Kernel;
impl<P: Platform> Kernel<P> { impl<P: Platform> Kernel<P> {
pub(crate) fn handle_request_pages( pub(crate) fn handle_request_pages(

View File

@@ -4,10 +4,27 @@ mod lifecycle;
mod memory; mod memory;
mod simple; mod simple;
use domain::syscall::Syscall; use domain::{error::KernelError, message::Message, syscall::Syscall};
use platform::Platform; use platform::Platform;
use types::{bounded::CapSlot, id::ThreadId};
use crate::{Kernel, SyscallOutcome, SyscallResult}; use crate::Kernel;
pub enum SyscallOutcome {
Complete(SyscallResult),
BlockCaller(domain::thread::BlockReason),
SwitchTo(ThreadId),
TerminateCaller,
}
pub enum SyscallResult {
Ok,
Value(usize),
Slot(CapSlot),
Message(Message),
WakeReason(domain::syscall::WakeReason),
Error(KernelError),
}
impl<P: Platform> Kernel<P> { impl<P: Platform> Kernel<P> {
pub fn handle_syscall(&mut self, syscall: Syscall) -> SyscallOutcome { pub fn handle_syscall(&mut self, syscall: Syscall) -> SyscallOutcome {

View File

@@ -1,6 +1,7 @@
use platform::Platform; use platform::Platform;
use crate::{Kernel, SyscallOutcome, SyscallResult}; use super::{SyscallOutcome, SyscallResult};
use crate::Kernel;
impl<P: Platform> Kernel<P> { impl<P: Platform> Kernel<P> {
pub(crate) fn handle_get_time(&self) -> SyscallOutcome { pub(crate) fn handle_get_time(&self) -> SyscallOutcome {

View File

@@ -7,18 +7,20 @@ mod simple;
mod tick; mod tick;
use domain::memory::page_pool::PagePool; use domain::memory::page_pool::PagePool;
use domain::memory::MemoryRegion;
use domain::resource::Resource;
use domain::scheduler::Scheduler;
use domain::thread::{SavedContext, ThreadState};
use platform::Platform; use platform::Platform;
use types::{ use types::{
address::{EntryPoint, PhysicalAddress, StackPointer}, address::{EntryPoint, PhysicalAddress, StackPointer},
bounded::Priority, bounded::{CapSlot, Priority},
id::{CoreId, IrqId, ProcessId}, id::{CoreId, EndpointId, IrqId, ProcessId, ThreadId},
permission::PermissionSet,
time::{Ticks, TimerDuration, TimeSlice}, time::{Ticks, TimerDuration, TimeSlice},
}; };
use domain::memory::MemoryRegion; use crate::{Kernel, SyscallResult};
use domain::thread::SavedContext;
use crate::Kernel;
pub struct MockPlatform { pub struct MockPlatform {
ticks: Ticks, ticks: Ticks,
@@ -74,3 +76,74 @@ pub fn kernel_with_process() -> (Kernel<MockPlatform>, ProcessId) {
.unwrap(); .unwrap();
(kernel, pid) (kernel, pid)
} }
impl Kernel<MockPlatform> {
pub fn spawn_thread_for_test(
&mut self,
pid: ProcessId,
priority: Priority,
time_slice: TimeSlice,
) -> ThreadId {
let tid = self.threads.spawn(pid, priority, time_slice, None).expect("spawn");
let _ = self.processes.get_mut(pid).map(|p| p.add_thread(tid));
let core = self.platform.core_id();
self.scheduler.add(tid, priority, core);
tid
}
pub fn register_irq_for_test(&mut self, irq: IrqId, thread: ThreadId) {
let _ = self.irqs.register(irq, thread);
}
pub fn block_thread_for_test(
&mut self,
tid: ThreadId,
reason: domain::thread::BlockReason,
) {
let core = self.platform.core_id();
if let Ok(t) = self.threads.get_mut(tid) {
if matches!(t.state(), ThreadState::Ready) {
let _ = t.set_running(core);
}
let _ = t.block(reason);
}
self.scheduler.remove(tid);
}
pub fn switch_to_thread_for_test(&mut self, tid: ThreadId) {
let core = self.platform.core_id();
if let Some(current) = self.scheduler.current(core) {
if current == tid {
return;
}
if let Ok(t) = self.threads.get_mut(current) {
if matches!(t.state(), ThreadState::Running(_)) {
let priority = t.priority();
let _ = t.preempt();
self.scheduler.add(current, priority, core);
}
}
}
if let Ok(t) = self.threads.get(tid) {
if matches!(t.state(), ThreadState::Ready) {
self.scheduler.next(core);
let _ = self.threads.get_mut(tid).map(|t| t.set_running(core));
}
}
}
pub fn create_endpoint_for_test(&mut self) -> EndpointId {
self.endpoints.create().expect("create endpoint")
}
pub fn grant_cap_for_test(
&mut self,
pid: ProcessId,
resource: Resource,
permissions: PermissionSet,
) -> CapSlot {
self.grant_cap(pid, resource, permissions).expect("grant cap")
}
}