1pub struct Executor {
2 pub tasks: BTreeMap<TaskId, Task>,
3 pub task_queue: Arc<ArrayQueue<TaskId>>,
4 pub waker_cache: BTreeMap<TaskId, Waker>,
5}
6
7impl Executor {
8 pub fn new() -> Self {
9 return Executor{
10 tasks: BTreeMap::new(),
11 task_queue: Arc::new(ArrayQueue::new(100)),
12 waker_cache: BTreeMap::new(),
13 };
14 }
15
16 pub fn spawn(&mut self, task: Task) {
17 let task_id = task.id;
18 if self.tasks.insert(task.id, task).is_some() {
19 log::error!("A task with the same identifier already exists");
20 }
21
22 self.task_queue.push(task_id).expect("queue full");
23 }
24
25 pub fn run(&mut self) -> ! {
26 loop{
27 self.run_ready_tasks();
28 self.sleep_if_idle();
29 }
30 }
31
32 pub fn run_ready_tasks(&mut self) {
33 let Self {
35 tasks,
36 task_queue,
37 waker_cache,
38 } = self;
39
40 while let Some(task_id) = task_queue.pop() {
41 let task = match tasks.get_mut(&task_id) {
42 Some(task) => task,
43 None => continue,
44 };
45
46 let waker = waker_cache.entry(task_id)
47 .or_insert_with(|| TaskWaker::new(task_id, task_queue.clone()));
48
49 let mut context = Context::from_waker(waker);
50 }
51 }
52
53 pub fn sleep_if_idle(&self) {
54 use x86_64::instructions::interrupts::{self, enable_and_hlt};
55
56 interrupts::disable();
57 if self.task_queue.is_empty() {
58 enable_and_hlt();
59 } else {
60 interrupts::enable();
61 }
62 }
63}
64
65pub struct TaskWaker {
66 pub task_id: TaskId,
67 pub task_queue: Arc<ArrayQueue<TaskId>>,
68}
69
70impl TaskWaker {
71 pub fn new(task_id: TaskId, task_queue: Arc<ArrayQueue<TaskId>>) -> Waker {
72 Waker::from(Arc::new(TaskWaker {
73 task_id,
74 task_queue,
75 }))
76 }
77
78 pub fn wake_task(&self) {
79 self.task_queue.push(self.task_id).expect("task queue full");
80 }
81}
82
83impl Wake for TaskWaker {
84 fn wake(self: Arc<Self>) {
85 self.wake_task();
86 }
87
88 fn wake_by_ref(self: &Arc<Self>) {
89 self.wake_task();
90 }
91}
92
93use {
96 super::{Task, TaskId},
97 std_alloc::{collections::BTreeMap, sync::Arc, task::Wake},
98 core::task::{Context, Poll, Waker},
99 crossbeam_queue::ArrayQueue,
100};