feat(domain): add Thread constructor, accessors, and state machine transitions
This commit is contained in:
143
crates/domain/src/thread/mod.rs
Normal file
143
crates/domain/src/thread/mod.rs
Normal file
@@ -0,0 +1,143 @@
|
||||
use types::{
|
||||
bounded::{CapSlot, Priority},
|
||||
id::{CoreId, ProcessId, ThreadId},
|
||||
time::TimeSlice,
|
||||
};
|
||||
|
||||
use crate::error::KernelError;
|
||||
|
||||
#[cfg(test)]
|
||||
#[path = "tests.rs"]
|
||||
mod tests;
|
||||
|
||||
pub struct Thread {
|
||||
id: ThreadId,
|
||||
process: ProcessId,
|
||||
state: ThreadState,
|
||||
saved_context: SavedContext,
|
||||
priority: Priority,
|
||||
time_slice: TimeSlice,
|
||||
core_affinity: Option<CoreId>,
|
||||
}
|
||||
|
||||
pub enum ThreadState {
|
||||
Ready,
|
||||
Running(CoreId),
|
||||
Blocked(BlockReason),
|
||||
Dead,
|
||||
}
|
||||
|
||||
pub struct SavedContext {
|
||||
registers: [usize; 32],
|
||||
}
|
||||
|
||||
impl SavedContext {
|
||||
pub fn empty() -> Self {
|
||||
Self { registers: [0; 32] }
|
||||
}
|
||||
}
|
||||
|
||||
pub enum BlockReason {
|
||||
Sending(CapSlot),
|
||||
Receiving(CapSlot),
|
||||
WaitingForInterrupt(CapSlot),
|
||||
WaitingAny,
|
||||
}
|
||||
|
||||
impl Thread {
|
||||
pub fn new(
|
||||
id: ThreadId,
|
||||
process: ProcessId,
|
||||
priority: Priority,
|
||||
time_slice: TimeSlice,
|
||||
core_affinity: Option<CoreId>,
|
||||
) -> Self {
|
||||
Self {
|
||||
id,
|
||||
process,
|
||||
state: ThreadState::Ready,
|
||||
saved_context: SavedContext::empty(),
|
||||
priority,
|
||||
time_slice,
|
||||
core_affinity,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn id(&self) -> ThreadId {
|
||||
self.id
|
||||
}
|
||||
|
||||
pub fn process(&self) -> ProcessId {
|
||||
self.process
|
||||
}
|
||||
|
||||
pub fn state(&self) -> &ThreadState {
|
||||
&self.state
|
||||
}
|
||||
|
||||
pub fn priority(&self) -> Priority {
|
||||
self.priority
|
||||
}
|
||||
|
||||
pub fn time_slice(&self) -> &TimeSlice {
|
||||
&self.time_slice
|
||||
}
|
||||
|
||||
pub fn time_slice_mut(&mut self) -> &mut TimeSlice {
|
||||
&mut self.time_slice
|
||||
}
|
||||
|
||||
pub fn core_affinity(&self) -> Option<CoreId> {
|
||||
self.core_affinity
|
||||
}
|
||||
|
||||
pub fn set_running(&mut self, core: CoreId) -> Result<(), KernelError> {
|
||||
match self.state {
|
||||
ThreadState::Ready => {
|
||||
self.state = ThreadState::Running(core);
|
||||
Ok(())
|
||||
}
|
||||
_ => Err(KernelError::InvalidStateTransition(self.id)),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn block(&mut self, reason: BlockReason) -> Result<(), KernelError> {
|
||||
match self.state {
|
||||
ThreadState::Running(_) => {
|
||||
self.state = ThreadState::Blocked(reason);
|
||||
Ok(())
|
||||
}
|
||||
_ => Err(KernelError::InvalidStateTransition(self.id)),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn unblock(&mut self) -> Result<(), KernelError> {
|
||||
match self.state {
|
||||
ThreadState::Blocked(_) => {
|
||||
self.state = ThreadState::Ready;
|
||||
Ok(())
|
||||
}
|
||||
_ => Err(KernelError::InvalidStateTransition(self.id)),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn preempt(&mut self) -> Result<(), KernelError> {
|
||||
match self.state {
|
||||
ThreadState::Running(_) => {
|
||||
self.state = ThreadState::Ready;
|
||||
Ok(())
|
||||
}
|
||||
_ => Err(KernelError::InvalidStateTransition(self.id)),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn exit(&mut self) -> Result<(), KernelError> {
|
||||
match self.state {
|
||||
ThreadState::Running(_) => {
|
||||
self.state = ThreadState::Dead;
|
||||
Ok(())
|
||||
}
|
||||
_ => Err(KernelError::InvalidStateTransition(self.id)),
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user