refactor(kernel): split ipc/memory/lib/thread by concern; trim comments
This commit is contained in:
137
crates/domain/src/thread/table.rs
Normal file
137
crates/domain/src/thread/table.rs
Normal 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()
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user