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}