Files
asterinas/services/libs/jinux-std/src/process/process_group.rs
2023-05-04 14:41:42 +08:00

86 lines
2.5 KiB
Rust

use super::{
process_table,
signal::signals::{kernel::KernelSignal, user::UserSignal},
Pgid, Pid, Process,
};
use crate::prelude::*;
pub struct ProcessGroup {
inner: Mutex<ProcessGroupInner>,
}
struct ProcessGroupInner {
pgid: Pgid,
processes: BTreeMap<Pid, Arc<Process>>,
leader_process: Option<Arc<Process>>,
}
impl ProcessGroup {
fn default() -> Self {
ProcessGroup {
inner: Mutex::new(ProcessGroupInner {
pgid: 0,
processes: BTreeMap::new(),
leader_process: None,
}),
}
}
pub fn new(process: Arc<Process>) -> Self {
let process_group = ProcessGroup::default();
let pid = process.pid();
process_group.set_pgid(pid);
process_group.add_process(process.clone());
process_group.set_leader_process(process);
process_group
}
pub fn set_pgid(&self, pgid: Pgid) {
self.inner.lock().pgid = pgid;
}
pub fn set_leader_process(&self, leader_process: Arc<Process>) {
self.inner.lock().leader_process = Some(leader_process);
}
pub fn add_process(&self, process: Arc<Process>) {
self.inner.lock().processes.insert(process.pid(), process);
}
pub fn contains_process(&self, pid: Pid) -> bool {
self.inner.lock().processes.contains_key(&pid)
}
/// remove a process from this process group.
/// If this group contains no processes now, the group itself will be deleted from global table.
pub fn remove_process(&self, pid: Pid) {
let mut inner_lock = self.inner.lock();
inner_lock.processes.remove(&pid);
let len = inner_lock.processes.len();
let pgid = inner_lock.pgid;
// if self contains no process, remove self from table
if len == 0 {
// this must be the last statement
process_table::remove_process_group(pgid);
}
}
pub fn pgid(&self) -> Pgid {
self.inner.lock().pgid
}
/// send kernel signal to all processes in the group
pub fn kernel_signal(&self, signal: KernelSignal) {
for (_, process) in &self.inner.lock().processes {
process.enqueue_signal(Box::new(signal.clone()));
}
}
/// send user signal to all processes in the group
pub fn user_signal(&self, signal: UserSignal) {
for (_, process) in &self.inner.lock().processes {
process.enqueue_signal(Box::new(signal.clone()));
}
}
}