refactor(kernel): split ipc/memory/lib/thread by concern; trim comments

This commit is contained in:
2026-10-27 13:21:53 +01:00
parent b814bd9570
commit 95dbe7b9d5
34 changed files with 1239 additions and 1231 deletions

View File

@@ -0,0 +1,51 @@
//! Saved register state of a thread.
pub struct SavedContext {
registers: [usize; 32],
pc: usize,
status: usize,
}
impl SavedContext {
pub fn empty() -> Self {
Self {
registers: [0; 32],
pc: 0,
status: 0,
}
}
pub fn with_entry_and_stack(
entry: types::address::EntryPoint,
stack: types::address::StackPointer,
) -> Self {
let mut ctx = Self::empty();
ctx.pc = entry.raw();
ctx.registers[2] = stack.raw();
ctx
}
pub fn program_counter(&self) -> usize {
self.pc
}
pub fn set_pc(&mut self, pc: usize) {
self.pc = pc;
}
pub fn status(&self) -> usize {
self.status
}
pub fn set_status(&mut self, status: usize) {
self.status = status;
}
pub fn registers(&self) -> &[usize; 32] {
&self.registers
}
pub fn registers_mut(&mut self) -> &mut [usize; 32] {
&mut self.registers
}
}

View File

@@ -1,11 +1,16 @@
use types::{
bounded::Priority,
generation::Generation,
id::{CoreId, EndpointId, NotificationId, ProcessId, ThreadId},
time::TimeSlice,
};
use crate::{error::KernelError, generations::SlotGenerations};
use crate::error::KernelError;
mod context;
mod table;
pub use context::SavedContext;
pub use table::{MAX_THREADS, ThreadTable};
#[cfg(test)]
#[path = "tests.rs"]
@@ -29,56 +34,6 @@ pub enum ThreadState {
Dead,
}
pub struct SavedContext {
registers: [usize; 32],
pc: usize,
status: usize,
}
impl SavedContext {
pub fn empty() -> Self {
Self {
registers: [0; 32],
pc: 0,
status: 0,
}
}
pub fn with_entry_and_stack(
entry: types::address::EntryPoint,
stack: types::address::StackPointer,
) -> Self {
let mut ctx = Self::empty();
ctx.pc = entry.raw();
ctx.registers[2] = stack.raw();
ctx
}
pub fn program_counter(&self) -> usize {
self.pc
}
pub fn set_pc(&mut self, pc: usize) {
self.pc = pc;
}
pub fn status(&self) -> usize {
self.status
}
pub fn set_status(&mut self, status: usize) {
self.status = status;
}
pub fn registers(&self) -> &[usize; 32] {
&self.registers
}
pub fn registers_mut(&mut self) -> &mut [usize; 32] {
&mut self.registers
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum BlockReason {
/// Queued as a sender on the endpoint.
@@ -228,129 +183,3 @@ impl Thread {
}
}
}
pub const MAX_THREADS: usize = if cfg!(kani) { 3 } else { 256 };
pub struct ThreadTable {
threads: [Option<Thread>; MAX_THREADS],
generations: SlotGenerations<MAX_THREADS>,
}
impl ThreadTable {
pub fn new() -> Self {
Self {
threads: [const { None }; MAX_THREADS],
generations: SlotGenerations::new(),
}
}
/// Current generation of a live thread, so references to it (reply
/// slots) can detect that the id was reused.
pub fn generation(&self, id: ThreadId) -> Option<Generation> {
self.get(id).ok()?;
self.generations.current(id.raw() as usize)
}
fn free_slot(&self) -> Option<usize> {
self.threads
.iter()
.enumerate()
.position(|(i, t)| t.is_none() && self.generations.is_usable(i))
}
pub fn spawn(
&mut self,
process: ProcessId,
priority: Priority,
time_slice: TimeSlice,
core_affinity: Option<CoreId>,
) -> Result<ThreadId, KernelError> {
let idx = self.free_slot().ok_or(KernelError::TooManyThreads)?;
let id = ThreadId::from_raw(idx as u16);
*self
.threads
.get_mut(idx)
.ok_or(KernelError::TooManyThreads)? = Some(Thread::new(
id,
process,
priority,
time_slice,
core_affinity,
));
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.free_slot().ok_or(KernelError::TooManyThreads)?;
let id = ThreadId::from_raw(idx as u16);
*self
.threads
.get_mut(idx)
.ok_or(KernelError::TooManyThreads)? = Some(Thread::with_context(
id,
process,
priority,
time_slice,
core_affinity,
context,
));
Ok(id)
}
/// Every live thread with its id.
pub fn iter(&self) -> impl Iterator<Item = (ThreadId, &Thread)> {
self.threads
.iter()
.enumerate()
.filter_map(|(i, t)| Some((ThreadId::from_raw(i as u16), t.as_ref()?)))
}
pub fn get(&self, id: ThreadId) -> Result<&Thread, KernelError> {
let idx = id.raw() as usize;
self.threads
.get(idx)
.and_then(|s| s.as_ref())
.ok_or(KernelError::InvalidThread(id))
}
pub fn get_mut(&mut self, id: ThreadId) -> Result<&mut Thread, KernelError> {
let idx = id.raw() as usize;
self.threads
.get_mut(idx)
.and_then(|s| s.as_mut())
.ok_or(KernelError::InvalidThread(id))
}
pub fn destroy(&mut self, id: ThreadId) -> Result<Thread, KernelError> {
let idx = id.raw() as usize;
let thread = self
.threads
.get_mut(idx)
.and_then(|s| s.take())
.ok_or(KernelError::InvalidThread(id))?;
self.generations.advance(idx);
Ok(thread)
}
pub fn threads_for_process(&self, process: ProcessId) -> impl Iterator<Item = &Thread> {
self.threads
.iter()
.filter_map(|s| s.as_ref())
.filter(move |t| t.process() == process)
}
}
impl Default for ThreadTable {
fn default() -> Self {
Self::new()
}
}

View File

@@ -0,0 +1,137 @@
//! Fixed-capacity table of threads.
use types::{
bounded::Priority,
generation::Generation,
id::{CoreId, ProcessId, ThreadId},
time::TimeSlice,
};
use super::{SavedContext, Thread};
use crate::{error::KernelError, generations::SlotGenerations};
pub const MAX_THREADS: usize = if cfg!(kani) { 3 } else { 256 };
pub struct ThreadTable {
threads: [Option<Thread>; MAX_THREADS],
generations: SlotGenerations<MAX_THREADS>,
}
impl ThreadTable {
pub fn new() -> Self {
Self {
threads: [const { None }; MAX_THREADS],
generations: SlotGenerations::new(),
}
}
/// Current generation of a live thread, so references to it (reply
/// slots) can detect that the id was reused.
pub fn generation(&self, id: ThreadId) -> Option<Generation> {
self.get(id).ok()?;
self.generations.current(id.raw() as usize)
}
fn free_slot(&self) -> Option<usize> {
self.threads
.iter()
.enumerate()
.position(|(i, t)| t.is_none() && self.generations.is_usable(i))
}
pub fn spawn(
&mut self,
process: ProcessId,
priority: Priority,
time_slice: TimeSlice,
core_affinity: Option<CoreId>,
) -> Result<ThreadId, KernelError> {
let idx = self.free_slot().ok_or(KernelError::TooManyThreads)?;
let id = ThreadId::from_raw(idx as u16);
*self
.threads
.get_mut(idx)
.ok_or(KernelError::TooManyThreads)? = Some(Thread::new(
id,
process,
priority,
time_slice,
core_affinity,
));
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.free_slot().ok_or(KernelError::TooManyThreads)?;
let id = ThreadId::from_raw(idx as u16);
*self
.threads
.get_mut(idx)
.ok_or(KernelError::TooManyThreads)? = Some(Thread::with_context(
id,
process,
priority,
time_slice,
core_affinity,
context,
));
Ok(id)
}
/// Every live thread with its id.
pub fn iter(&self) -> impl Iterator<Item = (ThreadId, &Thread)> {
self.threads
.iter()
.enumerate()
.filter_map(|(i, t)| Some((ThreadId::from_raw(i as u16), t.as_ref()?)))
}
pub fn get(&self, id: ThreadId) -> Result<&Thread, KernelError> {
let idx = id.raw() as usize;
self.threads
.get(idx)
.and_then(|s| s.as_ref())
.ok_or(KernelError::InvalidThread(id))
}
pub fn get_mut(&mut self, id: ThreadId) -> Result<&mut Thread, KernelError> {
let idx = id.raw() as usize;
self.threads
.get_mut(idx)
.and_then(|s| s.as_mut())
.ok_or(KernelError::InvalidThread(id))
}
pub fn destroy(&mut self, id: ThreadId) -> Result<Thread, KernelError> {
let idx = id.raw() as usize;
let thread = self
.threads
.get_mut(idx)
.and_then(|s| s.take())
.ok_or(KernelError::InvalidThread(id))?;
self.generations.advance(idx);
Ok(thread)
}
pub fn threads_for_process(&self, process: ProcessId) -> impl Iterator<Item = &Thread> {
self.threads
.iter()
.filter_map(|s| s.as_ref())
.filter(move |t| t.process() == process)
}
}
impl Default for ThreadTable {
fn default() -> Self {
Self::new()
}
}