diff --git a/kernel/src/fs/file_table.rs b/kernel/src/fs/file_table.rs index 89012cec2..5a55c0529 100644 --- a/kernel/src/fs/file_table.rs +++ b/kernel/src/fs/file_table.rs @@ -15,7 +15,7 @@ use crate::{ prelude::*, process::{ posix_thread::FileTableRefMut, - signal::{constants::SIGIO, signals::kernel::KernelSignal, PollAdaptor}, + signal::{constants::SIGIO, PollAdaptor}, Pid, Process, }, }; @@ -405,10 +405,8 @@ impl OwnerObserver { impl Observer for OwnerObserver { fn on_events(&self, _events: &IoEvents) { - if self.file.status_flags().contains(StatusFlags::O_ASYNC) - && let Some(process) = self.owner.upgrade() - { - process.enqueue_signal(KernelSignal::new(SIGIO)); + if self.file.status_flags().contains(StatusFlags::O_ASYNC) { + crate::process::enqueue_signal_async(self.owner.clone(), SIGIO); } } } diff --git a/kernel/src/process/mod.rs b/kernel/src/process/mod.rs index 2350b5519..6e37b5e5e 100644 --- a/kernel/src/process/mod.rs +++ b/kernel/src/process/mod.rs @@ -23,8 +23,8 @@ pub use clone::{clone_child, CloneArgs, CloneFlags}; pub use credentials::{Credentials, Gid, Uid}; pub use kill::{kill, kill_all, kill_group, tgkill}; pub use process::{ - spawn_init_process, ExitCode, JobControl, Pgid, Pid, Process, ProcessGroup, Session, Sid, - Terminal, + enqueue_signal_async, spawn_init_process, ExitCode, JobControl, Pgid, Pid, Process, + ProcessGroup, Session, Sid, Terminal, }; pub use process_filter::ProcessFilter; pub use process_vm::{ diff --git a/kernel/src/process/process/mod.rs b/kernel/src/process/process/mod.rs index 08f047950..acf1658d1 100644 --- a/kernel/src/process/process/mod.rs +++ b/kernel/src/process/process/mod.rs @@ -600,14 +600,15 @@ impl Process { &self.sig_dispositions } - /// Enqueues a process-directed signal. This method should only be used for enqueue kernel - /// signal and fault signal. + /// Enqueues a process-directed signal. + /// + /// This method should only be used for enqueue kernel signals and fault signals. /// /// The signal may be delivered to any one of the threads that does not currently have the - /// signal blocked. If more than one of the threads has the signal unblocked, then this method + /// signal blocked. If more than one of the threads have the signal unblocked, then this method /// chooses an arbitrary thread to which to deliver the signal. - /// - /// TODO: restrict these method with access control tool. + // + // TODO: Restrict this method with the access control tool. pub fn enqueue_signal(&self, signal: impl Signal + Clone + 'static) { if self.status.is_zombie() { return; @@ -706,3 +707,21 @@ impl Process { } } } + +/// Enqueues a process-directed kernel signal asynchronously. +/// +/// This is the asynchronous version of [`Process::enqueue_signal`]. By asynchronous, this method +/// submits a work item and returns, so this method doesn't sleep and can be used in atomic mode. +pub fn enqueue_signal_async(process: Weak, signum: SigNum) { + use super::signal::signals::kernel::KernelSignal; + use crate::thread::work_queue; + + work_queue::submit_work_func( + move || { + if let Some(process) = process.upgrade() { + process.enqueue_signal(KernelSignal::new(signum)); + } + }, + work_queue::WorkPriority::High, + ); +}