process_list.rs 6.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204
  1. use core::sync::atomic::Ordering;
  2. use super::{Process, ProcessGroup, Session, Thread, WaitObject, WaitType};
  3. use crate::{
  4. kernel::{task::futex_wake, user::UserPointerMut},
  5. rcu::rcu_sync,
  6. };
  7. use alloc::{
  8. collections::btree_map::BTreeMap,
  9. sync::{Arc, Weak},
  10. };
  11. use eonix_runtime::task::Task;
  12. use eonix_sync::{AsProof as _, AsProofMut as _, RwLock};
  13. pub struct ProcessList {
  14. /// The init process.
  15. init: Option<Arc<Process>>,
  16. /// All threads.
  17. threads: BTreeMap<u32, Arc<Thread>>,
  18. /// All processes.
  19. processes: BTreeMap<u32, Weak<Process>>,
  20. /// All process groups.
  21. pgroups: BTreeMap<u32, Weak<ProcessGroup>>,
  22. /// All sessions.
  23. sessions: BTreeMap<u32, Weak<Session>>,
  24. }
  25. static GLOBAL_PROC_LIST: RwLock<ProcessList> = RwLock::new(ProcessList {
  26. init: None,
  27. threads: BTreeMap::new(),
  28. processes: BTreeMap::new(),
  29. pgroups: BTreeMap::new(),
  30. sessions: BTreeMap::new(),
  31. });
  32. impl ProcessList {
  33. pub fn get() -> &'static RwLock<Self> {
  34. &GLOBAL_PROC_LIST
  35. }
  36. pub fn add_session(&mut self, session: &Arc<Session>) {
  37. self.sessions.insert(session.sid, Arc::downgrade(session));
  38. }
  39. pub fn add_pgroup(&mut self, pgroup: &Arc<ProcessGroup>) {
  40. self.pgroups.insert(pgroup.pgid, Arc::downgrade(pgroup));
  41. }
  42. pub fn add_process(&mut self, process: &Arc<Process>) {
  43. self.processes.insert(process.pid, Arc::downgrade(process));
  44. }
  45. pub fn add_thread(&mut self, thread: &Arc<Thread>) {
  46. self.threads.insert(thread.tid, thread.clone());
  47. }
  48. pub fn remove_process(&mut self, pid: u32) {
  49. // Thread group leader has the same tid as the pid.
  50. if let Some(thread) = self.threads.remove(&pid) {
  51. self.processes.remove(&pid);
  52. // SAFETY: We wait until all references are dropped below with `rcu_sync()`.
  53. let session = unsafe { thread.process.session.swap(None) }.unwrap();
  54. let pgroup = unsafe { thread.process.pgroup.swap(None) }.unwrap();
  55. let _parent = unsafe { thread.process.parent.swap(None) }.unwrap();
  56. pgroup.remove_member(pid, self.prove_mut());
  57. Task::block_on(rcu_sync());
  58. if Arc::strong_count(&pgroup) == 1 {
  59. self.pgroups.remove(&pgroup.pgid);
  60. }
  61. if Arc::strong_count(&session) == 1 {
  62. self.sessions.remove(&session.sid);
  63. }
  64. } else {
  65. panic!("Process {} not found", pid);
  66. }
  67. }
  68. pub fn set_init_process(&mut self, init: Arc<Process>) {
  69. let old_init = self.init.replace(init);
  70. assert!(old_init.is_none(), "Init process already set");
  71. }
  72. pub fn init_process(&self) -> &Arc<Process> {
  73. self.init.as_ref().unwrap()
  74. }
  75. pub fn try_find_thread(&self, tid: u32) -> Option<&Arc<Thread>> {
  76. self.threads.get(&tid)
  77. }
  78. pub fn try_find_process(&self, pid: u32) -> Option<Arc<Process>> {
  79. self.processes.get(&pid).and_then(Weak::upgrade)
  80. }
  81. pub fn try_find_pgroup(&self, pgid: u32) -> Option<Arc<ProcessGroup>> {
  82. self.pgroups.get(&pgid).and_then(Weak::upgrade)
  83. }
  84. pub fn try_find_session(&self, sid: u32) -> Option<Arc<Session>> {
  85. self.sessions.get(&sid).and_then(Weak::upgrade)
  86. }
  87. /// Make the process a zombie and notify the parent.
  88. /// # Safety
  89. /// This function will destroy the process and all its threads.
  90. /// It is the caller's responsibility to ensure that the process is not
  91. /// running or will not run after this function is called.
  92. pub async unsafe fn do_exit(
  93. &mut self,
  94. thread: &Thread,
  95. exit_status: WaitType,
  96. is_exiting_group: bool,
  97. ) {
  98. let process = thread.process.clone();
  99. if process.pid == 1 {
  100. panic!("init exited");
  101. }
  102. let inner = process.inner.access_mut(self.prove_mut());
  103. thread.dead.store(true, Ordering::SeqCst);
  104. if is_exiting_group {
  105. // TODO: Send SIGKILL to all threads.
  106. // todo!()
  107. }
  108. if thread.tid != process.pid {
  109. self.threads.remove(&thread.tid);
  110. inner.threads.remove(&thread.tid).unwrap();
  111. }
  112. if let Some(clear_ctid) = thread.get_clear_ctid() {
  113. UserPointerMut::new(clear_ctid as *mut u32)
  114. .unwrap()
  115. .write(0u32)
  116. .expect("should clear child tid successfully");
  117. futex_wake(clear_ctid, None, 1)
  118. .await
  119. .expect("should wake up child tid");
  120. }
  121. if let Some(robust_list) = thread.get_robust_list() {
  122. let _ = robust_list.wake_all().await;
  123. }
  124. // main thread exit
  125. if thread.tid == process.pid {
  126. assert_eq!(thread.tid, process.pid);
  127. thread.files.close_all();
  128. // If we are the session leader, we should drop the control terminal.
  129. if process.session(self.prove()).sid == process.pid {
  130. if let Some(terminal) =
  131. Task::block_on(process.session(self.prove()).drop_control_terminal())
  132. {
  133. terminal.drop_session();
  134. }
  135. }
  136. // Release the MMList as well as the page table.
  137. unsafe {
  138. // SAFETY: We are exiting the process, so no one might be using it.
  139. process.mm_list.replace(None);
  140. }
  141. // Make children orphans (adopted by init)
  142. {
  143. let init = self.init_process();
  144. inner.children.retain(|_, child| {
  145. let child = child.upgrade().unwrap();
  146. // SAFETY: `child.parent` must be ourself. So we don't need to free it.
  147. unsafe { child.parent.swap(Some(init.clone())) };
  148. init.add_child(&child, self.prove_mut());
  149. false
  150. });
  151. }
  152. let mut init_notify = self.init_process().notify_batch();
  153. process
  154. .wait_list
  155. .drain_exited()
  156. .into_iter()
  157. .for_each(|item| init_notify.notify(item));
  158. init_notify.finish(self.prove());
  159. process.parent(self.prove()).notify(
  160. process.exit_signal,
  161. WaitObject {
  162. pid: process.pid,
  163. code: exit_status,
  164. },
  165. self.prove(),
  166. );
  167. }
  168. }
  169. }