process_list.rs 5.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187
  1. use alloc::{
  2. collections::btree_map::BTreeMap,
  3. sync::{Arc, Weak},
  4. };
  5. use bindings::KERNEL_PML4;
  6. use crate::{
  7. prelude::*,
  8. rcu::rcu_sync,
  9. sync::{AsRefMutPosition as _, AsRefPosition as _},
  10. };
  11. use lazy_static::lazy_static;
  12. use super::{Process, ProcessGroup, Session, Signal, Thread, WaitObject, WaitType};
  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. lazy_static! {
  26. static ref GLOBAL_PROC_LIST: RwSemaphore<ProcessList> = {
  27. RwSemaphore::new(ProcessList {
  28. init: None,
  29. threads: BTreeMap::new(),
  30. processes: BTreeMap::new(),
  31. pgroups: BTreeMap::new(),
  32. sessions: BTreeMap::new(),
  33. })
  34. };
  35. }
  36. impl ProcessList {
  37. pub fn get() -> &'static RwSemaphore<Self> {
  38. &GLOBAL_PROC_LIST
  39. }
  40. pub fn add_session(&mut self, session: &Arc<Session>) {
  41. self.sessions.insert(session.sid, Arc::downgrade(session));
  42. }
  43. pub fn add_pgroup(&mut self, pgroup: &Arc<ProcessGroup>) {
  44. self.pgroups.insert(pgroup.pgid, Arc::downgrade(pgroup));
  45. }
  46. pub fn add_process(&mut self, process: &Arc<Process>) {
  47. self.processes.insert(process.pid, Arc::downgrade(process));
  48. }
  49. pub fn add_thread(&mut self, thread: &Arc<Thread>) {
  50. self.threads.insert(thread.tid, thread.clone());
  51. }
  52. pub fn kill_current(signal: Signal) -> ! {
  53. unsafe {
  54. let mut process_list = ProcessList::get().lock();
  55. eonix_preempt::disable();
  56. // SAFETY: Preemption disabled.
  57. process_list.do_kill_process(&Thread::current().process, WaitType::Signaled(signal));
  58. }
  59. unsafe {
  60. // SAFETY: Preempt count == 1.
  61. Thread::exit();
  62. }
  63. }
  64. pub fn remove_process(&mut self, pid: u32) {
  65. // Thread group leader has the same tid as the pid.
  66. if let Some(thread) = self.threads.remove(&pid) {
  67. self.processes.remove(&pid);
  68. // SAFETY: We wait until all references are dropped below with `rcu_sync()`.
  69. let session = unsafe { thread.process.session.swap(None) }.unwrap();
  70. let pgroup = unsafe { thread.process.pgroup.swap(None) }.unwrap();
  71. let _parent = unsafe { thread.process.parent.swap(None) }.unwrap();
  72. pgroup.remove_member(pid, self.as_pos_mut());
  73. rcu_sync();
  74. if Arc::strong_count(&pgroup) == 1 {
  75. self.pgroups.remove(&pgroup.pgid);
  76. }
  77. if Arc::strong_count(&session) == 1 {
  78. self.sessions.remove(&session.sid);
  79. }
  80. } else {
  81. panic!("Process {} not found", pid);
  82. }
  83. }
  84. pub fn set_init_process(&mut self, init: Arc<Process>) {
  85. let old_init = self.init.replace(init);
  86. assert!(old_init.is_none(), "Init process already set");
  87. }
  88. pub fn init_process(&self) -> &Arc<Process> {
  89. self.init.as_ref().unwrap()
  90. }
  91. pub fn try_find_thread(&self, tid: u32) -> Option<&Arc<Thread>> {
  92. self.threads.get(&tid)
  93. }
  94. pub fn try_find_process(&self, pid: u32) -> Option<Arc<Process>> {
  95. self.processes.get(&pid).and_then(Weak::upgrade)
  96. }
  97. pub fn try_find_pgroup(&self, pgid: u32) -> Option<Arc<ProcessGroup>> {
  98. self.pgroups.get(&pgid).and_then(Weak::upgrade)
  99. }
  100. pub fn try_find_session(&self, sid: u32) -> Option<Arc<Session>> {
  101. self.sessions.get(&sid).and_then(Weak::upgrade)
  102. }
  103. /// Make the process a zombie and notify the parent.
  104. /// # Safety
  105. /// This function needs to be called with preemption disabled.
  106. pub unsafe fn do_kill_process(&mut self, process: &Arc<Process>, status: WaitType) {
  107. if process.pid == 1 {
  108. panic!("init exited");
  109. }
  110. let inner = process.inner.access_mut(self.as_pos_mut());
  111. // TODO!!!!!!: When we are killing multiple threads, we need to wait until all
  112. // the threads are stopped then proceed.
  113. for thread in inner.threads.values().map(|t| t.upgrade().unwrap()) {
  114. assert!(thread.tid == Thread::current().tid);
  115. // TODO: Send SIGKILL to all threads.
  116. thread.files.close_all();
  117. }
  118. // If we are the session leader, we should drop the control terminal.
  119. if process.session(self.as_pos()).sid == process.pid {
  120. if let Some(terminal) = process.session(self.as_pos()).drop_control_terminal() {
  121. terminal.drop_session();
  122. }
  123. }
  124. // Release the MMList as well as the page table.
  125. // Before we release the page table, we need to switch to the kernel page table.
  126. arch::set_root_page_table(KERNEL_PML4 as usize);
  127. unsafe {
  128. process.mm_list.release();
  129. }
  130. // Make children orphans (adopted by init)
  131. {
  132. let init = self.init_process();
  133. inner.children.retain(|_, child| {
  134. let child = child.upgrade().unwrap();
  135. // SAFETY: `child.parent` must be ourself. So we don't need to free it.
  136. unsafe { child.parent.swap(Some(init.clone())) };
  137. init.add_child(&child, self.as_pos_mut());
  138. false
  139. });
  140. }
  141. let mut init_notify = self.init_process().notify_batch();
  142. process
  143. .wait_list
  144. .drain_exited()
  145. .into_iter()
  146. .for_each(|item| init_notify.notify(item));
  147. init_notify.finish(self.as_pos());
  148. process.parent(self.as_pos()).notify(
  149. WaitObject {
  150. pid: process.pid,
  151. code: status,
  152. },
  153. self.as_pos(),
  154. );
  155. }
  156. }