1#![allow(dead_code)]
19
20use alloc::{collections::BTreeMap, vec::Vec};
21use core::sync::atomic::{AtomicU64, Ordering};
22
23use spin::Mutex;
24
25use crate::syscall::{SyscallError, SyscallResult};
26
27const MAX_SIGNALFD_INSTANCES: usize = 1024;
29
30pub const SFD_NONBLOCK: u32 = 0x800;
32pub const SFD_CLOEXEC: u32 = 0x80000;
34
35const MAX_SIGNAL: usize = 64;
37
38#[repr(C)]
41#[derive(Debug, Clone, Copy)]
42pub struct SignalfdSiginfo {
43 pub ssi_signo: u32,
45 pub ssi_errno: i32,
47 pub ssi_code: i32,
49 pub ssi_pid: u32,
51 pub ssi_uid: u32,
53 pub ssi_fd: i32,
55 pub ssi_tid: u32,
57 pub ssi_band: u32,
59 pub ssi_overrun: u32,
61 pub ssi_trapno: u32,
63 pub ssi_status: i32,
65 pub ssi_int: i32,
67 pub ssi_ptr: u64,
69 pub ssi_utime: u64,
71 pub ssi_stime: u64,
73 pub ssi_addr: u64,
75 pub ssi_addr_lsb: u16,
77 _pad: [u8; 46],
79}
80
81impl Default for SignalfdSiginfo {
82 fn default() -> Self {
83 unsafe { core::mem::zeroed() }
85 }
86}
87
88#[derive(Debug, Clone, Default)]
90pub struct SigSet {
91 bits: u64,
92}
93
94impl SigSet {
95 pub fn new() -> Self {
96 Self { bits: 0 }
97 }
98
99 pub fn is_set(&self, signum: u32) -> bool {
100 if signum == 0 || signum as usize > MAX_SIGNAL {
101 return false;
102 }
103 (self.bits & (1u64 << (signum - 1))) != 0
104 }
105
106 pub fn set(&mut self, signum: u32) {
107 if signum > 0 && (signum as usize) <= MAX_SIGNAL {
108 self.bits |= 1u64 << (signum - 1);
109 }
110 }
111
112 pub fn from_raw(bits: u64) -> Self {
113 Self { bits }
114 }
115
116 pub fn raw(&self) -> u64 {
117 self.bits
118 }
119}
120
121#[derive(Debug, Clone)]
123struct PendingSignal {
124 signum: u32,
125 sender_pid: u32,
126}
127
128struct SignalFdInstance {
130 mask: SigSet,
132 nonblock: bool,
134 pending: Vec<PendingSignal>,
136 owner_pid: u64,
138}
139
140static SIGNALFD_REGISTRY: Mutex<BTreeMap<u32, SignalFdInstance>> = Mutex::new(BTreeMap::new());
142
143static NEXT_SIGNALFD_ID: AtomicU64 = AtomicU64::new(1);
145
146pub fn signalfd_create(fd: i32, mask: u64, flags: u32) -> SyscallResult {
156 let pid = crate::process::current_process()
157 .map(|p| p.pid.0)
158 .unwrap_or(0);
159
160 if fd != -1 {
161 let sfd_id = fd as u32;
163 let mut registry = SIGNALFD_REGISTRY.lock();
164 let instance = registry
165 .get_mut(&sfd_id)
166 .ok_or(SyscallError::BadFileDescriptor)?;
167 instance.mask = SigSet::from_raw(mask);
168 return Ok(sfd_id as usize);
169 }
170
171 let nonblock = (flags & SFD_NONBLOCK) != 0;
173
174 let instance = SignalFdInstance {
175 mask: SigSet::from_raw(mask),
176 nonblock,
177 pending: Vec::new(),
178 owner_pid: pid,
179 };
180
181 let id = NEXT_SIGNALFD_ID.fetch_add(1, Ordering::Relaxed) as u32;
182
183 let mut registry = SIGNALFD_REGISTRY.lock();
184 if registry.len() >= MAX_SIGNALFD_INSTANCES {
185 return Err(SyscallError::OutOfMemory);
186 }
187 registry.insert(id, instance);
188 Ok(id as usize)
189}
190
191pub fn deliver_signal(target_pid: u64, signum: u32, sender_pid: u32) {
196 let mut registry = SIGNALFD_REGISTRY.lock();
197 for instance in registry.values_mut() {
198 if instance.owner_pid == target_pid && instance.mask.is_set(signum) {
199 instance.pending.push(PendingSignal { signum, sender_pid });
200 }
201 }
202}
203
204pub fn signalfd_read(sfd_id: u32) -> Result<SignalfdSiginfo, SyscallError> {
209 let start = crate::timer::get_uptime_ms();
210 const MAX_BLOCK_MS: u64 = 30_000;
211
212 loop {
213 let mut registry = SIGNALFD_REGISTRY.lock();
214 let instance = registry
215 .get_mut(&sfd_id)
216 .ok_or(SyscallError::BadFileDescriptor)?;
217
218 if !instance.pending.is_empty() {
219 let sig = instance.pending.remove(0);
220 return Ok(SignalfdSiginfo {
221 ssi_signo: sig.signum,
222 ssi_pid: sig.sender_pid,
223 ..SignalfdSiginfo::default()
224 });
225 }
226
227 if instance.nonblock {
228 return Err(SyscallError::WouldBlock);
229 }
230
231 drop(registry);
232 if crate::timer::get_uptime_ms() - start >= MAX_BLOCK_MS {
233 return Err(SyscallError::WouldBlock);
234 }
235 crate::sched::yield_cpu();
236 }
237}
238
239pub fn is_readable(sfd_id: u32) -> bool {
242 let registry = SIGNALFD_REGISTRY.lock();
243 registry.get(&sfd_id).is_some_and(|i| !i.pending.is_empty())
244}
245
246pub fn signalfd_close(sfd_id: u32) -> SyscallResult {
248 let mut registry = SIGNALFD_REGISTRY.lock();
249 registry
250 .remove(&sfd_id)
251 .ok_or(SyscallError::BadFileDescriptor)?;
252 Ok(0)
253}
254
255use alloc::sync::Arc;
258
259use super::{DirEntry, Metadata, NodeType, Permissions, VfsNode};
260use crate::error::KernelError;
261
262pub struct SignalFdNode {
268 sfd_id: u32,
269}
270
271impl SignalFdNode {
272 pub fn new(sfd_id: u32) -> Self {
273 Self { sfd_id }
274 }
275
276 pub fn sfd_id(&self) -> u32 {
278 self.sfd_id
279 }
280}
281
282impl VfsNode for SignalFdNode {
283 fn node_type(&self) -> NodeType {
284 NodeType::CharDevice
285 }
286
287 fn read(&self, _offset: usize, buffer: &mut [u8]) -> Result<usize, KernelError> {
288 if buffer.len() < 128 {
289 return Err(KernelError::InvalidArgument {
290 name: "buflen",
291 value: "must be at least 128 bytes for signalfd",
292 });
293 }
294 let info = signalfd_read(self.sfd_id).map_err(|e| match e {
295 SyscallError::WouldBlock => KernelError::WouldBlock,
296 _ => KernelError::FsError(crate::error::FsError::BadFileDescriptor),
297 })?;
298 let bytes = unsafe {
300 core::slice::from_raw_parts(&info as *const SignalfdSiginfo as *const u8, 128)
301 };
302 buffer[..128].copy_from_slice(bytes);
303 Ok(128)
304 }
305
306 fn write(&self, _offset: usize, _data: &[u8]) -> Result<usize, KernelError> {
307 Err(KernelError::PermissionDenied {
309 operation: "write signalfd",
310 })
311 }
312
313 fn poll_readiness(&self) -> u16 {
314 let mut events = 0u16;
315 if is_readable(self.sfd_id) {
316 events |= 0x0001; }
318 events
319 }
320
321 fn metadata(&self) -> Result<Metadata, KernelError> {
322 Ok(Metadata {
323 size: 0,
324 node_type: NodeType::CharDevice,
325 permissions: Permissions::from_mode(0o666),
326 uid: 0,
327 gid: 0,
328 created: 0,
329 modified: 0,
330 accessed: 0,
331 inode: 0,
332 })
333 }
334
335 fn readdir(&self) -> Result<Vec<DirEntry>, KernelError> {
336 Err(KernelError::FsError(crate::error::FsError::NotADirectory))
337 }
338
339 fn lookup(&self, _name: &str) -> Result<Arc<dyn VfsNode>, KernelError> {
340 Err(KernelError::FsError(crate::error::FsError::NotADirectory))
341 }
342
343 fn create(
344 &self,
345 _name: &str,
346 _permissions: Permissions,
347 ) -> Result<Arc<dyn VfsNode>, KernelError> {
348 Err(KernelError::FsError(crate::error::FsError::NotADirectory))
349 }
350
351 fn mkdir(
352 &self,
353 _name: &str,
354 _permissions: Permissions,
355 ) -> Result<Arc<dyn VfsNode>, KernelError> {
356 Err(KernelError::FsError(crate::error::FsError::NotADirectory))
357 }
358
359 fn unlink(&self, _name: &str) -> Result<(), KernelError> {
360 Err(KernelError::FsError(crate::error::FsError::NotADirectory))
361 }
362
363 fn truncate(&self, _size: usize) -> Result<(), KernelError> {
364 Err(KernelError::PermissionDenied {
365 operation: "truncate signalfd",
366 })
367 }
368}
369
370impl Drop for SignalFdNode {
371 fn drop(&mut self) {
372 let _ = signalfd_close(self.sfd_id);
373 }
374}
375
376#[cfg(test)]
377mod tests {
378 use super::*;
379
380 #[test]
381 fn test_sigset_basic() {
382 let mut s = SigSet::new();
383 assert!(!s.is_set(1));
384 s.set(1); assert!(s.is_set(1));
386 assert!(!s.is_set(2));
387 }
388
389 #[test]
390 fn test_sigset_from_raw() {
391 let s = SigSet::from_raw(0b110); assert!(!s.is_set(1));
393 assert!(s.is_set(2));
394 assert!(s.is_set(3));
395 assert!(!s.is_set(4));
396 }
397
398 #[test]
399 fn test_sigset_boundary() {
400 let mut s = SigSet::new();
401 s.set(0); assert!(!s.is_set(0));
403 s.set(64);
404 assert!(s.is_set(64));
405 s.set(65); assert!(!s.is_set(65));
407 }
408
409 #[test]
410 fn test_signalfd_create_and_close() {
411 SIGNALFD_REGISTRY.lock().clear();
412
413 let id = signalfd_create(-1, 0b10, SFD_NONBLOCK).unwrap() as u32;
414 signalfd_close(id).unwrap();
415 assert!(signalfd_read(id).is_err());
416 }
417
418 #[test]
419 fn test_signalfd_update_mask() {
420 SIGNALFD_REGISTRY.lock().clear();
421
422 let id = signalfd_create(-1, 0b10, 0).unwrap();
423 signalfd_create(id as i32, 0b110, 0).unwrap();
425
426 deliver_signal(0, 3, 42);
428 let info = signalfd_read(id as u32).unwrap();
429 assert_eq!(info.ssi_signo, 3);
430 assert_eq!(info.ssi_pid, 42);
431 }
432
433 #[test]
434 fn test_signalfd_deliver_and_read() {
435 SIGNALFD_REGISTRY.lock().clear();
436
437 let id = signalfd_create(-1, 0b10, 0).unwrap() as u32;
439
440 assert!(signalfd_read(id).is_err());
442
443 deliver_signal(0, 2, 100);
445
446 let info = signalfd_read(id).unwrap();
447 assert_eq!(info.ssi_signo, 2);
448 assert_eq!(info.ssi_pid, 100);
449
450 assert!(signalfd_read(id).is_err());
452 }
453
454 #[test]
455 fn test_signalfd_ignores_unmasked() {
456 SIGNALFD_REGISTRY.lock().clear();
457
458 let id = signalfd_create(-1, 0b1, SFD_NONBLOCK).unwrap() as u32;
460
461 deliver_signal(0, 2, 50);
463
464 assert!(signalfd_read(id).is_err());
466 }
467
468 #[test]
469 fn test_signalfd_siginfo_size() {
470 assert_eq!(core::mem::size_of::<SignalfdSiginfo>(), 128);
471 }
472}