refactor(kernel): move SyscallOutcome/Result to syscall module, move test helpers to tests module
This commit is contained in:
@@ -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")
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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(
|
||||||
|
|||||||
@@ -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(
|
||||||
|
|||||||
@@ -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(
|
||||||
|
|||||||
@@ -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(
|
||||||
|
|||||||
@@ -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 {
|
||||||
|
|||||||
@@ -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 {
|
||||||
|
|||||||
@@ -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")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user