コード例 #1
0
void sig_unmaskpendingsignal(void)
{
   FAR _TCB       *rtcb = (FAR _TCB*)g_readytorun.head;
   sigset_t        unmaskedset;
   FAR sigpendq_t *pendingsig;
   int             signo;

   /* Prohibit any context switches until we are done with this.
    * We may still be performing signal operations from interrupt
    * handlers, however, none of the pending signals that we
    * are concerned with here should be effected.
    */

   sched_lock();

   /* Get the set of pending signals that were just unmasked.  The
    * following operation should be safe because the sigprocmask
    * can only be changed on this thread of execution.
    */

   unmaskedset = ~(rtcb->sigprocmask) & sig_pendingset(rtcb);

   /* Loop while there are unmasked pending signals to be processed. */

   while (unmaskedset != NULL_SIGNAL_SET)
    {
      /* Pending signals will be processed from lowest numbered signal
       * to highest
       */

      signo = sig_lowest(&unmaskedset);
      if (signo != ERROR)
        {
          /* Remove the signal from the set of unmasked signals.  NOTE:
           * this implicitly assumes that only one instance for a given
           * signal number is pending.
           */

          sigdelset(&unmaskedset, signo);

          /* Remove the pending signal from the list of pending signals */

          if ((pendingsig = sig_removependingsignal(rtcb, signo)) != NULL)
            {
              /* If there is one, then process it like a normal signal */

              sig_received(rtcb, &pendingsig->info);

              /* Then remove it from the pending signal list */

              sig_releasependingsignal(pendingsig);
            }
        }
    }

  sched_unlock();
}
コード例 #2
0
ファイル: sig_pending.c プロジェクト: jrosberg/NuttX-L21
int sigpending(FAR sigset_t *set)
{
  FAR struct tcb_s *rtcb = (FAR struct tcb_s*)g_readytorun.head;
  int ret = ERROR;

  if (set)
    {
      *set = sig_pendingset(rtcb);
      ret = OK;
    }

  return ret;
}
コード例 #3
0
int sigsuspend(FAR const sigset_t *set)
{
  FAR struct tcb_s *rtcb = (FAR struct tcb_s *)g_readytorun.head;
  sigset_t intersection;
  sigset_t saved_sigprocmask;
  FAR sigpendq_t *sigpend;
  irqstate_t saved_state;
  int unblocksigno;

  /* Several operations must be performed below:  We must determine if any
   * signal is pending and, if not, wait for the signal.  Since signals can
   * be posted from the interrupt level, there is a race condition that
   * can only be eliminated by disabling interrupts!
   */

  sched_lock();  /* Not necessary */
  saved_state = irqsave();

  /* Check if there is a pending signal corresponding to one of the
   * signals that will be unblocked by the new sigprocmask.
   */

  intersection = ~(*set) & sig_pendingset(rtcb);
  if (intersection != NULL_SIGNAL_SET)
    {
      /* One or more of the signals in intersections is sufficient to cause
       * us to not wait.  Pick the lowest numbered signal and mark it not
       * pending.
       */

      unblocksigno = sig_lowest(&intersection);
      sigpend = sig_removependingsignal(rtcb, unblocksigno);
      ASSERT(sigpend);

      sig_releasependingsignal(sigpend);
      irqrestore(saved_state);
    }
  else
    {
      /* Its time to wait. Save a copy of the old sigprocmask and install
       * the new (temporary) sigprocmask
       */

      saved_sigprocmask = rtcb->sigprocmask;
      rtcb->sigprocmask = *set;
      rtcb->sigwaitmask = NULL_SIGNAL_SET;

      /* And wait until one of the unblocked signals is posted */

      up_block_task(rtcb, TSTATE_WAIT_SIG);

      /* We are running again, restore the original sigprocmask */

      rtcb->sigprocmask = saved_sigprocmask;
      irqrestore(saved_state);

      /* Now, handle the (rare?) case where (a) a blocked signal was received
       * while the task was suspended but (b) restoring the original
       * sigprocmask will unblock the signal.
       */

      sig_unmaskpendingsignal();
    }

  sched_unlock();
  return ERROR;
}
コード例 #4
0
ファイル: sig_timedwait.c プロジェクト: rmsilva/nuttx
int sigtimedwait(FAR const sigset_t *set, FAR struct siginfo *info,
                 FAR const struct timespec *timeout)
{
    FAR struct tcb_s *rtcb = (FAR struct tcb_s*)g_readytorun.head;
    sigset_t intersection;
    FAR sigpendq_t *sigpend;
    irqstate_t saved_state;
    int32_t waitticks;
    int ret = ERROR;

    DEBUGASSERT(rtcb->waitdog == NULL);

    sched_lock();  /* Not necessary */

    /* Several operations must be performed below:  We must determine if any
     * signal is pending and, if not, wait for the signal.  Since signals can
     * be posted from the interrupt level, there is a race condition that
     * can only be eliminated by disabling interrupts!
     */

    saved_state = irqsave();

    /* Check if there is a pending signal corresponding to one of the
     * signals in the pending signal set argument.
     */

    intersection = *set & sig_pendingset(rtcb);
    if (intersection != NULL_SIGNAL_SET)
    {
        /* One or more of the signals in intersections is sufficient to cause
         * us to not wait.  Pick the lowest numbered signal and mark it not
         * pending.
         */

        sigpend = sig_removependingsignal(rtcb, sig_lowest(&intersection));
        ASSERT(sigpend);

        /* Return the signal info to the caller if so requested */

        if (info)
        {
            memcpy(info, &sigpend->info, sizeof(struct siginfo));
        }

        /* Then dispose of the pending signal structure properly */

        sig_releasependingsignal(sigpend);
        irqrestore(saved_state);

        /* The return value is the number of the signal that awakened us */

        ret = sigpend->info.si_signo;
    }

    /* We will have to wait for a signal to be posted to this task. */

    else
    {
        /* Save the set of pending signals to wait for */

        rtcb->sigwaitmask = *set;

        /* Check if we should wait for the timeout */

        if (timeout)
        {
            /* Convert the timespec to system clock ticks, making sure that
             * the resulting delay is greater than or equal to the requested
             * time in nanoseconds.
             */

#ifdef CONFIG_HAVE_LONG_LONG
            uint64_t waitticks64 = ((uint64_t)timeout->tv_sec * NSEC_PER_SEC +
                                    (uint64_t)timeout->tv_nsec + NSEC_PER_TICK - 1) /
                                   NSEC_PER_TICK;
            DEBUGASSERT(waitticks64 <= UINT32_MAX);
            waitticks = (uint32_t)waitticks64;
#else
            uint32_t waitmsec;

            DEBUGASSERT(timeout->tv_sec < UINT32_MAX / MSEC_PER_SEC);
            waitmsec = timeout->tv_sec * MSEC_PER_SEC +
                       (timeout->tv_nsec + NSEC_PER_MSEC - 1) / NSEC_PER_MSEC;
            waitticks = MSEC2TICK(waitmsec);
#endif

            /* Create a watchdog */

            rtcb->waitdog = wd_create();
            DEBUGASSERT(rtcb->waitdog);

            if (rtcb->waitdog)
            {
                /* This little bit of nonsense is necessary for some
                 * processors where sizeof(pointer) < sizeof(uint32_t).
                 * see wdog.h.
                 */

                wdparm_t wdparm;
                wdparm.pvarg = (FAR void *)rtcb;

                /* Start the watchdog */

                wd_start(rtcb->waitdog, waitticks, (wdentry_t)sig_timeout, 1,
                         wdparm.dwarg);

                /* Now wait for either the signal or the watchdog */

                up_block_task(rtcb, TSTATE_WAIT_SIG);

                /* We no longer need the watchdog */

                wd_delete(rtcb->waitdog);
                rtcb->waitdog = NULL;
            }

            /* REVISIT: And do what if there are no watchdog timers?  The wait
             * will fail and we will return something bogus.
             */
        }

        /* No timeout, just wait */

        else
        {
            /* And wait until one of the unblocked signals is posted */

            up_block_task(rtcb, TSTATE_WAIT_SIG);
        }

        /* We are running again, clear the sigwaitmask */

        rtcb->sigwaitmask = NULL_SIGNAL_SET;

        /* When we awaken, the cause will be in the TCB.  Get the signal number
         * or timeout) that awakened us.
         */

        if (GOOD_SIGNO(rtcb->sigunbinfo.si_signo))
        {
            /* We were awakened by a signal... but is it one of the signals that
             * we were waiting for?
             */

            if (sigismember(set, rtcb->sigunbinfo.si_signo))
            {
                /* Yes.. the return value is the number of the signal that
                 * awakened us.
                 */

                ret = rtcb->sigunbinfo.si_signo;
            }
            else
            {
                /* No... then set EINTR and report an error */

                set_errno(EINTR);
                ret = ERROR;
            }
        }
        else
        {
            /* Otherwise, we must have been awakened by the timeout.  Set EGAIN
             * and return an error.
             */

            DEBUGASSERT(rtcb->sigunbinfo.si_signo == SIG_WAIT_TIMEOUT);
            set_errno(EAGAIN);
            ret = ERROR;
        }

        /* Return the signal info to the caller if so requested */

        if (info)
        {
            memcpy(info, &rtcb->sigunbinfo, sizeof(struct siginfo));
        }

        irqrestore(saved_state);
    }

    sched_unlock();
    return ret;
}