1 /*
2 * Copyright (c) 2006-2023, RT-Thread Development Team
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 *
6 * Change Logs:
7 * Date Author Notes
8 * 2020-02-23 Jesven first version.
9 * 2023-07-06 Shell update the generation, pending and delivery API
10 * 2023-11-22 Shell support for job control signal
11 */
12
13 #ifndef __LWP_SIGNAL_H__
14 #define __LWP_SIGNAL_H__
15
16 #include "syscall_generic.h"
17
18 #include <rtthread.h>
19 #include <sys/signal.h>
20
21 #ifdef __cplusplus
22 extern "C" {
23 #endif
24
25 #define _USIGNAL_SIGMASK(signo) (1u << ((signo)-1))
26 #define LWP_SIG_NO_IGN_SET \
27 (_USIGNAL_SIGMASK(SIGCONT) | _USIGNAL_SIGMASK(SIGSTOP) | \
28 _USIGNAL_SIGMASK(SIGKILL))
29 #define LWP_SIG_IGNORE_SET \
30 (_USIGNAL_SIGMASK(SIGCHLD) | _USIGNAL_SIGMASK(SIGURG) | \
31 _USIGNAL_SIGMASK(SIGWINCH) /* from 4.3 BSD, not POSIX.1 */)
32 #define LWP_SIG_JOBCTL_SET \
33 (_USIGNAL_SIGMASK(SIGCONT) | _USIGNAL_SIGMASK(SIGSTOP) | \
34 _USIGNAL_SIGMASK(SIGTSTP) | _USIGNAL_SIGMASK(SIGTTIN) | \
35 _USIGNAL_SIGMASK(SIGTTOU))
36 #define LWP_SIG_STOP_SET \
37 (_USIGNAL_SIGMASK(SIGSTOP) | _USIGNAL_SIGMASK(SIGTSTP) | \
38 _USIGNAL_SIGMASK(SIGTTIN) | _USIGNAL_SIGMASK(SIGTTOU))
39 #define LWP_SIG_ACT_DFL ((lwp_sighandler_t)0)
40 #define LWP_SIG_ACT_IGN ((lwp_sighandler_t)1)
41 #define LWP_SIG_USER_SA_FLAGS \
42 (SA_NOCLDSTOP | SA_NOCLDWAIT | SA_SIGINFO | SA_ONSTACK | SA_RESTART | \
43 SA_NODEFER | SA_RESETHAND | SA_EXPOSE_TAGBITS)
44 #define LWP_SIG_INVALID_TIMER ((timer_t)-1)
45
46 typedef enum
47 {
48 LWP_SIG_MASK_CMD_BLOCK,
49 LWP_SIG_MASK_CMD_UNBLOCK,
50 LWP_SIG_MASK_CMD_SET_MASK,
51 __LWP_SIG_MASK_CMD_WATERMARK
52 } lwp_sig_mask_cmd_t;
53
54 /**
55 * LwP implementation of POSIX signal
56 */
57 struct lwp_signal
58 {
59 timer_t real_timer;
60 struct lwp_sigqueue sig_queue;
61 rt_thread_t sig_dispatch_thr[_LWP_NSIG];
62
63 lwp_sighandler_t sig_action[_LWP_NSIG];
64 lwp_sigset_t sig_action_mask[_LWP_NSIG];
65
66 lwp_sigset_t sig_action_nodefer;
67 lwp_sigset_t sig_action_onstack;
68 lwp_sigset_t sig_action_restart;
69 lwp_sigset_t sig_action_siginfo;
70 lwp_sigset_t sig_action_nocldstop;
71 lwp_sigset_t sig_action_nocldwait;
72 };
73
74 struct rt_lwp;
75 struct rt_processgroup;
76
77 #ifndef ARCH_MM_MMU
78 void lwp_sighandler_set(int sig, lwp_sighandler_t func);
79 void lwp_thread_sighandler_set(int sig, lwp_sighandler_t func);
80 #endif
81
lwp_sigqueue_init(lwp_sigqueue_t sigq)82 rt_inline void lwp_sigqueue_init(lwp_sigqueue_t sigq)
83 {
84 rt_memset(&sigq->sigset_pending, 0, sizeof(lwp_sigset_t));
85 rt_list_init(&sigq->siginfo_list);
86 }
87
88 /**
89 * @brief release the signal queue
90 *
91 * @param sigq target signal queue
92 */
93 void lwp_sigqueue_clear(lwp_sigqueue_t sigq);
94
95 rt_err_t lwp_signal_init(struct lwp_signal *sig);
96
97 rt_err_t lwp_signal_detach(struct lwp_signal *signal);
98
lwp_thread_signal_detach(struct lwp_thread_signal * tsig)99 rt_inline void lwp_thread_signal_detach(struct lwp_thread_signal *tsig)
100 {
101 lwp_sigqueue_clear(&tsig->sig_queue);
102 }
103
104 /**
105 * @brief send a signal to the process
106 *
107 * @param lwp the process to be killed
108 * @param signo the signal number
109 * @param code as in siginfo
110 * @param value as in siginfo
111 * @return rt_err_t RT_EINVAL if the parameter is invalid, RT_EOK as
112 * successful
113 *
114 * @note the *signal_kill have the same definition of a successful return as
115 * kill() in IEEE Std 1003.1-2017
116 */
117 rt_err_t lwp_signal_kill(struct rt_lwp *lwp, long signo, long code,
118 lwp_siginfo_ext_t value);
119
120 /**
121 * @brief set or examine the signal action of signo
122 *
123 * @param signo signal number
124 * @param act the signal action
125 * @param oact the old signal action
126 * @return rt_err_t
127 */
128 rt_err_t lwp_signal_action(struct rt_lwp *lwp, int signo,
129 const struct lwp_sigaction *restrict act,
130 struct lwp_sigaction *restrict oact);
131
132 /**
133 * @brief send a signal to the thread
134 *
135 * @param thread target thread
136 * @param signo the signal number
137 * @param code as in siginfo
138 * @param value as in siginfo
139 * @return rt_err_t RT_EINVAL if the parameter is invalid, RT_EOK as
140 * successful
141 */
142 rt_err_t lwp_thread_signal_kill(rt_thread_t thread, long signo, long code,
143 lwp_siginfo_ext_t value);
144
145 /**
146 * @brief set signal mask of target thread
147 *
148 * @param thread the target thread
149 * @param how command
150 * @param sigset operand
151 * @param oset the address to old set
152 * @return rt_err_t
153 */
154 rt_err_t lwp_thread_signal_mask(rt_thread_t thread, lwp_sig_mask_cmd_t how,
155 const lwp_sigset_t *sigset, lwp_sigset_t *oset);
156
157 /**
158 * @brief Catch signal if exists and no return, otherwise return with no
159 * side effect
160 *
161 * @param exp_frame the exception frame on kernel stack
162 */
163 void lwp_thread_signal_catch(void *exp_frame);
164
165 /**
166 * @brief Check if it's okay to suspend for current lwp thread
167 *
168 * @param thread target thread
169 * @param suspend_flag suspend flag of target thread
170 * @return int 1 if can be suspended, otherwise not
171 */
172 int lwp_thread_signal_suspend_check(rt_thread_t thread, int suspend_flag);
173
174 /**
175 * @brief Asynchronously wait for signal
176 *
177 * @param thread target thread
178 * @param sigset the signals to be waited
179 * @param info address of user siginfo
180 * @param timeout timeout of waiting
181 * @return rt_err_t
182 */
183 rt_err_t lwp_thread_signal_timedwait(rt_thread_t thread, lwp_sigset_t *sigset,
184 siginfo_t *usi, struct timespec *timeout);
185
186 /**
187 * @brief Examine the set of signals that are blocked from delivery to the
188 * calling thread and that are pending on the process or the calling thread
189 *
190 * @param thread target thread
191 * @param sigset where mask of pending signals is returned
192 */
193 void lwp_thread_signal_pending(rt_thread_t thread, lwp_sigset_t *sigset);
194
195 /**
196 * @brief send a signal to the process group
197 *
198 * @param pgrp target process group
199 * @param signo the signal number
200 * @param code as in siginfo
201 * @param value as in siginfo
202 * @return rt_err_t RT_EINVAL if the parameter is invalid, RT_EOK as
203 * successful
204 */
205 rt_err_t lwp_pgrp_signal_kill(struct rt_processgroup *pgrp, long signo,
206 long code, lwp_siginfo_ext_t value);
207
lwp_sigismember(lwp_sigset_t * set,int _sig)208 rt_inline int lwp_sigismember(lwp_sigset_t *set, int _sig)
209 {
210 unsigned long sig = _sig - 1;
211
212 if (_LWP_NSIG_WORDS == 1)
213 {
214 return 1 & (set->sig[0] >> sig);
215 }
216 else
217 {
218 return 1 & (set->sig[sig / _LWP_NSIG_BPW] >> (sig % _LWP_NSIG_BPW));
219 }
220 }
221
222 struct itimerspec;
223
224 rt_bool_t lwp_sigisign(struct rt_lwp *lwp, int _sig);
225
226 rt_err_t lwp_signal_setitimer(struct rt_lwp *lwp, int which,
227 const struct itimerspec *restrict new,
228 struct itimerspec *restrict old);
229
230 rt_bool_t lwp_signal_restart_syscall(struct rt_lwp *lwp, int error_code);
231
232 rt_err_t lwp_signal_kill_all(long signo, long code, lwp_siginfo_ext_t value);
233
234 #ifdef __cplusplus
235 }
236 #endif
237
238 #endif /* __LWP_SIGNAL_H__ */
239