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
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
|
/*
* Copyright (c) 2006-2023, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
* 2017/10/1 Bernard The first version
*/
#include <rthw.h>
#include <rtthread.h>
#include <sys/time.h>
#include <sys/errno.h>
#include "posix_signal.h"
#define sig_valid(sig_no) (sig_no >= 0 && sig_no < RT_SIG_MAX)
/**
* @brief Sets the disposition of a signal.
*
* @note The signal() function chooses one of three ways to handle the signal @p sig.
* The @p func argument specifies the action:
* - SIG_DFL: default handling.
* - SIG_IGN: ignore the signal.
* - function pointer: user-defined handler.
* This function is a simplified interface; the sigaction() function is recommended for portable applications.
*
* @param sig is the signal number (e.g., SIGINT, SIGTERM).
* @param func is the disposition or function to be called when the signal is received.
*
* @return Upon successful completion, signal() returns the previous disposition of the signal.
* On failure, SIG_ERR is returned and errno is set to indicate the error.
*
*/
void (*signal(int sig, void (*func)(int))) (int)
{
return rt_signal_install(sig, func);
}
/**
* @brief This function will examines, changes, or examines and changes the signal mask of the calling thread.
*
* @param how indicates the way in which the existing set of blocked signals should be changed.
* The following are the possible values for option:
*
* SIG_BLOCK The set of blocked signals is the union of the current set and the set argument.
*
* SIG_UNBLOCK The signals in set are removed from the current set of blocked signals.
* It is permissible to attempt to unblock a signal which is not blocked.
*
* SIG_SETMASK The set of blocked signals is set to the argument set.
*
* @param set is a pointer to a sigset_t object that specifies the new set of blocked signals.
* If set is NULL, then the signal mask is unchanged (i.e., how is ignored)
*
* @param oset is a pointer to a sigset_t object that is used to return the previous set of blocked signals.
* If oset is non-NULL, the previous value of the signal mask is stored in it.
*
* @return Returns 0 on success.
*/
int sigprocmask (int how, const sigset_t *set, sigset_t *oset)
{
rt_base_t level;
rt_thread_t tid;
tid = rt_thread_self();
level = rt_hw_interrupt_disable();
if (oset) *oset = tid->sig_mask;
if (set)
{
switch(how)
{
case SIG_BLOCK:
tid->sig_mask |= *set;
break;
case SIG_UNBLOCK:
tid->sig_mask &= ~*set;
break;
case SIG_SETMASK:
tid->sig_mask = *set;
break;
default:
break;
}
}
rt_hw_interrupt_enable(level);
return 0;
}
/**
* @brief This function will examines the signal mask of the calling thread.
*
* @param set is a pointer to a sigset_t object that is used to return the previous set of blocked signals.
* If set is non-NULL, the previous value of the signal mask is stored in it.
*
* @return Returns 0 on success.
*/
int sigpending (sigset_t *set)
{
sigprocmask(SIG_SETMASK, RT_NULL, set);
return 0;
}
/**
* @brief This function will temporarily replace the signal mask of the calling thread
* with the mask given and then suspends the thread until delivery of an expected signal
* or a signal whose action is to terminate a process.
*
* @param set is a pointer of a sigset_t object that is used to replace the original mask of the calling thread.
*
* @return Returns 0 on success.
* If the return value is any other values, it means that the signal wait failed.
*/
int sigsuspend (const sigset_t *set)
{
int ret = 0;
sigset_t origin_set;
sigset_t suspend_set;
siginfo_t info; /* unless paremeter */
/* get the origin signal information */
sigpending(&origin_set);
/* set the new signal information */
sigprocmask(SIG_BLOCK, set, RT_NULL);
sigpending(&suspend_set);
ret = rt_signal_wait(&suspend_set, &info, RT_WAITING_FOREVER);
/* restore the original sigprocmask */
sigprocmask(SIG_UNBLOCK, (sigset_t *)0xffffUL, RT_NULL);
sigprocmask(SIG_BLOCK, &origin_set, RT_NULL);
return ret;
}
/**
* @brief This function will install or confirm action for specified signal.
*
* @param signum is the signal to be handled.
*
* @param act is the new signal action, or NULL to restore default action.
*
* @param oldact returns the previous signal action, or NULL if not required.
*
* @return Returns 0 on success or -1 on failure.
*/
int sigaction(int signum, const struct sigaction *act, struct sigaction *oldact)
{
rt_sighandler_t old = RT_NULL;
if (!sig_valid(signum)) return -RT_ERROR;
if (act)
old = rt_signal_install(signum, act->sa_handler);
else
{
old = rt_signal_install(signum, RT_NULL);
rt_signal_install(signum, old);
}
if (oldact)
oldact->sa_handler = old;
return 0;
}
/**
* @brief This function will suspends execution of the calling thread until one of
* the signals in the given set is pending. If none of the signals specified
* are pending, it will wait for the specified time interval.
*
* @param set is the set of signal values to be waited for.
*
* @param info is a pointer to the received signal info.
*
* @param timeout is a pointer to a timespec structure that specifys the waiting time.
*
* @return Return 0 on success. Otherwise, return -1 and set errno to indicate the error.
*/
int sigtimedwait(const sigset_t *set, siginfo_t *info, const struct timespec *timeout)
{
int ret = 0;
int tick = RT_WAITING_FOREVER;
if (timeout)
{
tick = timeout->tv_sec * RT_TICK_PER_SECOND + timeout->tv_nsec * RT_TICK_PER_SECOND / NANOSECOND_PER_SECOND;
}
ret = rt_signal_wait(set, info, tick);
if (ret == 0) return 0;
errno = ret;
return -1;
}
/**
* @brief This function will suspend execution of the calling thread until one of
* the specified signal becomes pending and return the signal number.
*
* @param set is the set of signal values to be waited for.
*
* @param sig is a pointer to the received signal number.
*
* @return Return 0 on success or -1 on failure.
*/
int sigwait(const sigset_t *set, int *sig)
{
siginfo_t si;
if (sigtimedwait(set, &si, 0) < 0)
return -1;
*sig = si.si_signo;
return 0;
}
/**
* @brief This function will suspend execution of the calling thread until one of
* the specified signal is pending.
*
* @param set is the set of signal values to be waited for.
*
* @param info is a pointer to the received signal info.
*
* @return Return 0 on success or -1 on failure.
*/
int sigwaitinfo(const sigset_t *set, siginfo_t *info)
{
return sigtimedwait(set, info, NULL);
}
/**
* @brief This function willsend a signal to the caller
*
* @param sig is the signal that is to be sent.
*
* @return Returns 0 on success.
*/
int raise(int sig)
{
rt_thread_kill(rt_thread_self(), sig);
return 0;
}
#include <sys/types.h>
/**
* @brief Sends a signal to the caller.
*
* This function sends the signal specified by @p sig to the caller.
*
* @param sig The signal to be sent.
* This should be one of the standard signal macros such as SIGUSR1, SIGUSR2, etc.
*
* @return Returns 0 on success. If an error occurs, -1 is returned and errno is set appropriately.
*/
int sigqueue (pid_t pid, int signo, const union sigval value)
{
/* no support, signal queue */
return -1;
}
|