1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
use alloc::{boxed::Box, collections::vec_deque::VecDeque};
use core::array;
use crate::{SignalInfo, SignalSet};
/// Structure to record pending signals.
pub struct PendingSignals {
/// The pending signals.
///
/// Note that does not correspond to `pending signals` as described in
/// Linux. `Pending signals` in Linux refers to the signals that are
/// delivered but blocked from delivery, while `pending` here refers to any
/// signal that is delivered and not yet handled.
pub set: SignalSet,
/// Signal info of standard signals (1-31).
info_std: [Option<Box<SignalInfo>>; 32],
/// Signal info queue for real-time signals.
info_rt: [VecDeque<SignalInfo>; 33],
}
impl Default for PendingSignals {
fn default() -> Self {
Self {
set: SignalSet::default(),
info_std: Default::default(),
info_rt: array::from_fn(|_| VecDeque::new()),
}
}
}
impl PendingSignals {
/// Puts a signal into the pending queue.
///
/// Returns `true` if the signal was added, `false` if the signal is
/// standard and ignored (i.e. already pending).
pub fn put_signal(&mut self, sig: SignalInfo) -> bool {
let signo = sig.signo();
let added = self.set.add(signo);
if signo.is_realtime() {
self.info_rt[signo as usize - 32].push_back(sig);
} else {
if !added {
// At most one standard signal can be pending.
return false;
}
self.info_std[signo as usize] = Some(Box::new(sig));
}
true
}
/// Dequeues the next pending signal contained in `mask`, if any.
pub fn dequeue_signal(&mut self, mask: &SignalSet) -> Option<SignalInfo> {
self.set.dequeue(mask).and_then(|signo| {
if signo.is_realtime() {
let queue = &mut self.info_rt[signo as usize - 32];
let result = queue.pop_front();
if !queue.is_empty() {
self.set.add(signo);
}
result
} else {
self.info_std[signo as usize].take().map(|boxed| *boxed)
}
})
}
}