kernel/
process_array.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 2025.
4
5//! Data structure for storing `Process`es.
6//!
7//! Many Tock boards store a fixed-length array of process control blocks
8//! (PCB) for easy management and traversal of running processes. The
9//! `ProcessArray` type facilitates this.
10//!
11//! The general type for the process array abstraction is
12//! `[&Process; NUM_PROCS]`. That is, the array is only sized to store
13//! references to each PCB. The actual PCB is allocated in the process's
14//! allocated memory.
15
16use crate::process;
17use core::cell::Cell;
18
19/// Represents a slot for a process in a [`ProcessArray`].
20///
21/// A slot can be empty (`None`), or hold a reference to a
22/// [`Process`](process::Process).
23///
24/// The `ProcessSlot` type is useful for allowing slices of processes without
25/// knowing the fixed number of processes, or being templated on `NUM_PROCS`.
26/// That is, interfaces can use `[ProcessSlot]` to just use an array of process
27/// slots.
28#[derive(Clone)]
29pub struct ProcessSlot {
30    /// Optionally points to a process.
31    pub(crate) proc: Cell<Option<&'static dyn process::Process>>,
32}
33
34impl ProcessSlot {
35    pub(crate) fn set(&self, process: &'static dyn process::Process) {
36        self.proc.set(Some(process));
37    }
38
39    /// Return the underlying [`process::Process`] if the slot contains a
40    /// process.
41    pub fn get(&self) -> Option<&'static dyn process::Process> {
42        self.proc.get()
43    }
44
45    /// Check if the slot contains a process with a matching process ID.
46    pub fn contains_process_with_id(&self, identifier: usize) -> bool {
47        match self.proc.get() {
48            Some(process) => process.processid().id() == identifier,
49            None => false,
50        }
51    }
52}
53
54/// Storage for a fixed-size array of `Process`es.
55pub struct ProcessArray<const NUM_PROCS: usize> {
56    processes: [ProcessSlot; NUM_PROCS],
57}
58
59impl<const NUM_PROCS: usize> ProcessArray<NUM_PROCS> {
60    pub const fn new() -> Self {
61        Self {
62            processes: [const {
63                ProcessSlot {
64                    proc: Cell::new(None),
65                }
66            }; NUM_PROCS],
67        }
68    }
69
70    pub fn as_slice(&self) -> &[ProcessSlot] {
71        &self.processes
72    }
73}
74
75impl<const NUM_PROCS: usize> core::ops::Index<usize> for ProcessArray<NUM_PROCS> {
76    type Output = ProcessSlot;
77
78    fn index(&self, i: usize) -> &ProcessSlot {
79        &self.processes[i]
80    }
81}