source: rtems/cpukit/posix/src/psignal.c @ 948721c

4.104.114.84.95
Last change on this file since 948721c was 948721c, checked in by Mark Johannes <Mark.Johannes@…>, on 08/15/96 at 16:24:44

pthread_kill: moved check for SA_SIGINFO to allow for validation of all
parameters. Also changed returns to macro of -1 and errno set.

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