mirror of
https://github.com/asterinas/asterinas.git
synced 2025-06-28 03:43:23 +00:00
Replace the Pausers' usage with Waiter/WaitQueue
This commit is contained in:
committed by
Tate, Hongliang Tian
parent
822caf34f4
commit
42e28763c5
@ -59,7 +59,7 @@ pub fn do_exit_group(term_status: TermStatus) {
|
||||
// Notify parent
|
||||
let signal = KernelSignal::new(SIGCHLD);
|
||||
parent.enqueue_signal(signal);
|
||||
parent.children_pauser().resume_all();
|
||||
parent.children_wait_queue().wake_all();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2,13 +2,14 @@
|
||||
|
||||
#![allow(unused_variables)]
|
||||
|
||||
use ostd::sync::WaitQueue;
|
||||
|
||||
use crate::{
|
||||
prelude::*,
|
||||
process::{
|
||||
signal::{
|
||||
constants::{SIGCONT, SIGHUP},
|
||||
signals::kernel::KernelSignal,
|
||||
Pauser,
|
||||
},
|
||||
ProcessGroup, Session,
|
||||
},
|
||||
@ -22,7 +23,7 @@ use crate::{
|
||||
pub struct JobControl {
|
||||
foreground: SpinLock<Weak<ProcessGroup>>,
|
||||
session: SpinLock<Weak<Session>>,
|
||||
pauser: Arc<Pauser>,
|
||||
wait_queue: WaitQueue,
|
||||
}
|
||||
|
||||
impl JobControl {
|
||||
@ -31,7 +32,7 @@ impl JobControl {
|
||||
Self {
|
||||
foreground: SpinLock::new(Weak::new()),
|
||||
session: SpinLock::new(Weak::new()),
|
||||
pauser: Pauser::new(),
|
||||
wait_queue: WaitQueue::new(),
|
||||
}
|
||||
}
|
||||
|
||||
@ -73,7 +74,7 @@ impl JobControl {
|
||||
let session = current.session().unwrap();
|
||||
*self.session.lock() = Arc::downgrade(&session);
|
||||
|
||||
self.pauser.resume_all();
|
||||
self.wait_queue.wake_all();
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@ -129,7 +130,7 @@ impl JobControl {
|
||||
}
|
||||
|
||||
*self.foreground.lock() = Arc::downgrade(process_group);
|
||||
self.pauser.resume_all();
|
||||
self.wait_queue.wake_all();
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@ -146,7 +147,7 @@ impl JobControl {
|
||||
}
|
||||
|
||||
// Slow path
|
||||
self.pauser.pause_until(|| {
|
||||
self.wait_queue.pause_until(|| {
|
||||
if self.current_belongs_to_foreground() {
|
||||
Some(())
|
||||
} else {
|
||||
|
@ -9,11 +9,9 @@ use super::{
|
||||
process_vm::{Heap, InitStackReader, ProcessVm},
|
||||
rlimit::ResourceLimits,
|
||||
signal::{
|
||||
constants::SIGCHLD,
|
||||
sig_disposition::SigDispositions,
|
||||
sig_num::{AtomicSigNum, SigNum},
|
||||
signals::Signal,
|
||||
Pauser,
|
||||
},
|
||||
status::ProcessStatus,
|
||||
Credentials, TermStatus,
|
||||
@ -39,6 +37,7 @@ use aster_rights::Full;
|
||||
use atomic::Atomic;
|
||||
pub use builder::ProcessBuilder;
|
||||
pub use job_control::JobControl;
|
||||
use ostd::sync::WaitQueue;
|
||||
pub use process_group::ProcessGroup;
|
||||
pub use session::Session;
|
||||
pub use terminal::Terminal;
|
||||
@ -63,7 +62,7 @@ pub struct Process {
|
||||
|
||||
process_vm: ProcessVm,
|
||||
/// Wait for child status changed
|
||||
children_pauser: Arc<Pauser>,
|
||||
children_wait_queue: WaitQueue,
|
||||
|
||||
// Mutable Part
|
||||
/// The executable path.
|
||||
@ -189,7 +188,7 @@ impl Process {
|
||||
) -> Arc<Self> {
|
||||
// SIGCHID does not interrupt pauser. Child process will
|
||||
// resume paused parent when doing exit.
|
||||
let children_pauser = Pauser::new_with_mask(SIGCHLD.into());
|
||||
let children_wait_queue = WaitQueue::new();
|
||||
|
||||
let prof_clock = ProfClock::new();
|
||||
|
||||
@ -198,7 +197,7 @@ impl Process {
|
||||
threads: Mutex::new(threads),
|
||||
executable_path: RwLock::new(executable_path),
|
||||
process_vm,
|
||||
children_pauser,
|
||||
children_wait_queue,
|
||||
status: ProcessStatus::new_uninit(),
|
||||
parent: ParentProcess::new(parent),
|
||||
children: Mutex::new(BTreeMap::new()),
|
||||
@ -343,8 +342,8 @@ impl Process {
|
||||
self.children.lock().contains_key(pid)
|
||||
}
|
||||
|
||||
pub fn children_pauser(&self) -> &Arc<Pauser> {
|
||||
&self.children_pauser
|
||||
pub fn children_wait_queue(&self) -> &WaitQueue {
|
||||
&self.children_wait_queue
|
||||
}
|
||||
|
||||
// *********** Process group & Session***********
|
||||
|
@ -5,10 +5,11 @@ use core::{
|
||||
time::Duration,
|
||||
};
|
||||
|
||||
use ostd::sync::{Waiter, Waker};
|
||||
|
||||
use crate::{
|
||||
events::{IoEvents, Observer, Subject},
|
||||
prelude::*,
|
||||
process::signal::Pauser,
|
||||
};
|
||||
|
||||
/// A pollee maintains a set of active events, which can be polled with
|
||||
@ -136,6 +137,8 @@ pub struct Poller {
|
||||
event_counter: Arc<EventCounter>,
|
||||
// All pollees that are interesting to this poller
|
||||
pollees: Vec<Weak<PolleeInner>>,
|
||||
// A waiter used to pause the current thread.
|
||||
waiter: Waiter,
|
||||
}
|
||||
|
||||
impl Default for Poller {
|
||||
@ -147,23 +150,25 @@ impl Default for Poller {
|
||||
impl Poller {
|
||||
/// Constructs a new `Poller`.
|
||||
pub fn new() -> Self {
|
||||
let (waiter, waker) = Waiter::new_pair();
|
||||
Self {
|
||||
event_counter: Arc::new(EventCounter::new()),
|
||||
event_counter: Arc::new(EventCounter::new(waker)),
|
||||
pollees: Vec::new(),
|
||||
waiter,
|
||||
}
|
||||
}
|
||||
|
||||
/// Wait until there are any interesting events happen since last `wait`. The `wait`
|
||||
/// can be interrupted by signal.
|
||||
pub fn wait(&self) -> Result<()> {
|
||||
self.event_counter.read(None)?;
|
||||
self.event_counter.read(&self.waiter, None)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Wait until there are any interesting events happen since last `wait` or a given timeout
|
||||
/// is expired. This method can be interrupted by signal.
|
||||
pub fn wait_timeout(&self, timeout: &Duration) -> Result<()> {
|
||||
self.event_counter.read(Some(timeout))?;
|
||||
self.event_counter.read(&self.waiter, Some(timeout))?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@ -188,20 +193,18 @@ impl Drop for Poller {
|
||||
/// A counter for wait and wakeup.
|
||||
struct EventCounter {
|
||||
counter: AtomicUsize,
|
||||
pauser: Arc<Pauser>,
|
||||
waker: Arc<Waker>,
|
||||
}
|
||||
|
||||
impl EventCounter {
|
||||
pub fn new() -> Self {
|
||||
let pauser = Pauser::new();
|
||||
|
||||
pub fn new(waker: Arc<Waker>) -> Self {
|
||||
Self {
|
||||
counter: AtomicUsize::new(0),
|
||||
pauser,
|
||||
waker,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn read(&self, timeout: Option<&Duration>) -> Result<usize> {
|
||||
pub fn read(&self, waiter: &Waiter, timeout: Option<&Duration>) -> Result<usize> {
|
||||
let cond = || {
|
||||
let val = self.counter.swap(0, Ordering::Relaxed);
|
||||
if val > 0 {
|
||||
@ -212,15 +215,15 @@ impl EventCounter {
|
||||
};
|
||||
|
||||
if let Some(timeout) = timeout {
|
||||
self.pauser.pause_until_or_timeout(cond, timeout)
|
||||
waiter.pause_until_or_timeout(cond, timeout)
|
||||
} else {
|
||||
self.pauser.pause_until(cond)
|
||||
waiter.pause_until(cond)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn write(&self) {
|
||||
self.counter.fetch_add(1, Ordering::Relaxed);
|
||||
self.pauser.resume_one();
|
||||
self.waker.wake_up();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2,7 +2,11 @@
|
||||
|
||||
#![allow(dead_code)]
|
||||
|
||||
use super::{process_filter::ProcessFilter, ExitCode, Pid, Process};
|
||||
use super::{
|
||||
process_filter::ProcessFilter,
|
||||
signal::{constants::SIGCHLD, with_signal_blocked},
|
||||
ExitCode, Pid, Process,
|
||||
};
|
||||
use crate::{prelude::*, process::process_table, thread::thread_table};
|
||||
|
||||
// The definition of WaitOptions is from Occlum
|
||||
@ -27,48 +31,51 @@ impl WaitOptions {
|
||||
pub fn wait_child_exit(
|
||||
child_filter: ProcessFilter,
|
||||
wait_options: WaitOptions,
|
||||
ctx: &Context,
|
||||
) -> Result<Option<Arc<Process>>> {
|
||||
let current = current!();
|
||||
let zombie_child = current.children_pauser().pause_until(|| {
|
||||
let unwaited_children = current
|
||||
.children()
|
||||
.lock()
|
||||
.values()
|
||||
.filter(|child| match child_filter {
|
||||
ProcessFilter::Any => true,
|
||||
ProcessFilter::WithPid(pid) => child.pid() == pid,
|
||||
ProcessFilter::WithPgid(pgid) => child.pgid() == pgid,
|
||||
})
|
||||
.cloned()
|
||||
.collect::<Vec<_>>();
|
||||
let current = ctx.process;
|
||||
let zombie_child = with_signal_blocked(ctx, SIGCHLD.into(), || {
|
||||
current.children_wait_queue().pause_until(|| {
|
||||
let unwaited_children = current
|
||||
.children()
|
||||
.lock()
|
||||
.values()
|
||||
.filter(|child| match child_filter {
|
||||
ProcessFilter::Any => true,
|
||||
ProcessFilter::WithPid(pid) => child.pid() == pid,
|
||||
ProcessFilter::WithPgid(pgid) => child.pgid() == pgid,
|
||||
})
|
||||
.cloned()
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
if unwaited_children.is_empty() {
|
||||
return Some(Err(Error::with_message(
|
||||
Errno::ECHILD,
|
||||
"the process has no child to wait",
|
||||
)));
|
||||
}
|
||||
|
||||
// return immediately if we find a zombie child
|
||||
let zombie_child = unwaited_children.iter().find(|child| child.is_zombie());
|
||||
|
||||
if let Some(zombie_child) = zombie_child {
|
||||
let zombie_pid = zombie_child.pid();
|
||||
if wait_options.contains(WaitOptions::WNOWAIT) {
|
||||
// does not reap child, directly return
|
||||
return Some(Ok(Some(zombie_child.clone())));
|
||||
} else {
|
||||
reap_zombie_child(¤t, zombie_pid);
|
||||
return Some(Ok(Some(zombie_child.clone())));
|
||||
if unwaited_children.is_empty() {
|
||||
return Some(Err(Error::with_message(
|
||||
Errno::ECHILD,
|
||||
"the process has no child to wait",
|
||||
)));
|
||||
}
|
||||
}
|
||||
|
||||
if wait_options.contains(WaitOptions::WNOHANG) {
|
||||
return Some(Ok(None));
|
||||
}
|
||||
// return immediately if we find a zombie child
|
||||
let zombie_child = unwaited_children.iter().find(|child| child.is_zombie());
|
||||
|
||||
// wait
|
||||
None
|
||||
if let Some(zombie_child) = zombie_child {
|
||||
let zombie_pid = zombie_child.pid();
|
||||
if wait_options.contains(WaitOptions::WNOWAIT) {
|
||||
// does not reap child, directly return
|
||||
return Some(Ok(Some(zombie_child.clone())));
|
||||
} else {
|
||||
reap_zombie_child(current, zombie_pid);
|
||||
return Some(Ok(Some(zombie_child.clone())));
|
||||
}
|
||||
}
|
||||
|
||||
if wait_options.contains(WaitOptions::WNOHANG) {
|
||||
return Some(Ok(None));
|
||||
}
|
||||
|
||||
// wait
|
||||
None
|
||||
})
|
||||
})??;
|
||||
|
||||
Ok(zombie_child)
|
||||
|
Reference in New Issue
Block a user