process.rs 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513
  1. use core::{
  2. ptr::addr_of,
  3. sync::atomic::{AtomicU32, Ordering},
  4. };
  5. use alloc::{
  6. collections::{btree_map::BTreeMap, vec_deque::VecDeque},
  7. sync::{Arc, Weak},
  8. };
  9. use bindings::{ECHILD, EINTR, EPERM, ESRCH};
  10. use crate::{
  11. kernel::mem::MMList,
  12. prelude::*,
  13. rcu::{rcu_sync, RCUPointer, RCUReadGuard},
  14. sync::{
  15. AsRefMutPosition as _, AsRefPosition as _, CondVar, RefMutPosition, RefPosition,
  16. RwSemReadGuard, SpinGuard,
  17. },
  18. };
  19. use super::{signal::RaiseResult, ProcessGroup, ProcessList, Session, Signal, Thread};
  20. #[derive(Debug)]
  21. pub struct Process {
  22. /// Process id
  23. ///
  24. /// This should never change during the life of the process.
  25. pub pid: u32,
  26. pub wait_list: WaitList,
  27. pub mm_list: Arc<MMList>,
  28. /// Parent process
  29. ///
  30. /// `parent` must be valid during the whole life of the process.
  31. /// The only case where it may be `None` is when it is the init process
  32. /// or the process is kernel thread.
  33. pub(super) parent: RCUPointer<Process>,
  34. /// Process group
  35. ///
  36. /// `pgroup` must be valid during the whole life of the process.
  37. /// The only case where it may be `None` is when the process is kernel thread.
  38. pub(super) pgroup: RCUPointer<ProcessGroup>,
  39. /// Session
  40. ///
  41. /// `session` must be valid during the whole life of the process.
  42. /// The only case where it may be `None` is when the process is kernel thread.
  43. pub(super) session: RCUPointer<Session>,
  44. /// All things related to the process list.
  45. pub(super) inner: Locked<ProcessInner, ProcessList>,
  46. }
  47. #[derive(Debug)]
  48. pub(super) struct ProcessInner {
  49. pub(super) children: BTreeMap<u32, Weak<Process>>,
  50. pub(super) threads: BTreeMap<u32, Weak<Thread>>,
  51. }
  52. #[derive(Debug)]
  53. pub struct WaitList {
  54. wait_procs: Spin<VecDeque<WaitObject>>,
  55. cv_wait_procs: CondVar,
  56. }
  57. pub struct NotifyBatch<'waitlist, 'process, 'cv> {
  58. wait_procs: SpinGuard<'waitlist, VecDeque<WaitObject>>,
  59. process: &'process Process,
  60. cv: &'cv CondVar,
  61. needs_notify: bool,
  62. }
  63. pub struct Entry<'waitlist, 'proclist, 'cv> {
  64. wait_procs: SpinGuard<'waitlist, VecDeque<WaitObject>>,
  65. process_list: RwSemReadGuard<'proclist, ProcessList>,
  66. cv: &'cv CondVar,
  67. want_stop: bool,
  68. want_continue: bool,
  69. }
  70. pub struct DrainExited<'waitlist> {
  71. wait_procs: SpinGuard<'waitlist, VecDeque<WaitObject>>,
  72. }
  73. #[derive(Debug, Clone, Copy, PartialEq, Eq)]
  74. pub enum WaitType {
  75. Exited(u32),
  76. Signaled(Signal),
  77. Stopped(Signal),
  78. Continued,
  79. }
  80. #[derive(Debug, Clone, Copy)]
  81. pub struct WaitObject {
  82. pub pid: u32,
  83. pub code: WaitType,
  84. }
  85. impl WaitType {
  86. pub fn to_wstatus(self) -> u32 {
  87. match self {
  88. WaitType::Exited(status) => (status & 0xff) << 8,
  89. WaitType::Signaled(signal) if signal.is_coredump() => signal.to_signum() | 0x80,
  90. WaitType::Signaled(signal) => signal.to_signum(),
  91. WaitType::Stopped(signal) => 0x7f | (signal.to_signum() << 8),
  92. WaitType::Continued => 0xffff,
  93. }
  94. }
  95. }
  96. impl WaitObject {
  97. pub fn stopped(&self) -> Option<Signal> {
  98. if let WaitType::Stopped(signal) = self.code {
  99. Some(signal)
  100. } else {
  101. None
  102. }
  103. }
  104. pub fn is_continue(&self) -> bool {
  105. matches!(self.code, WaitType::Continued)
  106. }
  107. }
  108. /// PID 0 and 1 is created manually so we start from 2.
  109. static NEXT_PID: AtomicU32 = AtomicU32::new(2);
  110. impl Process {
  111. pub fn alloc_pid() -> u32 {
  112. NEXT_PID.fetch_add(1, Ordering::Relaxed)
  113. }
  114. pub fn new_cloned(other: &Arc<Self>, procs: &mut ProcessList) -> Arc<Self> {
  115. let procs_addr = addr_of!(*procs);
  116. // SAFETY: We are holding the process list lock.
  117. let other_pgroup = unsafe { other.pgroup.load_locked().unwrap() };
  118. let other_session = unsafe { other.session.load_locked().unwrap() };
  119. let process = Arc::new(Self {
  120. pid: Self::alloc_pid(),
  121. wait_list: WaitList::new(),
  122. mm_list: MMList::new_cloned(&other.mm_list),
  123. parent: RCUPointer::new_with(other.clone()),
  124. pgroup: RCUPointer::new_with(other_pgroup.clone()),
  125. session: RCUPointer::new_with(other_session.clone()),
  126. inner: Locked::new(
  127. ProcessInner {
  128. children: BTreeMap::new(),
  129. threads: BTreeMap::new(),
  130. },
  131. procs_addr,
  132. ),
  133. });
  134. procs.add_process(&process);
  135. other.add_child(&process, procs.as_pos_mut());
  136. other_pgroup.add_member(&process, procs.as_pos_mut());
  137. process
  138. }
  139. pub(super) unsafe fn new_for_init(pid: u32, procs: &mut ProcessList) -> Arc<Self> {
  140. Arc::new(Self {
  141. pid,
  142. wait_list: WaitList::new(),
  143. mm_list: MMList::new(),
  144. parent: RCUPointer::empty(),
  145. pgroup: RCUPointer::empty(),
  146. session: RCUPointer::empty(),
  147. inner: Locked::new(
  148. ProcessInner {
  149. children: BTreeMap::new(),
  150. threads: BTreeMap::new(),
  151. },
  152. procs,
  153. ),
  154. })
  155. }
  156. pub fn raise(&self, signal: Signal, procs: RefPosition<'_, ProcessList>) {
  157. let inner = self.inner.access(procs);
  158. for thread in inner.threads.values().map(|t| t.upgrade().unwrap()) {
  159. if let RaiseResult::Finished = thread.raise(signal) {
  160. break;
  161. }
  162. }
  163. }
  164. pub(super) fn add_child(&self, child: &Arc<Process>, procs: RefMutPosition<'_, ProcessList>) {
  165. assert!(self
  166. .inner
  167. .access_mut(procs)
  168. .children
  169. .insert(child.pid, Arc::downgrade(child))
  170. .is_none());
  171. }
  172. pub(super) fn add_thread(&self, thread: &Arc<Thread>, procs: RefMutPosition<'_, ProcessList>) {
  173. assert!(self
  174. .inner
  175. .access_mut(procs)
  176. .threads
  177. .insert(thread.tid, Arc::downgrade(thread))
  178. .is_none());
  179. }
  180. pub fn wait(
  181. &self,
  182. no_block: bool,
  183. trace_stop: bool,
  184. trace_continue: bool,
  185. ) -> KResult<Option<WaitObject>> {
  186. let wait_object = {
  187. let mut waits = self.wait_list.entry(trace_stop, trace_continue);
  188. loop {
  189. if let Some(object) = waits.get() {
  190. break object;
  191. }
  192. if self
  193. .inner
  194. .access(waits.process_list.as_pos())
  195. .children
  196. .is_empty()
  197. {
  198. return Err(ECHILD);
  199. }
  200. if no_block {
  201. return Ok(None);
  202. }
  203. waits.wait()?;
  204. }
  205. };
  206. if wait_object.stopped().is_some() || wait_object.is_continue() {
  207. Ok(Some(wait_object))
  208. } else {
  209. let mut procs = ProcessList::get().lock();
  210. procs.remove_process(wait_object.pid);
  211. assert!(self
  212. .inner
  213. .access_mut(procs.as_pos_mut())
  214. .children
  215. .remove(&wait_object.pid)
  216. .is_some());
  217. Ok(Some(wait_object))
  218. }
  219. }
  220. /// Create a new session for the process.
  221. pub fn setsid(self: &Arc<Self>) -> KResult<u32> {
  222. let mut procs = ProcessList::get().lock();
  223. // If there exists a session that has the same sid as our pid, we can't create a new
  224. // session. The standard says that we should create a new process group and be the
  225. // only process in the new process group and session.
  226. if procs.try_find_session(self.pid).is_some() {
  227. return Err(EPERM);
  228. }
  229. let session = Session::new(procs.as_mut(), self);
  230. let pgroup = session.new_group(procs.as_mut(), self);
  231. {
  232. let _old_session = unsafe { self.session.swap(Some(session.clone())) }.unwrap();
  233. let old_pgroup = unsafe { self.pgroup.swap(Some(pgroup.clone())) }.unwrap();
  234. old_pgroup.remove_member(self.pid, procs.as_pos_mut());
  235. rcu_sync();
  236. }
  237. Ok(pgroup.pgid)
  238. }
  239. /// Set the process group id of the process to `pgid`.
  240. ///
  241. /// This function does the actual work.
  242. fn do_setpgid(self: &Arc<Self>, pgid: u32, procs: &mut ProcessList) -> KResult<()> {
  243. // SAFETY: We are holding the process list lock.
  244. let session = unsafe { self.session.load_locked().unwrap() };
  245. let pgroup = unsafe { self.pgroup.load_locked().unwrap() };
  246. // Changing the process group of a session leader is not allowed.
  247. if session.sid == self.pid {
  248. return Err(EPERM);
  249. }
  250. let new_pgroup = if let Some(new_pgroup) = procs.try_find_pgroup(pgid) {
  251. // Move us to an existing process group.
  252. // Check that the two groups are in the same session.
  253. if new_pgroup.session.upgrade().unwrap().sid != session.sid {
  254. return Err(EPERM);
  255. }
  256. // If we are already in the process group, we are done.
  257. if new_pgroup.pgid == pgroup.pgid {
  258. return Ok(());
  259. }
  260. new_pgroup.add_member(self, procs.as_pos_mut());
  261. new_pgroup
  262. } else {
  263. // Create a new process group only if `pgid` matches our `pid`.
  264. if pgid != self.pid {
  265. return Err(EPERM);
  266. }
  267. session.new_group(procs, self)
  268. };
  269. pgroup.remove_member(self.pid, procs.as_pos_mut());
  270. {
  271. let _old_pgroup = unsafe { self.pgroup.swap(Some(new_pgroup)) }.unwrap();
  272. rcu_sync();
  273. }
  274. Ok(())
  275. }
  276. /// Set the process group id of the process `pid` to `pgid`.
  277. ///
  278. /// This function should be called on the process that issued the syscall in order to do
  279. /// permission checks.
  280. pub fn setpgid(self: &Arc<Self>, pid: u32, pgid: u32) -> KResult<()> {
  281. let mut procs = ProcessList::get().lock();
  282. // We may set pgid of either the calling process or a child process.
  283. if pid == self.pid {
  284. self.do_setpgid(pgid, procs.as_mut())
  285. } else {
  286. let child = {
  287. // If `pid` refers to one of our children, the thread leaders must be
  288. // in out children list.
  289. let children = &self.inner.access(procs.as_pos()).children;
  290. let child = {
  291. let child = children.get(&pid);
  292. child.and_then(Weak::upgrade).ok_or(ESRCH)?
  293. };
  294. // Changing the process group of a child is only allowed
  295. // if we are in the same session.
  296. if child.session(procs.as_pos()).sid != self.session(procs.as_pos()).sid {
  297. return Err(EPERM);
  298. }
  299. child
  300. };
  301. // TODO: Check whether we, as a child, have already performed an `execve`.
  302. // If so, we should return `Err(EACCES)`.
  303. child.do_setpgid(pgid, procs.as_mut())
  304. }
  305. }
  306. /// Provide locked (consistent) access to the session.
  307. pub fn session<'r>(&'r self, _procs: RefPosition<'r, ProcessList>) -> BorrowedArc<'r, Session> {
  308. // SAFETY: We are holding the process list lock.
  309. unsafe { self.session.load_locked() }.unwrap()
  310. }
  311. /// Provide locked (consistent) access to the process group.
  312. pub fn pgroup<'r>(
  313. &'r self,
  314. _procs: RefPosition<'r, ProcessList>,
  315. ) -> BorrowedArc<'r, ProcessGroup> {
  316. // SAFETY: We are holding the process list lock.
  317. unsafe { self.pgroup.load_locked() }.unwrap()
  318. }
  319. /// Provide locked (consistent) access to the parent process.
  320. pub fn parent<'r>(&'r self, _procs: RefPosition<'r, ProcessList>) -> BorrowedArc<'r, Process> {
  321. // SAFETY: We are holding the process list lock.
  322. unsafe { self.parent.load_locked() }.unwrap()
  323. }
  324. /// Provide RCU locked (maybe inconsistent) access to the session.
  325. pub fn session_rcu(&self) -> RCUReadGuard<'_, BorrowedArc<Session>> {
  326. self.session.load().unwrap()
  327. }
  328. /// Provide RCU locked (maybe inconsistent) access to the process group.
  329. pub fn pgroup_rcu(&self) -> RCUReadGuard<'_, BorrowedArc<ProcessGroup>> {
  330. self.pgroup.load().unwrap()
  331. }
  332. /// Provide RCU locked (maybe inconsistent) access to the parent process.
  333. pub fn parent_rcu(&self) -> Option<RCUReadGuard<'_, BorrowedArc<Process>>> {
  334. self.parent.load()
  335. }
  336. pub fn notify(&self, wait: WaitObject, procs: RefPosition<'_, ProcessList>) {
  337. self.wait_list.notify(wait);
  338. self.raise(Signal::SIGCHLD, procs);
  339. }
  340. pub fn notify_batch(&self) -> NotifyBatch<'_, '_, '_> {
  341. NotifyBatch {
  342. wait_procs: self.wait_list.wait_procs.lock(),
  343. process: self,
  344. cv: &self.wait_list.cv_wait_procs,
  345. needs_notify: false,
  346. }
  347. }
  348. }
  349. impl WaitList {
  350. pub fn new() -> Self {
  351. Self {
  352. wait_procs: Spin::new(VecDeque::new()),
  353. cv_wait_procs: CondVar::new(),
  354. }
  355. }
  356. fn notify(&self, wait: WaitObject) {
  357. let mut wait_procs = self.wait_procs.lock();
  358. wait_procs.push_back(wait);
  359. self.cv_wait_procs.notify_all();
  360. }
  361. pub fn drain_exited(&self) -> DrainExited {
  362. DrainExited {
  363. wait_procs: self.wait_procs.lock(),
  364. }
  365. }
  366. /// # Safety
  367. /// Locks `ProcessList` and `WaitList` at the same time. When `wait` is called,
  368. /// releases the lock on `ProcessList` and `WaitList` and waits on `cv_wait_procs`.
  369. pub fn entry(&self, want_stop: bool, want_continue: bool) -> Entry {
  370. Entry {
  371. process_list: ProcessList::get().lock_shared(),
  372. wait_procs: self.wait_procs.lock(),
  373. cv: &self.cv_wait_procs,
  374. want_stop,
  375. want_continue,
  376. }
  377. }
  378. }
  379. impl Entry<'_, '_, '_> {
  380. pub fn get(&mut self) -> Option<WaitObject> {
  381. if let Some(idx) = self
  382. .wait_procs
  383. .iter()
  384. .enumerate()
  385. .filter(|(_, item)| {
  386. if item.stopped().is_some() {
  387. self.want_stop
  388. } else if item.is_continue() {
  389. self.want_continue
  390. } else {
  391. true
  392. }
  393. })
  394. .map(|(idx, _)| idx)
  395. .next()
  396. {
  397. Some(self.wait_procs.remove(idx).unwrap())
  398. } else {
  399. None
  400. }
  401. }
  402. pub fn wait(&mut self) -> KResult<()> {
  403. // SAFETY: We will lock it again after returning from `cv.wait`.
  404. unsafe { self.wait_procs.force_unlock() };
  405. self.cv.wait(&mut self.process_list);
  406. // SAFETY: We will lock it again.
  407. unsafe { self.wait_procs.force_relock() };
  408. if Thread::current().signal_list.has_pending_signal() {
  409. return Err(EINTR);
  410. }
  411. Ok(())
  412. }
  413. }
  414. impl DrainExited<'_> {
  415. pub fn into_iter(&mut self) -> impl Iterator<Item = WaitObject> + '_ {
  416. // We don't propagate stop and continue to the new parent.
  417. self.wait_procs
  418. .drain(..)
  419. .filter(|item| item.stopped().is_none() && !item.is_continue())
  420. }
  421. }
  422. impl NotifyBatch<'_, '_, '_> {
  423. pub fn notify(&mut self, wait: WaitObject) {
  424. self.needs_notify = true;
  425. self.wait_procs.push_back(wait);
  426. }
  427. /// Finish the batch and notify all if we have notified some processes.
  428. pub fn finish(mut self, procs: RefPosition<'_, ProcessList>) {
  429. if self.needs_notify {
  430. self.cv.notify_all();
  431. self.process.raise(Signal::SIGCHLD, procs);
  432. self.needs_notify = false;
  433. }
  434. }
  435. }
  436. impl Drop for NotifyBatch<'_, '_, '_> {
  437. fn drop(&mut self) {
  438. if self.needs_notify {
  439. panic!("NotifyBatch dropped without calling finish");
  440. }
  441. }
  442. }