diff --git a/src/context/signal.rs b/src/context/signal.rs index 8cd01a6632..83acb3423e 100644 --- a/src/context/signal.rs +++ b/src/context/signal.rs @@ -81,9 +81,9 @@ pub fn excp_handler(_signal: usize) { let Some(_eh) = context.sig.as_ref().and_then(|s| s.excp_handler) else { drop(context); - // TODO: Send exception event to process manager - todo!() + drop(current); + crate::syscall::exit_this_context(); }; - // TODO + // TODO: call exception handler, similar to the signal handler case } diff --git a/src/syscall/debug.rs b/src/syscall/debug.rs index fcc304c167..b41efbb2fc 100644 --- a/src/syscall/debug.rs +++ b/src/syscall/debug.rs @@ -208,7 +208,7 @@ impl SyscallDebugInfo { } #[cfg(feature = "syscall_debug")] pub fn debug_start([a, b, c, d, e, f]: [usize; 6]) { - let do_debug = if true || crate::context::current().read().name.contains("acpid") { + let do_debug = if false && crate::context::current().read().name.contains("login") { if a == SYS_CLOCK_GETTIME || a == SYS_YIELD || a == SYS_FUTEX { false } else if (a == SYS_WRITE || a == SYS_FSYNC) && (b == 1 || b == 2) { diff --git a/src/syscall/process.rs b/src/syscall/process.rs index fa4443cdc9..8e6df328cc 100644 --- a/src/syscall/process.rs +++ b/src/syscall/process.rs @@ -1,10 +1,5 @@ -use alloc::{collections::VecDeque, sync::Arc, vec::Vec}; -use core::{mem, num::NonZeroUsize, sync::atomic::Ordering}; -use spinning_top::RwSpinlock; -use syscall::{ - sig_bit, EventFlags, RtSigInfo, SenderInfo, SIGCHLD, SIGKILL, SIGSTOP, SIGTERM, SIGTSTP, - SIGTTIN, SIGTTOU, -}; +use alloc::{sync::Arc, vec::Vec}; +use core::{mem, num::NonZeroUsize}; use rmm::Arch; use spin::RwLock; @@ -12,17 +7,17 @@ use spin::RwLock; use crate::{ context::{ memory::{AddrSpace, Grant, PageSpan}, - Context, ContextRef, + ContextRef, }, event, scheme::GlobalSchemes, + syscall::EventFlags, }; use crate::{ - context, interrupt, + context, paging::{Page, VirtualAddress, PAGE_SIZE}, - ptrace, - syscall::{error::*, flag::MapFlags, ptrace_event}, + syscall::{error::*, flag::MapFlags}, Bootstrap, CurrentRmmArch, }; @@ -69,249 +64,6 @@ pub fn exit_this_context() -> ! { unreachable!(); } -pub fn send_signal( - context: Arc>, - sig: usize, - mode: KillMode, - is_sigchld_to_parent: bool, - killed_self: &mut bool, - sender: SenderInfo, -) -> Result<()> { - /* - if sig > 64 { - return Err(Error::new(EINVAL)); - } - - let sig_group = (sig - 1) / 32; - let sig_idx = sig - 1; - - let (context_lock, process_lock) = match target { - KillTarget::Thread(ref c) => (Arc::clone(&c), Arc::clone(&c.read().process)), - KillTarget::Process(ref p) => ( - p.read() - .threads - .iter() - .filter_map(|t| t.upgrade()) - .next() - .ok_or(Error::new(ESRCH))?, - Arc::clone(p), - ), - }; - let proc_info = process_lock.read().info; - - enum SendResult { - Succeeded, - SucceededSigchld { - orig_signal: usize, - }, - SucceededSigcont { - }, - FullQ, - Invalid, - } - - let result = (|| { - let is_self = context::is_current(&context_lock); - - // If sig = 0, test that process exists and can be signalled, but don't send any - // signal. - if sig == 0 { - return SendResult::Succeeded; - } - - let mut process_guard = process_lock.write(); - - if sig == SIGCONT - && let ProcessStatus::Stopped(_sig) = process_guard.status - { - // Convert stopped processes to blocked if sending SIGCONT, regardless of whether - // SIGCONT is blocked or ignored. It can however be controlled whether the process - // will additionally ignore, defer, or handle that signal. - process_guard.status = ProcessStatus::PossiblyRunnable; - drop(process_guard); - - let mut context_guard = context_lock.write(); - if let Some((_, pctl, _)) = context_guard.sigcontrol() { - if !pctl.signal_will_ign(SIGCONT, false) { - pctl.pending.fetch_or(sig_bit(SIGCONT), Ordering::Relaxed); - } - drop(context_guard); - - // TODO: which threads should become Runnable? - for thread in process_lock - .read() - .threads - .iter() - .filter_map(|t| t.upgrade()) - { - let mut thread = thread.write(); - if let Some((tctl, _, _)) = thread.sigcontrol() { - tctl.word[0].fetch_and( - !(sig_bit(SIGSTOP) - | sig_bit(SIGTTIN) - | sig_bit(SIGTTOU) - | sig_bit(SIGTSTP)), - Ordering::Relaxed, - ); - } - thread.unblock(); - } - } - // POSIX XSI allows but does not reqiure SIGCHLD to be sent when SIGCONT occurs. - return SendResult::SucceededSigcont { - }; - } - drop(process_guard); - let mut context_guard = context_lock.write(); - if sig == SIGSTOP - || (matches!(sig, SIGTTIN | SIGTTOU | SIGTSTP) - && context_guard - .sigcontrol() - .map_or(false, |(_, proc, _)| proc.signal_will_stop(sig))) - { - context_guard.status = context::Status::Blocked; - drop(context_guard); - process_lock.write().status = ProcessStatus::Stopped(sig); - - // TODO: Actually wait for, or IPI the context first, then clear bit. Not atomically safe otherwise. - let mut already = false; - for thread in process_lock - .read() - .threads - .iter() - .filter_map(|t| t.upgrade()) - { - let mut thread = thread.write(); - if let Some((tctl, pctl, _)) = thread.sigcontrol() { - if !already { - pctl.pending.fetch_and(!sig_bit(SIGCONT), Ordering::Relaxed); - already = true; - } - tctl.word[0].fetch_and(!sig_bit(SIGCONT), Ordering::Relaxed); - } - } - - return SendResult::SucceededSigchld { - orig_signal: sig, - }; - } - if sig == SIGKILL { - context_guard.being_sigkilled = true; - context_guard.unblock(); - drop(context_guard); - *killed_self |= is_self; - - // exit() will signal the parent, rather than immediately in kill() - return SendResult::Succeeded; - } - if let Some((tctl, pctl, sigst)) = context_guard.sigcontrol() - && !pctl.signal_will_ign(sig, is_sigchld_to_parent) - { - match target { - KillTarget::Thread(_) => { - tctl.sender_infos[sig_idx].store(sender.raw(), Ordering::Relaxed); - - let _was_new = tctl.word[sig_group].fetch_or(sig_bit(sig), Ordering::Release); - if (tctl.word[sig_group].load(Ordering::Relaxed) >> 32) & sig_bit(sig) != 0 { - context_guard.unblock(); - *killed_self |= is_self; - } - } - KillTarget::Process(proc) => { - match mode { - KillMode::Queued(arg) => { - if sig_group != 1 || sig_idx < 32 || sig_idx >= 64 { - return SendResult::Invalid; - } - let rtidx = sig_idx - 32; - //log::info!("QUEUEING {arg:?} RTIDX {rtidx}"); - if rtidx >= sigst.rtqs.len() { - sigst.rtqs.resize_with(rtidx + 1, VecDeque::new); - } - let rtq = sigst.rtqs.get_mut(rtidx).unwrap(); - - // TODO: configurable limit? - if rtq.len() > 32 { - return SendResult::FullQ; - } - - rtq.push_back(arg); - } - KillMode::Idempotent => { - if pctl.pending.load(Ordering::Acquire) & sig_bit(sig) != 0 { - // If already pending, do not send this signal. While possible that - // another thread is concurrently clearing pending, and that other - // spuriously awoken threads would benefit from actually receiving - // this signal, there is no requirement by POSIX for such signals - // not to be mergeable. So unless the signal handler is observed to - // happen-before this syscall, it can be ignored. The pending bits - // would certainly have been cleared, thus contradicting this - // already reached statement. - return SendResult::Succeeded; - } - - if sig_group != 0 { - return SendResult::Invalid; - } - pctl.sender_infos[sig_idx].store(sender.raw(), Ordering::Relaxed); - } - } - - pctl.pending.fetch_or(sig_bit(sig), Ordering::Release); - drop(context_guard); - - for thread in proc.read().threads.iter().filter_map(|t| t.upgrade()) { - let mut thread = thread.write(); - let Some((tctl, _, _)) = thread.sigcontrol() else { - continue; - }; - if (tctl.word[sig_group].load(Ordering::Relaxed) >> 32) & sig_bit(sig) != 0 - { - thread.unblock(); - *killed_self |= is_self; - break; - } - } - } - } - SendResult::Succeeded - } else { - // Discard signals if sighandler is unset. This includes both special contexts such - // as bootstrap, and child processes or threads that have not yet been started. - // This is semantically equivalent to having all signals except SIGSTOP and SIGKILL - // blocked/ignored (SIGCONT can be ignored and masked, but will always continue - // stopped processes first). - SendResult::Succeeded - } - })(); - - match result { - SendResult::Succeeded => (), - SendResult::FullQ => return Err(Error::new(EAGAIN)), - SendResult::Invalid => return Err(Error::new(EINVAL)), - SendResult::SucceededSigchld { - ppid, - pgid, - orig_signal, - } => { - } - SendResult::SucceededSigcont { ppid, pgid } => { - // POSIX XSI allows but does not require SIGCONT to send signals to the parent. - //send_signal(KillTarget::Process(parent), SIGCHLD, true, killed_self)?; - } - } - - Ok(()) - */ - Ok(()) -} - -#[derive(Clone, Copy)] -pub enum KillMode { - Idempotent, - Queued(RtSigInfo), -} - pub fn mprotect(address: usize, size: usize, flags: MapFlags) -> Result<()> { // println!("mprotect {:#X}, {}, {:#X}", address, size, flags); @@ -394,26 +146,3 @@ pub unsafe fn bootstrap_mem(bootstrap: &crate::Bootstrap) -> &'static [u8] { bootstrap.page_count * PAGE_SIZE, ) } -pub fn sigdequeue(out: UserSliceWo, sig_idx: u32) -> Result<()> { - let current = context::current(); - let mut current = current.write(); - let Some((_tctl, pctl, st)) = current.sigcontrol() else { - return Err(Error::new(ESRCH)); - }; - if sig_idx >= 32 { - return Err(Error::new(EINVAL)); - } - let q = st - .rtqs - .get_mut(sig_idx as usize) - .ok_or(Error::new(EAGAIN))?; - let Some(front) = q.pop_front() else { - return Err(Error::new(EAGAIN)); - }; - if q.is_empty() { - pctl.pending - .fetch_and(!(1 << (32 + sig_idx as usize)), Ordering::Relaxed); - } - out.copy_exactly(&front)?; - Ok(()) -}