strat9_kernel/process/sched_classes/
real_time.rs1use super::{CurrentRuntime, SchedClassRq};
4use crate::{arch::x86_64::timer::TIMER_HZ, process::task::Task};
5use alloc::{collections::VecDeque, sync::Arc};
6
7const RT_RR_QUANTUM_TICKS: u64 = TIMER_HZ / 10;
12
13#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
15pub struct RealTimePriority(u8);
16
17impl RealTimePriority {
18 pub const MIN: Self = Self(0);
19 pub const MAX: Self = Self(99);
20
21 pub fn new(prio: u8) -> Self {
23 Self(prio.clamp(Self::MIN.0, Self::MAX.0))
24 }
25
26 pub fn get(self) -> u8 {
28 self.0
29 }
30}
31
32pub struct RealTimeClassRq {
33 queues: [VecDeque<Arc<Task>>; 100],
34 bitmap: u128, }
36
37impl RealTimeClassRq {
38 pub fn new() -> Self {
40 const EMPTY: VecDeque<Arc<Task>> = VecDeque::new();
41 Self {
42 queues: [EMPTY; 100],
43 bitmap: 0,
44 }
45 }
46
47 fn set_bit(&mut self, prio: u8) {
49 self.bitmap |= 1u128 << prio;
50 }
51
52 fn clear_bit(&mut self, prio: u8) {
54 self.bitmap &= !(1u128 << prio);
55 }
56}
57
58impl SchedClassRq for RealTimeClassRq {
59 fn enqueue(&mut self, task: Arc<Task>) {
61 let prio = match task.sched_policy() {
62 super::SchedPolicy::RealTimeRR { prio } => prio.get(),
63 super::SchedPolicy::RealTimeFifo { prio } => prio.get(),
64 _ => return, };
66 self.queues[prio as usize].push_back(task);
67 self.set_bit(prio);
68 }
69
70 fn len(&self) -> usize {
72 self.queues.iter().map(|q| q.len()).sum()
73 }
74
75 fn pick_next(&mut self) -> Option<Arc<Task>> {
77 if self.bitmap == 0 {
78 return None;
79 }
80 let highest = 127 - self.bitmap.leading_zeros() as u8;
82 let q = &mut self.queues[highest as usize];
83 let task = q.pop_front()?;
84 if q.is_empty() {
85 self.clear_bit(highest);
86 }
87 Some(task)
88 }
89
90 fn update_current(&mut self, rt: &CurrentRuntime, task: &Task, is_yield: bool) -> bool {
92 if is_yield {
93 return true;
94 }
95 let policy = task.sched_policy();
96 match policy {
97 super::SchedPolicy::RealTimeRR { .. } => {
98 rt.period_delta_ticks >= RT_RR_QUANTUM_TICKS
100 }
101 super::SchedPolicy::RealTimeFifo { .. } => {
102 false
104 }
105 _ => false,
106 }
107 }
108
109 fn remove(&mut self, task_id: crate::process::TaskId) -> bool {
111 let mut removed = false;
112 let mut bits = self.bitmap;
113 while bits != 0 {
114 let i = bits.trailing_zeros() as usize;
115 let q = &mut self.queues[i];
116 let old_len = q.len();
117 q.retain(|t| t.id != task_id);
118 if q.len() < old_len {
119 removed = true;
120 if q.is_empty() {
121 self.clear_bit(i as u8);
122 }
123 }
124 bits &= !(1u128 << i);
125 }
126 removed
127 }
128}