// vi:syntax=yggdrasil-abi:

enum Signal(u32) {
    /// Process has tried to perform an illegal memory operation
    MemoryAccessViolation = 1,
    /// Process has hit a breakpoint or was aborted
    Aborted = 2,
    /// Process was killed (cannot be handled)
    Killed = 3,
    /// Process was interrupted
    Interrupted = 4,
    /// Debugger attached (cannot be handled)
    Debug = 5,
    /// Undefined instruction in process code
    InvalidInstruction = 6,
    /// Process was asked to terminate
    Terminated = 7,
}

newtype ProcessId(u31);
newtype ProcessGroupId(u32);
newtype ThreadId(u32);

#[default(_)]
bitfield WaitFlags(u32) {
    /// Makes the wait call return immediately. If the requested query didn't match any exited
    /// processes, will return Error::WouldBlock instead.
    NON_BLOCKING: 1,
}

// Spawn
#[default(_)]
bitfield SpawnFlags(u32) {
    /// Disables Address Space Layout Randomization for relocatable binaries
    DISABLE_ASLR: 1,
}

/// Controls how processes are created
#[derive(Clone, Debug)]
#[repr(C)]
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],
    /// Environment for the child process
    pub environment: &'a [&'a str],
    /// Working directory
    pub directory: Option<&'a str>,
    /// Root path
    pub root: Option<&'a str>,
    /// Optional arguments to specify details of the creation
    pub optional: &'a [SpawnOption],
    /// Extra flags controlling the new process behavior
    pub flags: SpawnFlags,
}

/// Legacy execve(2) arguments
#[allow(missing_docs)]
#[derive(Clone, Debug)]
#[repr(C)]
struct ExecveOptions<'a> {
    pub program: &'a str,
    pub arguments: &'a [&'a str],
    pub environment: &'a [&'a str],
}

/// Controls how threads are spawned within a process
#[derive(Clone, Debug)]
#[repr(C)]
struct ThreadSpawnOptions {
    /// Thread entry function
    pub entry: extern "C" fn(usize) -> !,
    /// Thread argument value
    pub argument: usize,
    /// Thread stack pointer. NOTE: it's the caller's responsibility to allocate a proper stack for
    /// the thread.
    pub stack_top: usize,
}

// Signal

/// Data provided by the kernel to signal entry function
#[derive(Clone, Debug)]
#[repr(C)]
struct SignalEntryData {
    /// Which signal was issued
    pub signal: Signal,
    /// Saved frame of the context that was interrupted
    pub frame: SavedFrame,
}
