Ejemplo n.º 1
0
int sig_received(FAR _TCB *stcb, siginfo_t *info)
{
  irqstate_t saved_state;
  int        ret = ERROR;

  sdbg("TCB=0x%08x signo=%d code=%d value=%d mask=%08x\n",
       stcb, info->si_signo, info->si_code,
       info->si_value.sival_int, stcb->sigprocmask);

  if (stcb && info)
    {
      ret = OK;

      /****************** MASKED SIGNAL HANDLING ******************/

      /* Check if the signal is masked -- if it is, it will be added to the
       * list of pending signals.
       */

      if (sigismember(&stcb->sigprocmask, info->si_signo))
        {
          /* Check if the task is waiting for this pending signal.  If so,
           * then unblock it. This must be performed in a critical section
           * because signals can be queued from the interrupt level.
           */

          saved_state = irqsave();
          if (stcb->task_state == TSTATE_WAIT_SIG &&
              sigismember(&stcb->sigwaitmask, info->si_signo))
            {
              memcpy(&stcb->sigunbinfo, info, sizeof(siginfo_t));
              stcb->sigwaitmask = NULL_SIGNAL_SET;
              up_unblock_task(stcb);
              irqrestore(saved_state);
            }

          /* Its not one we are waiting for... Add it to the list of pending
           * signals.
           */

          else
            {
              irqrestore(saved_state);
              if (!sig_addpendingsignal(stcb, info))
                {
                  PANIC(OSERR_FAILEDTOADDSIGNAL);
                }
            }
        }

      /****************** UNMASKED SIGNAL HANDLING ******************/

      else
        {
          /* Queue any sigaction's requested by this task. */

          ret = sig_queueaction(stcb, info);

          /* Then schedule execution of the signal handling action on
           * the recipients thread.
           */

          up_schedule_sigaction(stcb, sig_deliver);

          /* Check if the task is waiting for an unmasked signal.  If so,
           * then unblock it. This must be performed in a critical section
           * because signals can be queued from the interrupt level.
           */

          saved_state = irqsave();
          if (stcb->task_state == TSTATE_WAIT_SIG)
            {
              memcpy(&stcb->sigunbinfo, info, sizeof(siginfo_t));
              stcb->sigwaitmask = NULL_SIGNAL_SET;
              up_unblock_task(stcb);
            }
          irqrestore(saved_state);

          /* If the task neither was waiting for the signal nor had a signal
           * handler attached to the signal, then the default action is
           * simply to ignore the signal
           */

          /****************** OTHER SIGNAL HANDLING ******************/

         /* If the task is blocked waiting for a semaphore, then that
          * task must be unblocked when a signal is received.
          */

         if (stcb->task_state == TSTATE_WAIT_SEM)
           {
             sem_waitirq(stcb);
           }

         /* If the task is blocked waiting on a message queue, then that
          * task must be unblocked when a signal is received.
          */

#ifndef CONFIG_DISABLE_MQUEUE
        if (stcb->task_state == TSTATE_WAIT_MQNOTEMPTY ||
            stcb->task_state == TSTATE_WAIT_MQNOTFULL)
           {
             mq_waitirq(stcb);
           }
#endif
       }
   }

  return ret;
}
Ejemplo n.º 2
0
int sig_tcbdispatch(FAR struct tcb_s *stcb, siginfo_t *info)
{
  irqstate_t saved_state;
  int ret = OK;

  sdbg("TCB=0x%08x signo=%d code=%d value=%d mask=%08x\n",
       stcb, info->si_signo, info->si_code,
       info->si_value.sival_int, stcb->sigprocmask);

  DEBUGASSERT(stcb && info);

  /************************* MASKED SIGNAL HANDLING ************************/

  /* Check if the signal is masked -- if it is, it will be added to the list
   * of pending signals.
   */

  if (sigismember(&stcb->sigprocmask, info->si_signo))
    {
      /* Check if the task is waiting for this pending signal.  If so, then unblock it.
       * This must be performed in a critical section because signals can be queued
       * from the interrupt level.
       */

      saved_state = irqsave();
      if (stcb->task_state == TSTATE_WAIT_SIG &&
          sigismember(&stcb->sigwaitmask, info->si_signo))
        {
          memcpy(&stcb->sigunbinfo, info, sizeof(siginfo_t));
          stcb->sigwaitmask = NULL_SIGNAL_SET;
          up_unblock_task(stcb);
          irqrestore(saved_state);
        }

      /* Its not one we are waiting for... Add it to the list of pending
       * signals.
       */

      else
        {
          irqrestore(saved_state);
          FAR sigpendq_t *sigpend = sig_addpendingsignal(stcb, info);
          ASSERT(sigpend);
#ifdef __clang_analyzer__
          /* clang analyzer does not understand memory ownership transfer */
          free(sigpend);
#endif
        }
    }

  /************************ UNMASKED SIGNAL HANDLING ***********************/

  else
    {
      /* Queue any sigaction's requested by this task. */

      ret = sig_queueaction(stcb, info);

      /* Then schedule execution of the signal handling action on the
       * recipient's thread.
       */

      up_schedule_sigaction(stcb, sig_deliver);

      /* Check if the task is waiting for an unmasked signal.  If so, then
       * unblock it. This must be performed in a critical section because
       * signals can be queued from the interrupt level.
       */

      saved_state = irqsave();
      if (stcb->task_state == TSTATE_WAIT_SIG)
        {
          memcpy(&stcb->sigunbinfo, info, sizeof(siginfo_t));
          stcb->sigwaitmask = NULL_SIGNAL_SET;
          up_unblock_task(stcb);
        }

      irqrestore(saved_state);

      /* If the task neither was waiting for the signal nor had a signal
       * handler attached to the signal, then the default action is
       * simply to ignore the signal
       */

      /*********************** OTHER SIGNAL HANDLING ***********************/

      /* If the task is blocked waiting for a semaphore, then that task must
       * be unblocked when a signal is received.
       */

      if (stcb->task_state == TSTATE_WAIT_SEM)
        {
          sem_waitirq(stcb, EINTR);
        }

      /* If the task is blocked waiting on a message queue, then that task
       * must be unblocked when a signal is received.
       */

#ifndef CONFIG_DISABLE_MQUEUE
      if (stcb->task_state == TSTATE_WAIT_MQNOTEMPTY ||
          stcb->task_state == TSTATE_WAIT_MQNOTFULL)
        {
          mq_waitirq(stcb, EINTR);
        }
#endif
    }

  return ret;
}