66 * Change Logs:
77 * Date Author Notes
88 * 2017/10/5 Bernard the first version
9+ * 2019/02/15 Jesven fixed the problem of si_list
910 */
1011
1112#include <stdint.h>
@@ -37,7 +38,7 @@ struct siginfo_node
3738
3839static struct rt_mempool * _rt_siginfo_pool ;
3940static void _signal_deliver (rt_thread_t tid );
40- void rt_thread_handle_sig (rt_bool_t clean_state );
41+ void rt_thread_handle_sig (void );
4142
4243static void _signal_default_handler (int signo )
4344{
@@ -47,22 +48,37 @@ static void _signal_default_handler(int signo)
4748
4849static void _signal_entry (void * parameter )
4950{
51+ register rt_base_t level ;
5052 rt_thread_t tid = rt_thread_self ();
5153
5254 dbg_enter ;
5355
54- /* handle signal */
55- rt_thread_handle_sig (RT_FALSE );
56+ while (1 )
57+ {
58+ level = rt_hw_interrupt_disable ();
59+ if (tid -> stat & RT_THREAD_STAT_SIGNAL )
60+ {
61+ rt_hw_interrupt_enable (level );
62+
63+ /* handle signal */
64+ rt_thread_handle_sig ();
65+ }
66+ else
67+ {
68+ /*
69+ * Note: interrupt is disabled and no reentrant issue.
70+ *
71+ * no signal status in tid->stat.
72+ */
73+ break ;
74+ }
75+ }
5676
5777 /* never come back... */
58- rt_hw_interrupt_disable ();
59- /* return to thread */
6078 tid -> sp = tid -> sig_ret ;
6179 tid -> sig_ret = RT_NULL ;
6280
6381 LOG_D ("switch back to: 0x%08x" , tid -> sp );
64- tid -> stat &= ~RT_THREAD_STAT_SIGNAL ;
65-
6682 rt_hw_context_switch_to ((rt_uint32_t ) & (tid -> sp ));
6783}
6884
@@ -80,10 +96,15 @@ static void _signal_deliver(rt_thread_t tid)
8096{
8197 rt_ubase_t level ;
8298
99+ level = rt_hw_interrupt_disable ();
100+
83101 /* thread is not interested in pended signals */
84- if (!(tid -> sig_pending & tid -> sig_mask )) return ;
102+ if (!(tid -> sig_pending & tid -> sig_mask ))
103+ {
104+ rt_hw_interrupt_enable (level );
105+ return ;
106+ }
85107
86- level = rt_hw_interrupt_disable ();
87108 if ((tid -> stat & RT_THREAD_STAT_MASK ) == RT_THREAD_SUSPEND )
88109 {
89110 /* resume thread to handle signal */
@@ -106,7 +127,7 @@ static void _signal_deliver(rt_thread_t tid)
106127 rt_hw_interrupt_enable (level );
107128
108129 /* do signal action in self thread context */
109- rt_thread_handle_sig (RT_TRUE );
130+ rt_thread_handle_sig ();
110131 }
111132 else if (!((tid -> stat & RT_THREAD_STAT_SIGNAL_MASK ) & RT_THREAD_STAT_SIGNAL ))
112133 {
@@ -133,12 +154,13 @@ static void _signal_deliver(rt_thread_t tid)
133154
134155rt_sighandler_t rt_signal_install (int signo , rt_sighandler_t handler )
135156{
157+ rt_base_t level ;
136158 rt_sighandler_t old = RT_NULL ;
137159 rt_thread_t tid = rt_thread_self ();
138160
139161 if (!sig_valid (signo )) return SIG_ERR ;
140162
141- rt_enter_critical ();
163+ level = rt_hw_interrupt_disable ();
142164 if (tid -> sig_vectors == RT_NULL )
143165 {
144166 rt_thread_alloc_sig (tid );
@@ -152,7 +174,7 @@ rt_sighandler_t rt_signal_install(int signo, rt_sighandler_t handler)
152174 else if (handler == SIG_DFL ) tid -> sig_vectors [signo ] = _signal_default_handler ;
153175 else tid -> sig_vectors [signo ] = handler ;
154176 }
155- rt_exit_critical ( );
177+ rt_hw_interrupt_enable ( level );
156178
157179 return old ;
158180}
@@ -270,7 +292,20 @@ int rt_signal_wait(const rt_sigset_t *set, rt_siginfo_t *si, rt_int32_t timeout)
270292
271293 LOG_D ("sigwait: %d sig raised!" , signo );
272294 if (si_prev ) si_prev -> list .next = si_node -> list .next ;
273- else tid -> si_list = si_node -> list .next ;
295+ else
296+ {
297+ struct siginfo_node * node_next ;
298+
299+ if (si_node -> list .next )
300+ {
301+ node_next = (void * )rt_slist_entry (si_node -> list .next , struct siginfo_node , list );
302+ tid -> si_list = node_next ;
303+ }
304+ else
305+ {
306+ tid -> si_list = RT_NULL ;
307+ }
308+ }
274309
275310 /* clear pending */
276311 tid -> sig_pending &= ~sig_mask (signo );
@@ -279,7 +314,14 @@ int rt_signal_wait(const rt_sigset_t *set, rt_siginfo_t *si, rt_int32_t timeout)
279314 }
280315
281316 si_prev = si_node ;
282- si_node = (void * )rt_slist_entry (si_node -> list .next , struct siginfo_node , list );
317+ if (si_node -> list .next )
318+ {
319+ si_node = (void * )rt_slist_entry (si_node -> list .next , struct siginfo_node , list );
320+ }
321+ else
322+ {
323+ si_node = RT_NULL ;
324+ }
283325 }
284326
285327__done_int :
@@ -289,14 +331,15 @@ int rt_signal_wait(const rt_sigset_t *set, rt_siginfo_t *si, rt_int32_t timeout)
289331 return ret ;
290332}
291333
292- void rt_thread_handle_sig (rt_bool_t clean_state )
334+ void rt_thread_handle_sig (void )
293335{
294336 rt_base_t level ;
295337
296338 rt_thread_t tid = rt_thread_self ();
297339 struct siginfo_node * si_node ;
298340
299341 level = rt_hw_interrupt_disable ();
342+
300343 if (tid -> sig_pending & tid -> sig_mask )
301344 {
302345 /* if thread is not waiting for signal */
@@ -318,25 +361,24 @@ void rt_thread_handle_sig(rt_bool_t clean_state)
318361
319362 signo = si_node -> si .si_signo ;
320363 handler = tid -> sig_vectors [signo ];
364+ tid -> sig_pending &= ~sig_mask (signo );
321365 rt_hw_interrupt_enable (level );
322366
323367 LOG_D ("handle signal: %d, handler 0x%08x" , signo , handler );
324368 if (handler ) handler (signo );
325369
326370 level = rt_hw_interrupt_disable ();
327- tid -> sig_pending &= ~sig_mask (signo );
328371 error = - RT_EINTR ;
329372
330373 rt_mp_free (si_node ); /* release this siginfo node */
331374 /* set errno in thread tcb */
332375 tid -> error = error ;
333376 }
334377
335- /* whether clean signal status */
336- if ( clean_state == RT_TRUE ) tid -> stat &= ~RT_THREAD_STAT_SIGNAL ;
378+ /* clean state */
379+ tid -> stat &= ~RT_THREAD_STAT_SIGNAL ;
337380 }
338381 }
339-
340382 rt_hw_interrupt_enable (level );
341383}
342384
@@ -362,30 +404,30 @@ void rt_thread_alloc_sig(rt_thread_t tid)
362404void rt_thread_free_sig (rt_thread_t tid )
363405{
364406 rt_base_t level ;
365- struct siginfo_node * si_list ;
407+ struct siginfo_node * si_node ;
366408 rt_sighandler_t * sig_vectors ;
367409
368410 level = rt_hw_interrupt_disable ();
369- si_list = (struct siginfo_node * )tid -> si_list ;
411+ si_node = (struct siginfo_node * )tid -> si_list ;
370412 tid -> si_list = RT_NULL ;
371413
372414 sig_vectors = tid -> sig_vectors ;
373415 tid -> sig_vectors = RT_NULL ;
374416 rt_hw_interrupt_enable (level );
375417
376- if (si_list )
418+ if (si_node )
377419 {
378420 struct rt_slist_node * node ;
379- struct siginfo_node * si_node ;
421+ struct rt_slist_node * node_to_free ;
380422
381423 LOG_D ("free signal info list" );
382- node = & (si_list -> list );
424+ node = & (si_node -> list );
383425 do
384426 {
385- si_node = rt_slist_entry (node , struct siginfo_node , list );
386- rt_mp_free (si_node );
387-
427+ node_to_free = node ;
388428 node = node -> next ;
429+ si_node = rt_slist_entry (node_to_free , struct siginfo_node , list );
430+ rt_mp_free (si_node );
389431 } while (node );
390432 }
391433
@@ -416,30 +458,23 @@ int rt_thread_kill(rt_thread_t tid, int sig)
416458 struct rt_slist_node * node ;
417459 struct siginfo_node * entry ;
418460
419- node = (struct rt_slist_node * )tid -> si_list ;
420- rt_hw_interrupt_enable (level );
461+ si_node = (struct siginfo_node * )tid -> si_list ;
462+ if (si_node )
463+ node = (struct rt_slist_node * )& si_node -> list ;
464+ else
465+ node = RT_NULL ;
421466
422467 /* update sig info */
423- rt_enter_critical ();
424468 for (; (node ) != RT_NULL ; node = node -> next )
425469 {
426470 entry = rt_slist_entry (node , struct siginfo_node , list );
427471 if (entry -> si .si_signo == sig )
428472 {
429473 memcpy (& (entry -> si ), & si , sizeof (siginfo_t ));
430- rt_exit_critical ( );
474+ rt_hw_interrupt_enable ( level );
431475 return 0 ;
432476 }
433477 }
434- rt_exit_critical ();
435-
436- /* disable interrupt to protect tcb */
437- level = rt_hw_interrupt_disable ();
438- }
439- else
440- {
441- /* a new signal */
442- tid -> sig_pending |= sig_mask (sig );
443478 }
444479 rt_hw_interrupt_enable (level );
445480
@@ -450,14 +485,22 @@ int rt_thread_kill(rt_thread_t tid, int sig)
450485 memcpy (& (si_node -> si ), & si , sizeof (siginfo_t ));
451486
452487 level = rt_hw_interrupt_disable ();
453- if (! tid -> si_list ) tid -> si_list = si_node ;
454- else
488+
489+ if ( tid -> si_list )
455490 {
456491 struct siginfo_node * si_list ;
457492
458493 si_list = (struct siginfo_node * )tid -> si_list ;
459494 rt_slist_append (& (si_list -> list ), & (si_node -> list ));
460495 }
496+ else
497+ {
498+ tid -> si_list = si_node ;
499+ }
500+
501+ /* a new signal */
502+ tid -> sig_pending |= sig_mask (sig );
503+
461504 rt_hw_interrupt_enable (level );
462505 }
463506 else
0 commit comments