xref: /nrf52832-nimble/rt-thread/src/signal.c (revision 104654410c56c573564690304ae786df310c91fc)
1*10465441SEvalZero /*
2*10465441SEvalZero  * Copyright (c) 2006-2018, RT-Thread Development Team
3*10465441SEvalZero  *
4*10465441SEvalZero  * SPDX-License-Identifier: Apache-2.0
5*10465441SEvalZero  *
6*10465441SEvalZero  * Change Logs:
7*10465441SEvalZero  * Date           Author       Notes
8*10465441SEvalZero  * 2017/10/5      Bernard      the first version
9*10465441SEvalZero  * 2018/09/17     Jesven       fix: in _signal_deliver RT_THREAD_STAT_MASK to RT_THREAD_STAT_SIGNAL_MASK
10*10465441SEvalZero  * 2018/11/22     Jesven       in smp version rt_hw_context_switch_to add a param
11*10465441SEvalZero  */
12*10465441SEvalZero 
13*10465441SEvalZero #include <stdint.h>
14*10465441SEvalZero #include <string.h>
15*10465441SEvalZero 
16*10465441SEvalZero #include <rthw.h>
17*10465441SEvalZero #include <rtthread.h>
18*10465441SEvalZero 
19*10465441SEvalZero #ifdef RT_USING_SIGNALS
20*10465441SEvalZero 
21*10465441SEvalZero #ifndef RT_SIG_INFO_MAX
22*10465441SEvalZero #define RT_SIG_INFO_MAX 32
23*10465441SEvalZero #endif
24*10465441SEvalZero 
25*10465441SEvalZero // #define DBG_ENABLE
26*10465441SEvalZero #define DBG_SECTION_NAME    "SIGN"
27*10465441SEvalZero #define DBG_COLOR
28*10465441SEvalZero #define DBG_LEVEL           DBG_LOG
29*10465441SEvalZero #include <rtdbg.h>
30*10465441SEvalZero 
31*10465441SEvalZero #define sig_mask(sig_no)    (1u << sig_no)
32*10465441SEvalZero #define sig_valid(sig_no)   (sig_no >= 0 && sig_no < RT_SIG_MAX)
33*10465441SEvalZero 
34*10465441SEvalZero struct siginfo_node
35*10465441SEvalZero {
36*10465441SEvalZero     siginfo_t si;
37*10465441SEvalZero     struct rt_slist_node list;
38*10465441SEvalZero };
39*10465441SEvalZero 
40*10465441SEvalZero static struct rt_mempool *_rt_siginfo_pool;
41*10465441SEvalZero static void _signal_deliver(rt_thread_t tid);
42*10465441SEvalZero void rt_thread_handle_sig(rt_bool_t clean_state);
43*10465441SEvalZero 
_signal_default_handler(int signo)44*10465441SEvalZero static void _signal_default_handler(int signo)
45*10465441SEvalZero {
46*10465441SEvalZero     LOG_I("handled signo[%d] with default action.", signo);
47*10465441SEvalZero     return ;
48*10465441SEvalZero }
49*10465441SEvalZero 
_signal_entry(void * parameter)50*10465441SEvalZero static void _signal_entry(void *parameter)
51*10465441SEvalZero {
52*10465441SEvalZero     rt_thread_t tid = rt_thread_self();
53*10465441SEvalZero 
54*10465441SEvalZero     dbg_enter;
55*10465441SEvalZero 
56*10465441SEvalZero     /* handle signal */
57*10465441SEvalZero     rt_thread_handle_sig(RT_FALSE);
58*10465441SEvalZero 
59*10465441SEvalZero     /* never come back... */
60*10465441SEvalZero     rt_hw_interrupt_disable();
61*10465441SEvalZero     /* return to thread */
62*10465441SEvalZero     tid->sp = tid->sig_ret;
63*10465441SEvalZero     tid->sig_ret = RT_NULL;
64*10465441SEvalZero 
65*10465441SEvalZero     LOG_D("switch back to: 0x%08x\n", tid->sp);
66*10465441SEvalZero     tid->stat &= ~RT_THREAD_STAT_SIGNAL;
67*10465441SEvalZero 
68*10465441SEvalZero #ifdef RT_USING_SMP
69*10465441SEvalZero     rt_hw_context_switch_to((rt_ubase_t)&(tid->sp), tid);
70*10465441SEvalZero #else
71*10465441SEvalZero     rt_hw_context_switch_to((rt_ubase_t)&(tid->sp));
72*10465441SEvalZero #endif /*RT_USING_SMP*/
73*10465441SEvalZero }
74*10465441SEvalZero 
75*10465441SEvalZero /*
76*10465441SEvalZero  * To deliver a signal to thread, there are cases:
77*10465441SEvalZero  * 1. When thread is suspended, function resumes thread and
78*10465441SEvalZero  * set signal stat;
79*10465441SEvalZero  * 2. When thread is ready:
80*10465441SEvalZero  *   - If function delivers a signal to self thread, just handle
81*10465441SEvalZero  *    it.
82*10465441SEvalZero  *   - If function delivers a signal to another ready thread, OS
83*10465441SEvalZero  *    should build a slice context to handle it.
84*10465441SEvalZero  */
_signal_deliver(rt_thread_t tid)85*10465441SEvalZero static void _signal_deliver(rt_thread_t tid)
86*10465441SEvalZero {
87*10465441SEvalZero     rt_ubase_t level;
88*10465441SEvalZero 
89*10465441SEvalZero     /* thread is not interested in pended signals */
90*10465441SEvalZero     if (!(tid->sig_pending & tid->sig_mask)) return;
91*10465441SEvalZero 
92*10465441SEvalZero     level = rt_hw_interrupt_disable();
93*10465441SEvalZero     if ((tid->stat & RT_THREAD_STAT_MASK) == RT_THREAD_SUSPEND)
94*10465441SEvalZero     {
95*10465441SEvalZero         /* resume thread to handle signal */
96*10465441SEvalZero         rt_thread_resume(tid);
97*10465441SEvalZero         /* add signal state */
98*10465441SEvalZero         tid->stat |= RT_THREAD_STAT_SIGNAL;
99*10465441SEvalZero 
100*10465441SEvalZero         rt_hw_interrupt_enable(level);
101*10465441SEvalZero 
102*10465441SEvalZero         /* re-schedule */
103*10465441SEvalZero         rt_schedule();
104*10465441SEvalZero     }
105*10465441SEvalZero     else
106*10465441SEvalZero     {
107*10465441SEvalZero         if (tid == rt_thread_self())
108*10465441SEvalZero         {
109*10465441SEvalZero             /* add signal state */
110*10465441SEvalZero             tid->stat |= RT_THREAD_STAT_SIGNAL;
111*10465441SEvalZero 
112*10465441SEvalZero             rt_hw_interrupt_enable(level);
113*10465441SEvalZero 
114*10465441SEvalZero             /* do signal action in self thread context */
115*10465441SEvalZero             rt_thread_handle_sig(RT_TRUE);
116*10465441SEvalZero         }
117*10465441SEvalZero         else if (!((tid->stat & RT_THREAD_STAT_SIGNAL_MASK) & RT_THREAD_STAT_SIGNAL))
118*10465441SEvalZero         {
119*10465441SEvalZero             /* add signal state */
120*10465441SEvalZero             tid->stat |= RT_THREAD_STAT_SIGNAL;
121*10465441SEvalZero 
122*10465441SEvalZero             /* point to the signal handle entry */
123*10465441SEvalZero             tid->sig_ret = tid->sp;
124*10465441SEvalZero             tid->sp = rt_hw_stack_init((void *)_signal_entry, RT_NULL,
125*10465441SEvalZero                                        (void *)((char *)tid->sig_ret - 32), RT_NULL);
126*10465441SEvalZero 
127*10465441SEvalZero             rt_hw_interrupt_enable(level);
128*10465441SEvalZero             LOG_D("signal stack pointer @ 0x%08x", tid->sp);
129*10465441SEvalZero 
130*10465441SEvalZero             /* re-schedule */
131*10465441SEvalZero             rt_schedule();
132*10465441SEvalZero         }
133*10465441SEvalZero         else
134*10465441SEvalZero         {
135*10465441SEvalZero             rt_hw_interrupt_enable(level);
136*10465441SEvalZero         }
137*10465441SEvalZero     }
138*10465441SEvalZero }
139*10465441SEvalZero 
rt_signal_install(int signo,rt_sighandler_t handler)140*10465441SEvalZero rt_sighandler_t rt_signal_install(int signo, rt_sighandler_t handler)
141*10465441SEvalZero {
142*10465441SEvalZero     rt_sighandler_t old = RT_NULL;
143*10465441SEvalZero     rt_thread_t tid = rt_thread_self();
144*10465441SEvalZero 
145*10465441SEvalZero     if (!sig_valid(signo)) return SIG_ERR;
146*10465441SEvalZero 
147*10465441SEvalZero     rt_enter_critical();
148*10465441SEvalZero     if (tid->sig_vectors == RT_NULL)
149*10465441SEvalZero     {
150*10465441SEvalZero         rt_thread_alloc_sig(tid);
151*10465441SEvalZero     }
152*10465441SEvalZero 
153*10465441SEvalZero     if (tid->sig_vectors)
154*10465441SEvalZero     {
155*10465441SEvalZero         old = tid->sig_vectors[signo];
156*10465441SEvalZero 
157*10465441SEvalZero         if (handler == SIG_IGN) tid->sig_vectors[signo] = RT_NULL;
158*10465441SEvalZero         else if (handler == SIG_DFL) tid->sig_vectors[signo] = _signal_default_handler;
159*10465441SEvalZero         else tid->sig_vectors[signo] = handler;
160*10465441SEvalZero     }
161*10465441SEvalZero     rt_exit_critical();
162*10465441SEvalZero 
163*10465441SEvalZero     return old;
164*10465441SEvalZero }
165*10465441SEvalZero 
rt_signal_mask(int signo)166*10465441SEvalZero void rt_signal_mask(int signo)
167*10465441SEvalZero {
168*10465441SEvalZero     rt_base_t level;
169*10465441SEvalZero     rt_thread_t tid = rt_thread_self();
170*10465441SEvalZero 
171*10465441SEvalZero     level = rt_hw_interrupt_disable();
172*10465441SEvalZero 
173*10465441SEvalZero     tid->sig_mask &= ~sig_mask(signo);
174*10465441SEvalZero 
175*10465441SEvalZero     rt_hw_interrupt_enable(level);
176*10465441SEvalZero }
177*10465441SEvalZero 
rt_signal_unmask(int signo)178*10465441SEvalZero void rt_signal_unmask(int signo)
179*10465441SEvalZero {
180*10465441SEvalZero     rt_base_t level;
181*10465441SEvalZero     rt_thread_t tid = rt_thread_self();
182*10465441SEvalZero 
183*10465441SEvalZero     level = rt_hw_interrupt_disable();
184*10465441SEvalZero 
185*10465441SEvalZero     tid->sig_mask |= sig_mask(signo);
186*10465441SEvalZero 
187*10465441SEvalZero     /* let thread handle pended signals */
188*10465441SEvalZero     if (tid->sig_mask & tid->sig_pending)
189*10465441SEvalZero     {
190*10465441SEvalZero         rt_hw_interrupt_enable(level);
191*10465441SEvalZero         _signal_deliver(tid);
192*10465441SEvalZero     }
193*10465441SEvalZero     else
194*10465441SEvalZero     {
195*10465441SEvalZero         rt_hw_interrupt_enable(level);
196*10465441SEvalZero     }
197*10465441SEvalZero }
198*10465441SEvalZero 
rt_signal_wait(const rt_sigset_t * set,rt_siginfo_t * si,rt_int32_t timeout)199*10465441SEvalZero int rt_signal_wait(const rt_sigset_t *set, rt_siginfo_t *si, rt_int32_t timeout)
200*10465441SEvalZero {
201*10465441SEvalZero     int ret = RT_EOK;
202*10465441SEvalZero     rt_base_t   level;
203*10465441SEvalZero     rt_thread_t tid = rt_thread_self();
204*10465441SEvalZero     struct siginfo_node *si_node = RT_NULL, *si_prev = RT_NULL;
205*10465441SEvalZero 
206*10465441SEvalZero     /* current context checking */
207*10465441SEvalZero     RT_DEBUG_IN_THREAD_CONTEXT;
208*10465441SEvalZero 
209*10465441SEvalZero     /* parameters check */
210*10465441SEvalZero     if (set == NULL || *set == 0 || si == NULL )
211*10465441SEvalZero     {
212*10465441SEvalZero         ret = -RT_EINVAL;
213*10465441SEvalZero         goto __done_return;
214*10465441SEvalZero     }
215*10465441SEvalZero 
216*10465441SEvalZero     /* clear siginfo to avoid unknown value */
217*10465441SEvalZero     memset(si, 0x0, sizeof(rt_siginfo_t));
218*10465441SEvalZero 
219*10465441SEvalZero     level = rt_hw_interrupt_disable();
220*10465441SEvalZero 
221*10465441SEvalZero     /* already pending */
222*10465441SEvalZero     if (tid->sig_pending & *set) goto __done;
223*10465441SEvalZero 
224*10465441SEvalZero     if (timeout == 0)
225*10465441SEvalZero     {
226*10465441SEvalZero         ret = -RT_ETIMEOUT;
227*10465441SEvalZero         goto __done_int;
228*10465441SEvalZero     }
229*10465441SEvalZero 
230*10465441SEvalZero     /* suspend self thread */
231*10465441SEvalZero     rt_thread_suspend(tid);
232*10465441SEvalZero     /* set thread stat as waiting for signal */
233*10465441SEvalZero     tid->stat |= RT_THREAD_STAT_SIGNAL_WAIT;
234*10465441SEvalZero 
235*10465441SEvalZero     /* start timeout timer */
236*10465441SEvalZero     if (timeout != RT_WAITING_FOREVER)
237*10465441SEvalZero     {
238*10465441SEvalZero         /* reset the timeout of thread timer and start it */
239*10465441SEvalZero         rt_timer_control(&(tid->thread_timer),
240*10465441SEvalZero                          RT_TIMER_CTRL_SET_TIME,
241*10465441SEvalZero                          &timeout);
242*10465441SEvalZero         rt_timer_start(&(tid->thread_timer));
243*10465441SEvalZero     }
244*10465441SEvalZero     rt_hw_interrupt_enable(level);
245*10465441SEvalZero 
246*10465441SEvalZero     /* do thread scheduling */
247*10465441SEvalZero     rt_schedule();
248*10465441SEvalZero 
249*10465441SEvalZero     level = rt_hw_interrupt_disable();
250*10465441SEvalZero 
251*10465441SEvalZero     /* remove signal waiting flag */
252*10465441SEvalZero     tid->stat &= ~RT_THREAD_STAT_SIGNAL_WAIT;
253*10465441SEvalZero 
254*10465441SEvalZero     /* check errno of thread */
255*10465441SEvalZero     if (tid->error == -RT_ETIMEOUT)
256*10465441SEvalZero     {
257*10465441SEvalZero         tid->error = RT_EOK;
258*10465441SEvalZero         rt_hw_interrupt_enable(level);
259*10465441SEvalZero 
260*10465441SEvalZero         /* timer timeout */
261*10465441SEvalZero         ret = -RT_ETIMEOUT;
262*10465441SEvalZero         goto __done_return;
263*10465441SEvalZero     }
264*10465441SEvalZero 
265*10465441SEvalZero __done:
266*10465441SEvalZero     /* to get the first matched pending signals */
267*10465441SEvalZero     si_node = (struct siginfo_node *)tid->si_list;
268*10465441SEvalZero     while (si_node)
269*10465441SEvalZero     {
270*10465441SEvalZero         int signo;
271*10465441SEvalZero 
272*10465441SEvalZero         signo = si_node->si.si_signo;
273*10465441SEvalZero         if (sig_mask(signo) & *set)
274*10465441SEvalZero         {
275*10465441SEvalZero             *si  = si_node->si;
276*10465441SEvalZero 
277*10465441SEvalZero             LOG_D("sigwait: %d sig raised!", signo);
278*10465441SEvalZero             if (si_prev) si_prev->list.next = si_node->list.next;
279*10465441SEvalZero             else tid->si_list = si_node->list.next;
280*10465441SEvalZero 
281*10465441SEvalZero             /* clear pending */
282*10465441SEvalZero             tid->sig_pending &= ~sig_mask(signo);
283*10465441SEvalZero             rt_mp_free(si_node);
284*10465441SEvalZero             break;
285*10465441SEvalZero         }
286*10465441SEvalZero 
287*10465441SEvalZero         si_prev = si_node;
288*10465441SEvalZero         si_node = (void *)rt_slist_entry(si_node->list.next, struct siginfo_node, list);
289*10465441SEvalZero      }
290*10465441SEvalZero 
291*10465441SEvalZero __done_int:
292*10465441SEvalZero     rt_hw_interrupt_enable(level);
293*10465441SEvalZero 
294*10465441SEvalZero __done_return:
295*10465441SEvalZero     return ret;
296*10465441SEvalZero }
297*10465441SEvalZero 
rt_thread_handle_sig(rt_bool_t clean_state)298*10465441SEvalZero void rt_thread_handle_sig(rt_bool_t clean_state)
299*10465441SEvalZero {
300*10465441SEvalZero     rt_base_t level;
301*10465441SEvalZero 
302*10465441SEvalZero     rt_thread_t tid = rt_thread_self();
303*10465441SEvalZero     struct siginfo_node *si_node;
304*10465441SEvalZero 
305*10465441SEvalZero     level = rt_hw_interrupt_disable();
306*10465441SEvalZero     if (tid->sig_pending & tid->sig_mask)
307*10465441SEvalZero     {
308*10465441SEvalZero         /* if thread is not waiting for signal */
309*10465441SEvalZero         if (!(tid->stat & RT_THREAD_STAT_SIGNAL_WAIT))
310*10465441SEvalZero         {
311*10465441SEvalZero             while (tid->sig_pending & tid->sig_mask)
312*10465441SEvalZero             {
313*10465441SEvalZero                 int signo, error;
314*10465441SEvalZero                 rt_sighandler_t handler;
315*10465441SEvalZero 
316*10465441SEvalZero                 si_node = (struct siginfo_node *)tid->si_list;
317*10465441SEvalZero                 if (!si_node) break;
318*10465441SEvalZero 
319*10465441SEvalZero                 /* remove this sig info node from list */
320*10465441SEvalZero                 if (si_node->list.next == RT_NULL)
321*10465441SEvalZero                     tid->si_list = RT_NULL;
322*10465441SEvalZero                 else
323*10465441SEvalZero                     tid->si_list = (void *)rt_slist_entry(si_node->list.next, struct siginfo_node, list);
324*10465441SEvalZero 
325*10465441SEvalZero                 signo   = si_node->si.si_signo;
326*10465441SEvalZero                 handler = tid->sig_vectors[signo];
327*10465441SEvalZero                 rt_hw_interrupt_enable(level);
328*10465441SEvalZero 
329*10465441SEvalZero                 LOG_D("handle signal: %d, handler 0x%08x", signo, handler);
330*10465441SEvalZero                 if (handler) handler(signo);
331*10465441SEvalZero 
332*10465441SEvalZero                 level = rt_hw_interrupt_disable();
333*10465441SEvalZero                 tid->sig_pending &= ~sig_mask(signo);
334*10465441SEvalZero                 error = -RT_EINTR;
335*10465441SEvalZero 
336*10465441SEvalZero                 rt_mp_free(si_node); /* release this siginfo node */
337*10465441SEvalZero                 /* set errno in thread tcb */
338*10465441SEvalZero                 tid->error = error;
339*10465441SEvalZero             }
340*10465441SEvalZero 
341*10465441SEvalZero             /* whether clean signal status */
342*10465441SEvalZero             if (clean_state == RT_TRUE) tid->stat &= ~RT_THREAD_STAT_SIGNAL;
343*10465441SEvalZero         }
344*10465441SEvalZero     }
345*10465441SEvalZero 
346*10465441SEvalZero     rt_hw_interrupt_enable(level);
347*10465441SEvalZero }
348*10465441SEvalZero 
rt_thread_alloc_sig(rt_thread_t tid)349*10465441SEvalZero void rt_thread_alloc_sig(rt_thread_t tid)
350*10465441SEvalZero {
351*10465441SEvalZero     int index;
352*10465441SEvalZero     rt_base_t level;
353*10465441SEvalZero     rt_sighandler_t *vectors;
354*10465441SEvalZero 
355*10465441SEvalZero     vectors = (rt_sighandler_t *)RT_KERNEL_MALLOC(sizeof(rt_sighandler_t) * RT_SIG_MAX);
356*10465441SEvalZero     RT_ASSERT(vectors != RT_NULL);
357*10465441SEvalZero 
358*10465441SEvalZero     for (index = 0; index < RT_SIG_MAX; index ++)
359*10465441SEvalZero     {
360*10465441SEvalZero         vectors[index] = _signal_default_handler;
361*10465441SEvalZero     }
362*10465441SEvalZero 
363*10465441SEvalZero     level = rt_hw_interrupt_disable();
364*10465441SEvalZero     tid->sig_vectors = vectors;
365*10465441SEvalZero     rt_hw_interrupt_enable(level);
366*10465441SEvalZero }
367*10465441SEvalZero 
rt_thread_free_sig(rt_thread_t tid)368*10465441SEvalZero void rt_thread_free_sig(rt_thread_t tid)
369*10465441SEvalZero {
370*10465441SEvalZero     rt_base_t level;
371*10465441SEvalZero     struct siginfo_node *si_list;
372*10465441SEvalZero     rt_sighandler_t *sig_vectors;
373*10465441SEvalZero 
374*10465441SEvalZero     level = rt_hw_interrupt_disable();
375*10465441SEvalZero     si_list = (struct siginfo_node *)tid->si_list;
376*10465441SEvalZero     tid->si_list = RT_NULL;
377*10465441SEvalZero 
378*10465441SEvalZero     sig_vectors = tid->sig_vectors;
379*10465441SEvalZero     tid->sig_vectors = RT_NULL;
380*10465441SEvalZero     rt_hw_interrupt_enable(level);
381*10465441SEvalZero 
382*10465441SEvalZero     if (si_list)
383*10465441SEvalZero     {
384*10465441SEvalZero         struct rt_slist_node *node;
385*10465441SEvalZero         struct siginfo_node  *si_node;
386*10465441SEvalZero 
387*10465441SEvalZero         LOG_D("free signal info list");
388*10465441SEvalZero         node = &(si_list->list);
389*10465441SEvalZero         do
390*10465441SEvalZero         {
391*10465441SEvalZero             si_node = rt_slist_entry(node, struct siginfo_node, list);
392*10465441SEvalZero             rt_mp_free(si_node);
393*10465441SEvalZero 
394*10465441SEvalZero             node = node->next;
395*10465441SEvalZero         } while (node);
396*10465441SEvalZero     }
397*10465441SEvalZero 
398*10465441SEvalZero     if (sig_vectors)
399*10465441SEvalZero     {
400*10465441SEvalZero         RT_KERNEL_FREE(sig_vectors);
401*10465441SEvalZero     }
402*10465441SEvalZero }
403*10465441SEvalZero 
rt_thread_kill(rt_thread_t tid,int sig)404*10465441SEvalZero int rt_thread_kill(rt_thread_t tid, int sig)
405*10465441SEvalZero {
406*10465441SEvalZero     siginfo_t si;
407*10465441SEvalZero     rt_base_t level;
408*10465441SEvalZero     struct siginfo_node *si_node;
409*10465441SEvalZero 
410*10465441SEvalZero     RT_ASSERT(tid != RT_NULL);
411*10465441SEvalZero     if (!sig_valid(sig)) return -RT_EINVAL;
412*10465441SEvalZero 
413*10465441SEvalZero     LOG_I("send signal: %d", sig);
414*10465441SEvalZero     si.si_signo = sig;
415*10465441SEvalZero     si.si_code  = SI_USER;
416*10465441SEvalZero     si.si_value.sival_ptr = RT_NULL;
417*10465441SEvalZero 
418*10465441SEvalZero     level = rt_hw_interrupt_disable();
419*10465441SEvalZero     if (tid->sig_pending & sig_mask(sig))
420*10465441SEvalZero     {
421*10465441SEvalZero         /* whether already emits this signal? */
422*10465441SEvalZero         struct rt_slist_node *node;
423*10465441SEvalZero         struct siginfo_node  *entry;
424*10465441SEvalZero 
425*10465441SEvalZero         node = (struct rt_slist_node *)tid->si_list;
426*10465441SEvalZero         rt_hw_interrupt_enable(level);
427*10465441SEvalZero 
428*10465441SEvalZero         /* update sig info */
429*10465441SEvalZero         rt_enter_critical();
430*10465441SEvalZero         for (; (node) != RT_NULL; node = node->next)
431*10465441SEvalZero         {
432*10465441SEvalZero             entry = rt_slist_entry(node, struct siginfo_node, list);
433*10465441SEvalZero             if (entry->si.si_signo == sig)
434*10465441SEvalZero             {
435*10465441SEvalZero                 memcpy(&(entry->si), &si, sizeof(siginfo_t));
436*10465441SEvalZero                 rt_exit_critical();
437*10465441SEvalZero                 return 0;
438*10465441SEvalZero             }
439*10465441SEvalZero         }
440*10465441SEvalZero         rt_exit_critical();
441*10465441SEvalZero 
442*10465441SEvalZero         /* disable interrupt to protect tcb */
443*10465441SEvalZero         level = rt_hw_interrupt_disable();
444*10465441SEvalZero     }
445*10465441SEvalZero     else
446*10465441SEvalZero     {
447*10465441SEvalZero         /* a new signal */
448*10465441SEvalZero         tid->sig_pending |= sig_mask(sig);
449*10465441SEvalZero     }
450*10465441SEvalZero     rt_hw_interrupt_enable(level);
451*10465441SEvalZero 
452*10465441SEvalZero     si_node = (struct siginfo_node *) rt_mp_alloc(_rt_siginfo_pool, 0);
453*10465441SEvalZero     if (si_node)
454*10465441SEvalZero     {
455*10465441SEvalZero         rt_slist_init(&(si_node->list));
456*10465441SEvalZero         memcpy(&(si_node->si), &si, sizeof(siginfo_t));
457*10465441SEvalZero 
458*10465441SEvalZero         level = rt_hw_interrupt_disable();
459*10465441SEvalZero         if (!tid->si_list) tid->si_list = si_node;
460*10465441SEvalZero         else
461*10465441SEvalZero         {
462*10465441SEvalZero             struct siginfo_node *si_list;
463*10465441SEvalZero 
464*10465441SEvalZero             si_list = (struct siginfo_node *)tid->si_list;
465*10465441SEvalZero             rt_slist_append(&(si_list->list), &(si_node->list));
466*10465441SEvalZero         }
467*10465441SEvalZero         rt_hw_interrupt_enable(level);
468*10465441SEvalZero     }
469*10465441SEvalZero     else
470*10465441SEvalZero     {
471*10465441SEvalZero         LOG_E("The allocation of signal info node failed.");
472*10465441SEvalZero     }
473*10465441SEvalZero 
474*10465441SEvalZero     /* deliver signal to this thread */
475*10465441SEvalZero     _signal_deliver(tid);
476*10465441SEvalZero 
477*10465441SEvalZero     return RT_EOK;
478*10465441SEvalZero }
479*10465441SEvalZero 
rt_system_signal_init(void)480*10465441SEvalZero int rt_system_signal_init(void)
481*10465441SEvalZero {
482*10465441SEvalZero     _rt_siginfo_pool = rt_mp_create("signal", RT_SIG_INFO_MAX, sizeof(struct siginfo_node));
483*10465441SEvalZero     if (_rt_siginfo_pool == RT_NULL)
484*10465441SEvalZero     {
485*10465441SEvalZero         LOG_E("create memory pool for signal info failed.");
486*10465441SEvalZero         RT_ASSERT(0);
487*10465441SEvalZero     }
488*10465441SEvalZero 
489*10465441SEvalZero     return 0;
490*10465441SEvalZero }
491*10465441SEvalZero 
492*10465441SEvalZero #endif
493