components/sched/
mlfq.rs

1// Licensed under the Apache License, Version 2.0 or the MIT License.
2// SPDX-License-Identifier: Apache-2.0 OR MIT
3// Copyright Tock Contributors 2022.
4
5//! Component for a multi-level feedback queue scheduler.
6//!
7//! This provides one Component, MLFQComponent.
8
9// Author: Hudson Ayers <hayers@stanford.edu>
10// Last modified: 03/31/2020
11
12use core::mem::MaybeUninit;
13
14use capsules_core::virtualizers::virtual_alarm::{MuxAlarm, VirtualMuxAlarm};
15use kernel::component::Component;
16use kernel::hil::time;
17use kernel::process::Process;
18use kernel::scheduler::mlfq::{MLFQProcessNode, MLFQSched};
19
20#[macro_export]
21macro_rules! mlfq_component_static {
22    ($A:ty, $N:expr $(,)?) => {{
23        let alarm = kernel::static_buf!(
24            capsules_core::virtualizers::virtual_alarm::VirtualMuxAlarm<'static, $A>
25        );
26        let mlfq_sched = kernel::static_buf!(
27            kernel::scheduler::mlfq::MLFQSched<
28                'static,
29                capsules_core::virtualizers::virtual_alarm::VirtualMuxAlarm<'static, $A>,
30            >
31        );
32        let mlfq_node = kernel::static_buf!(
33            [core::mem::MaybeUninit<kernel::scheduler::mlfq::MLFQProcessNode<'static>>; $N]
34        );
35
36        (alarm, mlfq_sched, mlfq_node)
37    };};
38}
39
40pub struct MLFQComponent<A: 'static + time::Alarm<'static>, const NUM_PROCS: usize> {
41    alarm_mux: &'static MuxAlarm<'static, A>,
42    processes: &'static [Option<&'static dyn Process>],
43}
44
45impl<A: 'static + time::Alarm<'static>, const NUM_PROCS: usize> MLFQComponent<A, NUM_PROCS> {
46    pub fn new(
47        alarm_mux: &'static MuxAlarm<'static, A>,
48        processes: &'static [Option<&'static dyn Process>],
49    ) -> MLFQComponent<A, NUM_PROCS> {
50        MLFQComponent {
51            alarm_mux,
52            processes,
53        }
54    }
55}
56
57impl<A: 'static + time::Alarm<'static>, const NUM_PROCS: usize> Component
58    for MLFQComponent<A, NUM_PROCS>
59{
60    type StaticInput = (
61        &'static mut MaybeUninit<VirtualMuxAlarm<'static, A>>,
62        &'static mut MaybeUninit<MLFQSched<'static, VirtualMuxAlarm<'static, A>>>,
63        &'static mut MaybeUninit<[MaybeUninit<MLFQProcessNode<'static>>; NUM_PROCS]>,
64    );
65    type Output = &'static mut MLFQSched<'static, VirtualMuxAlarm<'static, A>>;
66
67    fn finalize(self, static_buffer: Self::StaticInput) -> Self::Output {
68        let scheduler_alarm = static_buffer.0.write(VirtualMuxAlarm::new(self.alarm_mux));
69        scheduler_alarm.setup();
70
71        let scheduler = static_buffer.1.write(MLFQSched::new(scheduler_alarm));
72
73        const UNINIT: MaybeUninit<MLFQProcessNode<'static>> = MaybeUninit::uninit();
74        let nodes = static_buffer.2.write([UNINIT; NUM_PROCS]);
75
76        for (i, node) in nodes.iter_mut().enumerate() {
77            let init_node = node.write(MLFQProcessNode::new(&self.processes[i]));
78            scheduler.processes[0].push_head(init_node);
79        }
80        scheduler
81    }
82}