starnix_core/vfs/
pidfd.rs1use crate::mm::MemoryManager;
6use crate::task::{
7 CurrentTask, EventHandler, SignalHandler, SignalHandlerInner, ThreadGroup, ThreadGroupKey,
8 WaitCanceler, Waiter,
9};
10use crate::vfs::{
11 Anon, FileHandle, FileObject, FileOps, fileops_impl_dataless, fileops_impl_nonseekable,
12 fileops_impl_noop_sync,
13};
14use starnix_uapi::error;
15use starnix_uapi::errors::Errno;
16use starnix_uapi::open_flags::OpenFlags;
17use starnix_uapi::vfs::FdEvents;
18
19pub struct PidFdFileObject {
20 tg: ThreadGroupKey,
22
23 terminated_event: zx::EventPair,
25}
26
27impl PidFdFileObject {
28 fn get_signals_from_events(events: FdEvents) -> zx::Signals {
29 if events.contains(FdEvents::POLLIN) {
30 zx::Signals::EVENTPAIR_PEER_CLOSED
31 } else {
32 zx::Signals::NONE
33 }
34 }
35
36 fn get_events_from_signals(signals: zx::Signals) -> FdEvents {
37 let mut events = FdEvents::empty();
38
39 if signals.contains(zx::Signals::EVENTPAIR_PEER_CLOSED) {
40 events |= FdEvents::POLLIN;
41 }
42
43 events
44 }
45}
46
47pub fn new_pidfd(
48 current_task: &CurrentTask,
49 proc: &ThreadGroup,
50 mm: &MemoryManager,
51 flags: OpenFlags,
52) -> FileHandle {
53 let terminated_event = mm.drop_notifier.event();
62
63 Anon::new_private_file(
64 current_task,
65 Box::new(PidFdFileObject { tg: proc.into(), terminated_event }),
66 flags,
67 "[pidfd]",
68 )
69}
70
71impl FileOps for PidFdFileObject {
72 fileops_impl_nonseekable!();
73 fileops_impl_dataless!();
74 fileops_impl_noop_sync!();
75
76 fn as_thread_group_key(&self, _file: &FileObject) -> Result<ThreadGroupKey, Errno> {
77 Ok(self.tg.clone())
78 }
79
80 fn wait_async(
81 &self,
82 _file: &FileObject,
83 _current_task: &CurrentTask,
84 waiter: &Waiter,
85 events: FdEvents,
86 handler: EventHandler,
87 ) -> Option<WaitCanceler> {
88 let signal_handler = SignalHandler {
89 inner: SignalHandlerInner::ZxHandle(PidFdFileObject::get_events_from_signals),
90 event_handler: handler,
91 err_code: None,
92 };
93 let canceler = waiter
94 .wake_on_zircon_signals(
95 &self.terminated_event,
96 PidFdFileObject::get_signals_from_events(events),
97 signal_handler,
98 )
99 .unwrap(); Some(WaitCanceler::new_port(canceler))
101 }
102
103 fn query_events(
104 &self,
105 _file: &FileObject,
106 _current_task: &CurrentTask,
107 ) -> Result<FdEvents, Errno> {
108 match self
109 .terminated_event
110 .wait_one(zx::Signals::EVENTPAIR_PEER_CLOSED, zx::MonotonicInstant::ZERO)
111 .to_result()
112 {
113 Err(zx::Status::TIMED_OUT) => Ok(FdEvents::empty()),
114 Ok(zx::Signals::EVENTPAIR_PEER_CLOSED) => Ok(FdEvents::POLLIN),
115 result => unreachable!("unexpected result: {result:?}"),
116 }
117 }
118}
119
120pub fn new_zombie_pidfd(current_task: &CurrentTask, flags: OpenFlags) -> FileHandle {
121 Anon::new_private_file(current_task, Box::new(ZombiePidFdFileObject {}), flags, "[pidfd]")
122}
123
124struct ZombiePidFdFileObject {}
125
126impl FileOps for ZombiePidFdFileObject {
127 fileops_impl_nonseekable!();
128 fileops_impl_dataless!();
129 fileops_impl_noop_sync!();
130
131 fn as_thread_group_key(&self, _file: &FileObject) -> Result<ThreadGroupKey, Errno> {
132 error!(EINVAL)
134 }
135
136 fn wait_async(
137 &self,
138 _file: &FileObject,
139 _current_task: &CurrentTask,
140 _waiter: &Waiter,
141 _events: FdEvents,
142 _handler: EventHandler,
143 ) -> Option<WaitCanceler> {
144 None
146 }
147
148 fn query_events(
149 &self,
150 _file: &FileObject,
151 _current_task: &CurrentTask,
152 ) -> Result<FdEvents, Errno> {
153 Ok(FdEvents::POLLIN)
154 }
155}