Skip to main content

kernel_api/threading/
state.rs

1use core::fmt::{Debug, Formatter};
2use core::ptr::addr_of;
3use core::sync::atomic::{Ordering, AtomicU128};
4
5fn into_raw(state: ThreadState) -> u128 {
6	let tag = unsafe { *addr_of!(state).cast::<u8>() } as u128;
7
8	match state {
9		ThreadState::Killed(exit_code) => {
10			let upper = exit_code as u128;
11			(upper << 64) | tag
12		}
13		_ => tag,
14	}
15}
16
17fn from_raw(raw: u128) -> ThreadState {
18	let tag = raw as u8;
19
20	match tag {
21		0 => ThreadState::Ready,
22		1 => ThreadState::Running,
23		2 => ThreadState::Parked,
24		3 => ThreadState::NearlyParked,
25		4 => ThreadState::Killed((raw >> 64) as isize),
26		_ => unreachable!("invalid thread state"),
27	}
28}
29
30pub struct AtomicThreadState(AtomicU128);
31
32impl AtomicThreadState {
33	pub fn new(state: ThreadState) -> Self {
34		AtomicThreadState(AtomicU128::new(into_raw(state)))
35	}
36
37	pub fn store(&self, state: ThreadState, ordering: Ordering) {
38		self.0.store(into_raw(state), ordering);
39	}
40
41	pub fn load(&self, ordering: Ordering) -> ThreadState{
42		from_raw(self.0.load(ordering))
43	}
44
45	pub fn compare_exchange(&self, current: ThreadState, new: ThreadState, success: Ordering, failure: Ordering) -> Result<ThreadState, ThreadState> {
46		let current = into_raw(current);
47		let new = into_raw(new);
48		self.0.compare_exchange(current, new, success, failure)
49				.map(from_raw)
50				.map_err(from_raw)
51	}
52
53	pub fn fetch_update(&self, set_order: Ordering, fetch_order: Ordering, mut f: impl FnMut(ThreadState) -> Option<ThreadState>) -> Result<ThreadState, ThreadState> {
54		self.0.fetch_update(set_order, fetch_order, |val| f(from_raw(val)).map(into_raw))
55				.map(from_raw)
56				.map_err(from_raw)
57	}
58	
59	pub fn running(&self) -> bool {
60		matches!(
61			self.load(Ordering::SeqCst),
62			ThreadState::Running,
63		)
64	}
65
66	pub fn runnable(&self) -> bool {
67		matches!(
68			self.load(Ordering::SeqCst),
69			ThreadState::Running | ThreadState::Ready | ThreadState::NearlyParked,
70		)
71	}
72}
73
74impl Debug for AtomicThreadState {
75	fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result {
76		write!(f, "AtomicThreadState {{ {:?} }}", self.load(Ordering::Relaxed))
77	}
78}
79
80#[derive(Debug)]
81#[repr(u8)]
82pub enum ThreadState {
83	/// The thread is able to run, but has not yet been scheduled
84	Ready = 0,
85	/// The thread is actively running
86	Running = 1,
87	/// The thread is parked
88	Parked = 2,
89	/// The thread is in the process of being parked
90	NearlyParked = 3,
91	Killed(isize) = 4,
92}