1use crate::{
2 error::Result,
3 sched::thread::{self},
4 types::list::List,
5};
6
7pub struct Scheduler<const N: usize> {
8 queue: List<thread::RRList, thread::UId>,
9
10 current: Option<thread::UId>,
11 current_left: u32,
12 quantum: u32,
13}
14
15impl<const N: usize> Scheduler<N> {
16 pub const fn new() -> Self {
17 Self {
19 queue: List::new(),
20 current: None,
21 current_left: 0,
22 quantum: 1000,
23 }
24 }
25
26 pub fn enqueue(&mut self, uid: thread::UId, storage: &mut super::ThreadMap<N>) -> Result<()> {
27 self.queue
28 .push_back(uid, storage)
29 .map_err(|_| kerr!(InvalidArgument))
30 }
31
32 pub fn put(&mut self, uid: thread::UId, dt: u32) {
33 if let Some(current) = self.current {
34 if current == uid {
35 self.current_left = self.current_left.saturating_sub(dt);
36 }
37 }
38 }
39
40 pub fn pick(&mut self, storage: &mut super::ThreadMap<N>) -> Option<(thread::UId, u32)> {
41 match self.current {
42 Some(current) if self.current_left > 0 => return Some((current, self.current_left)),
43 Some(current) => {
44 if self.queue.pop_front(storage).is_err() {
45 bug!("current thread not found in queue");
48 }
49 if self.queue.push_back(current, storage).is_err() {
50 bug!("cannot push current thread back to queue");
53 }
54
55 self.current = self.queue.head();
56 self.current_left = self.quantum;
57 }
58 None => {
59 self.current = self.queue.head();
60 self.current_left = self.quantum;
61 }
62 }
63
64 self.current.map(|id| (id, self.current_left))
65 }
66
67 pub fn dequeue(&mut self, uid: thread::UId, storage: &mut super::ThreadMap<N>) -> Result<()> {
68 self.queue.remove(uid, storage)?;
69
70 if self.current == Some(uid) {
71 self.current = None;
72 }
73
74 Ok(())
75 }
76}