components/sched/
cooperative.rs

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
// Licensed under the Apache License, Version 2.0 or the MIT License.
// SPDX-License-Identifier: Apache-2.0 OR MIT
// Copyright Tock Contributors 2022.

//! Component for a cooperative scheduler.
//!
//! This provides one Component, CooperativeComponent.
//!
//! Usage
//! -----
//! ```rust
//! let scheduler = components::cooperative::CooperativeComponent::new(&PROCESSES)
//!     .finalize(components::cooperative_component_static!(NUM_PROCS));
//! ```

// Author: Hudson Ayers <hayers@stanford.edu>

use core::mem::MaybeUninit;
use kernel::component::Component;
use kernel::process::Process;
use kernel::scheduler::cooperative::{CoopProcessNode, CooperativeSched};

#[macro_export]
macro_rules! cooperative_component_static {
    ($N:expr $(,)?) => {{
        let coop_sched =
            kernel::static_buf!(kernel::scheduler::cooperative::CooperativeSched<'static>);
        let coop_nodes = kernel::static_buf!(
            [core::mem::MaybeUninit<kernel::scheduler::cooperative::CoopProcessNode<'static>>; $N]
        );

        (coop_sched, coop_nodes)
    };};
}

pub struct CooperativeComponent<const NUM_PROCS: usize> {
    processes: &'static [Option<&'static dyn Process>],
}

impl<const NUM_PROCS: usize> CooperativeComponent<NUM_PROCS> {
    pub fn new(
        processes: &'static [Option<&'static dyn Process>],
    ) -> CooperativeComponent<NUM_PROCS> {
        CooperativeComponent { processes }
    }
}

impl<const NUM_PROCS: usize> Component for CooperativeComponent<NUM_PROCS> {
    type StaticInput = (
        &'static mut MaybeUninit<CooperativeSched<'static>>,
        &'static mut MaybeUninit<[MaybeUninit<CoopProcessNode<'static>>; NUM_PROCS]>,
    );
    type Output = &'static mut CooperativeSched<'static>;

    fn finalize(self, static_buffer: Self::StaticInput) -> Self::Output {
        let scheduler = static_buffer.0.write(CooperativeSched::new());

        const UNINIT: MaybeUninit<CoopProcessNode<'static>> = MaybeUninit::uninit();
        let nodes = static_buffer.1.write([UNINIT; NUM_PROCS]);

        for (i, node) in nodes.iter_mut().enumerate() {
            let init_node = node.write(CoopProcessNode::new(&self.processes[i]));
            scheduler.processes.push_head(init_node);
        }
        scheduler
    }
}