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