Skip to main content

strat9_kernel/process/sched_classes/
real_time.rs

1// SPDX-License-Identifier: MPL-2.0
2
3use super::{CurrentRuntime, SchedClassRq};
4use crate::{arch::x86_64::timer::TIMER_HZ, process::task::Task};
5use alloc::{collections::VecDeque, sync::Arc};
6
7/// RT Round-Robin quantum in ticks.
8///
9/// POSIX specifies a minimum of 100ms for SCHED_RR (Linux default: 100ms).
10/// At TIMER_HZ=100: 10 ticks x 10 ms/tick = 100 ms.
11const RT_RR_QUANTUM_TICKS: u64 = TIMER_HZ / 10;
12
13/// Real-time priority (0-99). Higher value means higher priority.
14#[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    /// Creates a new instance.
22    pub fn new(prio: u8) -> Self {
23        Self(prio.clamp(Self::MIN.0, Self::MAX.0))
24    }
25
26    /// Performs the get operation.
27    pub fn get(self) -> u8 {
28        self.0
29    }
30}
31
32pub struct RealTimeClassRq {
33    queues: [VecDeque<Arc<Task>>; 100],
34    bitmap: u128, // 100 bits needed (0..=99)
35}
36
37impl RealTimeClassRq {
38    /// Creates a new instance.
39    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    /// Sets bit.
48    fn set_bit(&mut self, prio: u8) {
49        self.bitmap |= 1u128 << prio;
50    }
51
52    /// Performs the clear bit operation.
53    fn clear_bit(&mut self, prio: u8) {
54        self.bitmap &= !(1u128 << prio);
55    }
56}
57
58impl SchedClassRq for RealTimeClassRq {
59    /// Performs the enqueue operation.
60    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, // Ignore tasks that shouldn't be here
65        };
66        self.queues[prio as usize].push_back(task);
67        self.set_bit(prio);
68    }
69
70    /// Performs the len operation.
71    fn len(&self) -> usize {
72        self.queues.iter().map(|q| q.len()).sum()
73    }
74
75    /// Performs the pick next operation.
76    fn pick_next(&mut self) -> Option<Arc<Task>> {
77        if self.bitmap == 0 {
78            return None;
79        }
80        // Highest priority first (99 down to 0)
81        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    /// Updates current.
91    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                // Round Robin: preempt after RT_RR_QUANTUM_TICKS (POSIX >= 100 ms).
99                rt.period_delta_ticks >= RT_RR_QUANTUM_TICKS
100            }
101            super::SchedPolicy::RealTimeFifo { .. } => {
102                // FIFO: Run until blocked or yielded
103                false
104            }
105            _ => false,
106        }
107    }
108
109    /// Performs the remove operation.
110    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}