Start with full procmask, fix signal delivery.

This commit is contained in:
4lDO2
2024-01-26 11:49:02 +01:00
parent 5336cbd9e5
commit 5ac0be7ec1
6 changed files with 51 additions and 42 deletions
+1 -2
View File
@@ -242,8 +242,7 @@ impl Context {
ens: SchemeNamespace::from(0),
sig: SignalState {
pending: 0,
procmask: 0,
procmask: !0,
handler: None,
},
umask: 0o022,
+7 -10
View File
@@ -1,5 +1,5 @@
use alloc::sync::Arc;
use core::mem::{self, size_of};
use core::mem::size_of;
use syscall::{
flag::{
PTRACE_FLAG_IGNORE, PTRACE_STOP_SIGNAL, SIGCHLD, SIGCONT, SIGKILL, SIGSTOP, SIGTSTP,
@@ -14,12 +14,7 @@ use crate::{
syscall::usercopy::UserSlice,
};
pub fn is_user_handled(handler: Option<extern "C" fn(usize)>) -> bool {
let handler = handler.map(|ptr| ptr as usize).unwrap_or(0);
handler != SIG_DFL && handler != SIG_IGN
}
// TODO: Move everything but SIGKILL to userspace. SIGCONT and SIGSTOP does not necessarily need to
// TODO: Move everything but SIGKILL to userspace. SIGCONT and SIGSTOP do not necessarily need to
// be done from this current context.
pub fn signal_handler() {
let (action, sig) = {
@@ -29,6 +24,9 @@ pub fn signal_handler() {
// Lowest-numbered signal first.
// TODO: randomly?
if context.sig.deliverable() == 0 {
return;
}
let selected = context.sig.deliverable().trailing_zeros() as usize + 1;
context.sig.pending &= !(1 << (selected - 1));
@@ -46,8 +44,7 @@ pub fn signal_handler() {
if sig != SIGKILL && thumbs_down.unwrap_or(false) {
// If signal can be and was ignored
crate::syscall::sigreturn().unwrap();
unreachable!();
return;
}
if handler == SIG_DFL {
@@ -166,7 +163,7 @@ pub fn signal_handler() {
context.sig.procmask |= action.sa_mask;
if !action.sa_flags.contains(SigActionFlags::SA_NODEFER) {
context.sig.procmask &= !(1 << (sig - 1));
context.sig.procmask |= 1 << (sig - 1);
}
let Some(regs) = context.regs_mut() else {
+26 -9
View File
@@ -12,30 +12,37 @@ use crate::{
use super::{ContextId, Status};
unsafe fn update_runnable(context: &mut Context, cpu_id: LogicalCpuId) -> bool {
enum UpdateResult {
CanSwitch { signal: bool },
Skip,
}
unsafe fn update_runnable(context: &mut Context, cpu_id: LogicalCpuId) -> UpdateResult {
// Ignore already running contexts
if context.running {
return false;
return UpdateResult::Skip;
}
// Ignore contexts stopped by ptrace
if context.ptrace_stop {
return false;
return UpdateResult::Skip;
}
// Ignore contexts assigned to other CPUs
if !context.sched_affinity.contains(cpu_id) {
return false;
return UpdateResult::Skip;
}
//TODO: HACK TO WORKAROUND HANGS BY PINNING TO ONE CPU
if !context.cpu_id.map_or(true, |x| x == cpu_id) {
return false;
return UpdateResult::Skip;
}
let signal = context.sig.deliverable() != 0;
// Unblock when there are pending nonmasked signals.
if matches!(context.status, Status::Blocked) && context.sig.deliverable() != 0 {
context.unblock();
if matches!(context.status, Status::Blocked) && signal {
context.unblock_no_ipi();
}
// Wake from sleep
@@ -50,7 +57,11 @@ unsafe fn update_runnable(context: &mut Context, cpu_id: LogicalCpuId) -> bool {
}
// Switch to context if it needs to run
context.status.is_runnable()
if context.status.is_runnable() {
UpdateResult::CanSwitch { signal }
} else {
UpdateResult::Skip
}
}
struct SwitchResult {
@@ -144,9 +155,10 @@ pub unsafe fn switch() -> bool {
let mut next_context_guard = next_context_lock.write_arc();
// Update state of next context and check if runnable
if update_runnable(&mut *next_context_guard, cpu_id) {
if let UpdateResult::CanSwitch { signal } = update_runnable(&mut *next_context_guard, cpu_id) {
// Store locks for previous and next context
switch_context_opt = Some((prev_context_guard, next_context_guard));
percpu.switch_internals.switch_signal.set(signal);
break;
} else {
continue;
@@ -186,6 +198,10 @@ pub unsafe fn switch() -> bool {
arch::switch_to(prev_context, next_context);
if percpu.switch_internals.switch_signal.replace(false) {
crate::context::signal::signal_handler();
}
// NOTE: After switch_to is called, the return address can even be different from the
// current return address, meaning that we cannot use local variables here, and that we
// need to use the `switch_finish_hook` to be able to release the locks.
@@ -209,6 +225,7 @@ pub struct ContextSwitchPercpu {
// The ID of the idle process
idle_id: Cell<ContextId>,
switch_signal: Cell<bool>,
}
impl ContextSwitchPercpu {
pub fn context_id(&self) -> ContextId {