components/sched/
round_robin.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 round robin scheduler.
6//!
7//! This provides one Component, RoundRobinComponent.
8//!
9//! Usage
10//! -----
11//! ```rust
12//! let scheduler = components::round_robin::RoundRobinComponent::new(&PROCESSES)
13//!     .finalize(components::round_robin_component_static!(NUM_PROCS));
14//! ```
15
16// Author: Hudson Ayers <hayers@stanford.edu>
17// Last modified: 03/31/2020
18
19use core::mem::MaybeUninit;
20use kernel::component::Component;
21use kernel::process::Process;
22use kernel::scheduler::round_robin::{RoundRobinProcessNode, RoundRobinSched};
23
24#[macro_export]
25macro_rules! round_robin_component_static {
26    ($N:expr $(,)?) => {{
27        let rr_sched =
28            kernel::static_buf!(kernel::scheduler::round_robin::RoundRobinSched<'static>);
29        let rr_nodes = kernel::static_buf!(
30            [core::mem::MaybeUninit<kernel::scheduler::round_robin::RoundRobinProcessNode<'static>>;
31                $N]
32        );
33
34        (rr_sched, rr_nodes)
35    };};
36}
37
38pub struct RoundRobinComponent<const NUM_PROCS: usize> {
39    processes: &'static [Option<&'static dyn Process>],
40}
41
42impl<const NUM_PROCS: usize> RoundRobinComponent<NUM_PROCS> {
43    pub fn new(
44        processes: &'static [Option<&'static dyn Process>],
45    ) -> RoundRobinComponent<NUM_PROCS> {
46        RoundRobinComponent { processes }
47    }
48}
49
50impl<const NUM_PROCS: usize> Component for RoundRobinComponent<NUM_PROCS> {
51    type StaticInput = (
52        &'static mut MaybeUninit<RoundRobinSched<'static>>,
53        &'static mut MaybeUninit<[MaybeUninit<RoundRobinProcessNode<'static>>; NUM_PROCS]>,
54    );
55    type Output = &'static mut RoundRobinSched<'static>;
56
57    fn finalize(self, static_buffer: Self::StaticInput) -> Self::Output {
58        let scheduler = static_buffer.0.write(RoundRobinSched::new());
59
60        const UNINIT: MaybeUninit<RoundRobinProcessNode<'static>> = MaybeUninit::uninit();
61        let nodes = static_buffer.1.write([UNINIT; NUM_PROCS]);
62
63        for (i, node) in nodes.iter_mut().enumerate() {
64            let init_node = node.write(RoundRobinProcessNode::new(&self.processes[i]));
65            scheduler.processes.push_head(init_node);
66        }
67        scheduler
68    }
69}