Skip to content

Commit

Permalink
Moves sys_sigprocmask to SignalManager (#841)
Browse files Browse the repository at this point in the history
  • Loading branch information
ultimaweapon authored Apr 16, 2024
1 parent 44ee774 commit 048aaf4
Show file tree
Hide file tree
Showing 3 changed files with 103 additions and 92 deletions.
2 changes: 2 additions & 0 deletions src/kernel/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ use crate::process::{ProcManager, VThread};
use crate::regmgr::RegMgr;
use crate::rtld::{ExecError, LoadFlags, ModuleFlags, RuntimeLinker};
use crate::shm::SharedMemoryManager;
use crate::signal::SignalManager;
use crate::syscalls::Syscalls;
use crate::sysctl::Sysctl;
use crate::time::TimeManager;
Expand Down Expand Up @@ -362,6 +363,7 @@ fn run() -> Result<(), KernelError> {
let machdep = MachDep::new(&mut syscalls);
let budget = BudgetManager::new(&mut syscalls);

SignalManager::new(&mut syscalls);
DmemManager::new(&fs, &mut syscalls)?;
SharedMemoryManager::new(&mut syscalls);
Sysctl::new(&machdep, &mut syscalls);
Expand Down
86 changes: 0 additions & 86 deletions src/kernel/src/process/proc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@ use crate::errno::{EINVAL, ERANGE, ESRCH};
use crate::fs::Vnode;
use crate::idt::Idt;
use crate::info;
use crate::signal::{SignalSet, SIGKILL, SIGSTOP, SIG_BLOCK, SIG_SETMASK, SIG_UNBLOCK};
use crate::syscalls::{SysErr, SysIn, SysOut, Syscalls};
use crate::sysent::ProcAbi;
use crate::ucred::{AuthInfo, Gid, Privilege, Ucred, Uid};
Expand Down Expand Up @@ -98,7 +97,6 @@ impl VProc {
});

// TODO: Move all syscalls here to somewhere else.
sys.register(340, &vp, Self::sys_sigprocmask);
sys.register(455, &vp, Self::sys_thr_new);
sys.register(466, &vp, Self::sys_rtprio_thread);
sys.register(487, &vp, Self::sys_cpuset_getaffinity);
Expand Down Expand Up @@ -200,68 +198,6 @@ impl VProc {
&self.uptc
}

fn sys_sigprocmask(self: &Arc<Self>, td: &VThread, i: &SysIn) -> Result<SysOut, SysErr> {
// Get arguments.
let how: How = {
let how: i32 = i.args[0].try_into().unwrap();
how.try_into()?
};

let set: *const SignalSet = i.args[1].into();
let oset: *mut SignalSet = i.args[2].into();

// Convert set to an option.
let set = if set.is_null() {
None
} else {
Some(unsafe { *set })
};

// Keep the current mask for copying to the oset. We need to copy to the oset only when this
// function succees.
let mut mask = td.sigmask_mut();
let prev = *mask;

// Update the mask.
if let Some(mut set) = set {
match how {
How::Block => {
// Remove uncatchable signals.
set.remove(SIGKILL);
set.remove(SIGSTOP);

// Update mask.
*mask |= set;
}
How::Unblock => {
// Update mask.
*mask &= !set;

// TODO: Invoke signotify at the end.
}
How::SetMask => {
// Remove uncatchable signals.
set.remove(SIGKILL);
set.remove(SIGSTOP);

// Replace mask.
*mask = set;

// TODO: Invoke signotify at the end.
}
}

// TODO: Check if we need to invoke reschedule_signals.
}

// Copy output.
if !oset.is_null() {
unsafe { *oset = prev };
}

Ok(SysOut::ZERO)
}

fn sys_thr_new(self: &Arc<Self>, td: &VThread, i: &SysIn) -> Result<SysOut, SysErr> {
let param: *const ThrParam = i.args[0].into();
let param_size: i32 = i.args[1].try_into().unwrap();
Expand Down Expand Up @@ -550,28 +486,6 @@ impl VProc {
}
}

#[derive(Debug)]
enum How {
Block,
Unblock,
SetMask,
}

impl TryFrom<i32> for How {
type Error = SysErr;

fn try_from(value: i32) -> Result<Self, Self::Error> {
let how = match value {
SIG_BLOCK => How::Block,
SIG_UNBLOCK => How::Unblock,
SIG_SETMASK => How::SetMask,
_ => return Err(SysErr::Raw(EINVAL)),
};

Ok(how)
}
}

#[repr(C)]
struct ThrParam {
start_func: fn(usize),
Expand Down
107 changes: 101 additions & 6 deletions src/kernel/src/signal/mod.rs
Original file line number Diff line number Diff line change
@@ -1,12 +1,87 @@
pub use self::set::*;

use crate::errno::EINVAL;
use crate::process::VThread;
use crate::syscalls::{SysArg, SysErr, SysIn, SysOut, Syscalls};
use bitflags::bitflags;
use std::borrow::Cow;
use std::fmt::{Display, Formatter};
use std::num::NonZeroI32;
use std::sync::Arc;

mod set;

/// Manage process/thread signal.
pub struct SignalManager {}

impl SignalManager {
pub fn new(sys: &mut Syscalls) -> Arc<Self> {
// Register syscalls.
let mgr = Arc::new(Self {});

sys.register(340, &mgr, Self::sys_sigprocmask);

mgr
}

fn sys_sigprocmask(self: &Arc<Self>, td: &VThread, i: &SysIn) -> Result<SysOut, SysErr> {
// Get arguments.
let how: MaskOp = i.args[0].try_into()?;
let set: *const SignalSet = i.args[1].into();
let oset: *mut SignalSet = i.args[2].into();

// Convert set to an option.
let set = if set.is_null() {
None
} else {
Some(unsafe { *set })
};

// Keep the current mask for copying to the oset. We need to copy to the oset only when this
// function succees.
let mut mask = td.sigmask_mut();
let prev = *mask;

// Update the mask.
if let Some(mut set) = set {
match how {
MaskOp::Block => {
// Remove uncatchable signals.
set.remove(SIGKILL);
set.remove(SIGSTOP);

// Update mask.
*mask |= set;
}
MaskOp::Unblock => {
// Update mask.
*mask &= !set;

// TODO: Invoke signotify at the end.
}
MaskOp::Set => {
// Remove uncatchable signals.
set.remove(SIGKILL);
set.remove(SIGSTOP);

// Replace mask.
*mask = set;

// TODO: Invoke signotify at the end.
}
}

// TODO: Check if we need to invoke reschedule_signals.
}

// Copy output.
if !oset.is_null() {
unsafe { *oset = prev };
}

Ok(SysOut::ZERO)
}
}

#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct Signal(NonZeroI32);

Expand Down Expand Up @@ -85,14 +160,34 @@ pub fn strsignal(sig: Signal) -> Cow<'static, str> {
}

pub const SIG_MAXSIG: i32 = 128;
// List of sigprocmask operations. The value must be the same as PS4 kernel.
pub const SIG_BLOCK: i32 = 1;
pub const SIG_UNBLOCK: i32 = 2;
pub const SIG_SETMASK: i32 = 3;

pub const SIG_IGN: usize = 1;
pub const SIG_DFL: usize = 0;

/// List of sigprocmask operations. The value must be the same as PS4 kernel.
#[repr(i32)]
#[derive(Debug, Clone, Copy)]
pub enum MaskOp {
Block = 1, // SIG_BLOCK
Unblock = 2, // SIG_UNBLOCK
Set = 3, // SIG_SETMASK
}

impl TryFrom<SysArg> for MaskOp {
type Error = SysErr;

fn try_from(value: SysArg) -> Result<Self, Self::Error> {
let raw: i32 = value.try_into().map_err(|_| SysErr::Raw(EINVAL))?;
let op = match raw {
v if v == Self::Block as i32 => Self::Block,
v if v == Self::Unblock as i32 => Self::Unblock,
v if v == Self::Set as i32 => Self::Set,
_ => return Err(SysErr::Raw(EINVAL)),
};

Ok(op)
}
}

/// An iterator over all possible signals
pub struct SignalIter {
current: i32,
Expand Down

0 comments on commit 048aaf4

Please sign in to comment.