diff --git a/kernel/src/kernel.rs b/kernel/src/kernel.rs index fa7ae8692f..d1b0b05976 100644 --- a/kernel/src/kernel.rs +++ b/kernel/src/kernel.rs @@ -697,11 +697,7 @@ impl Kernel { // This is a potential security flaw: panic. panic!("Attempted to schedule an unrunnable process"); } - process::State::StoppedRunning => { - return_reason = process::StoppedExecutingReason::Stopped; - break; - } - process::State::StoppedYielded => { + process::State::Stopped(_) => { return_reason = process::StoppedExecutingReason::Stopped; break; } diff --git a/kernel/src/process.rs b/kernel/src/process.rs index 962c02c486..a0f16c77a7 100644 --- a/kernel/src/process.rs +++ b/kernel/src/process.rs @@ -869,12 +869,12 @@ impl From for ErrorCode { /// process states. /// /// While a process is running, it transitions between the `Running`, `Yielded`, -/// `StoppedRunning`, and `StoppedYielded` states. If an error occurs (e.g., a -/// memory access error), the kernel faults it and either leaves it in the -/// `Faulted` state, restarts it, or takes some other action defined by the -/// kernel fault policy. If the process issues an `exit-terminate` system call, -/// it enters the `Terminated` state. If it issues an `exit-restart` system -/// call, it terminates then tries to back to a runnable state. +/// `YieldedFor`, and `Stopped` states. If an error occurs (e.g., a memory +/// access error), the kernel faults it and either leaves it in the `Faulted` +/// state, restarts it, or takes some other action defined by the kernel fault +/// policy. If the process issues an `exit-terminate` system call, it enters the +/// `Terminated` state. If it issues an `exit-restart` system call, it +/// terminates then tries to back to a runnable state. /// /// When a process faults, it enters the `Faulted` state. To be restarted, it /// must first transition to the `Terminated` state, which means that all of its @@ -898,16 +898,12 @@ pub enum State { /// upcall. YieldedFor(UpcallId), - /// The process is stopped, and its previous state was Running. This is used - /// if the kernel forcibly stops a process when it is in the `Running` - /// state. This state indicates to the kernel not to schedule the process, - /// but if the process is to be resumed later it should be put back in the - /// running state so it will execute correctly. - StoppedRunning, - - /// The process is stopped, and it was stopped while it was yielded. If this - /// process needs to be resumed it should be put back in the `Yield` state. - StoppedYielded, + /// The process is stopped and the previous state the process was in when it + /// was stopped. This is used if the kernel forcibly stops a process. This + /// state indicates to the kernel not to schedule the process, but if the + /// process is to be resumed later it should be put back in its previous + /// state so it will execute correctly. + Stopped(StoppedState), /// The process ran, faulted while running, and is no longer runnable. For a /// faulted process to be made runnable, it must first be terminated (to @@ -920,6 +916,24 @@ pub enum State { Terminated, } +/// States a process could previously have been in when stopped. +/// +/// This is public so external implementations of `Process` can re-use these +/// process stopped states. +/// +/// These are recorded so the process can be returned to its previous state when +/// it is resumed. +#[derive(Copy, Clone, Debug, Eq, PartialEq)] +pub enum StoppedState { + /// The process was in the running state when it was stopped. + Running, + /// The process was in the yielded state when it was stopped. + Yielded, + /// The process was in the yielded for state when it was stopped with a + /// particular upcall it was waiting for. + YieldedFor(UpcallId), +} + /// The action the kernel should take when a process encounters a fault. /// /// When an exception occurs during a process's execution (a common example is a diff --git a/kernel/src/process_standard.rs b/kernel/src/process_standard.rs index 60dc5199e2..96f831cdcf 100644 --- a/kernel/src/process_standard.rs +++ b/kernel/src/process_standard.rs @@ -24,9 +24,10 @@ use crate::platform::chip::Chip; use crate::platform::mpu::{self, MPU}; use crate::process::BinaryVersion; use crate::process::ProcessBinary; -use crate::process::{Error, FunctionCall, FunctionCallSource, Process, State, Task}; +use crate::process::{Error, FunctionCall, FunctionCallSource, Process, Task}; use crate::process::{FaultAction, ProcessCustomGrantIdentifier, ProcessId}; use crate::process::{ProcessAddresses, ProcessSizes, ShortId}; +use crate::process::{State, StoppedState}; use crate::process_loading::ProcessLoadError; use crate::process_policies::ProcessFaultPolicy; use crate::processbuffer::{ReadOnlyProcessBuffer, ReadWriteProcessBuffer}; @@ -317,11 +318,7 @@ impl Process for ProcessStandard<'_, C> { fn is_running(&self) -> bool { match self.state.get() { - State::Running - | State::Yielded - | State::YieldedFor(_) - | State::StoppedRunning - | State::StoppedYielded => true, + State::Running | State::Yielded | State::YieldedFor(_) | State::Stopped(_) => true, _ => false, } } @@ -344,16 +341,27 @@ impl Process for ProcessStandard<'_, C> { fn stop(&self) { match self.state.get() { - State::Running => self.state.set(State::StoppedRunning), - State::Yielded => self.state.set(State::StoppedYielded), - _ => {} // Do nothing + State::Running => self.state.set(State::Stopped(StoppedState::Running)), + State::Yielded => self.state.set(State::Stopped(StoppedState::Yielded)), + State::YieldedFor(upcall_id) => self + .state + .set(State::Stopped(StoppedState::YieldedFor(upcall_id))), + State::Stopped(_stopped_state) => { + // Already stopped, nothing to do. + } + State::Faulted | State::Terminated => { + // Stop has no meaning on a inactive process. + } } } fn resume(&self) { match self.state.get() { - State::StoppedRunning => self.state.set(State::Running), - State::StoppedYielded => self.state.set(State::Yielded), + State::Stopped(stopped_state) => match stopped_state { + StoppedState::Running => self.state.set(State::Running), + StoppedState::Yielded => self.state.set(State::Yielded), + StoppedState::YieldedFor(upcall_id) => self.state.set(State::YieldedFor(upcall_id)), + }, _ => {} // Do nothing } }