yggdrasil/src/process.rs

104 lines
3.0 KiB
Rust

//! Data structures for process management
use core::num::NonZeroI32;
use crate::{arch::SavedFrame, io::RawFd, primitive_enum};
/// Code signalled by a process when it finishes or is terminated by a signal
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
#[repr(C)]
pub enum ExitCode {
/// Process exited normally, either with an error or with a 0
Exited(i32),
/// Process was killed by a signal
BySignal(Signal),
}
/// Defines an optional argument for controlling process creation
#[derive(Debug)]
pub enum SpawnOption {
/// Indicates a new process should inherit a file descriptor from its creator
InheritFile {
/// FD on the creator side
source: RawFd,
/// What FD number should be used in the child
child: RawFd,
},
}
primitive_enum! {
#[doc = "Defines signal numbers sent to processes"]
pub enum Signal: u32 {
#[doc = "Process has tried to perform an illegal memory operation"]
MemoryAccessViolation = 1,
#[doc = "Process has hit a breakpoint or was aborted"]
Aborted = 2,
#[doc = "Process was killed"]
Killed = 3,
#[doc = "Process was interrupted"]
Interrupted = 4,
}
}
/// Data provided by the kernel to signal entry function
#[derive(Clone, Debug)]
#[repr(C)]
pub struct SignalEntryData {
/// Which signal was issued
pub signal: Signal,
/// Saved frame of the context that was interrupted
pub frame: SavedFrame,
}
/// Controls how processes are created
#[derive(Clone, Debug)]
#[repr(C)]
pub struct SpawnOptions<'a> {
/// Creator-relative path to the binary to execute
pub program: &'a str,
/// Arguments to the child process
pub arguments: &'a [&'a str],
/// Optional arguments to specify details of the creation
pub optional: &'a [SpawnOption],
}
impl ExitCode {
/// Returned when a process has exited successfully
pub const SUCCESS: Self = Self::Exited(0);
/// Returns `true` if this ExitCode signals a successful exit
pub const fn is_success(self) -> bool {
matches!(self, Self::Exited(0))
}
/// Returns [Some] if the process exited with an error or was killed by a signal
pub fn as_failure(self) -> Option<NonZeroI32> {
match self {
Self::Exited(0) => None,
Self::Exited(n) => Some(unsafe { NonZeroI32::new_unchecked(n) }),
Self::BySignal(sig) => {
Some(unsafe { NonZeroI32::new_unchecked(u32::from(sig) as i32) })
}
}
}
}
impl From<i32> for ExitCode {
fn from(value: i32) -> Self {
match value {
-255..=255 => Self::Exited(value),
10000.. => Self::BySignal(Signal::try_from(value as u32 - 10000).unwrap()),
_ => todo!(),
}
}
}
impl From<ExitCode> for i32 {
fn from(value: ExitCode) -> Self {
match value {
ExitCode::BySignal(signal) => 10000 + u32::from(signal) as i32,
ExitCode::Exited(value) => value,
}
}
}