1#![no_std]
11#![deny(warnings, missing_docs)]
12
13extern crate alloc;
14use alloc::boxed::Box;
15use tg_kernel_context::LocalContext;
16use tg_signal::{Signal, SignalAction, SignalNo, SignalResult, MAX_SIG};
17
18mod default_action;
19use default_action::DefaultAction;
20mod signal_set;
21use signal_set::SignalSet;
22
23pub enum HandlingSignal {
25 Frozen,
27 UserSignal(LocalContext),
29}
30
31pub struct SignalImpl {
33 received: SignalSet,
35 mask: SignalSet,
37 handling: Option<HandlingSignal>,
39 actions: [Option<SignalAction>; MAX_SIG + 1],
41}
42
43impl SignalImpl {
44 pub fn new() -> Self {
46 Self {
47 received: SignalSet::empty(),
48 mask: SignalSet::empty(),
49 handling: None,
50 actions: [None; MAX_SIG + 1],
51 }
52 }
53}
54
55impl Default for SignalImpl {
56 fn default() -> Self {
57 Self::new()
58 }
59}
60
61impl SignalImpl {
62 fn fetch_signal(&mut self) -> Option<SignalNo> {
64 self.received.find_first_one(self.mask).map(|num| {
66 self.received.remove_bit(num);
67 num.into()
68 })
69 }
70
71 fn fetch_and_remove(&mut self, signal_no: SignalNo) -> bool {
73 if self.received.contain_bit(signal_no as usize)
74 && !self.mask.contain_bit(signal_no as usize)
75 {
76 self.received.remove_bit(signal_no as usize);
77 true
78 } else {
79 false
80 }
81 }
82}
83
84impl Signal for SignalImpl {
85 fn from_fork(&mut self) -> Box<dyn Signal> {
86 Box::new(Self {
87 received: SignalSet::empty(),
88 mask: self.mask,
89 handling: None,
90 actions: {
91 let mut actions = [None; MAX_SIG + 1];
92 actions.copy_from_slice(&self.actions);
93 actions
94 },
95 })
96 }
97
98 fn clear(&mut self) {
99 for action in &mut self.actions {
100 action.take();
101 }
102 }
103
104 fn add_signal(&mut self, signal: SignalNo) {
106 self.received.add_bit(signal as usize)
107 }
108
109 fn is_handling_signal(&self) -> bool {
111 self.handling.is_some()
112 }
113
114 fn set_action(&mut self, signum: SignalNo, action: &SignalAction) -> bool {
116 if signum == SignalNo::SIGKILL || signum == SignalNo::SIGSTOP {
117 false
118 } else {
119 self.actions[signum as usize] = Some(*action);
120 true
121 }
122 }
123
124 fn get_action_ref(&self, signum: SignalNo) -> Option<SignalAction> {
126 if signum == SignalNo::SIGKILL || signum == SignalNo::SIGSTOP {
127 None
128 } else {
129 Some(self.actions[signum as usize].unwrap_or(SignalAction::default()))
130 }
131 }
132
133 fn update_mask(&mut self, mask: usize) -> usize {
135 self.mask.set_new(mask.into())
136 }
137
138 fn handle_signals(&mut self, current_context: &mut LocalContext) -> SignalResult {
139 if self.is_handling_signal() {
143 match self.handling.as_ref().unwrap() {
144 HandlingSignal::Frozen => {
146 if self.fetch_and_remove(SignalNo::SIGCONT) {
148 self.handling.take();
149 SignalResult::Handled
150 } else {
151 SignalResult::ProcessSuspended
153 }
154 } _ => SignalResult::IsHandlingSignal,
156 }
157 } else if let Some(signal) = self.fetch_signal() {
158 match signal {
159 SignalNo::SIGKILL => SignalResult::ProcessKilled(-(signal as i32)),
161 SignalNo::SIGSTOP => {
162 self.handling = Some(HandlingSignal::Frozen);
163 SignalResult::ProcessSuspended
164 }
165 _ => {
166 if let Some(action) = self.actions[signal as usize] {
167 self.handling = Some(HandlingSignal::UserSignal(current_context.clone()));
170 *current_context.pc_mut() = action.handler;
173 *current_context.a_mut(0) = signal as usize;
174 SignalResult::Handled
175 } else {
176 DefaultAction::from(signal).into()
179 }
180 }
181 }
182 } else {
183 SignalResult::NoSignal
184 }
185 }
186
187 fn sig_return(&mut self, current_context: &mut LocalContext) -> bool {
188 let handling_signal = self.handling.take();
189 match handling_signal {
190 Some(HandlingSignal::UserSignal(old_ctx)) => {
191 *current_context = old_ctx;
194 true
195 }
196 _ => {
198 self.handling = handling_signal;
199 false
200 }
201 }
202 }
203}