kernel/sched/
thread.rs

1// ----------------------------------- Identifiers -----------------------------------
2
3use 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/// Id of a task. This is only unique within a Task.
11#[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/// Unique identifier for a thread. Build from TaskId and ThreadId.
36#[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
83// -------------------------------------------------------------------------
84
85pub struct ThreadDescriptor {
86    pub tid: ThreadId,
87    pub stack: Stack,
88    pub timing: Timing,
89}
90
91/// The timing information for a thread.
92#[derive(Debug, Clone, Copy, PartialEq, Eq)]
93pub struct Timing {
94    /// The period of the thread after which it should run again.
95    pub period: usize,
96    /// The deadline of the thread.
97    pub deadline: usize,
98    /// The execution time of the thread. (How much cpu time it needs)
99    pub exec_time: usize,
100}
101
102/// The state of a thread.
103pub enum RunState {
104    /// The thread is currently using the cpu.
105    Runs,
106    /// The thread is ready to run, but is not running.
107    Ready,
108    /// The thread is waiting for an event/signal to unblock it.
109    Waits,
110}
111
112pub struct ThreadState {
113    run_state: RunState,
114    stack: Stack,
115}
116
117/// The struct representing a thread.
118pub struct Thread {
119    /// The current state of the thread.
120    state: ThreadState,
121    /// The timing constraints of the thread.
122    timing: Timing,
123    /// The unique identifier of the thread.
124    tuid: ThreadUId,
125}
126
127impl Thread {
128    /// Create a new thread.
129    ///
130    /// `stack` - The stack of the thread.
131    /// `timing` - The timing constraints of the thread.
132    ///
133    /// Returns a new thread.
134    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}