source: rtems/c/src/exec/posix/src/psignal.c @ 281ad52

4.104.114.84.95
Last change on this file since 281ad52 was 281ad52, checked in by Joel Sherrill <joel.sherrill@…>, on 06/12/96 at 22:49:14

basic kill() which send a signal to pthread_self() appears to work.

  • Property mode set to 100644
File size: 26.0 KB
Line 
1/*
2 *  $Id$
3 */
4
5#include <assert.h>
6#include <errno.h>
7#include <pthread.h>
8#include <signal.h>
9
10#include <rtems/system.h>
11#include <rtems/score/isr.h>
12#include <rtems/score/thread.h>
13#include <rtems/score/tqdata.h>
14#include <rtems/posix/seterr.h>
15#include <rtems/posix/threadsup.h>
16#include <rtems/posix/pthread.h>
17#include <rtems/posix/time.h>
18
19/*
20 *  Currently 32 signals numbered 1-32 are defined
21 */
22
23#define SIGNAL_EMPTY_MASK  0x00000000
24#define SIGNAL_ALL_MASK    0xffffffff
25
26#define signo_to_mask( _sig ) (1 << ((_sig) - 1))
27
28#define is_valid_signo( _sig ) \
29  ((_sig) >= 1 && (_sig) <= 32 )
30
31/*** PROCESS WIDE STUFF ****/
32
33sigset_t  _POSIX_signals_Pending;
34
35void _POSIX_signals_Abormal_termination_handler( int signo )
36{
37  exit( 1 );
38}
39
40#define _POSIX_signals_Stop_handler NULL
41#define _POSIX_signals_Continue_handler NULL
42
43#define SIGACTION_TERMINATE \
44  { 0, SIGNAL_ALL_MASK, {_POSIX_signals_Abormal_termination_handler} }
45#define SIGACTION_IGNORE \
46  { 0, SIGNAL_ALL_MASK, {SIG_IGN} }
47#define SIGACTION_STOP \
48  { 0, SIGNAL_ALL_MASK, {_POSIX_signals_Stop_handler} }
49#define SIGACTION_CONTINUE \
50  { 0, SIGNAL_ALL_MASK, {_POSIX_signals_Continue_handler} }
51
52#define SIG_ARRAY_MAX  (SIGRTMAX + 1)
53struct sigaction _POSIX_signals_Default_vectors[ SIG_ARRAY_MAX ] = {
54  /* NO SIGNAL 0 */  SIGACTION_IGNORE,
55  /* SIGABRT     */  SIGACTION_TERMINATE,
56  /* SIGALRM     */  SIGACTION_TERMINATE,
57  /* SIGFPE      */  SIGACTION_TERMINATE,
58  /* SIGHUP      */  SIGACTION_TERMINATE,
59  /* SIGILL      */  SIGACTION_TERMINATE,
60  /* SIGINT      */  SIGACTION_TERMINATE,
61  /* SIGKILL     */  SIGACTION_TERMINATE,
62  /* SIGPIPE     */  SIGACTION_TERMINATE,
63  /* SIGQUIT     */  SIGACTION_TERMINATE,
64  /* SIGSEGV     */  SIGACTION_TERMINATE,
65  /* SIGTERM     */  SIGACTION_TERMINATE,
66  /* SIGUSR1     */  SIGACTION_TERMINATE,
67  /* SIGUSR2     */  SIGACTION_TERMINATE,
68  /* SIGRTMIN 14 */  SIGACTION_IGNORE,
69  /* SIGRT    15 */  SIGACTION_IGNORE,
70  /* SIGRT    16 */  SIGACTION_IGNORE,
71  /* SIGRT    17 */  SIGACTION_IGNORE,
72  /* SIGRT    18 */  SIGACTION_IGNORE,
73  /* SIGRT    19 */  SIGACTION_IGNORE,
74  /* SIGRT    20 */  SIGACTION_IGNORE,
75  /* SIGRT    21 */  SIGACTION_IGNORE,
76  /* SIGRT    22 */  SIGACTION_IGNORE,
77  /* SIGRT    23 */  SIGACTION_IGNORE,
78  /* SIGRT    24 */  SIGACTION_IGNORE,
79  /* SIGRT    25 */  SIGACTION_IGNORE,
80  /* SIGRT    26 */  SIGACTION_IGNORE,
81  /* SIGRT    27 */  SIGACTION_IGNORE,
82  /* SIGRT    28 */  SIGACTION_IGNORE,
83  /* SIGRT    29 */  SIGACTION_IGNORE,
84  /* SIGRT    30 */  SIGACTION_IGNORE,
85  /* SIGRT    31 */  SIGACTION_IGNORE,
86  /* SIGRTMAX 32 */  SIGACTION_IGNORE
87};
88
89struct sigaction _POSIX_signals_Vectors[ SIG_ARRAY_MAX ];
90
91Watchdog_Control _POSIX_signals_Alarm_timer;
92
93Thread_queue_Control _POSIX_signals_Wait_queue;
94
95typedef struct {
96  Chain_Node  Node;
97  siginfo_t   Info;
98}  POSIX_signals_Siginfo_node;
99
100Chain_Control _POSIX_signals_Inactive_siginfo;
101Chain_Control _POSIX_signals_Siginfo[ SIG_ARRAY_MAX ];
102
103/*PAGE
104 *
105 *  XXX - move these
106 */
107
108#define _States_Is_interruptible_signal( _states ) \
109  ( ((_states) & \
110    (STATES_WAITING_FOR_SIGNAL|STATES_INTERRUPTIBLE_BY_SIGNAL)) == \
111      (STATES_WAITING_FOR_SIGNAL|STATES_INTERRUPTIBLE_BY_SIGNAL))
112
113/*PAGE
114 *
115 *  _POSIX_signals_Unblock_thread
116 */
117
118/* XXX this routine could probably be cleaned up */
119void _POSIX_signals_Unblock_thread(
120  Thread_Control  *the_thread,
121  int              signo,
122  siginfo_t       *info
123)
124{
125  POSIX_API_Control  *api;
126  sigset_t            mask;
127  siginfo_t          *the_info = NULL;
128
129  api = the_thread->API_Extensions[ THREAD_API_POSIX ];
130
131  mask = signo_to_mask( signo );
132
133  /*
134   *  Is the thread is specifically waiting for a signal?
135   */
136
137  if ( _States_Is_interruptible_signal( the_thread->current_state ) ) {
138
139    if ( (the_thread->Wait.option & mask) || (~api->signals_blocked & mask) ) {
140      the_thread->Wait.return_code = EINTR;
141
142      the_info = (siginfo_t *) _Thread_Executing->Wait.return_argument;
143
144      if ( !info ) {
145        the_info->si_signo = signo;
146        the_info->si_code = SI_USER;
147        the_info->si_value.sival_int = 0;
148      } else {
149        *the_info = *info;
150      }
151     
152      _Thread_queue_Extract_with_proxy( the_thread );
153    }
154    return;
155  }
156
157  if ( ~api->signals_blocked & mask ) {
158    the_thread->do_post_task_switch_extension = TRUE;
159
160    if ( the_thread->current_state & STATES_INTERRUPTIBLE_BY_SIGNAL ) {
161      the_thread->Wait.return_code = EINTR;
162      if ( _States_Is_waiting_on_thread_queue(the_thread->current_state) )
163        _Thread_queue_Extract_with_proxy( the_thread );
164      else if ( _States_Is_delaying(the_thread->current_state)){
165        if ( _Watchdog_Is_active( &the_thread->Timer ) )
166          (void) _Watchdog_Remove( &the_thread->Timer );
167        _Thread_Unblock( the_thread );
168      }
169    }
170  }
171
172}
173
174/*PAGE
175 *
176 *  _POSIX_signals_Check_signal
177 */
178
179boolean _POSIX_signals_Check_signal(
180  POSIX_API_Control  *api,
181  int                 signo,
182  boolean             is_global
183)
184{
185  sigset_t            mask;
186  ISR_Level           level;
187  boolean             do_callout;
188  siginfo_t          *siginfo = NULL;  /* really needs to be set below */
189  siginfo_t           siginfo_struct;
190  sigset_t            saved_signals_blocked;
191
192  mask = signo_to_mask( signo );
193
194  do_callout = FALSE;
195
196  /* XXX this is not right for siginfo type signals yet */
197  /* XXX since they can't be cleared the same way */
198
199  _ISR_Disable( level );
200    if ( is_global ) {
201       if ( mask & (_POSIX_signals_Pending & ~api->signals_blocked ) ) {
202         _POSIX_signals_Pending &= ~mask;
203         do_callout = TRUE;
204       }
205    } else {
206      if ( mask & (api->signals_pending & ~api->signals_blocked ) ) {
207        api->signals_pending &= ~mask;
208        do_callout = TRUE;
209      }
210    }
211  _ISR_Enable( level );
212
213  if ( !do_callout )
214    return FALSE;
215
216  /*
217   *  Since we made a union of these, only one test is necessary but this is
218   *  safer.
219   */
220
221  assert( _POSIX_signals_Vectors[ signo ].sa_handler ||
222          _POSIX_signals_Vectors[ signo ].sa_sigaction );
223 
224  /*
225   *  Just to prevent sending a signal which is currently being ignored.
226   */
227
228  if ( _POSIX_signals_Vectors[ signo ].sa_handler == SIG_IGN )
229    return FALSE;
230
231  /*
232   *  Block the signals requested in sa_mask
233   */
234
235  saved_signals_blocked = api->signals_blocked;
236  api->signals_blocked |= _POSIX_signals_Vectors[ signo ].sa_mask;
237
238  switch ( _POSIX_signals_Vectors[ signo ].sa_flags ) {
239    case SA_SIGINFO:
240      assert( 0 );   /* XXX we haven't completely implemented this yet */
241      if ( !is_global ) {
242        siginfo = &siginfo_struct;
243        siginfo->si_signo = signo;
244        siginfo->si_code = SI_USER;
245        siginfo->si_value.sival_int = 0;
246      }
247      (*_POSIX_signals_Vectors[ signo ].sa_sigaction)(
248        signo,
249        siginfo,
250        NULL        /* context is undefined per 1003.1b-1993, p. 66 */
251      );
252      break;
253    default:
254      (*_POSIX_signals_Vectors[ signo ].sa_handler)( signo );
255      break;
256  }
257
258  /*
259   *  Restore the previous set of blocked signals
260   */
261 
262  api->signals_blocked = saved_signals_blocked;
263
264  return TRUE;
265}
266
267void _POSIX_signals_Post_switch_extension(
268  Thread_Control  *the_thread
269)
270{
271  POSIX_API_Control  *api;
272  int                 signo;
273  ISR_Level           level;
274
275  api = the_thread->API_Extensions[ THREAD_API_POSIX ];
276
277  /*
278   *  If we invoke any user code, there is the possibility that
279   *  a new signal has been posted that we should process so we
280   *  restart the loop if a signal handler was invoked.
281   *
282   *  The first thing done is to check there are any signals to be
283   *  processed at all.  No point in doing this loop otherwise.
284   */
285
286restart:
287  _ISR_Disable( level );
288    if ( !(~api->signals_blocked &
289          (api->signals_pending | _POSIX_signals_Pending)) )
290      return;
291  _ISR_Enable( level );
292
293  for ( signo = SIGRTMIN ; signo <= SIGRTMAX ; signo++ ) {
294
295    if ( _POSIX_signals_Check_signal( api, signo, FALSE ) )
296      goto restart;
297
298    if ( _POSIX_signals_Check_signal( api, signo, TRUE ) )
299      goto restart;
300
301  }
302
303  for ( signo = SIGABRT ; signo <= __SIGLASTNOTRT ; signo++ ) {
304
305    if ( _POSIX_signals_Check_signal( api, signo, FALSE ) )
306      goto restart;
307 
308    if ( _POSIX_signals_Check_signal( api, signo, TRUE ) )
309      goto restart;
310
311  }
312
313}
314
315/*PAGE
316 *
317 *  _POSIX_signals_Alarm_TSR
318 */
319 
320void _POSIX_signals_Alarm_TSR(
321  Objects_Id      id,
322  void           *argument
323)
324{
325  kill( getpid(), SIGALRM );
326}
327
328/*PAGE
329 *
330 *  _POSIX_signals_Manager_Initialization
331 */
332
333void _POSIX_signals_Manager_Initialization( void )
334{
335  unsigned32 signo;
336
337  /*
338   *  Insure we have the same number of vectors and default vector entries
339   */
340
341  assert(
342   sizeof(_POSIX_signals_Vectors) == sizeof(_POSIX_signals_Default_vectors)
343  );
344
345  memcpy(
346    _POSIX_signals_Vectors,
347    _POSIX_signals_Default_vectors,
348    sizeof( _POSIX_signals_Vectors )
349  );
350 
351  /*
352   *  Initialize the set of pending signals for the entire process
353   */
354
355  sigemptyset( &_POSIX_signals_Pending );
356
357  /*
358   *  Initialize the timer used to implement alarm().
359   */
360
361  _Watchdog_Initialize(
362    &_POSIX_signals_Alarm_timer,
363    _POSIX_signals_Alarm_TSR,
364    0,
365    NULL
366  );
367 
368  /*
369   *  Initialize the queue we use to block for signals
370   */
371 
372  _Thread_queue_Initialize(
373    &_POSIX_signals_Wait_queue,
374    OBJECTS_NO_CLASS,
375    THREAD_QUEUE_DISCIPLINE_PRIORITY,
376    STATES_WAITING_FOR_SIGNAL | STATES_INTERRUPTIBLE_BY_SIGNAL,
377    NULL,
378    EAGAIN
379  );
380
381  /* XXX status codes */
382  /*
383   *  XXX Allocate the siginfo pools.
384   */
385
386  for ( signo=1 ; signo<= SIGRTMAX ; signo++ )
387    _Chain_Initialize_empty( &_POSIX_signals_Siginfo[ signo ] );
388
389  /* XXX especially the inactive pool */
390}
391
392/*
393 *  3.3.3 Manipulate Signal Sets, P1003.1b-1993, p. 69
394 */
395
396int sigemptyset(
397  sigset_t   *set
398)
399{
400  if ( !set )
401    set_errno_and_return_minus_one( EFAULT );
402
403  *set = 0;
404  return 0;
405}
406
407/*
408 *  3.3.3 Manipulate Signal Sets, P1003.1b-1993, p. 69
409 */
410
411int sigfillset(
412  sigset_t   *set
413)
414{
415  if ( !set )
416    set_errno_and_return_minus_one( EFAULT );
417
418  *set = SIGNAL_ALL_MASK;
419  return 0;
420}
421
422/*
423 *  3.3.3 Manipulate Signal Sets, P1003.1b-1993, p. 69
424 */
425
426int sigaddset(
427  sigset_t   *set,
428  int         signo
429)
430{
431  if ( !set )
432    set_errno_and_return_minus_one( EFAULT );
433
434  if ( !is_valid_signo(signo) )
435    set_errno_and_return_minus_one( EINVAL );
436
437  *set |= signo_to_mask(signo);
438  return 0;
439}
440
441/*
442 *  3.3.3 Manipulate Signal Sets, P1003.1b-1993, p. 69
443 */
444
445int sigdelset(
446  sigset_t   *set,
447  int         signo
448)
449{
450  if ( !set )
451    set_errno_and_return_minus_one( EFAULT );
452 
453  if ( !is_valid_signo(signo) )
454    set_errno_and_return_minus_one( EINVAL );
455 
456  *set &= ~signo_to_mask(signo);
457  return 0;
458}
459
460/*
461 *  3.3.3 Manipulate Signal Sets, P1003.1b-1993, p. 69
462 */
463
464int sigismember(
465  const sigset_t   *set,
466  int               signo
467)
468{
469  if ( !set )
470    set_errno_and_return_minus_one( EFAULT );
471 
472  if ( !is_valid_signo(signo) )
473    set_errno_and_return_minus_one( EINVAL );
474 
475  if ( *set & signo_to_mask(signo) )
476    return 1;
477
478  return 0;
479}
480
481/*
482 *  3.3.4 Examine and Change Signal Action, P1003.1b-1993, p. 70
483 */
484
485int sigaction(
486  int                     sig,
487  const struct sigaction *act,
488  struct sigaction       *oact
489)
490{
491  ISR_Level     level;
492
493  if ( !is_valid_signo(sig) )
494    set_errno_and_return_minus_one( EINVAL );
495 
496  if ( oact )
497    *oact = _POSIX_signals_Vectors[ sig ];
498
499  /*
500   *  Some signals cannot be ignored (P1003.1b-1993, pp. 70-72 and references.
501   *
502   *  NOTE: Solaris documentation claims to "silently enforce" this which
503   *        contradicts the POSIX specification.
504   */
505
506  if ( sig == SIGKILL )
507    set_errno_and_return_minus_one( EINVAL );
508 
509  /*
510   *  Evaluate the new action structure and set the global signal vector
511   *  appropriately.
512   */
513
514  if ( act ) {
515
516    _ISR_Disable( level );
517      if ( act->sa_handler == SIG_DFL ) {
518        _POSIX_signals_Vectors[ sig ] = _POSIX_signals_Default_vectors[ sig ];
519      } else if ( act->sa_handler == SIG_DFL ) {
520        _POSIX_signals_Pending &= ~signo_to_mask( sig );
521      } else {
522        _POSIX_signals_Pending &= ~signo_to_mask( sig );
523        _POSIX_signals_Vectors[ sig ] = *act;
524      }
525    _ISR_Enable( level );
526  }
527
528  /*
529   *  No need to evaluate or dispatch because:
530   *
531   *    + If we were ignoring the signal before, none could be pending
532   *      now (signals not posted when SIG_IGN).
533   *    + If we are now ignoring a signal that was previously pending,
534   *      we clear the pending signal indicator.
535   */
536
537  return 0;
538}
539
540/*
541 *  3.3.5 Examine and Change Blocked Signals, P1003.1b-1993, p. 73
542 *
543 *  NOTE: P1003.1c/D10, p. 37 adds pthread_sigmask().
544 *
545 */
546
547int sigprocmask(
548  int               how,
549  const sigset_t   *set,
550  sigset_t         *oset
551)
552{
553  /*
554   *  P1003.1c/Draft 10, p. 38 maps sigprocmask to pthread_sigmask.
555   */
556
557  return pthread_sigmask( how, set, oset );
558}
559
560/*
561 *  3.3.5 Examine and Change Blocked Signals, P1003.1b-1993, p. 73
562 *
563 *  NOTE: P1003.1c/D10, p. 37 adds pthread_sigmask().
564 */
565
566int pthread_sigmask(
567  int               how,
568  const sigset_t   *set,
569  sigset_t         *oset
570)
571{
572  POSIX_API_Control  *api;
573
574  if ( !set && !oset )
575    set_errno_and_return_minus_one( EFAULT );
576
577  api = _Thread_Executing->API_Extensions[ THREAD_API_POSIX ];
578
579  if ( oset )
580    *oset = api->signals_blocked;
581 
582  if ( !set )
583    set_errno_and_return_minus_one( EFAULT );
584
585  switch ( how ) {
586    case SIG_BLOCK:
587      api->signals_blocked |= *set;
588      break;
589    case SIG_UNBLOCK:
590      api->signals_blocked &= ~*set;
591      break;
592    case SIG_SETMASK:
593      api->signals_blocked = *set;
594      break;
595    default:
596      set_errno_and_return_minus_one( EINVAL );
597  }
598
599  /* XXX are there critical section problems here? */
600
601  /* XXX evaluate the new set */
602
603  if ( ~api->signals_blocked &
604       (api->signals_pending | _POSIX_signals_Pending) ) {
605    _Thread_Executing->do_post_task_switch_extension = TRUE;
606    _Thread_Dispatch();
607  }
608
609  return 0;
610}
611
612/*
613 *  3.3.6 Examine Pending Signals, P1003.1b-1993, p. 75
614 */
615
616int sigpending(
617  sigset_t  *set
618)
619{
620  POSIX_API_Control  *api;
621 
622  if ( !set )
623    set_errno_and_return_minus_one( EFAULT );
624 
625  api = _Thread_Executing->API_Extensions[ THREAD_API_POSIX ];
626 
627  *set = api->signals_pending | _POSIX_signals_Pending;
628 
629  return 0;
630}
631
632/*
633 *  3.3.7 Wait for a Signal, P1003.1b-1993, p. 75
634 */
635
636int sigsuspend(
637  const sigset_t  *sigmask
638)
639{
640  sigset_t            saved_signals_blocked;
641  sigset_t            all_signals;
642  int                 status;
643  POSIX_API_Control  *api;
644
645  api = _Thread_Executing->API_Extensions[ THREAD_API_POSIX ];
646
647  saved_signals_blocked = api->signals_blocked;
648 
649  (void) sigfillset( &all_signals );
650
651  status = sigtimedwait( &all_signals, NULL, NULL );
652
653  api->signals_blocked = saved_signals_blocked;
654
655  return status;
656}
657
658/*
659 *  3.3.8 Synchronously Accept a Signal, P1003.1b-1993, p. 76
660 *
661 *  NOTE: P1003.1c/D10, p. 39 adds sigwait().
662 */
663
664int sigwaitinfo(
665  const sigset_t  *set,
666  siginfo_t       *info
667)
668{
669  return sigtimedwait( set, info, NULL );
670}
671
672/*
673 *  3.3.8 Synchronously Accept a Signal, P1003.1b-1993, p. 76
674 *
675 *  NOTE: P1003.1c/D10, p. 39 adds sigwait().
676 */
677
678int _POSIX_signals_Get_highest(
679  sigset_t   set
680)
681{
682  int signo;
683 
684  for ( signo = SIGRTMIN ; signo <= SIGRTMAX ; signo++ ) {
685    if ( set & signo_to_mask( signo ) )
686      return signo;
687  }
688 
689  for ( signo = SIGABRT ; signo <= __SIGLASTNOTRT ; signo++ ) {
690    if ( set & signo_to_mask( signo ) )
691      return signo;
692  }
693
694  return 0;
695}
696 
697
698int sigtimedwait(
699  const sigset_t         *set,
700  siginfo_t              *info,
701  const struct timespec  *timeout
702)
703{
704  Thread_Control    *the_thread;
705  POSIX_API_Control *api;
706  Watchdog_Interval  interval;
707  siginfo_t          signal_information;
708  siginfo_t         *the_info;
709 
710  interval = 0;
711  if ( timeout ) {
712
713    if (timeout->tv_nsec < 0 || timeout->tv_nsec >= TOD_NANOSECONDS_PER_SECOND)
714      set_errno_and_return_minus_one( EINVAL );
715
716    interval = _POSIX_Timespec_to_interval( timeout );
717  }
718
719  the_info = ( info ) ? info : &signal_information;
720
721  the_thread = _Thread_Executing;
722
723  api = the_thread->API_Extensions[ THREAD_API_POSIX ];
724
725  /*
726   *  What if they are already pending?
727   */
728
729  if ( *set & api->signals_pending ) {
730    /* XXX real info later */
731    the_info->si_signo = _POSIX_signals_Get_highest( api->signals_pending );
732    the_info->si_code = SI_USER;
733    the_info->si_value.sival_int = 0;
734  }
735
736  _Thread_Disable_dispatch();
737    the_thread->Wait.return_code     = EINTR;
738    the_thread->Wait.option          = *set;
739    the_thread->Wait.return_argument = (void *) the_info;
740    _Thread_queue_Enter_critical_section( &_POSIX_signals_Wait_queue );
741    _Thread_queue_Enqueue( &_POSIX_signals_Wait_queue, interval );
742  _Thread_Enable_dispatch();
743
744  errno = _Thread_Executing->Wait.return_code;
745  return the_info->si_signo;
746}
747
748/*
749 *  3.3.8 Synchronously Accept a Signal, P1003.1b-1993, p. 76
750 *
751 *  NOTE: P1003.1c/D10, p. 39 adds sigwait().
752 */
753
754int sigwait(
755  const sigset_t  *set,
756  int             *sig
757)
758{
759  int status;
760
761  status = sigtimedwait( set, NULL, NULL );
762
763  if ( status != -1 ) {
764    if ( sig )
765      *sig = status;
766    return 0;
767  }
768
769  return errno;
770}
771
772/*
773 *  3.3.9 Queue a Signal to a Process, P1003.1b-1993, p. 78
774 */
775
776int sigqueue(
777  pid_t               pid,
778  int                 signo,
779  const union sigval  value
780)
781{
782  return POSIX_NOT_IMPLEMENTED();
783}
784
785/*
786 *  3.3.2 Send a Signal to a Process, P1003.1b-1993, p. 68
787 *
788 *  NOTE: Behavior of kill() depends on _POSIX_SAVED_IDS.
789 */
790
791#define _POSIX_signals_Is_interested( _api, _mask ) \
792  ( ~(_api)->signals_blocked & (_mask) )
793         
794int kill(
795  pid_t pid,
796  int   sig
797)
798{
799  sigset_t              mask;
800  POSIX_API_Control    *api;
801  unsigned32            the_class;
802  unsigned32            index;
803  unsigned32            maximum;
804  Objects_Information  *the_info;
805  Objects_Control     **object_table;
806  Thread_Control       *the_thread;
807  Thread_Control       *interested_thread;
808  Priority_Control      interested_priority;
809  Chain_Control        *the_chain;
810  Chain_Node           *the_node;
811 
812  /*
813   *  Only supported for the "calling process" (i.e. this node).
814   */
815 
816  if( pid != getpid() )
817    set_errno_and_return_minus_one( ESRCH );
818
819  /*
820   *  If the signal is being ignored, then we are out of here.
821   */
822
823  if ( !sig || _POSIX_signals_Vectors[ sig ].sa_handler == SIG_IGN )
824    return 0;
825
826  /*
827   *  P1003.1c/Draft 10, p. 33 says that certain signals should always
828   *  be directed to the executing thread such as those caused by hardware
829   *  faults.
830   */
831
832  switch ( sig ) {
833    case SIGFPE:
834    case SIGILL:
835    case SIGSEGV:
836      return pthread_kill( pthread_self(), sig );
837    default:
838      break;
839  }
840
841  mask = signo_to_mask( sig );
842
843  _Thread_Disable_dispatch();
844
845  /*
846   *  Is the currently executing thread interested?  If so then it will
847   *  get it an execute it as soon as the dispatcher executes.
848   */
849
850  the_thread = _Thread_Executing;
851
852  api = the_thread->API_Extensions[ THREAD_API_POSIX ];
853  if ( _POSIX_signals_Is_interested( api, mask ) ) {
854    _POSIX_signals_Pending |= mask;
855    goto process_it;
856  }
857
858  /*
859   *  Is an interested thread waiting for this signal (sigwait())?
860   */
861
862  /* XXX violation of visibility -- need to define thread queue support */
863
864  for( index=0 ;
865       index < TASK_QUEUE_DATA_NUMBER_OF_PRIORITY_HEADERS ;
866       index++ ) {
867
868    the_chain = &_POSIX_signals_Wait_queue.Queues.Priority[ index ];
869 
870    for ( the_node = the_chain->first ;
871          !_Chain_Is_tail( the_chain, the_node ) ;
872          the_node = the_node->next ) {
873
874      the_thread = (Thread_Control *)the_node;
875      api = the_thread->API_Extensions[ THREAD_API_POSIX ];
876
877      if ((the_thread->Wait.option & mask) || (~api->signals_blocked & mask)) {
878        goto process_it;
879      }
880
881    }
882  }
883
884  /*
885   *  Since we did not deliver the signal to the current thread or to a
886   *  specific thread via sigwait() we will mark it as pending.
887   */
888
889  _POSIX_signals_Pending |= mask;
890
891  /*
892   *  Is any other thread interested?  The highest priority interested
893   *  thread is selected.  In the event of a tie, then the following
894   *  additional criteria is used:
895   *
896   *    + ready thread over blocked
897   *    + blocked on call interruptible by signal (can return EINTR)
898   *    + blocked on call not interruptible by signal
899   *
900   *  This looks at every thread in the system regardless of the creating API.
901   *
902   *  NOTES:
903   *
904   *    + rtems internal threads do not receive signals.
905   */
906
907  interested_thread = NULL;
908  interested_priority = PRIORITY_MAXIMUM + 1;
909
910  for ( the_class = OBJECTS_CLASSES_FIRST_THREAD_CLASS;
911        the_class <= OBJECTS_CLASSES_LAST_THREAD_CLASS;
912        the_class++ ) {
913
914    if ( the_class == OBJECTS_INTERNAL_THREADS )
915      continue;
916
917    the_info = _Objects_Information_table[ the_class ];
918
919    if ( !the_info )                        /* manager not installed */
920      continue;
921
922    maximum = the_info->maximum;
923    object_table = the_info->local_table;
924
925    assert( object_table );                 /* always at least 1 entry */
926
927    object_table++;                         /* skip entry 0 */
928
929    for ( index = 1 ; index <= maximum ; index++ ) {
930      the_thread = (Thread_Control *) object_table[ index ];
931
932      if ( !the_thread )
933        continue;
934
935      /*
936       *  If this thread is of lower priority than the interested thread,
937       *  go on to the next thread.
938       */
939
940      if ( the_thread->current_priority > interested_priority )
941        continue;
942
943      /*
944       *  If this thread is not interested, then go on to the next thread.
945       */
946
947      api = the_thread->API_Extensions[ THREAD_API_POSIX ];
948
949      if ( !api || !_POSIX_signals_Is_interested( api, mask ) )
950        continue;
951
952      /*
953       *  Now we know the thread under connsideration is interested.
954       *  If the thread under consideration is of higher priority, then
955       *  it becomes the interested thread.
956       */
957
958      if ( the_thread->current_priority < interested_priority ) {
959        interested_thread   = the_thread;
960        interested_priority = the_thread->current_priority;
961        continue;
962      }
963
964      /*
965       *  Now the thread and the interested thread have the same priority.
966       *  If the interested thread is ready, then we don't need to send it
967       *  to a blocked thread.
968       */
969
970      if ( _States_Is_ready( interested_thread->current_state ) )
971        continue;
972
973      /*
974       *  Now the interested thread is blocked.
975       *  If the thread we are considering is not, the it becomes the
976       *  interested thread.
977       */
978
979      if ( _States_Is_ready( the_thread->current_state ) ) {
980        interested_thread   = the_thread;
981        interested_priority = the_thread->current_priority;
982        continue;
983      }
984
985      /*
986       *  Now we know both threads are blocked.
987       *  If the interested thread is interruptible, then just use it.
988       */
989
990      /* XXX need a new states macro */
991      if ( interested_thread->current_state & STATES_INTERRUPTIBLE_BY_SIGNAL )
992        continue;
993
994      /*
995       *  Now both threads are blocked and the interested thread is not
996       *  interruptible.
997       *  If the thread under consideration is interruptible by a signal,
998       *  then it becomes the interested thread.
999       */
1000
1001      /* XXX need a new states macro */
1002      if ( the_thread->current_state & STATES_INTERRUPTIBLE_BY_SIGNAL ) {
1003        interested_thread   = the_thread;
1004        interested_priority = the_thread->current_priority;
1005      }
1006    }
1007  }
1008
1009  if ( interested_thread ) {
1010    the_thread = interested_thread;
1011    goto process_it;
1012  }
1013
1014  /*
1015   *  OK so no threads were interested right now.  It will be left on the
1016   *  global pending until a thread receives it.  The global set of threads
1017   *  can change interest in this signal in one of the following ways:
1018   *
1019   *    + a thread is created with the signal unblocked,
1020   *    + pthread_sigmask() unblocks the signal,
1021   *    + sigprocmask() unblocks the signal, OR
1022   *    + sigaction() which changes the handler to SIG_IGN.
1023   */
1024
1025  _Thread_Enable_dispatch();
1026  return 0;
1027
1028  /*
1029   *  We found a thread which was interested, so now we mark that this
1030   *  thread needs to do the post context switch extension so it can
1031   *  evaluate the signals pending.
1032   */
1033
1034process_it:
1035 
1036  api = the_thread->API_Extensions[ THREAD_API_POSIX ];
1037
1038  the_thread->do_post_task_switch_extension = TRUE;
1039
1040  _POSIX_signals_Unblock_thread( the_thread, sig, NULL );
1041
1042  _Thread_Enable_dispatch();
1043
1044   /* XXX take this out when a little more confident */
1045  /* SIGABRT comes from abort via assert and must work no matter what */
1046  if ( sig == SIGABRT ) {
1047    exit( 1 );
1048  }
1049  return 0;
1050}
1051
1052/*
1053 *  3.3.10 Send a Signal to a Thread, P1003.1c/D10, p. 43
1054 */
1055
1056int pthread_kill(
1057  pthread_t   thread,
1058  int         sig
1059)
1060{
1061  POSIX_API_Control  *api;
1062  Thread_Control     *the_thread;
1063  Objects_Locations  location;
1064
1065  if ( sig && !is_valid_signo(sig) )
1066    set_errno_and_return_minus_one( EINVAL );
1067
1068  if ( _POSIX_signals_Vectors[ sig ].sa_handler == SIG_IGN )
1069    return 0;
1070
1071  the_thread = _POSIX_Threads_Get( thread, &location );
1072  switch ( location ) {
1073    case OBJECTS_ERROR:
1074    case OBJECTS_REMOTE:
1075      return ESRCH;
1076    case OBJECTS_LOCAL:
1077      /*
1078       *  If sig == 0 then just validate arguments
1079       */
1080
1081      api = the_thread->API_Extensions[ THREAD_API_POSIX ];
1082
1083      if ( sig ) {
1084
1085        /* XXX critical section */
1086
1087        api->signals_pending |= signo_to_mask( sig );
1088
1089        _POSIX_signals_Unblock_thread( the_thread, sig, NULL );
1090    }
1091    _Thread_Enable_dispatch();
1092    return 0;
1093  }
1094
1095  return POSIX_BOTTOM_REACHED();
1096}
1097
1098/*
1099 *  3.4.1 Schedule Alarm, P1003.1b-1993, p. 79
1100 */
1101
1102Watchdog_Control _POSIX_signals_Alarm_timer;
1103
1104unsigned int alarm(
1105  unsigned int seconds
1106)
1107{
1108  unsigned int      remaining = 0;
1109  Watchdog_Control *the_timer;
1110
1111  the_timer = &_POSIX_signals_Alarm_timer;
1112
1113  switch ( _Watchdog_Remove( the_timer ) ) {
1114    case WATCHDOG_INACTIVE:
1115    case WATCHDOG_BEING_INSERTED:
1116      break;
1117 
1118    case WATCHDOG_ACTIVE:
1119    case WATCHDOG_REMOVE_IT:
1120      remaining = the_timer->initial -
1121                  (the_timer->stop_time - the_timer->start_time);
1122      break;
1123  }
1124
1125  _Watchdog_Insert_seconds( the_timer, seconds );
1126
1127  return remaining;
1128}
1129
1130/*
1131 *  3.4.2 Suspend Process Execution, P1003.1b-1993, p. 81
1132 */
1133
1134int pause( void )
1135{
1136  sigset_t  all_signals;
1137  int       status;
1138 
1139  (void) sigfillset( &all_signals );
1140 
1141  status = sigtimedwait( &all_signals, NULL, NULL );
1142 
1143  return status;
1144}
Note: See TracBrowser for help on using the repository browser.