1#![allow(dead_code)]
2
3use core::ptr::NonNull;
4
5use crate::priority_queue::*;
6use crate::timeout_queue::*;
7use crate::*;
8
9pub(crate) type TaskQueue = PriorityQueue<Task, Priority>;
10type TimeQueue = TimeoutQueue<Task, RelativeTime>;
11
12pub(crate) fn current_task() -> Option<&'static mut Task> {
17 ready_queue::front() }
19
20pub(crate) fn detach_current_task() -> Option<&'static mut Task> {
21 ready_queue::pop_front() }
23
24mod ready_queue {
25 use super::*;
26
27 static mut READY_QUEUE: TaskQueue = TaskQueue::new();
28
29 pub(crate) fn front() -> Option<&'static mut Task> {
30 unsafe { READY_QUEUE.front() }
31 }
32
33 pub(crate) fn pop_front() -> Option<&'static mut Task> {
34 unsafe { READY_QUEUE.pop_front() }
35 }
36
37 pub(crate) fn attach(task: &mut Task) {
38 unsafe {
39 READY_QUEUE.insert_priority_order(task);
40 }
41 }
42
43 pub(crate) fn detach(task: &mut Task) {
44 unsafe {
45 READY_QUEUE.remove(task);
46 }
47 }
48
49 pub(crate) fn is_attached(task: &Task) -> bool {
50 task.queue == Some(unsafe { NonNull::new_unchecked(&mut READY_QUEUE as *mut TaskQueue) })
51 }
52}
53
54mod timeout_queue {
59 use super::*;
60
61 static mut TIME_QUEUE: TimeQueue = TimeQueue::new();
62
63 pub(crate) fn sig_tim(tick: RelativeTime) {
64 unsafe {
65 TIME_QUEUE.sig_tim(tick);
66 }
67 }
68
69 pub(crate) fn attach(task: &mut Task, time: RelativeTime) {
70 unsafe {
71 TIME_QUEUE.add(task, time);
72 }
73 }
74
75 pub(crate) fn detach(task: &mut Task) {
76 unsafe {
77 TIME_QUEUE.remove(task);
78 }
79 }
80
81 pub(crate) fn is_attached(task: &Task) -> bool {
82 !task.timeout.prev.is_none()
83 }
84}
85
86pub fn supply_time_tick_for_timeout(tick: RelativeTime) {
87 timeout_queue::sig_tim(tick);
88}
89
90struct Timeout {
95 difftim: RelativeTime,
96 next: Option<NonNull<Task>>,
97 prev: Option<NonNull<Task>>,
98}
99
100impl Timeout {
101 const fn new() -> Self {
102 Timeout {
103 difftim: 0,
104 next: None,
105 prev: None,
106 }
107 }
108}
109
110pub struct Task {
112 context: crate::context::Context,
113 queue: Option<NonNull<TaskQueue>>,
114 next: Option<NonNull<Task>>,
115 priority: Priority,
116 task: Option<fn(isize)>,
117 exinf: isize,
118 actcnt: ActivateCount,
119 timeout: Timeout,
120 result: Result<(), Error>,
121}
122
123impl Task {
124 pub const fn new() -> Self {
126 Task {
127 context: Context::new(),
128 queue: None,
129 next: None,
130 priority: 0,
131 task: None,
132 exinf: 0,
133 actcnt: 0,
134 timeout: Timeout::new(),
135 result: Ok(()),
136 }
137 }
138
139 pub fn create(&mut self, exinf: isize, task: fn(isize), priority: Priority, stack: &mut [u8]) {
141 extern "C" fn task_entry(exinf: isize) {
142 unsafe {
143 let task_ptr = exinf as *mut Task;
144 let task = &mut *task_ptr;
145 loop {
146 while task.actcnt > 0 {
147 task.actcnt -= 1;
148 cpu_unlock();
149 (task.task.unwrap())(task.exinf);
150 cpu_lock();
151 }
152 task.detach_from_queue();
153 task_switch()
154 }
155 }
156 }
157
158 self.exinf = exinf;
159 self.task = Some(task);
160 self.priority = priority;
161
162 let task_ptr = self as *mut Task;
163 self.context.create(stack, task_entry, task_ptr as isize);
164 }
165
166 pub(crate) fn result(&self) -> Result<(), Error> {
167 self.result
168 }
169
170 pub(crate) fn set_result(&mut self, result: Result<(), Error>) {
171 self.result = result;
172 }
173
174 pub(crate) fn is_attached_to_ready_queue(&self) -> bool {
175 ready_queue::is_attached(self)
176 }
177
178 pub(crate) fn is_attached_to_timeout(&self) -> bool {
179 timeout_queue::is_attached(self)
180 }
181
182 pub(crate) fn is_attached_to_any_queue(&self) -> bool {
183 self.queue != None
184 }
185
186 pub(crate) fn is_attached_to_wait_queue(&self) -> bool {
187 !self.is_attached_to_ready_queue() && self.is_attached_to_any_queue()
188 }
189
190 pub(crate) fn attach_to_ready_queue(&mut self) {
191 debug_assert!(!self.is_attached_to_timeout());
192 debug_assert!(!self.is_attached_to_any_queue());
193 ready_queue::attach(self);
194 }
195
196 pub(crate) fn attach_to_queue(&mut self, que: &mut TaskQueue, order: Order) {
197 debug_assert!(!self.is_attached_to_any_queue());
198 match order {
199 Order::Priority => {
200 que.insert_priority_order(self);
201 }
202 Order::Fifo => {
203 que.push_back(self);
204 }
205 }
206 }
207
208 pub(crate) fn detach_from_queue(&mut self) {
209 match self.queue {
210 Some(mut que) => unsafe {
211 que.as_mut().remove(self);
212 },
213 _ => {}
214 }
215 }
216
217 pub(crate) fn attach_to_timeout(&mut self, time: RelativeTime) {
218 debug_assert_eq!(self.timeout.prev, None);
219 timeout_queue::attach(self, time);
220 }
221
222 pub(crate) fn detach_from_timeout(&mut self) {
223 if !self.timeout.prev.is_none() {
224 timeout_queue::detach(self);
225 }
226 }
227
228 unsafe fn switch(&mut self) {
230 self.context.switch();
231 }
232
233 pub fn priority(&self) -> Priority {
234 self.priority
235 }
236
237 pub fn activate(&mut self) {
238 let _sc = SystemCall::new();
239 self.actcnt += 1;
240 if self.queue == None {
241 self.attach_to_ready_queue();
242 set_dispatch_reserve_flag();
243 }
244 }
245}
246
247impl PriorityObject<Task, Priority> for Task {
248 fn next(&self) -> Option<NonNull<Task>> {
249 self.next
250 }
251 fn set_next(&mut self, next: Option<NonNull<Task>>) {
252 self.next = next;
253 }
254 fn priority(&self) -> Priority {
255 self.priority
256 }
257 fn queue(&self) -> Option<NonNull<TaskQueue>> {
258 self.queue
259 }
260
261 fn set_queue(&mut self, que: Option<NonNull<TaskQueue>>) {
262 self.queue = que;
263 }
264
265 fn queue_dropped(&mut self) {}
266}
267
268impl TimeoutObject<Task, RelativeTime> for Task {
269 fn difftim(&self) -> RelativeTime {
270 self.timeout.difftim
271 }
272 fn set_difftim(&mut self, difftim: RelativeTime) {
273 self.timeout.difftim = difftim;
274 }
275
276 fn next(&self) -> Option<NonNull<Task>> {
277 self.timeout.next
278 }
279 fn set_next(&mut self, next: Option<NonNull<Task>>) {
280 self.timeout.next = next;
281 }
282
283 fn prev(&self) -> Option<NonNull<Task>> {
284 self.timeout.prev
285 }
286 fn set_prev(&mut self, prev: Option<NonNull<Task>>) {
287 self.timeout.prev = prev;
288 }
289
290 fn timeout(&mut self) {
291 self.detach_from_queue();
292 self.attach_to_ready_queue();
293 self.result = Err(Error::Timeout);
294 set_dispatch_reserve_flag();
295 }
296
297 fn queue_dropped(&mut self) {}
298}
299
300pub(crate) unsafe fn task_switch() {
301 let head = ready_queue::front();
302 match head {
303 None => {
304 context_switch_to_system();
306 }
307 Some(task) => {
308 task.switch();
309 }
310 };
311}