示例#1
0
void _POSIX_signals_Action_handler(
  Thread_Control  *executing,
  Thread_Action   *action,
  Per_CPU_Control *cpu,
  ISR_Level        level
)
{
  POSIX_API_Control  *api;
  int                 signo;
  ISR_lock_Context    lock_context;
  int                 hold_errno;

  (void) action;
  _Thread_Action_release_and_ISR_enable( cpu, level );

  api = executing->API_Extensions[ THREAD_API_POSIX ];

  /*
   *  We need to ensure that if the signal handler executes a call
   *  which overwrites the unblocking status, we restore it.
   */
  hold_errno = executing->Wait.return_code;

  /*
   * api may be NULL in case of a thread close in progress
   */
  if ( !api )
    return;

  /*
   *  If we invoke any user code, there is the possibility that
   *  a new signal has been posted that we should process so we
   *  restart the loop if a signal handler was invoked.
   *
   *  The first thing done is to check there are any signals to be
   *  processed at all.  No point in doing this loop otherwise.
   */
  while (1) {
    _POSIX_signals_Acquire( &lock_context );
      if ( !(~api->signals_blocked &
            (api->signals_pending | _POSIX_signals_Pending)) ) {
       _POSIX_signals_Release( &lock_context );
       break;
     }
    _POSIX_signals_Release( &lock_context );

    for ( signo = SIGRTMIN ; signo <= SIGRTMAX ; signo++ ) {
      _POSIX_signals_Check_signal( api, signo, false );
      _POSIX_signals_Check_signal( api, signo, true );
    }
    /* Unfortunately - nothing like __SIGFIRSTNOTRT in newlib signal .h */

    for ( signo = SIGHUP ; signo <= __SIGLASTNOTRT ; signo++ ) {
      _POSIX_signals_Check_signal( api, signo, false );
      _POSIX_signals_Check_signal( api, signo, true );
    }
  }

  executing->Wait.return_code = hold_errno;
}
示例#2
0
bool _POSIX_signals_Clear_signals(
  POSIX_API_Control  *api,
  int                 signo,
  siginfo_t          *info,
  bool                is_global,
  bool                check_blocked,
  bool                do_signals_acquire_release
)
{
  sigset_t                    mask;
  sigset_t                    signals_blocked;
  ISR_lock_Context            lock_context;
  bool                        do_callout;
  POSIX_signals_Siginfo_node *psiginfo;

  mask = signo_to_mask( signo );

  do_callout = false;

  /* set blocked signals based on if checking for them, SIGNAL_ALL_MASK
   * insures that no signals are blocked and all are checked.
   */

  if ( check_blocked )
    signals_blocked = ~api->signals_blocked;
  else
    signals_blocked = SIGNAL_ALL_MASK;

  /* XXX is this right for siginfo type signals? */
  /* XXX are we sure they can be cleared the same way? */

  if ( do_signals_acquire_release ) {
    _POSIX_signals_Acquire( &lock_context );
  }

    if ( is_global ) {
       if ( mask & (_POSIX_signals_Pending & signals_blocked) ) {
         if ( _POSIX_signals_Vectors[ signo ].sa_flags == SA_SIGINFO ) {
           psiginfo = (POSIX_signals_Siginfo_node *)
             _Chain_Get_unprotected( &_POSIX_signals_Siginfo[ signo ] );
           _POSIX_signals_Clear_process_signals( signo );
           /*
            *  It may be impossible to get here with an empty chain
            *  BUT until that is proven we need to be defensive and
            *  protect against it.
            */
           if ( psiginfo ) {
             *info = psiginfo->Info;
             _Chain_Append_unprotected(
               &_POSIX_signals_Inactive_siginfo,
               &psiginfo->Node
             );
           } else
             do_callout = false;
         }
         _POSIX_signals_Clear_process_signals( signo );
         do_callout = true;
       }
    } else {
      if ( mask & (api->signals_pending & signals_blocked) ) {
        api->signals_pending &= ~mask;
        do_callout = true;
      }
    }

  if ( do_signals_acquire_release ) {
    _POSIX_signals_Release( &lock_context );
  }

  return do_callout;
}
示例#3
0
static void _POSIX_signals_Action_handler(
  Thread_Control   *executing,
  Thread_Action    *action,
  ISR_lock_Context *lock_context
)
{
  POSIX_API_Control *api;
  int                signo;
  uint32_t           hold_errno;

  (void) action;
  _Thread_State_release( executing, lock_context );

  api = executing->API_Extensions[ THREAD_API_POSIX ];

  /*
   *  We need to ensure that if the signal handler executes a call
   *  which overwrites the unblocking status, we restore it.
   */
  hold_errno = executing->Wait.return_code;

  /*
   * api may be NULL in case of a thread close in progress
   */
  if ( !api )
    return;

  /*
   *  In case the executing thread is blocked or about to block on something
   *  that uses the thread wait information, then this is a kernel bug.
   */
  _Assert(
    ( _Thread_Wait_flags_get( executing )
      & ( THREAD_WAIT_STATE_BLOCKED | THREAD_WAIT_STATE_INTEND_TO_BLOCK ) ) == 0
  );

  /*
   *  If we invoke any user code, there is the possibility that
   *  a new signal has been posted that we should process so we
   *  restart the loop if a signal handler was invoked.
   *
   *  The first thing done is to check there are any signals to be
   *  processed at all.  No point in doing this loop otherwise.
   */
  while (1) {
    Thread_queue_Context queue_context;

    _Thread_queue_Context_initialize( &queue_context );
    _POSIX_signals_Acquire( &queue_context );
      if ( !(api->signals_unblocked &
            (api->signals_pending | _POSIX_signals_Pending)) ) {
       _POSIX_signals_Release( &queue_context );
       break;
     }
    _POSIX_signals_Release( &queue_context );

    for ( signo = SIGRTMIN ; signo <= SIGRTMAX ; signo++ ) {
      _POSIX_signals_Check_signal( api, signo, false );
      _POSIX_signals_Check_signal( api, signo, true );
    }
    /* Unfortunately - nothing like __SIGFIRSTNOTRT in newlib signal .h */

    for ( signo = SIGHUP ; signo <= __SIGLASTNOTRT ; signo++ ) {
      _POSIX_signals_Check_signal( api, signo, false );
      _POSIX_signals_Check_signal( api, signo, true );
    }
  }

  executing->Wait.return_code = hold_errno;
}