1use core::{borrow::Borrow, ffi::c_void};
4
5use hal::Stack;
6use hal::stack::Stacklike;
7
8use crate::{mem::array::IndexMap, sched::task::TaskId, utils::KernelError};
9
10#[derive(Clone, Copy, Debug, PartialEq, PartialOrd, Eq, Ord)]
12pub struct ThreadId {
13 id: usize,
14 owner: TaskId,
15}
16
17impl ThreadId {
18 pub fn new(id: usize, owner: TaskId) -> Self {
19 Self { id, owner }
20 }
21
22 pub fn as_usize(&self) -> usize {
23 self.id
24 }
25
26 pub fn owner(&self) -> TaskId {
27 self.owner
28 }
29
30 pub fn into_uid(&self, uid: usize) -> ThreadUId {
31 ThreadUId { uid, tid: *self }
32 }
33}
34
35#[derive(Clone, Copy, Debug)]
37pub struct ThreadUId {
38 uid: usize,
39 tid: ThreadId,
40}
41
42impl ThreadUId {
43 pub fn tid(&self) -> ThreadId {
44 self.tid
45 }
46}
47
48impl PartialEq for ThreadUId {
49 fn eq(&self, other: &Self) -> bool {
50 self.uid == other.uid
51 }
52}
53
54impl Eq for ThreadUId {}
55
56impl Borrow<usize> for ThreadUId {
57 fn borrow(&self) -> &usize {
58 &self.uid
59 }
60}
61
62impl Default for ThreadUId {
63 fn default() -> Self {
64 Self {
65 uid: 0,
66 tid: ThreadId::new(0, TaskId::User(0)),
67 }
68 }
69}
70
71impl PartialOrd for ThreadUId {
72 fn partial_cmp(&self, other: &Self) -> Option<core::cmp::Ordering> {
73 Some(self.cmp(other))
74 }
75}
76
77impl Ord for ThreadUId {
78 fn cmp(&self, other: &Self) -> core::cmp::Ordering {
79 self.uid.cmp(&other.uid)
80 }
81}
82
83pub struct ThreadDescriptor {
86 pub tid: ThreadId,
87 pub stack: Stack,
88 pub timing: Timing,
89}
90
91#[derive(Debug, Clone, Copy, PartialEq, Eq)]
93pub struct Timing {
94 pub period: usize,
96 pub deadline: usize,
98 pub exec_time: usize,
100}
101
102pub enum RunState {
104 Runs,
106 Ready,
108 Waits,
110}
111
112pub struct ThreadState {
113 run_state: RunState,
114 stack: Stack,
115}
116
117pub struct Thread {
119 state: ThreadState,
121 timing: Timing,
123 tuid: ThreadUId,
125}
126
127impl Thread {
128 fn new(tuid: ThreadUId, stack: Stack, timing: Timing) -> Self {
135 Self {
136 state: ThreadState {
137 run_state: RunState::Ready,
138 stack,
139 },
140 timing,
141 tuid,
142 }
143 }
144
145 pub fn update_sp(&mut self, sp: *mut c_void) -> Result<(), KernelError> {
146 let sp = self.state.stack.create_sp(sp)?;
147 self.state.stack.set_sp(sp);
148 Ok(())
149 }
150
151 pub fn update_run_state(&mut self, state: RunState) {
152 self.state.run_state = state;
153 }
154
155 pub fn timing(&self) -> &Timing {
156 &self.timing
157 }
158
159 pub fn sp(&self) -> *mut c_void {
160 self.state.stack.sp()
161 }
162
163 pub fn tuid(&self) -> ThreadUId {
164 self.tuid
165 }
166}
167
168pub struct ThreadMap<const N: usize> {
169 map: IndexMap<ThreadUId, Thread, N>,
170}
171
172impl<const N: usize> ThreadMap<N> {
173 pub const fn new() -> Self {
174 Self {
175 map: IndexMap::new(),
176 }
177 }
178
179 pub fn create(&mut self, desc: ThreadDescriptor) -> Result<ThreadUId, KernelError> {
180 let idx = self.map.find_empty().ok_or(KernelError::OutOfMemory)?;
181 let tuid = desc.tid.into_uid(idx);
182 let thread = Thread::new(tuid, desc.stack, desc.timing);
183
184 self.map.insert(&tuid, thread)?;
185 Ok(tuid)
186 }
187
188 pub fn get_mut(&mut self, id: &ThreadUId) -> Option<&mut Thread> {
189 self.map.get_mut(id)
190 }
191
192 pub fn get(&self, id: &ThreadUId) -> Option<&Thread> {
193 self.map.get(id)
194 }
195
196 pub fn remove(&mut self, id: &ThreadUId) -> Option<Thread> {
197 self.map.remove(id)
198 }
199}