process.rs 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511
  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
  261. } else {
  262. // Create a new process group only if `pgid` matches our `pid`.
  263. if pgid != self.pid {
  264. return Err(EPERM);
  265. }
  266. session.new_group(procs, self)
  267. };
  268. pgroup.remove_member(self.pid, procs.as_pos_mut());
  269. {
  270. let _old_pgroup = unsafe { self.pgroup.swap(Some(new_pgroup)) }.unwrap();
  271. rcu_sync();
  272. }
  273. Ok(())
  274. }
  275. /// Set the process group id of the process `pid` to `pgid`.
  276. ///
  277. /// This function should be called on the process that issued the syscall in order to do
  278. /// permission checks.
  279. pub fn setpgid(self: &Arc<Self>, pid: u32, pgid: u32) -> KResult<()> {
  280. let mut procs = ProcessList::get().lock();
  281. // We may set pgid of either the calling process or a child process.
  282. if pid == self.pid {
  283. self.do_setpgid(pgid, procs.as_mut())
  284. } else {
  285. let child = {
  286. // If `pid` refers to one of our children, the thread leaders must be
  287. // in out children list.
  288. let children = &self.inner.access(procs.as_pos()).children;
  289. let child = {
  290. let child = children.get(&pid);
  291. child.and_then(Weak::upgrade).ok_or(ESRCH)?
  292. };
  293. // Changing the process group of a child is only allowed
  294. // if we are in the same session.
  295. if child.session(procs.as_pos()).sid != self.session(procs.as_pos()).sid {
  296. return Err(EPERM);
  297. }
  298. child
  299. };
  300. // TODO: Check whether we, as a child, have already performed an `execve`.
  301. // If so, we should return `Err(EACCES)`.
  302. child.do_setpgid(pgid, procs.as_mut())
  303. }
  304. }
  305. /// Provide locked (consistent) access to the session.
  306. pub fn session<'r>(&'r self, _procs: RefPosition<'r, ProcessList>) -> BorrowedArc<'r, Session> {
  307. // SAFETY: We are holding the process list lock.
  308. unsafe { self.session.load_locked() }.unwrap()
  309. }
  310. /// Provide locked (consistent) access to the process group.
  311. pub fn pgroup<'r>(
  312. &'r self,
  313. _procs: RefPosition<'r, ProcessList>,
  314. ) -> BorrowedArc<'r, ProcessGroup> {
  315. // SAFETY: We are holding the process list lock.
  316. unsafe { self.pgroup.load_locked() }.unwrap()
  317. }
  318. /// Provide locked (consistent) access to the parent process.
  319. pub fn parent<'r>(&'r self, _procs: RefPosition<'r, ProcessList>) -> BorrowedArc<'r, Process> {
  320. // SAFETY: We are holding the process list lock.
  321. unsafe { self.parent.load_locked() }.unwrap()
  322. }
  323. /// Provide RCU locked (maybe inconsistent) access to the session.
  324. pub fn session_rcu(&self) -> RCUReadGuard<'_, BorrowedArc<Session>> {
  325. self.session.load().unwrap()
  326. }
  327. /// Provide RCU locked (maybe inconsistent) access to the process group.
  328. pub fn pgroup_rcu(&self) -> RCUReadGuard<'_, BorrowedArc<ProcessGroup>> {
  329. self.pgroup.load().unwrap()
  330. }
  331. /// Provide RCU locked (maybe inconsistent) access to the parent process.
  332. pub fn parent_rcu(&self) -> Option<RCUReadGuard<'_, BorrowedArc<Process>>> {
  333. self.parent.load()
  334. }
  335. pub fn notify(&self, wait: WaitObject, procs: RefPosition<'_, ProcessList>) {
  336. self.wait_list.notify(wait);
  337. self.raise(Signal::SIGCHLD, procs);
  338. }
  339. pub fn notify_batch(&self) -> NotifyBatch<'_, '_, '_> {
  340. NotifyBatch {
  341. wait_procs: self.wait_list.wait_procs.lock(),
  342. process: self,
  343. cv: &self.wait_list.cv_wait_procs,
  344. needs_notify: false,
  345. }
  346. }
  347. }
  348. impl WaitList {
  349. pub fn new() -> Self {
  350. Self {
  351. wait_procs: Spin::new(VecDeque::new()),
  352. cv_wait_procs: CondVar::new(),
  353. }
  354. }
  355. fn notify(&self, wait: WaitObject) {
  356. let mut wait_procs = self.wait_procs.lock();
  357. wait_procs.push_back(wait);
  358. self.cv_wait_procs.notify_all();
  359. }
  360. pub fn drain_exited(&self) -> DrainExited {
  361. DrainExited {
  362. wait_procs: self.wait_procs.lock(),
  363. }
  364. }
  365. /// # Safety
  366. /// Locks `ProcessList` and `WaitList` at the same time. When `wait` is called,
  367. /// releases the lock on `ProcessList` and `WaitList` and waits on `cv_wait_procs`.
  368. pub fn entry(&self, want_stop: bool, want_continue: bool) -> Entry {
  369. Entry {
  370. process_list: ProcessList::get().lock_shared(),
  371. wait_procs: self.wait_procs.lock(),
  372. cv: &self.cv_wait_procs,
  373. want_stop,
  374. want_continue,
  375. }
  376. }
  377. }
  378. impl Entry<'_, '_, '_> {
  379. pub fn get(&mut self) -> Option<WaitObject> {
  380. if let Some(idx) = self
  381. .wait_procs
  382. .iter()
  383. .enumerate()
  384. .filter(|(_, item)| {
  385. if item.stopped().is_some() {
  386. self.want_stop
  387. } else if item.is_continue() {
  388. self.want_continue
  389. } else {
  390. true
  391. }
  392. })
  393. .map(|(idx, _)| idx)
  394. .next()
  395. {
  396. Some(self.wait_procs.remove(idx).unwrap())
  397. } else {
  398. None
  399. }
  400. }
  401. pub fn wait(&mut self) -> KResult<()> {
  402. // SAFETY: We will lock it again after returning from `cv.wait`.
  403. unsafe { self.wait_procs.force_unlock() };
  404. self.cv.wait(&mut self.process_list);
  405. // SAFETY: We will lock it again.
  406. unsafe { self.wait_procs.force_relock() };
  407. if Thread::current().signal_list.has_pending_signal() {
  408. return Err(EINTR);
  409. }
  410. Ok(())
  411. }
  412. }
  413. impl DrainExited<'_> {
  414. pub fn into_iter(&mut self) -> impl Iterator<Item = WaitObject> + '_ {
  415. // We don't propagate stop and continue to the new parent.
  416. self.wait_procs
  417. .drain(..)
  418. .filter(|item| item.stopped().is_none() && !item.is_continue())
  419. }
  420. }
  421. impl NotifyBatch<'_, '_, '_> {
  422. pub fn notify(&mut self, wait: WaitObject) {
  423. self.needs_notify = true;
  424. self.wait_procs.push_back(wait);
  425. }
  426. /// Finish the batch and notify all if we have notified some processes.
  427. pub fn finish(mut self, procs: RefPosition<'_, ProcessList>) {
  428. if self.needs_notify {
  429. self.cv.notify_all();
  430. self.process.raise(Signal::SIGCHLD, procs);
  431. self.needs_notify = false;
  432. }
  433. }
  434. }
  435. impl Drop for NotifyBatch<'_, '_, '_> {
  436. fn drop(&mut self) {
  437. if self.needs_notify {
  438. panic!("NotifyBatch dropped without calling finish");
  439. }
  440. }
  441. }