Skip to content
Snippets Groups Projects
Verified Commit 63509e75 authored by Jacob Lorentzon's avatar Jacob Lorentzon
Browse files

Use new signal ABI where 'actions' are in shmem.

parent 71800d2b
No related branches found
No related tags found
1 merge request!480Refactor redox runtime and impl signals in userspace
...@@ -317,9 +317,7 @@ __relibc_internal_sigentry_crit_second: ...@@ -317,9 +317,7 @@ __relibc_internal_sigentry_crit_second:
tcb_sa_off = const offset_of!(crate::Tcb, os_specific) + offset_of!(RtSigarea, arch), tcb_sa_off = const offset_of!(crate::Tcb, os_specific) + offset_of!(RtSigarea, arch),
tcb_sc_off = const offset_of!(crate::Tcb, os_specific) + offset_of!(RtSigarea, control), tcb_sc_off = const offset_of!(crate::Tcb, os_specific) + offset_of!(RtSigarea, control),
supports_xsave = sym SUPPORTS_XSAVE, supports_xsave = sym SUPPORTS_XSAVE,
SIGW0_PENDING_MASK = const !( SIGW0_PENDING_MASK = const !0,
SIGW0_TSTP_IS_STOP_BIT | SIGW0_TTIN_IS_STOP_BIT | SIGW0_TTOU_IS_STOP_BIT | SIGW0_NOCLDSTOP_BIT | SIGW0_UNUSED1 | SIGW0_UNUSED2
),
SIGW1_PENDING_MASK = const !0, SIGW1_PENDING_MASK = const !0,
REDZONE_SIZE = const 128, REDZONE_SIZE = const 128,
STACK_ALIGN = const 64, // if xsave is used STACK_ALIGN = const 64, // if xsave is used
......
use core::cell::{Cell, UnsafeCell}; use core::cell::{Cell, UnsafeCell};
use core::ffi::c_int; use core::ffi::c_int;
use core::sync::atomic::Ordering; use core::sync::atomic::{AtomicUsize, Ordering};
use syscall::{Error, Result, SetSighandlerData, SigProcControl, Sigcontrol, SigcontrolFlags, EINVAL, SIGCHLD, SIGCONT, SIGKILL, SIGSTOP, SIGTSTP, SIGTTIN, SIGTTOU, SIGURG, SIGW0_NOCLDSTOP_BIT, SIGW0_TSTP_IS_STOP_BIT, SIGW0_TTIN_IS_STOP_BIT, SIGW0_TTOU_IS_STOP_BIT, SIGWINCH, data::AtomicU64}; use syscall::{RawAction, SIGABRT, SIGBUS, SIGFPE, SIGILL, SIGQUIT, SIGSEGV, SIGSYS, SIGTRAP, SIGXCPU, SIGXFSZ};
use syscall::{Error, Result, SetSighandlerData, SigProcControl, Sigcontrol, SigcontrolFlags, EINVAL, SIGCHLD, SIGCONT, SIGKILL, SIGSTOP, SIGTSTP, SIGTTIN, SIGTTOU, SIGURG, SIGWINCH, data::AtomicU64};
use crate::{arch::*, Tcb}; use crate::{arch::*, Tcb};
use crate::sync::Mutex; use crate::sync::Mutex;
...@@ -57,11 +58,16 @@ unsafe fn inner(stack: &mut SigStack) { ...@@ -57,11 +58,16 @@ unsafe fn inner(stack: &mut SigStack) {
arch_pre(stack, &mut *os.arch.get()); arch_pre(stack, &mut *os.arch.get());
let sigaction = { let sigaction = {
let mut guard = SIGACTIONS.lock(); let mut guard = SIGACTIONS_LOCK.lock();
let action = guard[stack.sig_num]; let action = convert_old(&PROC_CONTROL_STRUCT.actions[stack.sig_num - 1]);
if action.flags.contains(SigactionFlags::RESETHAND) { if action.flags.contains(SigactionFlags::RESETHAND) {
// TODO: other things that must be set // TODO: other things that must be set
guard[stack.sig_num].kind = SigactionKind::Default; drop(guard);
sigaction(stack.sig_num as u8, Some(&Sigaction {
kind: SigactionKind::Default,
mask: 0,
flags: SigactionFlags::empty(),
}), None);
} }
action action
}; };
...@@ -191,6 +197,44 @@ pub struct Sigaction { ...@@ -191,6 +197,44 @@ pub struct Sigaction {
pub mask: u64, pub mask: u64,
pub flags: SigactionFlags, pub flags: SigactionFlags,
} }
impl Sigaction {
fn ip(&self) -> usize {
unsafe {
match self.kind {
SigactionKind::Handled { handler } => if self.flags.contains(SigactionFlags::SIGINFO) {
handler.sigaction.map_or(0, |a| a as usize)
} else {
handler.handler.map_or(0, |a| a as usize)
}
_ => 0,
}
}
}
}
const MASK_DONTCARE: u64 = !0;
fn convert_old(action: &RawAction) -> Sigaction {
let old_first = action.first.load(Ordering::Relaxed);
let old_mask = action.user_data.load(Ordering::Relaxed);
let handler = (old_first & !(u64::from(STORED_FLAGS) << 32)) as usize;
let flags = SigactionFlags::from_bits_retain(((old_first >> 32) as u32) & STORED_FLAGS);
let kind = if handler == default_handler as usize {
SigactionKind::Default
} else if flags.contains(SigactionFlags::IGNORED) {
SigactionKind::Ignore
} else {
SigactionKind::Handled { handler: unsafe { core::mem::transmute(handler as usize) } }
};
Sigaction {
mask: old_mask,
flags,
kind,
}
}
pub fn sigaction(signal: u8, new: Option<&Sigaction>, old: Option<&mut Sigaction>) -> Result<()> { pub fn sigaction(signal: u8, new: Option<&Sigaction>, old: Option<&mut Sigaction>) -> Result<()> {
if matches!(usize::from(signal), 0 | 32 | SIGKILL | SIGSTOP | 65..) { if matches!(usize::from(signal), 0 | 32 | SIGKILL | SIGSTOP | 65..) {
...@@ -199,62 +243,46 @@ pub fn sigaction(signal: u8, new: Option<&Sigaction>, old: Option<&mut Sigaction ...@@ -199,62 +243,46 @@ pub fn sigaction(signal: u8, new: Option<&Sigaction>, old: Option<&mut Sigaction
let _sigguard = tmp_disable_signals(); let _sigguard = tmp_disable_signals();
let ctl = current_sigctl(); let ctl = current_sigctl();
let mut guard = SIGACTIONS.lock();
let old_ignmask = IGNMASK.load(Ordering::Relaxed); let action = &PROC_CONTROL_STRUCT.actions[usize::from(signal) - 1];
if let Some(old) = old { if let Some(old) = old {
*old = guard[usize::from(signal)]; *old = convert_old(action);
} }
let Some(new) = new else { let Some(new) = new else {
return Ok(()); return Ok(());
}; };
guard[usize::from(signal)] = *new;
let sig_group = usize::from(signal) / 32; let explicit_handler = new.ip();
let sig_bit32 = 1 << ((signal - 1) % 32);
match (usize::from(signal), new.kind) { let (mask, flags, handler) = match (usize::from(signal), new.kind) {
(_, SigactionKind::Ignore) | (SIGURG | SIGWINCH, SigactionKind::Default) => { (_, SigactionKind::Ignore) | (SIGURG | SIGWINCH, SigactionKind::Default) => {
IGNMASK.store(old_ignmask | sig_bit(signal.into()), Ordering::Relaxed); // TODO: POSIX specifies that pending signals shall be discarded if set to SIG_IGN by
// mark the signal as masked
ctl.word[sig_group].fetch_and(!(sig_bit32 << 32), Ordering::Relaxed);
// POSIX specifies that pending signals shall be discarded if set to SIG_IGN by
// sigaction. // sigaction.
// TODO: handle tmp_disable_signals // TODO: handle tmp_disable_signals
(MASK_DONTCARE, SigactionFlags::IGNORED, if matches!(new.kind, SigactionKind::Default) {
default_handler as usize
} else {
0
})
} }
// TODO: Handle pending signals before these flags are set. // TODO: Handle pending signals before these flags are set.
(SIGTSTP, SigactionKind::Default) => { (SIGTSTP | SIGTTOU | SIGTTIN, SigactionKind::Default) => (MASK_DONTCARE, SigactionFlags::SIG_SPECIFIC, default_handler as usize),
PROC_CONTROL_STRUCT.word[0].fetch_or(SIGW0_TSTP_IS_STOP_BIT, Ordering::SeqCst);
}
(SIGTTIN, SigactionKind::Default) => {
PROC_CONTROL_STRUCT.word[0].fetch_or(SIGW0_TTIN_IS_STOP_BIT, Ordering::SeqCst);
}
(SIGTTOU, SigactionKind::Default) => {
PROC_CONTROL_STRUCT.word[0].fetch_or(SIGW0_TTOU_IS_STOP_BIT, Ordering::SeqCst);
}
(SIGCHLD, SigactionKind::Default) => { (SIGCHLD, SigactionKind::Default) => {
if new.flags.contains(SigactionFlags::NOCLDSTOP) { let nocldstop_bit = new.flags & SigactionFlags::SIG_SPECIFIC;
PROC_CONTROL_STRUCT.word[0].fetch_or(SIGW0_NOCLDSTOP_BIT, Ordering::SeqCst); (MASK_DONTCARE, SigactionFlags::IGNORED | nocldstop_bit, default_handler as usize)
} else {
PROC_CONTROL_STRUCT.word[0].fetch_and(!SIGW0_NOCLDSTOP_BIT, Ordering::SeqCst);
}
IGNMASK.store(old_ignmask | sig_bit(signal.into()), Ordering::Relaxed);
// mark the signal as masked
ctl.word[sig_group].fetch_or(sig_bit32, Ordering::Relaxed);
} }
(_, SigactionKind::Default) => { (_, SigactionKind::Default) => {
IGNMASK.store(old_ignmask & !sig_bit(signal.into()), Ordering::Relaxed); (new.mask, new.flags, default_handler as usize)
// TODO: update mask
//ctl.word[usize::from(signal)].fetch_or();
}, },
(_, SigactionKind::Handled { .. }) => (), (_, SigactionKind::Handled { .. }) => {
} (new.mask, new.flags, explicit_handler)
}
};
action.first.store((handler as u64) | (u64::from(flags.bits() & STORED_FLAGS) << 32), Ordering::Relaxed);
action.user_data.store(mask, Ordering::Relaxed);
Ok(()) Ok(())
} }
...@@ -296,26 +324,23 @@ bitflags::bitflags! { ...@@ -296,26 +324,23 @@ bitflags::bitflags! {
// Some flags are ignored by the rt, but they match relibc's 1:1 to simplify conversion. // Some flags are ignored by the rt, but they match relibc's 1:1 to simplify conversion.
#[derive(Clone, Copy, Default)] #[derive(Clone, Copy, Default)]
pub struct SigactionFlags: u32 { pub struct SigactionFlags: u32 {
const NOCLDSTOP = 1;
const NOCLDWAIT = 2; const NOCLDWAIT = 2;
const SIGINFO = 4; const RESTORER = 4;
const RESTORER = 0x0400_0000; const SIGINFO = 0x0200_0000;
const ONSTACK = 0x0800_0000; const ONSTACK = 0x0400_0000;
const RESTART = 0x1000_0000; const RESTART = 0x0800_0000;
const NODEFER = 0x4000_0000; const NODEFER = 0x1000_0000;
const RESETHAND = 0x8000_0000; const RESETHAND = 0x2000_0000;
const SIG_SPECIFIC = 0x4000_0000;
const IGNORED = 0x8000_0000;
} }
} }
fn default_term_handler(sig: c_int) {
syscall::exit((sig as usize) << 8); const STORED_FLAGS: u32 = 0xfe00_0000;
}
fn default_core_handler(sig: c_int) { fn default_handler(sig: c_int) {
syscall::exit((sig as usize) << 8); syscall::exit((sig as usize) << 8);
} }
fn default_ign_handler(_: c_int) {
}
fn stop_handler_sentinel(_: c_int) {
}
#[derive(Clone, Copy)] #[derive(Clone, Copy)]
pub union SignalHandler { pub union SignalHandler {
...@@ -323,22 +348,16 @@ pub union SignalHandler { ...@@ -323,22 +348,16 @@ pub union SignalHandler {
pub sigaction: Option<unsafe extern "C" fn(c_int, *const (), *mut ())>, pub sigaction: Option<unsafe extern "C" fn(c_int, *const (), *mut ())>,
} }
struct TheDefault { static SIGACTIONS_LOCK: Mutex<()> = Mutex::new(());
actions: [Sigaction; 64],
ignmask: u64,
}
// indexed directly by signal number
static SIGACTIONS: Mutex<[Sigaction; 64]> = Mutex::new([Sigaction { flags: SigactionFlags::empty(), mask: 0, kind: SigactionKind::Default }; 64]);
static IGNMASK: AtomicU64 = AtomicU64::new(sig_bit(SIGCHLD) | sig_bit(SIGURG) | sig_bit(SIGWINCH));
static PROC_CONTROL_STRUCT: SigProcControl = SigProcControl { static PROC_CONTROL_STRUCT: SigProcControl = SigProcControl {
word: [ pending: AtomicU64::new(0),
//AtomicU64::new(SIGW0_TSTP_IS_STOP_BIT | SIGW0_TTIN_IS_STOP_BIT | SIGW0_TTOU_IS_STOP_BIT | 0xffff_ffff_0000_0000), actions: [const {
AtomicU64::new(0xffff_ffff_0000_0000), // "allow all, no pending" RawAction {
AtomicU64::new(0xffff_ffff_0000_0000), // "allow all, no pending" first: AtomicU64::new(0),
], user_data: AtomicU64::new(0),
}
}; 64],
}; };
fn combine_allowset([lo, hi]: [u64; 2]) -> u64 { fn combine_allowset([lo, hi]: [u64; 2]) -> u64 {
...@@ -353,7 +372,7 @@ const fn sig_bit(sig: usize) -> u64 { ...@@ -353,7 +372,7 @@ const fn sig_bit(sig: usize) -> u64 {
pub fn setup_sighandler(area: &RtSigarea) { pub fn setup_sighandler(area: &RtSigarea) {
{ {
let mut sigactions = SIGACTIONS.lock(); let mut sigactions = SIGACTIONS_LOCK.lock();
} }
let arch = unsafe { &mut *area.arch.get() }; let arch = unsafe { &mut *area.arch.get() };
{ {
......
...@@ -36,14 +36,14 @@ pub const NSIG: usize = 32; ...@@ -36,14 +36,14 @@ pub const NSIG: usize = 32;
pub const SIGRTMIN: usize = 35; pub const SIGRTMIN: usize = 35;
pub const SIGRTMAX: usize = 64; pub const SIGRTMAX: usize = 64;
pub const SA_NOCLDSTOP: usize = 0x0000_0001;
pub const SA_NOCLDWAIT: usize = 0x0000_0002; pub const SA_NOCLDWAIT: usize = 0x0000_0002;
pub const SA_SIGINFO: usize = 0x0000_0004; pub const SA_RESTORER: usize = 0x0000_0004; // TODO: remove
pub const SA_RESTORER: usize = 0x0400_0000; pub const SA_SIGINFO: usize = 0x0200_0000;
pub const SA_ONSTACK: usize = 0x0800_0000; pub const SA_ONSTACK: usize = 0x0400_0000;
pub const SA_RESTART: usize = 0x1000_0000; pub const SA_RESTART: usize = 0x0800_0000;
pub const SA_NODEFER: usize = 0x4000_0000; pub const SA_NODEFER: usize = 0x1000_0000;
pub const SA_RESETHAND: usize = 0x8000_0000; pub const SA_RESETHAND: usize = 0x2000_0000;
pub const SA_NOCLDSTOP: usize = 0x4000_0000;
pub const SS_ONSTACK: usize = 0x00000001; pub const SS_ONSTACK: usize = 0x00000001;
pub const SS_DISABLE: usize = 0x00000002; pub const SS_DISABLE: usize = 0x00000002;
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment