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

4.104.114.84.95
Last change on this file since df3e78a was df3e78a, checked in by Joel Sherrill <joel.sherrill@…>, on Apr 19, 1999 at 3:54:03 PM

The default action for real-time signals is supposed to be SIGACTION_TERMINATE.
Jiri Gaisler caught this and submitted a patch but a subsequent patch
backed it out accidentally.

  • Property mode set to 100644
File size: 21.8 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/psignal.h>
18#include <rtems/posix/pthread.h>
19#include <rtems/posix/time.h>
20#include <stdio.h>
21
22
23/*
24 *  Currently 32 signals numbered 1-32 are defined
25 */
26
27#define SIGNAL_EMPTY_MASK  0x00000000
28#define SIGNAL_ALL_MASK    0xffffffff
29
30#define signo_to_mask( _sig ) (1 << ((_sig) - 1))
31
32#define is_valid_signo( _sig ) \
33  ((_sig) >= 1 && (_sig) <= 32 )
34
35/*** PROCESS WIDE STUFF ****/
36
37sigset_t  _POSIX_signals_Pending;
38
39void _POSIX_signals_Abnormal_termination_handler( int signo )
40{
41  exit( 1 );
42}
43
44#define SIG_ARRAY_MAX  (SIGRTMAX + 1)
45struct sigaction _POSIX_signals_Default_vectors[ SIG_ARRAY_MAX ] = {
46  /* NO SIGNAL 0 */  SIGACTION_IGNORE,
47  /* SIGHUP    1 */  SIGACTION_TERMINATE,
48  /* SIGINT    2 */  SIGACTION_TERMINATE,
49  /* SIGQUIT   3 */  SIGACTION_TERMINATE,
50  /* SIGILL    4 */  SIGACTION_TERMINATE,
51  /* SIGTRAP   5 */  SIGACTION_TERMINATE,
52  /* SIGIOT    6 */  SIGACTION_TERMINATE,
53  /* SIGABRT   6     SIGACTION_TERMINATE, -- alias for SIGIOT */
54  /* SIGEMT    7 */  SIGACTION_TERMINATE,
55  /* SIGFPE    8 */  SIGACTION_TERMINATE,
56  /* SIGKILL   9 */  SIGACTION_TERMINATE,
57  /* SIGBUS   10 */  SIGACTION_TERMINATE,
58  /* SIGSEGV  11 */  SIGACTION_TERMINATE,
59  /* SIGSYS   12 */  SIGACTION_TERMINATE,
60  /* SIGPIPE  13 */  SIGACTION_TERMINATE,
61  /* SIGALRM  14 */  SIGACTION_TERMINATE,
62  /* SIGTERM  15 */  SIGACTION_TERMINATE,
63  /* SIGUSR1  16 */  SIGACTION_TERMINATE,
64  /* SIGUSR2  17 */  SIGACTION_TERMINATE,
65  /* SIGRTMIN 18 */  SIGACTION_TERMINATE,
66  /* SIGRT    19 */  SIGACTION_TERMINATE,
67  /* SIGRT    20 */  SIGACTION_TERMINATE,
68  /* SIGRT    21 */  SIGACTION_TERMINATE,
69  /* SIGRT    22 */  SIGACTION_TERMINATE,
70  /* SIGRT    23 */  SIGACTION_TERMINATE,
71  /* SIGRT    24 */  SIGACTION_TERMINATE,
72  /* SIGRT    25 */  SIGACTION_TERMINATE,
73  /* SIGRT    26 */  SIGACTION_TERMINATE,
74  /* SIGRT    27 */  SIGACTION_TERMINATE,
75  /* SIGRT    28 */  SIGACTION_TERMINATE,
76  /* SIGRT    29 */  SIGACTION_TERMINATE,
77  /* SIGRT    30 */  SIGACTION_TERMINATE,
78  /* SIGRT    31 */  SIGACTION_TERMINATE,
79  /* SIGRTMAX 32 */  SIGACTION_TERMINATE
80};
81
82struct sigaction _POSIX_signals_Vectors[ SIG_ARRAY_MAX ];
83
84Watchdog_Control _POSIX_signals_Alarm_timer;
85
86Thread_queue_Control _POSIX_signals_Wait_queue;
87
88Chain_Control _POSIX_signals_Inactive_siginfo;
89Chain_Control _POSIX_signals_Siginfo[ SIG_ARRAY_MAX ];
90
91/*PAGE
92 *
93 *  XXX - move these
94 */
95
96#define _States_Is_interruptible_signal( _states ) \
97  ( ((_states) & \
98    (STATES_WAITING_FOR_SIGNAL|STATES_INTERRUPTIBLE_BY_SIGNAL)) == \
99      (STATES_WAITING_FOR_SIGNAL|STATES_INTERRUPTIBLE_BY_SIGNAL))
100
101/*PAGE
102 *
103 *  _POSIX_signals_Unblock_thread
104 */
105
106/* XXX this routine could probably be cleaned up */
107boolean _POSIX_signals_Unblock_thread( 
108  Thread_Control  *the_thread,
109  int              signo,
110  siginfo_t       *info
111)
112{
113  POSIX_API_Control  *api;
114  sigset_t            mask;
115  siginfo_t          *the_info = NULL;
116
117  api = the_thread->API_Extensions[ THREAD_API_POSIX ];
118
119  mask = signo_to_mask( signo );
120
121  /*
122   *  Is the thread is specifically waiting for a signal?
123   */
124
125  if ( _States_Is_interruptible_signal( the_thread->current_state ) ) {
126
127    if ( (the_thread->Wait.option & mask) || (~api->signals_blocked & mask) ) {
128      the_thread->Wait.return_code = EINTR;
129
130      the_info = (siginfo_t *) the_thread->Wait.return_argument;
131
132      if ( !info ) {
133        the_info->si_signo = signo;
134        the_info->si_code = SI_USER;
135        the_info->si_value.sival_int = 0;
136      } else {
137        *the_info = *info;
138      }
139     
140      _Thread_queue_Extract_with_proxy( the_thread );
141      return TRUE;
142    }
143
144    /*
145     *  This should only be reached via pthread_kill().
146     */
147
148    return FALSE;
149  }
150
151  if ( ~api->signals_blocked & mask ) {
152    the_thread->do_post_task_switch_extension = TRUE;
153
154    if ( the_thread->current_state & STATES_INTERRUPTIBLE_BY_SIGNAL ) {
155      the_thread->Wait.return_code = EINTR;
156      if ( _States_Is_waiting_on_thread_queue(the_thread->current_state) )
157        _Thread_queue_Extract_with_proxy( the_thread );
158      else if ( _States_Is_delaying(the_thread->current_state)){
159        if ( _Watchdog_Is_active( &the_thread->Timer ) )
160          (void) _Watchdog_Remove( &the_thread->Timer );
161        _Thread_Unblock( the_thread );
162      }
163    }
164  }
165  return FALSE;
166
167}
168
169/*PAGE
170 *
171 *  _POSIX_signals_Set_process_signals
172 */
173 
174void _POSIX_signals_Set_process_signals(
175  sigset_t   mask
176)
177{
178  ISR_Level  level;
179 
180  _ISR_Disable( level );
181    if ( !_POSIX_signals_Pending )
182      _Thread_Do_post_task_switch_extension++;
183    _POSIX_signals_Pending |= mask;
184  _ISR_Enable( level );
185}
186
187/*PAGE
188 *
189 *  _POSIX_signals_Clear_process_signals
190 */
191
192void _POSIX_signals_Clear_process_signals(
193  sigset_t   mask
194)
195{
196  ISR_Level  level;
197
198  _ISR_Disable( level );
199    _POSIX_signals_Pending &= ~mask;
200    if ( !_POSIX_signals_Pending )
201      _Thread_Do_post_task_switch_extension--;
202  _ISR_Enable( level );
203}
204
205/*PAGE
206 *
207 *  _POSIX_signals_Clear_signals
208 */
209 
210boolean _POSIX_signals_Clear_signals(
211  POSIX_API_Control  *api,
212  int                 signo,
213  siginfo_t          *info,
214  boolean             is_global,
215  boolean             check_blocked
216)
217{
218  sigset_t                    mask;
219  sigset_t                    signals_blocked;
220  ISR_Level                   level;
221  boolean                     do_callout;
222  POSIX_signals_Siginfo_node *psiginfo;
223 
224  mask = signo_to_mask( signo );
225 
226  do_callout = FALSE;
227 
228  /* set blocked signals based on if checking for them, SIGNAL_ALL_MASK
229   * insures that no signals are blocked and all are checked.
230   */
231
232  if ( check_blocked )
233    signals_blocked = ~api->signals_blocked;
234  else
235    signals_blocked = SIGNAL_ALL_MASK;
236
237  /* XXX this is not right for siginfo type signals yet */
238  /* XXX since they can't be cleared the same way */
239 
240  _ISR_Disable( level );
241    if ( is_global ) {
242       if ( mask & (_POSIX_signals_Pending & signals_blocked) ) {
243         if ( _POSIX_signals_Vectors[ signo ].sa_flags == SA_SIGINFO ) {
244           psiginfo = (POSIX_signals_Siginfo_node *)
245             _Chain_Get_unprotected( &_POSIX_signals_Siginfo[ signo ] );
246           if ( _Chain_Is_empty( &_POSIX_signals_Siginfo[ signo ] ) )
247             _POSIX_signals_Clear_process_signals( mask );
248           if ( psiginfo ) {
249             *info = psiginfo->Info;
250             _Chain_Append_unprotected(
251               &_POSIX_signals_Inactive_siginfo,
252               &psiginfo->Node
253             );
254           } else
255             do_callout = FALSE;
256         } else
257           _POSIX_signals_Clear_process_signals( mask );
258         do_callout = TRUE;
259       }
260    } else {
261      if ( mask & (api->signals_pending & signals_blocked) ) {
262        api->signals_pending &= ~mask;
263        do_callout = TRUE;
264      }
265    }
266  _ISR_Enable( level );
267  return do_callout; 
268}
269
270
271/*PAGE
272 *
273 *  _POSIX_signals_Check_signal
274 */
275
276boolean _POSIX_signals_Check_signal(
277  POSIX_API_Control  *api,
278  int                 signo,
279  boolean             is_global
280)
281{
282  siginfo_t                   siginfo_struct;
283  sigset_t                    saved_signals_blocked;
284
285  if ( ! _POSIX_signals_Clear_signals( api, signo, &siginfo_struct,
286                                       is_global, TRUE ) )
287    return FALSE;
288
289  /*
290   *  Since we made a union of these, only one test is necessary but this is
291   *  safer.
292   */ 
293
294  assert( _POSIX_signals_Vectors[ signo ].sa_handler ||
295          _POSIX_signals_Vectors[ signo ].sa_sigaction );
296 
297  /*
298   *  Just to prevent sending a signal which is currently being ignored.
299   */
300
301  if ( _POSIX_signals_Vectors[ signo ].sa_handler == SIG_IGN )
302    return FALSE;
303
304  /*
305   *  Block the signals requested in sa_mask
306   */
307
308  saved_signals_blocked = api->signals_blocked;
309  api->signals_blocked |= _POSIX_signals_Vectors[ signo ].sa_mask;
310
311  /* Here, the signal handler function executes */
312
313  switch ( _POSIX_signals_Vectors[ signo ].sa_flags ) {
314    case SA_SIGINFO:
315/*
316 *
317 *     assert( is_global );
318 */
319      (*_POSIX_signals_Vectors[ signo ].sa_sigaction)(
320        signo,
321        &siginfo_struct,
322        NULL        /* context is undefined per 1003.1b-1993, p. 66 */
323      );
324      break;
325    default:
326      (*_POSIX_signals_Vectors[ signo ].sa_handler)( signo );
327      break;
328  }
329
330  /*
331   *  Restore the previous set of blocked signals
332   */
333 
334  api->signals_blocked = saved_signals_blocked;
335
336  return TRUE;
337}
338
339void _POSIX_signals_Post_switch_extension(
340  Thread_Control  *the_thread
341)
342{
343  POSIX_API_Control  *api;
344  int                 signo;
345  ISR_Level           level;
346
347  api = the_thread->API_Extensions[ THREAD_API_POSIX ];
348
349  /*
350   *  If we invoke any user code, there is the possibility that
351   *  a new signal has been posted that we should process so we
352   *  restart the loop if a signal handler was invoked.
353   *
354   *  The first thing done is to check there are any signals to be
355   *  processed at all.  No point in doing this loop otherwise.
356   */
357
358restart:
359  _ISR_Disable( level );
360    if ( !(~api->signals_blocked & 
361          (api->signals_pending | _POSIX_signals_Pending)) ) {
362     _ISR_Enable( level );
363     return;
364   }
365  _ISR_Enable( level );
366
367  for ( signo = SIGRTMIN ; signo <= SIGRTMAX ; signo++ ) {
368
369    if ( _POSIX_signals_Check_signal( api, signo, FALSE ) )
370      goto restart;
371
372    if ( _POSIX_signals_Check_signal( api, signo, TRUE ) )
373      goto restart;
374
375  }
376
377/* XXX - add __SIGFIRSTNOTRT or something like that to newlib siginfo.h */
378
379  for ( signo = SIGHUP ; signo <= __SIGLASTNOTRT ; signo++ ) {
380
381    if ( _POSIX_signals_Check_signal( api, signo, FALSE ) )
382      goto restart;
383 
384    if ( _POSIX_signals_Check_signal( api, signo, TRUE ) )
385      goto restart;
386
387  }
388
389}
390
391/*PAGE
392 *
393 *  _POSIX_signals_Alarm_TSR
394 */
395 
396void _POSIX_signals_Alarm_TSR(
397  Objects_Id      id,
398  void           *argument
399)
400{
401  int status;
402
403  status = kill( getpid(), SIGALRM );
404  /* XXX can't print from an ISR, should this be fatal? */
405  assert( !status );
406}
407
408/*PAGE
409 *
410 *  _POSIX_signals_Manager_Initialization
411 */
412
413void _POSIX_signals_Manager_Initialization(
414  int  maximum_queued_signals
415)
416{
417  unsigned32 signo;
418
419  /*
420   *  Insure we have the same number of vectors and default vector entries
421   */
422
423  assert(
424   sizeof(_POSIX_signals_Vectors) == sizeof(_POSIX_signals_Default_vectors)
425  );
426
427  memcpy( 
428    _POSIX_signals_Vectors,
429    _POSIX_signals_Default_vectors,
430    sizeof( _POSIX_signals_Vectors )
431  );
432 
433  /*
434   *  Initialize the set of pending signals for the entire process
435   */
436
437  sigemptyset( &_POSIX_signals_Pending );
438
439  /*
440   *  Initialize the timer used to implement alarm().
441   */
442
443  _Watchdog_Initialize(
444    &_POSIX_signals_Alarm_timer,
445    _POSIX_signals_Alarm_TSR,
446    0,
447    NULL
448  );
449 
450  /*
451   *  Initialize the queue we use to block for signals
452   */
453 
454  _Thread_queue_Initialize(
455    &_POSIX_signals_Wait_queue,
456    OBJECTS_NO_CLASS,
457    THREAD_QUEUE_DISCIPLINE_PRIORITY,
458    STATES_WAITING_FOR_SIGNAL | STATES_INTERRUPTIBLE_BY_SIGNAL,
459    NULL,
460    EAGAIN
461  );
462
463  /* XXX status codes */
464
465  /*
466   *  Allocate the siginfo pools.
467   */
468
469  for ( signo=1 ; signo<= SIGRTMAX ; signo++ )
470    _Chain_Initialize_empty( &_POSIX_signals_Siginfo[ signo ] );
471
472  _Chain_Initialize(
473    &_POSIX_signals_Inactive_siginfo,
474    _Workspace_Allocate_or_fatal_error(
475      maximum_queued_signals * sizeof( POSIX_signals_Siginfo_node )
476    ),
477    maximum_queued_signals,
478    sizeof( POSIX_signals_Siginfo_node )
479  );
480}
481
482/*
483 *  3.3.3 Manipulate Signal Sets, P1003.1b-1993, p. 69
484 */
485
486int sigemptyset(
487  sigset_t   *set
488)
489{
490  if ( !set )
491    set_errno_and_return_minus_one( EINVAL );
492
493  *set = 0;
494  return 0;
495}
496
497/*
498 *  3.3.3 Manipulate Signal Sets, P1003.1b-1993, p. 69
499 */
500
501int sigfillset(
502  sigset_t   *set
503)
504{
505  if ( !set )
506    set_errno_and_return_minus_one( EINVAL );
507
508  *set = SIGNAL_ALL_MASK;
509  return 0;
510}
511
512/*
513 *  3.3.3 Manipulate Signal Sets, P1003.1b-1993, p. 69
514 */
515
516int sigaddset(
517  sigset_t   *set,
518  int         signo
519)
520{
521  if ( !set )
522    set_errno_and_return_minus_one( EINVAL );
523
524  if ( !signo )
525    return 0;
526
527  if ( !is_valid_signo(signo) )
528    set_errno_and_return_minus_one( EINVAL );
529
530  *set |= signo_to_mask(signo);
531  return 0;
532}
533
534/*
535 *  3.3.3 Manipulate Signal Sets, P1003.1b-1993, p. 69
536 */
537
538int sigdelset(
539  sigset_t   *set,
540  int         signo
541)
542{
543  if ( !set )
544    set_errno_and_return_minus_one( EINVAL );
545 
546  if ( !signo )
547    return 0;
548
549  if ( !is_valid_signo(signo) )
550    set_errno_and_return_minus_one( EINVAL );
551 
552  *set &= ~signo_to_mask(signo);
553  return 0;
554}
555
556/*
557 *  3.3.3 Manipulate Signal Sets, P1003.1b-1993, p. 69
558 */
559
560int sigismember(
561  const sigset_t   *set,
562  int               signo
563)
564{
565  if ( !set ) 
566    set_errno_and_return_minus_one( EINVAL );
567 
568  if ( !signo )
569    return 0;
570
571  if ( !is_valid_signo(signo) )
572    set_errno_and_return_minus_one( EINVAL );
573 
574  if ( *set & signo_to_mask(signo) )
575    return 1;
576
577  return 0;
578}
579
580/*
581 *  3.3.4 Examine and Change Signal Action, P1003.1b-1993, p. 70
582 */
583
584/* ***************************************************************************
585 * The signal handler is notified to the timers manager when the
586 * timer is set. So, the timers manager knows the signal handler.
587 * ***************************************************************************/
588
589int sigaction(
590  int                     sig,
591  const struct sigaction *act,
592  struct sigaction       *oact
593)
594{
595  ISR_Level     level;
596
597 
598  if ( oact )
599    *oact = _POSIX_signals_Vectors[ sig ];
600
601  if ( !sig )
602    return 0;
603
604  if ( !is_valid_signo(sig) )
605    set_errno_and_return_minus_one( EINVAL );
606 
607  /*
608   *  Some signals cannot be ignored (P1003.1b-1993, pp. 70-72 and references.
609   *
610   *  NOTE: Solaris documentation claims to "silently enforce" this which
611   *        contradicts the POSIX specification.
612   */
613
614  if ( sig == SIGKILL )
615    set_errno_and_return_minus_one( EINVAL );
616 
617  /*
618   *  Evaluate the new action structure and set the global signal vector
619   *  appropriately.
620   */
621
622  if ( act ) {
623
624    /*
625     *  Unless the user is installing the default signal actions, then
626     *  we can just copy the provided sigaction structure into the vectors.
627     */
628
629    _ISR_Disable( level );
630      if ( act->sa_handler == SIG_DFL ) {
631        _POSIX_signals_Vectors[ sig ] = _POSIX_signals_Default_vectors[ sig ];
632      } else {
633         _POSIX_signals_Clear_process_signals( signo_to_mask(sig) );
634         _POSIX_signals_Vectors[ sig ] = *act;
635      } 
636    _ISR_Enable( level );
637  }
638
639  /*
640   *  No need to evaluate or dispatch because:
641   *
642   *    + If we were ignoring the signal before, none could be pending
643   *      now (signals not posted when SIG_IGN).
644   *    + If we are now ignoring a signal that was previously pending,
645   *      we clear the pending signal indicator.
646   */
647
648  return 0;
649}
650
651/*
652 *  3.3.5 Examine and Change Blocked Signals, P1003.1b-1993, p. 73
653 *
654 *  NOTE: P1003.1c/D10, p. 37 adds pthread_sigmask().
655 *
656 */
657
658int sigprocmask(
659  int               how,
660  const sigset_t   *set,
661  sigset_t         *oset
662)
663{
664  /*
665   *  P1003.1c/Draft 10, p. 38 maps sigprocmask to pthread_sigmask.
666   */
667
668  return pthread_sigmask( how, set, oset );
669}
670
671/*
672 *  3.3.5 Examine and Change Blocked Signals, P1003.1b-1993, p. 73
673 *
674 *  NOTE: P1003.1c/D10, p. 37 adds pthread_sigmask().
675 */
676
677int pthread_sigmask(
678  int               how,
679  const sigset_t   *set,
680  sigset_t         *oset
681)
682{
683  POSIX_API_Control  *api;
684
685  if ( !set && !oset )
686    set_errno_and_return_minus_one( EINVAL );
687
688  api = _Thread_Executing->API_Extensions[ THREAD_API_POSIX ];
689
690  if ( oset )
691    *oset = api->signals_blocked;
692 
693  if ( !set )
694    return 0;
695
696  switch ( how ) {
697    case SIG_BLOCK:
698      api->signals_blocked |= *set;
699      break;
700    case SIG_UNBLOCK:
701      api->signals_blocked &= ~*set;
702      break;
703    case SIG_SETMASK:
704      api->signals_blocked = *set;
705      break;
706    default:
707      set_errno_and_return_minus_one( EINVAL );
708  }
709
710  /* XXX are there critical section problems here? */
711
712  /* XXX evaluate the new set */
713
714  if ( ~api->signals_blocked & 
715       (api->signals_pending | _POSIX_signals_Pending) ) {
716    _Thread_Executing->do_post_task_switch_extension = TRUE;
717    _Thread_Dispatch();
718  }
719
720  return 0;
721}
722
723/*
724 *  3.3.6 Examine Pending Signals, P1003.1b-1993, p. 75
725 */
726
727int sigpending(
728  sigset_t  *set
729)
730{
731  POSIX_API_Control  *api;
732 
733  if ( !set )
734    set_errno_and_return_minus_one( EINVAL );
735 
736  api = _Thread_Executing->API_Extensions[ THREAD_API_POSIX ];
737 
738  *set = api->signals_pending | _POSIX_signals_Pending;
739 
740  return 0;
741}
742
743/*
744 *  3.3.7 Wait for a Signal, P1003.1b-1993, p. 75
745 */
746
747int sigsuspend(
748  const sigset_t  *sigmask
749)
750{
751  sigset_t            saved_signals_blocked;
752  sigset_t            all_signals;
753  int                 status;
754  POSIX_API_Control  *api;
755
756  api = _Thread_Executing->API_Extensions[ THREAD_API_POSIX ];
757
758  status = sigprocmask( SIG_BLOCK, sigmask, &saved_signals_blocked );
759 
760  (void) sigfillset( &all_signals );
761
762  status = sigtimedwait( &all_signals, NULL, NULL );
763
764  (void) sigprocmask( SIG_SETMASK, &saved_signals_blocked, NULL );
765
766  return status;
767}
768
769/*
770 *  3.3.8 Synchronously Accept a Signal, P1003.1b-1993, p. 76
771 *
772 *  NOTE: P1003.1c/D10, p. 39 adds sigwait().
773 */
774
775int sigwaitinfo(
776  const sigset_t  *set,
777  siginfo_t       *info
778)
779{
780  return sigtimedwait( set, info, NULL );
781}
782
783/*
784 *  3.3.8 Synchronously Accept a Signal, P1003.1b-1993, p. 76
785 *
786 *  NOTE: P1003.1c/D10, p. 39 adds sigwait().
787 */
788
789int _POSIX_signals_Get_highest( 
790  sigset_t   set
791)
792{
793  int signo;
794 
795  for ( signo = SIGRTMIN ; signo <= SIGRTMAX ; signo++ ) {
796    if ( set & signo_to_mask( signo ) )
797      return signo;
798  }
799 
800/* XXX - add __SIGFIRSTNOTRT or something like that to newlib siginfo.h */
801
802  for ( signo = SIGHUP ; signo <= __SIGLASTNOTRT ; signo++ ) {
803    if ( set & signo_to_mask( signo ) )
804      return signo;
805  }
806
807  return 0;
808}
809
810int sigtimedwait(
811  const sigset_t         *set,
812  siginfo_t              *info,
813  const struct timespec  *timeout
814)
815{
816  Thread_Control    *the_thread;
817  POSIX_API_Control *api;
818  Watchdog_Interval  interval;
819  siginfo_t          signal_information;
820  siginfo_t         *the_info;
821  int                signo;
822 
823  the_info = ( info ) ? info : &signal_information;
824
825  the_thread = _Thread_Executing;
826
827  api = the_thread->API_Extensions[ THREAD_API_POSIX ];
828
829  /*
830   *  What if they are already pending?
831   */
832
833  /* API signals pending? */
834
835  if ( *set & api->signals_pending ) {
836    /* XXX real info later */
837    the_info->si_signo = _POSIX_signals_Get_highest( api->signals_pending );
838    _POSIX_signals_Clear_signals( api, the_info->si_signo, the_info,
839                                  FALSE, FALSE );
840    the_info->si_code = SI_USER;
841    the_info->si_value.sival_int = 0;
842    return the_info->si_signo;
843  }
844
845  /* Process pending signals? */
846
847  if ( *set & _POSIX_signals_Pending) {
848    signo = _POSIX_signals_Get_highest( _POSIX_signals_Pending );
849    _POSIX_signals_Clear_signals( api, signo, the_info, TRUE, FALSE );
850
851    if ( !info ) {
852      the_info->si_signo = signo;
853      the_info->si_code = SI_USER;
854      the_info->si_value.sival_int = 0;
855    }
856  }
857
858  interval = 0;
859  if ( timeout ) {
860
861    if (timeout->tv_nsec < 0 || timeout->tv_nsec >= TOD_NANOSECONDS_PER_SECOND)
862      set_errno_and_return_minus_one( EINVAL );
863
864    interval = _POSIX_Timespec_to_interval( timeout );
865  }
866
867  the_info->si_signo = -1;
868
869  _Thread_Disable_dispatch();
870    the_thread->Wait.queue           = &_POSIX_signals_Wait_queue;
871    the_thread->Wait.return_code     = EINTR;
872    the_thread->Wait.option          = *set;
873    the_thread->Wait.return_argument = (void *) the_info;
874    _Thread_queue_Enter_critical_section( &_POSIX_signals_Wait_queue ); 
875    _Thread_queue_Enqueue( &_POSIX_signals_Wait_queue, interval ); 
876  _Thread_Enable_dispatch();
877
878  /*
879   * When the thread set free by a signal, it is needed to eliminate
880   * that signal
881   */
882
883  _POSIX_signals_Clear_signals( api, the_info->si_signo, the_info,
884                                FALSE, FALSE );
885
886  errno = _Thread_Executing->Wait.return_code;
887  return the_info->si_signo;
888}
889
890/*
891 *  3.3.8 Synchronously Accept a Signal, P1003.1b-1993, p. 76
892 *
893 *  NOTE: P1003.1c/D10, p. 39 adds sigwait().
894 */
895
896int sigwait(
897  const sigset_t  *set,
898  int             *sig
899)
900{
901  int status;
902
903  status = sigtimedwait( set, NULL, NULL );
904
905  if ( status != -1 ) {
906    if ( sig )
907      *sig = status;
908    return 0;
909  }
910
911  return errno;
912}
913
914/*
915 *  3.3.9 Queue a Signal to a Process, P1003.1b-1993, p. 78
916 */
917
918int sigqueue(
919  pid_t               pid,
920  int                 signo,
921  const union sigval  value
922)
923{
924  return killinfo( pid, signo, &value );
925}
926
927/*
928 *  3.3.10 Send a Signal to a Thread, P1003.1c/D10, p. 43
929 */
930
931int pthread_kill(
932  pthread_t   thread,
933  int         sig
934)
935{
936  POSIX_API_Control  *api;
937  Thread_Control     *the_thread;
938  Objects_Locations  location;
939
940  if ( sig && !is_valid_signo(sig) )
941    set_errno_and_return_minus_one( EINVAL );
942/*
943  if ( _POSIX_signals_Vectors[ sig ].sa_flags == SA_SIGINFO )
944    set_errno_and_return_minus_one( ENOSYS );
945*/
946  /*
947   *  RTEMS does not support sending  a siginfo signal to a specific thread.
948   */
949
950  the_thread = _POSIX_Threads_Get( thread, &location );
951  switch ( location ) {
952    case OBJECTS_ERROR:
953    case OBJECTS_REMOTE:
954      set_errno_and_return_minus_one( ESRCH );
955    case OBJECTS_LOCAL:
956      /*
957       *  If sig == 0 then just validate arguments
958       */
959
960      api = the_thread->API_Extensions[ THREAD_API_POSIX ];
961
962      if ( sig ) {
963
964        if ( _POSIX_signals_Vectors[ sig ].sa_handler == SIG_IGN ) {
965          _Thread_Enable_dispatch();
966          return 0;
967        }
968
969        /* XXX critical section */
970
971        api->signals_pending |= signo_to_mask( sig );
972
973        (void) _POSIX_signals_Unblock_thread( the_thread, sig, NULL );
974
975        the_thread->do_post_task_switch_extension = TRUE;
976
977        if ( _ISR_Is_in_progress() && _Thread_Is_executing( the_thread ) )
978          _ISR_Signals_to_thread_executing = TRUE;
979      }
980      _Thread_Enable_dispatch();
981      return 0;
982  }
983
984  return POSIX_BOTTOM_REACHED();
985}
Note: See TracBrowser for help on using the repository browser.