process_group.rs 2.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687
  1. use super::{Process, ProcessList, Session, Signal};
  2. use alloc::{
  3. collections::btree_map::BTreeMap,
  4. sync::{Arc, Weak},
  5. };
  6. use eonix_sync::{Locked, Proof, ProofMut};
  7. pub struct ProcessGroupBuilder {
  8. pgid: Option<u32>,
  9. leader: Option<Weak<Process>>,
  10. session: Option<Arc<Session>>,
  11. }
  12. #[derive(Debug)]
  13. pub struct ProcessGroup {
  14. pub pgid: u32,
  15. pub _leader: Weak<Process>,
  16. pub session: Weak<Session>,
  17. pub processes: Locked<BTreeMap<u32, Weak<Process>>, ProcessList>,
  18. }
  19. impl ProcessGroupBuilder {
  20. pub const fn new() -> Self {
  21. Self {
  22. pgid: None,
  23. leader: None,
  24. session: None,
  25. }
  26. }
  27. pub fn leader(mut self, leader: &Arc<Process>) -> Self {
  28. self.pgid = Some(leader.pid);
  29. self.leader = Some(Arc::downgrade(leader));
  30. self
  31. }
  32. pub fn session(mut self, session: Arc<Session>) -> Self {
  33. self.session = Some(session);
  34. self
  35. }
  36. pub fn build(self, process_list: &mut ProcessList) -> Arc<ProcessGroup> {
  37. let pgid = self.pgid.expect("PGID is not set");
  38. let leader = self.leader.expect("Leader is not set");
  39. let session = self.session.expect("Session is not set");
  40. let pgroup = Arc::new(ProcessGroup {
  41. pgid,
  42. session: Arc::downgrade(&session),
  43. processes: Locked::new(BTreeMap::from([(pgid, leader.clone())]), process_list),
  44. _leader: leader,
  45. });
  46. process_list.add_pgroup(&pgroup);
  47. session.add_member(process_list, &pgroup);
  48. pgroup
  49. }
  50. }
  51. impl ProcessGroup {
  52. pub(super) fn add_member(&self, process: &Arc<Process>, procs: ProofMut<'_, ProcessList>) {
  53. assert!(self
  54. .processes
  55. .access_mut(procs)
  56. .insert(process.pid, Arc::downgrade(process))
  57. .is_none());
  58. }
  59. pub(super) fn remove_member(&self, pid: u32, procs: ProofMut<'_, ProcessList>) {
  60. let processes = self.processes.access_mut(procs);
  61. assert!(processes.remove(&pid).is_some());
  62. if processes.is_empty() {
  63. self.session
  64. .upgrade()
  65. .unwrap()
  66. .remove_member(self.pgid, procs);
  67. }
  68. }
  69. pub fn raise(&self, signal: Signal, procs: Proof<'_, ProcessList>) {
  70. let processes = self.processes.access(procs);
  71. for process in processes.values().map(|p| p.upgrade().unwrap()) {
  72. process.raise(signal, procs);
  73. }
  74. }
  75. }