1use core::sync::atomic::{AtomicU64, Ordering};
4#[cfg(not(feature = "kernel"))]
5use core::time::Duration;
6
7#[cfg(not(feature = "kernel"))]
8use crate::syscall::*;
9use crate::syscall::{ThreadSyncFlags, ThreadSyncOp, ThreadSyncReference, ThreadSyncSleep};
10#[allow(unused_imports)]
11use crate::{
12 object::{ObjID, Protections},
13 syscall::{MapFlags, ThreadSpawnArgs, ThreadSpawnFlags},
14};
15
16pub mod event;
17#[derive(Default)]
19#[repr(C)]
20pub struct ThreadRepr {
21 version: u32,
22 flags: u32,
23 #[cfg(not(feature = "kernel"))]
24 status: AtomicU64,
25 #[cfg(feature = "kernel")]
26 pub status: AtomicU64,
27 code: AtomicU64,
28}
29
30#[derive(Debug, Clone, Copy, PartialEq, PartialOrd, Ord, Eq, Hash)]
40#[repr(u8)]
41pub enum ExecutionState {
42 Running,
44 Sleeping,
46 Suspended,
48 Exited = 255,
50}
51
52impl ExecutionState {
53 pub fn from_status(status: u64) -> Self {
54 match status & 0xff {
56 1 => ExecutionState::Sleeping,
57 2 => ExecutionState::Suspended,
58 255 => ExecutionState::Exited,
59 _ => ExecutionState::Running,
60 }
61 }
62
63 pub fn to_status(&self) -> u64 {
64 match self {
65 ExecutionState::Running => 0,
66 ExecutionState::Sleeping => 1,
67 ExecutionState::Suspended => 2,
68 ExecutionState::Exited => 255,
69 }
70 }
71}
72
73impl ThreadRepr {
74 pub fn get_state(&self) -> ExecutionState {
75 let status = self.status.load(Ordering::Acquire);
76 ExecutionState::from_status(status)
77 }
78
79 pub fn get_code(&self) -> u64 {
80 self.code.load(Ordering::SeqCst)
81 }
82
83 pub fn set_state(&self, state: ExecutionState, code: u64) -> ExecutionState {
84 let mut old_status = self.status.load(Ordering::SeqCst);
85 loop {
86 let old_state = ExecutionState::from_status(old_status);
87 if old_state == ExecutionState::Exited {
88 return old_state;
89 }
90
91 let status = state as u8 as u64;
92 if state == ExecutionState::Exited {
93 self.code.store(code, Ordering::SeqCst);
94 }
95
96 let result = self.status.compare_exchange(
97 old_status,
98 status,
99 Ordering::SeqCst,
100 Ordering::SeqCst,
101 );
102 match result {
103 Ok(_) => {
104 if !(old_state == ExecutionState::Running && state == ExecutionState::Sleeping
105 || old_state == ExecutionState::Sleeping
106 && state == ExecutionState::Running)
107 && old_state != state
108 {
109 #[cfg(not(feature = "kernel"))]
110 let _ = sys_thread_sync(
111 &mut [ThreadSync::new_wake(ThreadSyncWake::new(
112 ThreadSyncReference::Virtual(&self.status),
113 usize::MAX,
114 ))],
115 None,
116 );
117 }
118 return old_state;
119 }
120 Err(x) => {
121 old_status = x;
122 }
123 }
124 }
125 }
126
127 pub fn waitable(&self, state: ExecutionState) -> ThreadSyncSleep {
129 ThreadSyncSleep::new(
130 ThreadSyncReference::Virtual(&self.status),
131 state as u64,
132 ThreadSyncOp::Equal,
133 ThreadSyncFlags::INVERT,
134 )
135 }
136
137 pub fn waitable_until_not(&self, state: ExecutionState) -> ThreadSyncSleep {
139 ThreadSyncSleep::new(
140 ThreadSyncReference::Virtual(&self.status),
141 state as u64,
142 ThreadSyncOp::Equal,
143 ThreadSyncFlags::empty(),
144 )
145 }
146
147 #[cfg(not(feature = "kernel"))]
148 pub fn wait(
151 &self,
152 expected: ExecutionState,
153 timeout: Option<Duration>,
154 ) -> Option<(ExecutionState, u64)> {
155 let mut status = self.get_state();
156 loop {
157 if status != expected {
158 return Some((status, self.code.load(Ordering::SeqCst)));
159 }
160 let op = self.waitable_until_not(expected);
161 sys_thread_sync(&mut [ThreadSync::new_sleep(op)], timeout).unwrap();
162 status = self.get_state();
163 if timeout.is_some() && status == expected {
164 return None;
165 }
166 }
167 }
168
169 #[cfg(not(feature = "kernel"))]
170 pub fn wait_until(
173 &self,
174 target: ExecutionState,
175 timeout: Option<Duration>,
176 ) -> Option<(ExecutionState, u64)> {
177 let mut status = self.get_state();
178 loop {
179 if status == target {
180 return Some((status, self.code.load(Ordering::SeqCst)));
181 }
182 let op = self.waitable(target);
183 sys_thread_sync(&mut [ThreadSync::new_sleep(op)], timeout).unwrap();
184 status = self.get_state();
185 if timeout.is_some() && status != target {
186 return None;
187 }
188 }
189 }
190}