2024-03-12 13:48:09 +02:00
|
|
|
//! Data structures for process management
|
|
|
|
|
2024-11-17 23:32:07 +02:00
|
|
|
use core::{ffi::CStr, fmt, marker::PhantomData, time::Duration};
|
2024-03-12 13:48:09 +02:00
|
|
|
|
2024-11-17 23:32:07 +02:00
|
|
|
use crate::io::{FileMode, RawFd};
|
2024-03-12 13:48:09 +02:00
|
|
|
|
|
|
|
mod exit;
|
2024-11-17 23:32:07 +02:00
|
|
|
pub mod thread;
|
2024-03-12 13:48:09 +02:00
|
|
|
|
2024-03-13 14:25:02 +02:00
|
|
|
pub use crate::generated::{
|
2024-10-31 22:53:46 +02:00
|
|
|
ExecveOptions, ProcessGroupId, ProcessId, Signal, SignalEntryData, SpawnFlags, SpawnOptions,
|
|
|
|
ThreadId, ThreadSpawnOptions,
|
2024-03-13 14:25:02 +02:00
|
|
|
};
|
2024-03-12 13:48:09 +02:00
|
|
|
pub use exit::ExitCode;
|
2024-11-17 23:32:07 +02:00
|
|
|
pub use thread::ThreadOption;
|
|
|
|
|
|
|
|
// TODO this is ugly
|
|
|
|
pub mod auxv {
|
|
|
|
pub const TLS_MASTER_COPY: u64 = 0x80;
|
|
|
|
pub const TLS_FULL_SIZE: u64 = 0x81;
|
|
|
|
pub const TLS_DATA_SIZE: u64 = 0x82;
|
|
|
|
pub const TLS_ALIGN: u64 = 0x83;
|
|
|
|
|
|
|
|
pub const TLS_MODULE_ID: u64 = 0x84;
|
|
|
|
pub const TLS_MODULE_OFFSET: u64 = 0x85;
|
|
|
|
|
|
|
|
pub const TLS_ALREADY_INITIALIZED: u64 = 0x86;
|
|
|
|
|
|
|
|
pub const NULL: u64 = 0x00;
|
|
|
|
}
|
2024-03-13 14:25:02 +02:00
|
|
|
|
|
|
|
/// 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,
|
|
|
|
},
|
|
|
|
/// The new process should be placed in the specified group
|
2024-03-13 17:55:14 +02:00
|
|
|
SetProcessGroup(ProcessGroupId),
|
2024-03-13 14:25:02 +02:00
|
|
|
/// Gain terminal control for the given FD
|
|
|
|
GainTerminal(RawFd),
|
2024-03-19 23:11:03 +02:00
|
|
|
/// Attach debugging to a channel in parent's I/O context. The process will start in
|
|
|
|
/// single-stepping mode
|
|
|
|
AttachDebug(RawFd),
|
2024-03-13 14:25:02 +02:00
|
|
|
}
|
2024-03-12 13:48:09 +02:00
|
|
|
|
|
|
|
/// Describes a single mutex operation
|
|
|
|
#[derive(Clone, Debug)]
|
|
|
|
#[repr(C)]
|
|
|
|
pub enum MutexOperation {
|
|
|
|
/// Waits on the mutex object until it is different from "compare value"
|
|
|
|
Wait(u32, Option<Duration>),
|
2024-11-19 01:47:28 +02:00
|
|
|
/// Waits on the mutex object until it becomes equal to the "compare value"
|
|
|
|
WaitUntil(u32, Option<Duration>),
|
2024-03-12 13:48:09 +02:00
|
|
|
/// Wakes a single mutex-waiting thread
|
|
|
|
Wake,
|
|
|
|
/// Wakes all threads waiting on the mutex
|
|
|
|
WakeAll,
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Provides some amount of process-related information
|
|
|
|
#[derive(Clone, Debug)]
|
|
|
|
pub enum ProcessInfoElement {
|
|
|
|
/// Mask applied to file modes when creating new files/directories
|
|
|
|
Umask(FileMode),
|
|
|
|
}
|
|
|
|
|
2024-11-17 23:32:07 +02:00
|
|
|
#[derive(Debug, Clone, Copy)]
|
|
|
|
#[repr(C)]
|
|
|
|
pub struct AuxValue {
|
|
|
|
pub tag: u64,
|
|
|
|
pub val: u64,
|
|
|
|
}
|
|
|
|
|
|
|
|
#[derive(Clone, Copy)]
|
|
|
|
pub struct StringArgIter<'a> {
|
|
|
|
ptr: *const *const u8,
|
|
|
|
_pd: PhantomData<&'a ProgramArgumentInner>,
|
|
|
|
}
|
|
|
|
|
|
|
|
#[derive(Clone, Copy)]
|
|
|
|
pub struct AuxValueIter<'a> {
|
|
|
|
ptr: *const AuxValue,
|
|
|
|
_pd: PhantomData<&'a ProgramArgumentInner>,
|
|
|
|
}
|
|
|
|
|
|
|
|
#[repr(C)]
|
|
|
|
pub struct ProgramArgumentInner {
|
|
|
|
pub args: *const *const u8,
|
|
|
|
pub envs: *const *const u8,
|
|
|
|
pub auxv: *const AuxValue,
|
2024-03-12 13:48:09 +02:00
|
|
|
}
|
2024-03-12 14:47:15 +02:00
|
|
|
|
|
|
|
impl ProcessId {
|
|
|
|
pub const ZERO: Self = Self(0);
|
|
|
|
}
|
|
|
|
|
|
|
|
impl fmt::Display for ProcessId {
|
|
|
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
|
|
|
write!(f, "<Process {}>", self.0)
|
|
|
|
}
|
|
|
|
}
|
2024-03-13 17:55:14 +02:00
|
|
|
|
|
|
|
impl fmt::Display for ProcessGroupId {
|
|
|
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
|
|
|
write!(f, "<Process group {}>", self.0)
|
|
|
|
}
|
|
|
|
}
|
2024-11-17 23:32:07 +02:00
|
|
|
|
|
|
|
impl<'a> Iterator for StringArgIter<'a> {
|
|
|
|
type Item = &'a CStr;
|
|
|
|
|
|
|
|
fn next(&mut self) -> Option<Self::Item> {
|
|
|
|
if self.ptr.is_null() {
|
|
|
|
return None;
|
|
|
|
}
|
|
|
|
let entry = unsafe { self.ptr.read() };
|
|
|
|
if entry.is_null() {
|
|
|
|
return None;
|
|
|
|
}
|
|
|
|
self.ptr = unsafe { self.ptr.add(1) };
|
|
|
|
let entry = unsafe { CStr::from_ptr(entry.cast()) };
|
|
|
|
Some(entry)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl<'a> Iterator for AuxValueIter<'a> {
|
|
|
|
type Item = &'a AuxValue;
|
|
|
|
|
|
|
|
fn next(&mut self) -> Option<Self::Item> {
|
|
|
|
if self.ptr.is_null() {
|
|
|
|
return None;
|
|
|
|
}
|
|
|
|
let entry = unsafe { &*self.ptr };
|
|
|
|
if entry.tag == auxv::NULL {
|
|
|
|
return None;
|
|
|
|
}
|
|
|
|
self.ptr = unsafe { self.ptr.add(1) };
|
|
|
|
Some(entry)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl ProgramArgumentInner {
|
|
|
|
pub fn args(&self) -> impl Iterator<Item = &CStr> {
|
|
|
|
StringArgIter {
|
|
|
|
ptr: self.args,
|
|
|
|
_pd: PhantomData,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn envs(&self) -> impl Iterator<Item = &CStr> {
|
|
|
|
StringArgIter {
|
|
|
|
ptr: self.envs,
|
|
|
|
_pd: PhantomData,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn auxv(&self) -> impl Iterator<Item = &AuxValue> {
|
|
|
|
AuxValueIter {
|
|
|
|
ptr: self.auxv,
|
|
|
|
_pd: PhantomData,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2024-11-19 12:15:34 +02:00
|
|
|
|
|
|
|
impl Signal {
|
|
|
|
pub fn is_synchronous(&self) -> bool {
|
|
|
|
matches!(self, Self::MemoryAccessViolation)
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn is_handleable(&self) -> bool {
|
|
|
|
!matches!(self, Self::Killed)
|
|
|
|
}
|
|
|
|
}
|