From 142505d8a47aa0cf9641b90870787890585abffd Mon Sep 17 00:00:00 2001 From: Gabriel Kaszewski Date: Sun, 18 Oct 2026 01:24:56 +0200 Subject: [PATCH] feat: add SavedContext::with_entry_and_stack, wire SpawnThread to preserve entry point and stack --- crates/domain/src/thread/mod.rs | 63 ++++++++++++++++++++++++++ crates/kernel/src/syscall/lifecycle.rs | 8 ++-- crates/kernel/src/tests/helpers.rs | 4 ++ crates/kernel/src/tests/lifecycle.rs | 16 +++++++ 4 files changed, 88 insertions(+), 3 deletions(-) diff --git a/crates/domain/src/thread/mod.rs b/crates/domain/src/thread/mod.rs index 77a125e..3f2c665 100644 --- a/crates/domain/src/thread/mod.rs +++ b/crates/domain/src/thread/mod.rs @@ -31,10 +31,31 @@ pub struct SavedContext { registers: [usize; 32], } +pub const PC_REGISTER: usize = 0; +pub const SP_REGISTER: usize = 1; + impl SavedContext { pub fn empty() -> Self { 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 { @@ -63,6 +84,29 @@ impl Thread { } } + pub fn with_context( + id: ThreadId, + process: ProcessId, + priority: Priority, + time_slice: TimeSlice, + core_affinity: Option, + 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 { self.id } @@ -173,6 +217,25 @@ impl ThreadTable { Ok(id) } + pub fn spawn_with_context( + &mut self, + process: ProcessId, + priority: Priority, + time_slice: TimeSlice, + core_affinity: Option, + context: SavedContext, + ) -> Result { + 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> { let idx = id.raw() as usize; self.threads diff --git a/crates/kernel/src/syscall/lifecycle.rs b/crates/kernel/src/syscall/lifecycle.rs index 11d2da9..128940a 100644 --- a/crates/kernel/src/syscall/lifecycle.rs +++ b/crates/kernel/src/syscall/lifecycle.rs @@ -7,16 +7,18 @@ impl Kernel

{ pub(crate) fn handle_spawn_thread( &mut self, pid: types::id::ProcessId, - _entry: types::address::EntryPoint, - _stack: types::address::StackPointer, + entry: types::address::EntryPoint, + stack: types::address::StackPointer, ) -> SyscallOutcome { use domain::scheduler::Scheduler; + use domain::thread::SavedContext; let priority = types::bounded::Priority::new(16) .unwrap_or_else(|| unreachable!()); 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, Err(e) => return SyscallOutcome::Complete(SyscallResult::Error(e)), }; diff --git a/crates/kernel/src/tests/helpers.rs b/crates/kernel/src/tests/helpers.rs index b106fbf..ab22fb3 100644 --- a/crates/kernel/src/tests/helpers.rs +++ b/crates/kernel/src/tests/helpers.rs @@ -97,4 +97,8 @@ impl Kernel { ) -> CapSlot { 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() + } } diff --git a/crates/kernel/src/tests/lifecycle.rs b/crates/kernel/src/tests/lifecycle.rs index ad83368..c766596 100644 --- a/crates/kernel/src/tests/lifecycle.rs +++ b/crates/kernel/src/tests/lifecycle.rs @@ -3,6 +3,7 @@ use crate::{SyscallOutcome, SyscallResult}; use domain::syscall::Syscall; use types::address::{DataRef, EntryPoint, StackPointer}; use types::bounded::CapSlot; +use types::id::ThreadId; #[test] 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] fn create_process_with_cap_succeeds() { let (mut k, _) = kernel_with_process();