Changeset 07d880f4 in rtems


Ignore:
Timestamp:
01/31/99 20:45:31 (25 years ago)
Author:
Joel Sherrill <joel.sherrill@…>
Branches:
4.10, 4.11, 4.8, 4.9, 5, master
Children:
7dbab720
Parents:
379d2ed
Message:

Split psignal.c into many more files. This reduced the amount of
object code that has to be loaded just for initializing the signal
manager.

Files:
38 added
5 edited

Legend:

Unmodified
Added
Removed
  • c/src/exec/posix/include/rtems/posix/psignal.h

    r379d2ed r07d880f4  
    66#define __RTEMS_POSIX_SIGNALS_h
    77
     8#include <rtems/posix/pthread.h>
     9
     10/*
     11 *  Currently 32 signals numbered 1-32 are defined
     12 */
     13
     14#define SIGNAL_EMPTY_MASK  0x00000000
     15#define SIGNAL_ALL_MASK    0xffffffff
     16
     17#define signo_to_mask( _sig ) (1 << ((_sig) - 1))
     18
     19#define is_valid_signo( _sig ) \
     20  ((_sig) >= 1 && (_sig) <= 32 )
     21
     22#define _States_Is_interruptible_signal( _states ) \
     23  ( ((_states) & \
     24    (STATES_WAITING_FOR_SIGNAL|STATES_INTERRUPTIBLE_BY_SIGNAL)) == \
     25      (STATES_WAITING_FOR_SIGNAL|STATES_INTERRUPTIBLE_BY_SIGNAL))
     26
     27#define SIGACTION_TERMINATE \
     28  { 0, SIGNAL_ALL_MASK, {_POSIX_signals_Abormal_termination_handler} }
     29#define SIGACTION_IGNORE \
     30  { 0, SIGNAL_ALL_MASK, {SIG_IGN} }
     31#define SIGACTION_STOP \
     32  { 0, SIGNAL_ALL_MASK, {_POSIX_signals_Stop_handler} }
     33#define SIGACTION_CONTINUE \
     34  { 0, SIGNAL_ALL_MASK, {_POSIX_signals_Continue_handler} }
     35
     36#define SIG_ARRAY_MAX  (SIGRTMAX + 1)
     37
     38/*
     39 *  Variables
     40 */
     41
     42extern sigset_t  _POSIX_signals_Pending;
     43
     44extern struct sigaction _POSIX_signals_Default_vectors[ SIG_ARRAY_MAX ];
     45
     46extern struct sigaction _POSIX_signals_Vectors[ SIG_ARRAY_MAX ];
     47
     48extern Watchdog_Control _POSIX_signals_Alarm_timer;
     49
     50extern Thread_queue_Control _POSIX_signals_Wait_queue;
     51
     52extern Chain_Control _POSIX_signals_Inactive_siginfo;
     53
     54extern Chain_Control _POSIX_signals_Siginfo[ SIG_ARRAY_MAX ];
     55
     56/*
     57 *  POSIX internal siginfo structure
     58 */
     59
    860typedef struct {
    961  Chain_Node  Node;
    1062  siginfo_t   Info;
    1163}  POSIX_signals_Siginfo_node;
     64
     65/*
     66 *  Internal routines
     67 */
    1268
    1369void _POSIX_signals_Manager_Initialization(
     
    1975);
    2076
     77boolean _POSIX_signals_Unblock_thread(
     78  Thread_Control  *the_thread,
     79  int              signo,
     80  siginfo_t       *info
     81);
     82
     83boolean _POSIX_signals_Clear_signals(
     84  POSIX_API_Control  *api,
     85  int                 signo,
     86  siginfo_t          *info,
     87  boolean             is_global,
     88  boolean             check_blocked
     89);
     90
     91int killinfo(
     92  pid_t               pid,
     93  int                 sig,
     94  const union sigval *value
     95);
     96
     97void _POSIX_signals_Set_process_signals(
     98  sigset_t   mask
     99);
     100
     101void _POSIX_signals_Set_process_signals(
     102  sigset_t   mask
     103);
     104
     105/*
     106 *  Default signal handlers
     107 */
     108
     109#define _POSIX_signals_Stop_handler NULL
     110#define _POSIX_signals_Continue_handler NULL
     111
     112void _POSIX_signals_Abormal_termination_handler( int signo );
     113
    21114#endif
    22115/* end of file */
  • c/src/exec/posix/src/Makefile.in

    r379d2ed r07d880f4  
    3030  pthreadattrgetscope pthreadattrsetscope
    3131
    32 C_PIECES= adasupp cond getpid key mutex $(PTHREAD_PIECES) psignal sched time \
     32PSIGNAL_PIECES=\
     33  psignal alarm kill killinfo pause pthreadkill pthreadsigmask \
     34  sigaction sigaddset sigdelset sigemptyset sigfillset sigismember \
     35  sigpending sigprocmask sigqueue sigsuspend sigtimedwait sigwait \
     36  sigwaitinfo
     37
     38C_PIECES= adasupp cond getpid key mutex $(PTHREAD_PIECES) \
     39  $(PSIGNAL_PIECES) sched time \
    3340  types unistd $(ENOSYS_C_PIECES)
     41
    3442C_FILES=$(C_PIECES:%=%.c)
    3543C_O_FILES=$(C_PIECES:%=${ARCH}/%.o)
  • c/src/exec/posix/src/psignal.c

    r379d2ed r07d880f4  
    1919#include <rtems/posix/time.h>
    2020
    21 /*
    22  *  Currently 32 signals numbered 1-32 are defined
    23  */
    24 
    25 #define SIGNAL_EMPTY_MASK  0x00000000
    26 #define SIGNAL_ALL_MASK    0xffffffff
    27 
    28 #define signo_to_mask( _sig ) (1 << ((_sig) - 1))
    29 
    30 #define is_valid_signo( _sig ) \
    31   ((_sig) >= 1 && (_sig) <= 32 )
    32 
    3321/*** PROCESS WIDE STUFF ****/
    3422
    3523sigset_t  _POSIX_signals_Pending;
    3624
    37 void _POSIX_signals_Abormal_termination_handler( int signo )
    38 {
    39   exit( 1 );
    40 }
    41 
    42 #define _POSIX_signals_Stop_handler NULL
    43 #define _POSIX_signals_Continue_handler NULL
    44 
    45 #define SIGACTION_TERMINATE \
    46   { 0, SIGNAL_ALL_MASK, {_POSIX_signals_Abormal_termination_handler} }
    47 #define SIGACTION_IGNORE \
    48   { 0, SIGNAL_ALL_MASK, {SIG_IGN} }
    49 #define SIGACTION_STOP \
    50   { 0, SIGNAL_ALL_MASK, {_POSIX_signals_Stop_handler} }
    51 #define SIGACTION_CONTINUE \
    52   { 0, SIGNAL_ALL_MASK, {_POSIX_signals_Continue_handler} }
    53 
    54 #define SIG_ARRAY_MAX  (SIGRTMAX + 1)
     25struct sigaction _POSIX_signals_Vectors[ SIG_ARRAY_MAX ];
     26
     27Watchdog_Control _POSIX_signals_Alarm_timer;
     28
     29Thread_queue_Control _POSIX_signals_Wait_queue;
     30
     31Chain_Control _POSIX_signals_Inactive_siginfo;
     32Chain_Control _POSIX_signals_Siginfo[ SIG_ARRAY_MAX ];
     33
    5534struct sigaction _POSIX_signals_Default_vectors[ SIG_ARRAY_MAX ] = {
    5635  /* NO SIGNAL 0 */  SIGACTION_IGNORE,
     
    9069};
    9170
    92 struct sigaction _POSIX_signals_Vectors[ SIG_ARRAY_MAX ];
    93 
    94 Watchdog_Control _POSIX_signals_Alarm_timer;
    95 
    96 Thread_queue_Control _POSIX_signals_Wait_queue;
    97 
    98 Chain_Control _POSIX_signals_Inactive_siginfo;
    99 Chain_Control _POSIX_signals_Siginfo[ SIG_ARRAY_MAX ];
    100 
    101 /*PAGE
    102  *
    103  *  XXX - move these
    104  */
    105 
    106 #define _States_Is_interruptible_signal( _states ) \
    107   ( ((_states) & \
    108     (STATES_WAITING_FOR_SIGNAL|STATES_INTERRUPTIBLE_BY_SIGNAL)) == \
    109       (STATES_WAITING_FOR_SIGNAL|STATES_INTERRUPTIBLE_BY_SIGNAL))
     71/*PAGE
     72 *
     73 *  _POSIX_signals_Abormal_termination_handler
     74 *
     75 */
     76
     77void _POSIX_signals_Abormal_termination_handler( int signo )
     78{
     79  exit( 1 );
     80}
    11081
    11182/*PAGE
     
    485456  );
    486457}
    487 
    488 /*
    489  *  3.3.3 Manipulate Signal Sets, P1003.1b-1993, p. 69
    490  */
    491 
    492 int sigemptyset(
    493   sigset_t   *set
    494 )
    495 {
    496   if ( !set )
    497     set_errno_and_return_minus_one( EINVAL );
    498 
    499   *set = 0;
    500   return 0;
    501 }
    502 
    503 /*
    504  *  3.3.3 Manipulate Signal Sets, P1003.1b-1993, p. 69
    505  */
    506 
    507 int sigfillset(
    508   sigset_t   *set
    509 )
    510 {
    511   if ( !set )
    512     set_errno_and_return_minus_one( EINVAL );
    513 
    514   *set = SIGNAL_ALL_MASK;
    515   return 0;
    516 }
    517 
    518 /*
    519  *  3.3.3 Manipulate Signal Sets, P1003.1b-1993, p. 69
    520  */
    521 
    522 int sigaddset(
    523   sigset_t   *set,
    524   int         signo
    525 )
    526 {
    527   if ( !set )
    528     set_errno_and_return_minus_one( EINVAL );
    529 
    530   if ( !signo )
    531     return 0;
    532 
    533   if ( !is_valid_signo(signo) )
    534     set_errno_and_return_minus_one( EINVAL );
    535 
    536   *set |= signo_to_mask(signo);
    537   return 0;
    538 }
    539 
    540 /*
    541  *  3.3.3 Manipulate Signal Sets, P1003.1b-1993, p. 69
    542  */
    543 
    544 int sigdelset(
    545   sigset_t   *set,
    546   int         signo
    547 )
    548 {
    549   if ( !set )
    550     set_errno_and_return_minus_one( EINVAL );
    551  
    552   if ( !signo )
    553     return 0;
    554 
    555   if ( !is_valid_signo(signo) )
    556     set_errno_and_return_minus_one( EINVAL );
    557  
    558   *set &= ~signo_to_mask(signo);
    559   return 0;
    560 }
    561 
    562 /*
    563  *  3.3.3 Manipulate Signal Sets, P1003.1b-1993, p. 69
    564  */
    565 
    566 int sigismember(
    567   const sigset_t   *set,
    568   int               signo
    569 )
    570 {
    571   if ( !set )
    572     set_errno_and_return_minus_one( EINVAL );
    573  
    574   if ( !signo )
    575     return 0;
    576 
    577   if ( !is_valid_signo(signo) )
    578     set_errno_and_return_minus_one( EINVAL );
    579  
    580   if ( *set & signo_to_mask(signo) )
    581     return 1;
    582 
    583   return 0;
    584 }
    585 
    586 /*
    587  *  3.3.4 Examine and Change Signal Action, P1003.1b-1993, p. 70
    588  */
    589 
    590 int sigaction(
    591   int                     sig,
    592   const struct sigaction *act,
    593   struct sigaction       *oact
    594 )
    595 {
    596   ISR_Level     level;
    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 
    658 int 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 
    677 int 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 
    727 int 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 
    747 int 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 
    775 int 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 
    789 int _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 
    810 int 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   errno = _Thread_Executing->Wait.return_code;
    879   return the_info->si_signo;
    880 }
    881 
    882 /*
    883  *  3.3.8 Synchronously Accept a Signal, P1003.1b-1993, p. 76
    884  *
    885  *  NOTE: P1003.1c/D10, p. 39 adds sigwait().
    886  */
    887 
    888 int sigwait(
    889   const sigset_t  *set,
    890   int             *sig
    891 )
    892 {
    893   int status;
    894 
    895   status = sigtimedwait( set, NULL, NULL );
    896 
    897   if ( status != -1 ) {
    898     if ( sig )
    899       *sig = status;
    900     return 0;
    901   }
    902 
    903   return errno;
    904 }
    905 
    906 /*PAGE
    907  *
    908  *  3.3.2 Send a Signal to a Process, P1003.1b-1993, p. 68
    909  *
    910  *  NOTE: Behavior of kill() depends on _POSIX_SAVED_IDS.
    911  */
    912 
    913 #define _POSIX_signals_Is_interested( _api, _mask ) \
    914   ( ~(_api)->signals_blocked & (_mask) )
    915          
    916 int killinfo(
    917   pid_t               pid,
    918   int                 sig,
    919   const union sigval *value
    920 )
    921 {
    922   sigset_t                     mask;
    923   POSIX_API_Control           *api;
    924   unsigned32                   the_class;
    925   unsigned32                   index;
    926   unsigned32                   maximum;
    927   Objects_Information         *the_info;
    928   Objects_Control            **object_table;
    929   Thread_Control              *the_thread;
    930   Thread_Control              *interested_thread;
    931   Priority_Control             interested_priority;
    932   Chain_Control               *the_chain;
    933   Chain_Node                  *the_node;
    934   siginfo_t                    siginfo_struct;
    935   siginfo_t                   *siginfo;
    936   POSIX_signals_Siginfo_node  *psiginfo;
    937  
    938   /*
    939    *  Only supported for the "calling process" (i.e. this node).
    940    */
    941  
    942   if( pid != getpid() )
    943     set_errno_and_return_minus_one( ESRCH );
    944 
    945   /*
    946    *  Validate the signal passed if not 0.
    947    */
    948  
    949   if ( sig && !is_valid_signo(sig) )
    950     set_errno_and_return_minus_one( EINVAL );
    951 
    952   /*
    953    *  If the signal is being ignored, then we are out of here.
    954    */
    955 
    956   if ( !sig || _POSIX_signals_Vectors[ sig ].sa_handler == SIG_IGN )
    957     return 0;
    958 
    959   /*
    960    *  P1003.1c/Draft 10, p. 33 says that certain signals should always
    961    *  be directed to the executing thread such as those caused by hardware
    962    *  faults.
    963    */
    964 
    965   switch ( sig ) {
    966     case SIGFPE:
    967     case SIGILL:
    968     case SIGSEGV:
    969       return pthread_kill( pthread_self(), sig );
    970     default:
    971       break;
    972   }
    973 
    974   mask = signo_to_mask( sig );
    975 
    976   /*
    977    *  Build up a siginfo structure
    978    */
    979 
    980   siginfo = &siginfo_struct;
    981   siginfo->si_signo = sig;
    982   siginfo->si_code = SI_USER;
    983   if ( !value ) {
    984     siginfo->si_value.sival_int = 0;
    985   } else {
    986     siginfo->si_value = *value;
    987   }
    988 
    989   _Thread_Disable_dispatch();
    990 
    991   /*
    992    *  Is the currently executing thread interested?  If so then it will
    993    *  get it an execute it as soon as the dispatcher executes.
    994    */
    995 
    996   the_thread = _Thread_Executing;
    997 
    998   api = the_thread->API_Extensions[ THREAD_API_POSIX ];
    999   if ( _POSIX_signals_Is_interested( api, mask ) ) {
    1000     goto process_it;
    1001   }
    1002 
    1003   /*
    1004    *  Is an interested thread waiting for this signal (sigwait())?
    1005    */
    1006 
    1007   /* XXX violation of visibility -- need to define thread queue support */
    1008 
    1009   for( index=0 ;
    1010        index < TASK_QUEUE_DATA_NUMBER_OF_PRIORITY_HEADERS ;
    1011        index++ ) {
    1012 
    1013     the_chain = &_POSIX_signals_Wait_queue.Queues.Priority[ index ];
    1014  
    1015     for ( the_node = the_chain->first ;
    1016           !_Chain_Is_tail( the_chain, the_node ) ;
    1017           the_node = the_node->next ) {
    1018 
    1019       the_thread = (Thread_Control *)the_node;
    1020       api = the_thread->API_Extensions[ THREAD_API_POSIX ];
    1021 
    1022       if ((the_thread->Wait.option & mask) || (~api->signals_blocked & mask)) {
    1023         goto process_it;
    1024       }
    1025 
    1026     }
    1027   }
    1028 
    1029   /*
    1030    *  Is any other thread interested?  The highest priority interested
    1031    *  thread is selected.  In the event of a tie, then the following
    1032    *  additional criteria is used:
    1033    *
    1034    *    + ready thread over blocked
    1035    *    + blocked on call interruptible by signal (can return EINTR)
    1036    *    + blocked on call not interruptible by signal
    1037    *
    1038    *  This looks at every thread in the system regardless of the creating API.
    1039    *
    1040    *  NOTES:
    1041    *
    1042    *    + rtems internal threads do not receive signals.
    1043    */
    1044 
    1045   interested_thread = NULL;
    1046   interested_priority = PRIORITY_MAXIMUM + 1;
    1047 
    1048   for ( the_class = OBJECTS_CLASSES_FIRST_THREAD_CLASS;
    1049         the_class <= OBJECTS_CLASSES_LAST_THREAD_CLASS;
    1050         the_class++ ) {
    1051 
    1052     if ( the_class == OBJECTS_INTERNAL_THREADS )
    1053       continue;
    1054 
    1055     the_info = _Objects_Information_table[ the_class ];
    1056 
    1057     if ( !the_info )                        /* manager not installed */
    1058       continue;
    1059 
    1060     maximum = the_info->maximum;
    1061     object_table = the_info->local_table;
    1062 
    1063     assert( object_table );                 /* always at least 1 entry */
    1064 
    1065     for ( index = 1 ; index <= maximum ; index++ ) {
    1066       the_thread = (Thread_Control *) object_table[ index ];
    1067 
    1068       if ( !the_thread )
    1069         continue;
    1070 
    1071       /*
    1072        *  If this thread is of lower priority than the interested thread,
    1073        *  go on to the next thread.
    1074        */
    1075 
    1076       if ( the_thread->current_priority > interested_priority )
    1077         continue;
    1078 
    1079       /*
    1080        *  If this thread is not interested, then go on to the next thread.
    1081        */
    1082 
    1083       api = the_thread->API_Extensions[ THREAD_API_POSIX ];
    1084 
    1085       if ( !api || !_POSIX_signals_Is_interested( api, mask ) )
    1086         continue;
    1087 
    1088       /*
    1089        *  Now we know the thread under connsideration is interested.
    1090        *  If the thread under consideration is of higher priority, then
    1091        *  it becomes the interested thread.
    1092        */
    1093 
    1094       if ( the_thread->current_priority < interested_priority ) {
    1095         interested_thread   = the_thread;
    1096         interested_priority = the_thread->current_priority;
    1097         continue;
    1098       }
    1099 
    1100       /*
    1101        *  Now the thread and the interested thread have the same priority.
    1102        *  If the interested thread is ready, then we don't need to send it
    1103        *  to a blocked thread.
    1104        */
    1105 
    1106       if ( _States_Is_ready( interested_thread->current_state ) )
    1107         continue;
    1108 
    1109       /*
    1110        *  Now the interested thread is blocked.
    1111        *  If the thread we are considering is not, the it becomes the
    1112        *  interested thread.
    1113        */
    1114 
    1115       if ( _States_Is_ready( the_thread->current_state ) ) {
    1116         interested_thread   = the_thread;
    1117         interested_priority = the_thread->current_priority;
    1118         continue;
    1119       }
    1120 
    1121       /*
    1122        *  Now we know both threads are blocked.
    1123        *  If the interested thread is interruptible, then just use it.
    1124        */
    1125 
    1126       /* XXX need a new states macro */
    1127       if ( interested_thread->current_state & STATES_INTERRUPTIBLE_BY_SIGNAL )
    1128         continue;
    1129 
    1130       /*
    1131        *  Now both threads are blocked and the interested thread is not
    1132        *  interruptible.
    1133        *  If the thread under consideration is interruptible by a signal,
    1134        *  then it becomes the interested thread.
    1135        */
    1136 
    1137       /* XXX need a new states macro */
    1138       if ( the_thread->current_state & STATES_INTERRUPTIBLE_BY_SIGNAL ) {
    1139         interested_thread   = the_thread;
    1140         interested_priority = the_thread->current_priority;
    1141       }
    1142     }
    1143   }
    1144 
    1145   if ( interested_thread ) {
    1146     the_thread = interested_thread;
    1147     goto process_it;
    1148   }
    1149 
    1150   /*
    1151    *  OK so no threads were interested right now.  It will be left on the
    1152    *  global pending until a thread receives it.  The global set of threads
    1153    *  can change interest in this signal in one of the following ways:
    1154    *
    1155    *    + a thread is created with the signal unblocked,
    1156    *    + pthread_sigmask() unblocks the signal,
    1157    *    + sigprocmask() unblocks the signal, OR
    1158    *    + sigaction() which changes the handler to SIG_IGN.
    1159    */
    1160 
    1161   the_thread = NULL;
    1162   goto post_process_signal;
    1163 
    1164   /*
    1165    *  We found a thread which was interested, so now we mark that this
    1166    *  thread needs to do the post context switch extension so it can
    1167    *  evaluate the signals pending.
    1168    */
    1169 
    1170 process_it:
    1171  
    1172   the_thread->do_post_task_switch_extension = TRUE;
    1173 
    1174   /*
    1175    *  Returns TRUE if the signal was synchronously given to a thread
    1176    *  blocked waiting for the signal.
    1177    */
    1178 
    1179   if ( _POSIX_signals_Unblock_thread( the_thread, sig, siginfo ) ) {
    1180     _Thread_Enable_dispatch();
    1181     return 0;
    1182   }
    1183 
    1184 post_process_signal:
    1185 
    1186   /*
    1187    *  We may have woken up a thread but we definitely need to post the
    1188    *  signal to the process wide information set.
    1189    */
    1190 
    1191   _POSIX_signals_Set_process_signals( mask );
    1192 
    1193   if ( _POSIX_signals_Vectors[ sig ].sa_flags == SA_SIGINFO ) {
    1194 
    1195     psiginfo = (POSIX_signals_Siginfo_node *)
    1196                _Chain_Get( &_POSIX_signals_Inactive_siginfo );
    1197     if ( !psiginfo )
    1198       set_errno_and_return_minus_one( EAGAIN );
    1199 
    1200     psiginfo->Info = *siginfo;
    1201 
    1202     _Chain_Append( &_POSIX_signals_Siginfo[ sig ], &psiginfo->Node );
    1203   }
    1204 
    1205   _Thread_Enable_dispatch();
    1206   return 0;
    1207 }
    1208 
    1209 /*PAGE
    1210  *
    1211  *  3.3.2 Send a Signal to a Process, P1003.1b-1993, p. 68
    1212  *
    1213  *  NOTE: Behavior of kill() depends on _POSIX_SAVED_IDS.
    1214  */
    1215 
    1216 int kill(
    1217   pid_t pid,
    1218   int   sig
    1219 )
    1220 {
    1221   return killinfo( pid, sig, NULL );
    1222 }
    1223 
    1224 /*
    1225  *  _kill_r
    1226  *
    1227  *  This is the Newlib dependent reentrant version of kill().
    1228  */
    1229 
    1230 #if defined(RTEMS_NEWLIB)
    1231 
    1232 #include <reent.h>
    1233 
    1234 int _kill_r(
    1235   struct _reent *ptr,
    1236   pid_t          pid,
    1237   int            sig
    1238 )
    1239 {
    1240   return kill( pid, sig );
    1241 }
    1242 #endif
    1243 
    1244 /*
    1245  *  3.3.9 Queue a Signal to a Process, P1003.1b-1993, p. 78
    1246  */
    1247 
    1248 int sigqueue(
    1249   pid_t               pid,
    1250   int                 signo,
    1251   const union sigval  value
    1252 )
    1253 {
    1254   return killinfo( pid, signo, &value );
    1255 }
    1256 
    1257 /*
    1258  *  3.3.10 Send a Signal to a Thread, P1003.1c/D10, p. 43
    1259  */
    1260 
    1261 int pthread_kill(
    1262   pthread_t   thread,
    1263   int         sig
    1264 )
    1265 {
    1266   POSIX_API_Control  *api;
    1267   Thread_Control     *the_thread;
    1268   Objects_Locations  location;
    1269 
    1270   if ( sig && !is_valid_signo(sig) )
    1271     set_errno_and_return_minus_one( EINVAL );
    1272 
    1273   if ( _POSIX_signals_Vectors[ sig ].sa_flags == SA_SIGINFO )
    1274     set_errno_and_return_minus_one( ENOSYS );
    1275 
    1276   /*
    1277    *  RTEMS does not support sending  a siginfo signal to a specific thread.
    1278    */
    1279 
    1280   the_thread = _POSIX_Threads_Get( thread, &location );
    1281   switch ( location ) {
    1282     case OBJECTS_ERROR:
    1283     case OBJECTS_REMOTE:
    1284       set_errno_and_return_minus_one( ESRCH );
    1285     case OBJECTS_LOCAL:
    1286       /*
    1287        *  If sig == 0 then just validate arguments
    1288        */
    1289 
    1290       api = the_thread->API_Extensions[ THREAD_API_POSIX ];
    1291 
    1292       if ( sig ) {
    1293 
    1294         if ( _POSIX_signals_Vectors[ sig ].sa_handler == SIG_IGN ) {
    1295           _Thread_Enable_dispatch();
    1296           return 0;
    1297         }
    1298 
    1299         /* XXX critical section */
    1300 
    1301         api->signals_pending |= signo_to_mask( sig );
    1302 
    1303         (void) _POSIX_signals_Unblock_thread( the_thread, sig, NULL );
    1304 
    1305         the_thread->do_post_task_switch_extension = TRUE;
    1306 
    1307         if ( _ISR_Is_in_progress() && _Thread_Is_executing( the_thread ) )
    1308           _ISR_Signals_to_thread_executing = TRUE;
    1309       }
    1310       _Thread_Enable_dispatch();
    1311       return 0;
    1312   }
    1313 
    1314   return POSIX_BOTTOM_REACHED();
    1315 }
    1316 
    1317 /*
    1318  *  3.4.1 Schedule Alarm, P1003.1b-1993, p. 79
    1319  */
    1320 
    1321 Watchdog_Control _POSIX_signals_Alarm_timer;
    1322 
    1323 unsigned int alarm(
    1324   unsigned int seconds
    1325 )
    1326 {
    1327   unsigned int      remaining = 0;
    1328   Watchdog_Control *the_timer;
    1329 
    1330   the_timer = &_POSIX_signals_Alarm_timer;
    1331 
    1332   switch ( _Watchdog_Remove( the_timer ) ) {
    1333     case WATCHDOG_INACTIVE:
    1334     case WATCHDOG_BEING_INSERTED:
    1335       break;
    1336  
    1337     case WATCHDOG_ACTIVE:
    1338     case WATCHDOG_REMOVE_IT:
    1339       remaining = the_timer->initial -
    1340                   (the_timer->stop_time - the_timer->start_time);
    1341       break;
    1342   }
    1343 
    1344   _Watchdog_Insert_seconds( the_timer, seconds );
    1345 
    1346   return remaining;
    1347 }
    1348 
    1349 /*
    1350  *  3.4.2 Suspend Process Execution, P1003.1b-1993, p. 81
    1351  */
    1352 
    1353 int pause( void )
    1354 {
    1355   sigset_t  all_signals;
    1356   int       status;
    1357  
    1358   (void) sigfillset( &all_signals );
    1359  
    1360   status = sigtimedwait( &all_signals, NULL, NULL );
    1361  
    1362   return status;
    1363 }
  • cpukit/posix/include/rtems/posix/psignal.h

    r379d2ed r07d880f4  
    66#define __RTEMS_POSIX_SIGNALS_h
    77
     8#include <rtems/posix/pthread.h>
     9
     10/*
     11 *  Currently 32 signals numbered 1-32 are defined
     12 */
     13
     14#define SIGNAL_EMPTY_MASK  0x00000000
     15#define SIGNAL_ALL_MASK    0xffffffff
     16
     17#define signo_to_mask( _sig ) (1 << ((_sig) - 1))
     18
     19#define is_valid_signo( _sig ) \
     20  ((_sig) >= 1 && (_sig) <= 32 )
     21
     22#define _States_Is_interruptible_signal( _states ) \
     23  ( ((_states) & \
     24    (STATES_WAITING_FOR_SIGNAL|STATES_INTERRUPTIBLE_BY_SIGNAL)) == \
     25      (STATES_WAITING_FOR_SIGNAL|STATES_INTERRUPTIBLE_BY_SIGNAL))
     26
     27#define SIGACTION_TERMINATE \
     28  { 0, SIGNAL_ALL_MASK, {_POSIX_signals_Abormal_termination_handler} }
     29#define SIGACTION_IGNORE \
     30  { 0, SIGNAL_ALL_MASK, {SIG_IGN} }
     31#define SIGACTION_STOP \
     32  { 0, SIGNAL_ALL_MASK, {_POSIX_signals_Stop_handler} }
     33#define SIGACTION_CONTINUE \
     34  { 0, SIGNAL_ALL_MASK, {_POSIX_signals_Continue_handler} }
     35
     36#define SIG_ARRAY_MAX  (SIGRTMAX + 1)
     37
     38/*
     39 *  Variables
     40 */
     41
     42extern sigset_t  _POSIX_signals_Pending;
     43
     44extern struct sigaction _POSIX_signals_Default_vectors[ SIG_ARRAY_MAX ];
     45
     46extern struct sigaction _POSIX_signals_Vectors[ SIG_ARRAY_MAX ];
     47
     48extern Watchdog_Control _POSIX_signals_Alarm_timer;
     49
     50extern Thread_queue_Control _POSIX_signals_Wait_queue;
     51
     52extern Chain_Control _POSIX_signals_Inactive_siginfo;
     53
     54extern Chain_Control _POSIX_signals_Siginfo[ SIG_ARRAY_MAX ];
     55
     56/*
     57 *  POSIX internal siginfo structure
     58 */
     59
    860typedef struct {
    961  Chain_Node  Node;
    1062  siginfo_t   Info;
    1163}  POSIX_signals_Siginfo_node;
     64
     65/*
     66 *  Internal routines
     67 */
    1268
    1369void _POSIX_signals_Manager_Initialization(
     
    1975);
    2076
     77boolean _POSIX_signals_Unblock_thread(
     78  Thread_Control  *the_thread,
     79  int              signo,
     80  siginfo_t       *info
     81);
     82
     83boolean _POSIX_signals_Clear_signals(
     84  POSIX_API_Control  *api,
     85  int                 signo,
     86  siginfo_t          *info,
     87  boolean             is_global,
     88  boolean             check_blocked
     89);
     90
     91int killinfo(
     92  pid_t               pid,
     93  int                 sig,
     94  const union sigval *value
     95);
     96
     97void _POSIX_signals_Set_process_signals(
     98  sigset_t   mask
     99);
     100
     101void _POSIX_signals_Set_process_signals(
     102  sigset_t   mask
     103);
     104
     105/*
     106 *  Default signal handlers
     107 */
     108
     109#define _POSIX_signals_Stop_handler NULL
     110#define _POSIX_signals_Continue_handler NULL
     111
     112void _POSIX_signals_Abormal_termination_handler( int signo );
     113
    21114#endif
    22115/* end of file */
  • cpukit/posix/src/psignal.c

    r379d2ed r07d880f4  
    1919#include <rtems/posix/time.h>
    2020
    21 /*
    22  *  Currently 32 signals numbered 1-32 are defined
    23  */
    24 
    25 #define SIGNAL_EMPTY_MASK  0x00000000
    26 #define SIGNAL_ALL_MASK    0xffffffff
    27 
    28 #define signo_to_mask( _sig ) (1 << ((_sig) - 1))
    29 
    30 #define is_valid_signo( _sig ) \
    31   ((_sig) >= 1 && (_sig) <= 32 )
    32 
    3321/*** PROCESS WIDE STUFF ****/
    3422
    3523sigset_t  _POSIX_signals_Pending;
    3624
    37 void _POSIX_signals_Abormal_termination_handler( int signo )
    38 {
    39   exit( 1 );
    40 }
    41 
    42 #define _POSIX_signals_Stop_handler NULL
    43 #define _POSIX_signals_Continue_handler NULL
    44 
    45 #define SIGACTION_TERMINATE \
    46   { 0, SIGNAL_ALL_MASK, {_POSIX_signals_Abormal_termination_handler} }
    47 #define SIGACTION_IGNORE \
    48   { 0, SIGNAL_ALL_MASK, {SIG_IGN} }
    49 #define SIGACTION_STOP \
    50   { 0, SIGNAL_ALL_MASK, {_POSIX_signals_Stop_handler} }
    51 #define SIGACTION_CONTINUE \
    52   { 0, SIGNAL_ALL_MASK, {_POSIX_signals_Continue_handler} }
    53 
    54 #define SIG_ARRAY_MAX  (SIGRTMAX + 1)
     25struct sigaction _POSIX_signals_Vectors[ SIG_ARRAY_MAX ];
     26
     27Watchdog_Control _POSIX_signals_Alarm_timer;
     28
     29Thread_queue_Control _POSIX_signals_Wait_queue;
     30
     31Chain_Control _POSIX_signals_Inactive_siginfo;
     32Chain_Control _POSIX_signals_Siginfo[ SIG_ARRAY_MAX ];
     33
    5534struct sigaction _POSIX_signals_Default_vectors[ SIG_ARRAY_MAX ] = {
    5635  /* NO SIGNAL 0 */  SIGACTION_IGNORE,
     
    9069};
    9170
    92 struct sigaction _POSIX_signals_Vectors[ SIG_ARRAY_MAX ];
    93 
    94 Watchdog_Control _POSIX_signals_Alarm_timer;
    95 
    96 Thread_queue_Control _POSIX_signals_Wait_queue;
    97 
    98 Chain_Control _POSIX_signals_Inactive_siginfo;
    99 Chain_Control _POSIX_signals_Siginfo[ SIG_ARRAY_MAX ];
    100 
    101 /*PAGE
    102  *
    103  *  XXX - move these
    104  */
    105 
    106 #define _States_Is_interruptible_signal( _states ) \
    107   ( ((_states) & \
    108     (STATES_WAITING_FOR_SIGNAL|STATES_INTERRUPTIBLE_BY_SIGNAL)) == \
    109       (STATES_WAITING_FOR_SIGNAL|STATES_INTERRUPTIBLE_BY_SIGNAL))
     71/*PAGE
     72 *
     73 *  _POSIX_signals_Abormal_termination_handler
     74 *
     75 */
     76
     77void _POSIX_signals_Abormal_termination_handler( int signo )
     78{
     79  exit( 1 );
     80}
    11081
    11182/*PAGE
     
    485456  );
    486457}
    487 
    488 /*
    489  *  3.3.3 Manipulate Signal Sets, P1003.1b-1993, p. 69
    490  */
    491 
    492 int sigemptyset(
    493   sigset_t   *set
    494 )
    495 {
    496   if ( !set )
    497     set_errno_and_return_minus_one( EINVAL );
    498 
    499   *set = 0;
    500   return 0;
    501 }
    502 
    503 /*
    504  *  3.3.3 Manipulate Signal Sets, P1003.1b-1993, p. 69
    505  */
    506 
    507 int sigfillset(
    508   sigset_t   *set
    509 )
    510 {
    511   if ( !set )
    512     set_errno_and_return_minus_one( EINVAL );
    513 
    514   *set = SIGNAL_ALL_MASK;
    515   return 0;
    516 }
    517 
    518 /*
    519  *  3.3.3 Manipulate Signal Sets, P1003.1b-1993, p. 69
    520  */
    521 
    522 int sigaddset(
    523   sigset_t   *set,
    524   int         signo
    525 )
    526 {
    527   if ( !set )
    528     set_errno_and_return_minus_one( EINVAL );
    529 
    530   if ( !signo )
    531     return 0;
    532 
    533   if ( !is_valid_signo(signo) )
    534     set_errno_and_return_minus_one( EINVAL );
    535 
    536   *set |= signo_to_mask(signo);
    537   return 0;
    538 }
    539 
    540 /*
    541  *  3.3.3 Manipulate Signal Sets, P1003.1b-1993, p. 69
    542  */
    543 
    544 int sigdelset(
    545   sigset_t   *set,
    546   int         signo
    547 )
    548 {
    549   if ( !set )
    550     set_errno_and_return_minus_one( EINVAL );
    551  
    552   if ( !signo )
    553     return 0;
    554 
    555   if ( !is_valid_signo(signo) )
    556     set_errno_and_return_minus_one( EINVAL );
    557  
    558   *set &= ~signo_to_mask(signo);
    559   return 0;
    560 }
    561 
    562 /*
    563  *  3.3.3 Manipulate Signal Sets, P1003.1b-1993, p. 69
    564  */
    565 
    566 int sigismember(
    567   const sigset_t   *set,
    568   int               signo
    569 )
    570 {
    571   if ( !set )
    572     set_errno_and_return_minus_one( EINVAL );
    573  
    574   if ( !signo )
    575     return 0;
    576 
    577   if ( !is_valid_signo(signo) )
    578     set_errno_and_return_minus_one( EINVAL );
    579  
    580   if ( *set & signo_to_mask(signo) )
    581     return 1;
    582 
    583   return 0;
    584 }
    585 
    586 /*
    587  *  3.3.4 Examine and Change Signal Action, P1003.1b-1993, p. 70
    588  */
    589 
    590 int sigaction(
    591   int                     sig,
    592   const struct sigaction *act,
    593   struct sigaction       *oact
    594 )
    595 {
    596   ISR_Level     level;
    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 
    658 int 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 
    677 int 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 
    727 int 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 
    747 int 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 
    775 int 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 
    789 int _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 
    810 int 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   errno = _Thread_Executing->Wait.return_code;
    879   return the_info->si_signo;
    880 }
    881 
    882 /*
    883  *  3.3.8 Synchronously Accept a Signal, P1003.1b-1993, p. 76
    884  *
    885  *  NOTE: P1003.1c/D10, p. 39 adds sigwait().
    886  */
    887 
    888 int sigwait(
    889   const sigset_t  *set,
    890   int             *sig
    891 )
    892 {
    893   int status;
    894 
    895   status = sigtimedwait( set, NULL, NULL );
    896 
    897   if ( status != -1 ) {
    898     if ( sig )
    899       *sig = status;
    900     return 0;
    901   }
    902 
    903   return errno;
    904 }
    905 
    906 /*PAGE
    907  *
    908  *  3.3.2 Send a Signal to a Process, P1003.1b-1993, p. 68
    909  *
    910  *  NOTE: Behavior of kill() depends on _POSIX_SAVED_IDS.
    911  */
    912 
    913 #define _POSIX_signals_Is_interested( _api, _mask ) \
    914   ( ~(_api)->signals_blocked & (_mask) )
    915          
    916 int killinfo(
    917   pid_t               pid,
    918   int                 sig,
    919   const union sigval *value
    920 )
    921 {
    922   sigset_t                     mask;
    923   POSIX_API_Control           *api;
    924   unsigned32                   the_class;
    925   unsigned32                   index;
    926   unsigned32                   maximum;
    927   Objects_Information         *the_info;
    928   Objects_Control            **object_table;
    929   Thread_Control              *the_thread;
    930   Thread_Control              *interested_thread;
    931   Priority_Control             interested_priority;
    932   Chain_Control               *the_chain;
    933   Chain_Node                  *the_node;
    934   siginfo_t                    siginfo_struct;
    935   siginfo_t                   *siginfo;
    936   POSIX_signals_Siginfo_node  *psiginfo;
    937  
    938   /*
    939    *  Only supported for the "calling process" (i.e. this node).
    940    */
    941  
    942   if( pid != getpid() )
    943     set_errno_and_return_minus_one( ESRCH );
    944 
    945   /*
    946    *  Validate the signal passed if not 0.
    947    */
    948  
    949   if ( sig && !is_valid_signo(sig) )
    950     set_errno_and_return_minus_one( EINVAL );
    951 
    952   /*
    953    *  If the signal is being ignored, then we are out of here.
    954    */
    955 
    956   if ( !sig || _POSIX_signals_Vectors[ sig ].sa_handler == SIG_IGN )
    957     return 0;
    958 
    959   /*
    960    *  P1003.1c/Draft 10, p. 33 says that certain signals should always
    961    *  be directed to the executing thread such as those caused by hardware
    962    *  faults.
    963    */
    964 
    965   switch ( sig ) {
    966     case SIGFPE:
    967     case SIGILL:
    968     case SIGSEGV:
    969       return pthread_kill( pthread_self(), sig );
    970     default:
    971       break;
    972   }
    973 
    974   mask = signo_to_mask( sig );
    975 
    976   /*
    977    *  Build up a siginfo structure
    978    */
    979 
    980   siginfo = &siginfo_struct;
    981   siginfo->si_signo = sig;
    982   siginfo->si_code = SI_USER;
    983   if ( !value ) {
    984     siginfo->si_value.sival_int = 0;
    985   } else {
    986     siginfo->si_value = *value;
    987   }
    988 
    989   _Thread_Disable_dispatch();
    990 
    991   /*
    992    *  Is the currently executing thread interested?  If so then it will
    993    *  get it an execute it as soon as the dispatcher executes.
    994    */
    995 
    996   the_thread = _Thread_Executing;
    997 
    998   api = the_thread->API_Extensions[ THREAD_API_POSIX ];
    999   if ( _POSIX_signals_Is_interested( api, mask ) ) {
    1000     goto process_it;
    1001   }
    1002 
    1003   /*
    1004    *  Is an interested thread waiting for this signal (sigwait())?
    1005    */
    1006 
    1007   /* XXX violation of visibility -- need to define thread queue support */
    1008 
    1009   for( index=0 ;
    1010        index < TASK_QUEUE_DATA_NUMBER_OF_PRIORITY_HEADERS ;
    1011        index++ ) {
    1012 
    1013     the_chain = &_POSIX_signals_Wait_queue.Queues.Priority[ index ];
    1014  
    1015     for ( the_node = the_chain->first ;
    1016           !_Chain_Is_tail( the_chain, the_node ) ;
    1017           the_node = the_node->next ) {
    1018 
    1019       the_thread = (Thread_Control *)the_node;
    1020       api = the_thread->API_Extensions[ THREAD_API_POSIX ];
    1021 
    1022       if ((the_thread->Wait.option & mask) || (~api->signals_blocked & mask)) {
    1023         goto process_it;
    1024       }
    1025 
    1026     }
    1027   }
    1028 
    1029   /*
    1030    *  Is any other thread interested?  The highest priority interested
    1031    *  thread is selected.  In the event of a tie, then the following
    1032    *  additional criteria is used:
    1033    *
    1034    *    + ready thread over blocked
    1035    *    + blocked on call interruptible by signal (can return EINTR)
    1036    *    + blocked on call not interruptible by signal
    1037    *
    1038    *  This looks at every thread in the system regardless of the creating API.
    1039    *
    1040    *  NOTES:
    1041    *
    1042    *    + rtems internal threads do not receive signals.
    1043    */
    1044 
    1045   interested_thread = NULL;
    1046   interested_priority = PRIORITY_MAXIMUM + 1;
    1047 
    1048   for ( the_class = OBJECTS_CLASSES_FIRST_THREAD_CLASS;
    1049         the_class <= OBJECTS_CLASSES_LAST_THREAD_CLASS;
    1050         the_class++ ) {
    1051 
    1052     if ( the_class == OBJECTS_INTERNAL_THREADS )
    1053       continue;
    1054 
    1055     the_info = _Objects_Information_table[ the_class ];
    1056 
    1057     if ( !the_info )                        /* manager not installed */
    1058       continue;
    1059 
    1060     maximum = the_info->maximum;
    1061     object_table = the_info->local_table;
    1062 
    1063     assert( object_table );                 /* always at least 1 entry */
    1064 
    1065     for ( index = 1 ; index <= maximum ; index++ ) {
    1066       the_thread = (Thread_Control *) object_table[ index ];
    1067 
    1068       if ( !the_thread )
    1069         continue;
    1070 
    1071       /*
    1072        *  If this thread is of lower priority than the interested thread,
    1073        *  go on to the next thread.
    1074        */
    1075 
    1076       if ( the_thread->current_priority > interested_priority )
    1077         continue;
    1078 
    1079       /*
    1080        *  If this thread is not interested, then go on to the next thread.
    1081        */
    1082 
    1083       api = the_thread->API_Extensions[ THREAD_API_POSIX ];
    1084 
    1085       if ( !api || !_POSIX_signals_Is_interested( api, mask ) )
    1086         continue;
    1087 
    1088       /*
    1089        *  Now we know the thread under connsideration is interested.
    1090        *  If the thread under consideration is of higher priority, then
    1091        *  it becomes the interested thread.
    1092        */
    1093 
    1094       if ( the_thread->current_priority < interested_priority ) {
    1095         interested_thread   = the_thread;
    1096         interested_priority = the_thread->current_priority;
    1097         continue;
    1098       }
    1099 
    1100       /*
    1101        *  Now the thread and the interested thread have the same priority.
    1102        *  If the interested thread is ready, then we don't need to send it
    1103        *  to a blocked thread.
    1104        */
    1105 
    1106       if ( _States_Is_ready( interested_thread->current_state ) )
    1107         continue;
    1108 
    1109       /*
    1110        *  Now the interested thread is blocked.
    1111        *  If the thread we are considering is not, the it becomes the
    1112        *  interested thread.
    1113        */
    1114 
    1115       if ( _States_Is_ready( the_thread->current_state ) ) {
    1116         interested_thread   = the_thread;
    1117         interested_priority = the_thread->current_priority;
    1118         continue;
    1119       }
    1120 
    1121       /*
    1122        *  Now we know both threads are blocked.
    1123        *  If the interested thread is interruptible, then just use it.
    1124        */
    1125 
    1126       /* XXX need a new states macro */
    1127       if ( interested_thread->current_state & STATES_INTERRUPTIBLE_BY_SIGNAL )
    1128         continue;
    1129 
    1130       /*
    1131        *  Now both threads are blocked and the interested thread is not
    1132        *  interruptible.
    1133        *  If the thread under consideration is interruptible by a signal,
    1134        *  then it becomes the interested thread.
    1135        */
    1136 
    1137       /* XXX need a new states macro */
    1138       if ( the_thread->current_state & STATES_INTERRUPTIBLE_BY_SIGNAL ) {
    1139         interested_thread   = the_thread;
    1140         interested_priority = the_thread->current_priority;
    1141       }
    1142     }
    1143   }
    1144 
    1145   if ( interested_thread ) {
    1146     the_thread = interested_thread;
    1147     goto process_it;
    1148   }
    1149 
    1150   /*
    1151    *  OK so no threads were interested right now.  It will be left on the
    1152    *  global pending until a thread receives it.  The global set of threads
    1153    *  can change interest in this signal in one of the following ways:
    1154    *
    1155    *    + a thread is created with the signal unblocked,
    1156    *    + pthread_sigmask() unblocks the signal,
    1157    *    + sigprocmask() unblocks the signal, OR
    1158    *    + sigaction() which changes the handler to SIG_IGN.
    1159    */
    1160 
    1161   the_thread = NULL;
    1162   goto post_process_signal;
    1163 
    1164   /*
    1165    *  We found a thread which was interested, so now we mark that this
    1166    *  thread needs to do the post context switch extension so it can
    1167    *  evaluate the signals pending.
    1168    */
    1169 
    1170 process_it:
    1171  
    1172   the_thread->do_post_task_switch_extension = TRUE;
    1173 
    1174   /*
    1175    *  Returns TRUE if the signal was synchronously given to a thread
    1176    *  blocked waiting for the signal.
    1177    */
    1178 
    1179   if ( _POSIX_signals_Unblock_thread( the_thread, sig, siginfo ) ) {
    1180     _Thread_Enable_dispatch();
    1181     return 0;
    1182   }
    1183 
    1184 post_process_signal:
    1185 
    1186   /*
    1187    *  We may have woken up a thread but we definitely need to post the
    1188    *  signal to the process wide information set.
    1189    */
    1190 
    1191   _POSIX_signals_Set_process_signals( mask );
    1192 
    1193   if ( _POSIX_signals_Vectors[ sig ].sa_flags == SA_SIGINFO ) {
    1194 
    1195     psiginfo = (POSIX_signals_Siginfo_node *)
    1196                _Chain_Get( &_POSIX_signals_Inactive_siginfo );
    1197     if ( !psiginfo )
    1198       set_errno_and_return_minus_one( EAGAIN );
    1199 
    1200     psiginfo->Info = *siginfo;
    1201 
    1202     _Chain_Append( &_POSIX_signals_Siginfo[ sig ], &psiginfo->Node );
    1203   }
    1204 
    1205   _Thread_Enable_dispatch();
    1206   return 0;
    1207 }
    1208 
    1209 /*PAGE
    1210  *
    1211  *  3.3.2 Send a Signal to a Process, P1003.1b-1993, p. 68
    1212  *
    1213  *  NOTE: Behavior of kill() depends on _POSIX_SAVED_IDS.
    1214  */
    1215 
    1216 int kill(
    1217   pid_t pid,
    1218   int   sig
    1219 )
    1220 {
    1221   return killinfo( pid, sig, NULL );
    1222 }
    1223 
    1224 /*
    1225  *  _kill_r
    1226  *
    1227  *  This is the Newlib dependent reentrant version of kill().
    1228  */
    1229 
    1230 #if defined(RTEMS_NEWLIB)
    1231 
    1232 #include <reent.h>
    1233 
    1234 int _kill_r(
    1235   struct _reent *ptr,
    1236   pid_t          pid,
    1237   int            sig
    1238 )
    1239 {
    1240   return kill( pid, sig );
    1241 }
    1242 #endif
    1243 
    1244 /*
    1245  *  3.3.9 Queue a Signal to a Process, P1003.1b-1993, p. 78
    1246  */
    1247 
    1248 int sigqueue(
    1249   pid_t               pid,
    1250   int                 signo,
    1251   const union sigval  value
    1252 )
    1253 {
    1254   return killinfo( pid, signo, &value );
    1255 }
    1256 
    1257 /*
    1258  *  3.3.10 Send a Signal to a Thread, P1003.1c/D10, p. 43
    1259  */
    1260 
    1261 int pthread_kill(
    1262   pthread_t   thread,
    1263   int         sig
    1264 )
    1265 {
    1266   POSIX_API_Control  *api;
    1267   Thread_Control     *the_thread;
    1268   Objects_Locations  location;
    1269 
    1270   if ( sig && !is_valid_signo(sig) )
    1271     set_errno_and_return_minus_one( EINVAL );
    1272 
    1273   if ( _POSIX_signals_Vectors[ sig ].sa_flags == SA_SIGINFO )
    1274     set_errno_and_return_minus_one( ENOSYS );
    1275 
    1276   /*
    1277    *  RTEMS does not support sending  a siginfo signal to a specific thread.
    1278    */
    1279 
    1280   the_thread = _POSIX_Threads_Get( thread, &location );
    1281   switch ( location ) {
    1282     case OBJECTS_ERROR:
    1283     case OBJECTS_REMOTE:
    1284       set_errno_and_return_minus_one( ESRCH );
    1285     case OBJECTS_LOCAL:
    1286       /*
    1287        *  If sig == 0 then just validate arguments
    1288        */
    1289 
    1290       api = the_thread->API_Extensions[ THREAD_API_POSIX ];
    1291 
    1292       if ( sig ) {
    1293 
    1294         if ( _POSIX_signals_Vectors[ sig ].sa_handler == SIG_IGN ) {
    1295           _Thread_Enable_dispatch();
    1296           return 0;
    1297         }
    1298 
    1299         /* XXX critical section */
    1300 
    1301         api->signals_pending |= signo_to_mask( sig );
    1302 
    1303         (void) _POSIX_signals_Unblock_thread( the_thread, sig, NULL );
    1304 
    1305         the_thread->do_post_task_switch_extension = TRUE;
    1306 
    1307         if ( _ISR_Is_in_progress() && _Thread_Is_executing( the_thread ) )
    1308           _ISR_Signals_to_thread_executing = TRUE;
    1309       }
    1310       _Thread_Enable_dispatch();
    1311       return 0;
    1312   }
    1313 
    1314   return POSIX_BOTTOM_REACHED();
    1315 }
    1316 
    1317 /*
    1318  *  3.4.1 Schedule Alarm, P1003.1b-1993, p. 79
    1319  */
    1320 
    1321 Watchdog_Control _POSIX_signals_Alarm_timer;
    1322 
    1323 unsigned int alarm(
    1324   unsigned int seconds
    1325 )
    1326 {
    1327   unsigned int      remaining = 0;
    1328   Watchdog_Control *the_timer;
    1329 
    1330   the_timer = &_POSIX_signals_Alarm_timer;
    1331 
    1332   switch ( _Watchdog_Remove( the_timer ) ) {
    1333     case WATCHDOG_INACTIVE:
    1334     case WATCHDOG_BEING_INSERTED:
    1335       break;
    1336  
    1337     case WATCHDOG_ACTIVE:
    1338     case WATCHDOG_REMOVE_IT:
    1339       remaining = the_timer->initial -
    1340                   (the_timer->stop_time - the_timer->start_time);
    1341       break;
    1342   }
    1343 
    1344   _Watchdog_Insert_seconds( the_timer, seconds );
    1345 
    1346   return remaining;
    1347 }
    1348 
    1349 /*
    1350  *  3.4.2 Suspend Process Execution, P1003.1b-1993, p. 81
    1351  */
    1352 
    1353 int pause( void )
    1354 {
    1355   sigset_t  all_signals;
    1356   int       status;
    1357  
    1358   (void) sigfillset( &all_signals );
    1359  
    1360   status = sigtimedwait( &all_signals, NULL, NULL );
    1361  
    1362   return status;
    1363 }
Note: See TracChangeset for help on using the changeset viewer.