feat: add SavedContext::with_entry_and_stack, wire SpawnThread to preserve entry point and stack

This commit is contained in:
2026-10-18 01:24:56 +02:00
parent 4833f2e2bb
commit 142505d8a4
4 changed files with 88 additions and 3 deletions

View File

@@ -31,10 +31,31 @@ pub struct SavedContext {
registers: [usize; 32], registers: [usize; 32],
} }
pub const PC_REGISTER: usize = 0;
pub const SP_REGISTER: usize = 1;
impl SavedContext { impl SavedContext {
pub fn empty() -> Self { pub fn empty() -> Self {
Self { registers: [0; 32] } Self { registers: [0; 32] }
} }
pub fn with_entry_and_stack(
entry: types::address::EntryPoint,
stack: types::address::StackPointer,
) -> Self {
let mut ctx = Self::empty();
ctx.registers[PC_REGISTER] = entry.raw();
ctx.registers[SP_REGISTER] = stack.raw();
ctx
}
pub fn program_counter(&self) -> usize {
self.registers[PC_REGISTER]
}
pub fn stack_pointer(&self) -> usize {
self.registers[SP_REGISTER]
}
} }
pub enum BlockReason { pub enum BlockReason {
@@ -63,6 +84,29 @@ impl Thread {
} }
} }
pub fn with_context(
id: ThreadId,
process: ProcessId,
priority: Priority,
time_slice: TimeSlice,
core_affinity: Option<CoreId>,
context: SavedContext,
) -> Self {
Self {
id,
process,
state: ThreadState::Ready,
saved_context: context,
priority,
time_slice,
core_affinity,
}
}
pub fn saved_context(&self) -> &SavedContext {
&self.saved_context
}
pub fn id(&self) -> ThreadId { pub fn id(&self) -> ThreadId {
self.id self.id
} }
@@ -173,6 +217,25 @@ impl ThreadTable {
Ok(id) Ok(id)
} }
pub fn spawn_with_context(
&mut self,
process: ProcessId,
priority: Priority,
time_slice: TimeSlice,
core_affinity: Option<CoreId>,
context: SavedContext,
) -> Result<ThreadId, KernelError> {
let idx = self
.threads
.iter()
.position(|s| s.is_none())
.ok_or(KernelError::TooManyThreads)?;
let id = ThreadId::from_raw(idx as u16);
self.threads[idx] = Some(Thread::with_context(id, process, priority, time_slice, core_affinity, context));
Ok(id)
}
pub fn get(&self, id: ThreadId) -> Result<&Thread, KernelError> { pub fn get(&self, id: ThreadId) -> Result<&Thread, KernelError> {
let idx = id.raw() as usize; let idx = id.raw() as usize;
self.threads self.threads

View File

@@ -7,16 +7,18 @@ impl<P: Platform> Kernel<P> {
pub(crate) fn handle_spawn_thread( pub(crate) fn handle_spawn_thread(
&mut self, &mut self,
pid: types::id::ProcessId, pid: types::id::ProcessId,
_entry: types::address::EntryPoint, entry: types::address::EntryPoint,
_stack: types::address::StackPointer, stack: types::address::StackPointer,
) -> SyscallOutcome { ) -> SyscallOutcome {
use domain::scheduler::Scheduler; use domain::scheduler::Scheduler;
use domain::thread::SavedContext;
let priority = types::bounded::Priority::new(16) let priority = types::bounded::Priority::new(16)
.unwrap_or_else(|| unreachable!()); .unwrap_or_else(|| unreachable!());
let time_slice = types::time::TimeSlice::new(100); let time_slice = types::time::TimeSlice::new(100);
let context = SavedContext::with_entry_and_stack(entry, stack);
let tid = match self.threads.spawn(pid, priority, time_slice, None) { let tid = match self.threads.spawn_with_context(pid, priority, time_slice, None, context) {
Ok(t) => t, Ok(t) => t,
Err(e) => return SyscallOutcome::Complete(SyscallResult::Error(e)), Err(e) => return SyscallOutcome::Complete(SyscallResult::Error(e)),
}; };

View File

@@ -97,4 +97,8 @@ impl Kernel<MockPlatform> {
) -> CapSlot { ) -> CapSlot {
self.grant_cap(pid, resource, permissions).expect("grant cap") self.grant_cap(pid, resource, permissions).expect("grant cap")
} }
pub fn thread_context(&self, tid: ThreadId) -> &domain::thread::SavedContext {
self.threads.get(tid).expect("thread").saved_context()
}
} }

View File

@@ -3,6 +3,7 @@ use crate::{SyscallOutcome, SyscallResult};
use domain::syscall::Syscall; use domain::syscall::Syscall;
use types::address::{DataRef, EntryPoint, StackPointer}; use types::address::{DataRef, EntryPoint, StackPointer};
use types::bounded::CapSlot; use types::bounded::CapSlot;
use types::id::ThreadId;
#[test] #[test]
fn spawn_thread_creates_ready_thread() { fn spawn_thread_creates_ready_thread() {
@@ -17,6 +18,21 @@ fn spawn_thread_creates_ready_thread() {
)); ));
} }
#[test]
fn spawn_thread_preserves_entry_and_stack() {
let (mut k, _) = kernel_with_process();
let tid = match k.handle_syscall(Syscall::SpawnThread {
entry: EntryPoint::from_raw(0xDEAD),
stack: StackPointer::from_raw(0xBEEF),
}) {
SyscallOutcome::Complete(SyscallResult::Value(v)) => ThreadId::from_raw(v as u16),
_ => panic!("expected Value"),
};
let ctx = k.thread_context(tid);
assert_eq!(ctx.program_counter(), 0xDEAD);
assert_eq!(ctx.stack_pointer(), 0xBEEF);
}
#[test] #[test]
fn create_process_with_cap_succeeds() { fn create_process_with_cap_succeeds() {
let (mut k, _) = kernel_with_process(); let (mut k, _) = kernel_with_process();