Ejemplo n.º 1
0
int sigqueue(int pid, int signo, void *sival_ptr)
#endif
{
#ifdef CONFIG_SCHED_HAVE_PARENT
  FAR struct tcb_s *rtcb = this_task();
#endif
  siginfo_t info;
  int ret;

#ifdef CONFIG_CAN_PASS_STRUCTS
  sdbg("pid=0x%08x signo=%d value=%d\n", pid, signo, value.sival_int);
#else
  sdbg("pid=0x%08x signo=%d value=%p\n", pid, signo, sival_ptr);
#endif

  /* Sanity checks */

  if (!GOOD_SIGNO(signo))
    {
      ret = -EINVAL;
      goto errout;
    }

  /* Create the siginfo structure */

  info.si_signo           = signo;
  info.si_code            = SI_QUEUE;
  info.si_errno           = OK;
#ifdef CONFIG_CAN_PASS_STRUCTS
  info.si_value           = value;
#else
  info.si_value.sival_ptr = sival_ptr;
#endif
#ifdef CONFIG_SCHED_HAVE_PARENT
  info.si_pid             = rtcb->pid;
  info.si_status          = OK;
#endif

  /* Send the signal */

  sched_lock();
  ret = sig_dispatch(pid, &info);
  sched_unlock();

  /* Check for errors */

  if (ret < 0)
    {
      goto errout;
    }

  return OK;

errout:
  set_errno(-ret);
  return ERROR;
}
Ejemplo n.º 2
0
int kill(pid_t pid, int signo)
{
#ifdef CONFIG_SCHED_HAVE_PARENT
  FAR struct tcb_s *rtcb = (FAR struct tcb_s *)g_readytorun.head;
#endif
  siginfo_t info;
  int ret;

  /* We do not support sending signals to process groups */

  if (pid <= 0)
    {
      ret = -ENOSYS;
      goto errout;
    }

  /* Make sure that the signal is valid */

  if (!GOOD_SIGNO(signo))
    {
      ret = -EINVAL;
      goto errout;
    }

  /* Keep things stationary through the following */

  sched_lock();

  /* Create the siginfo structure */

  info.si_signo           = signo;
  info.si_code            = SI_USER;
  info.si_errno           = EINTR;
  info.si_value.sival_ptr = NULL;
#ifdef CONFIG_SCHED_HAVE_PARENT
  info.si_pid             = rtcb->pid;
  info.si_status          = OK;
#endif

  /* Send the signal */

  ret = sig_dispatch(pid, &info);
  sched_unlock();

  if (ret < 0)
    {
      goto errout;
    }

  return OK;

errout:
  set_errno(-ret);
  return ERROR;
}
Ejemplo n.º 3
0
_sa_handler_t signal(int signo, _sa_handler_t func)
{
  struct sigaction act;
  struct sigaction oact;
  int ret;

  DEBUGASSERT(GOOD_SIGNO(signo) && func != SIG_ERR && func != SIG_HOLD);

  /* Initialize the sigaction structure */

  act.sa_handler = func;
  act.sa_flags   = 0;
  (void)sigemptyset(&act.sa_mask);

  /* Check for SIG_IGN and SIG_DFL (and someday SIG_HOLD)
   *
   * REVISIT:  Currently SIG_IGN, SIG_DFL, and SIG_HOLD have the same value
   * and cannot be distinguished.
   */

  if (func != SIG_DFL /* && func != SIG_IGN */)
    {
      /* Add the signal to the set of signals to be ignored when the signal
       * handler executes.
       */

      ret = sigaddset(&act.sa_mask, signo);
      if (ret < 0)
        {
          /* Would happen if signo were invalid */

          return (_sa_handler_t)SIG_ERR;
        }
    }

  /* Set the signal disposition */

  ret = sigaction(signo, &act, &oact);

  /* Upon successful completion, signal() will the signal's previous
   * disposition. Otherwise, SIG_ERR will be returned and errno set to
   * indicate the error.
   */

  if (ret == OK)
   {
     return oact.sa_handler;
   }

  return (_sa_handler_t)SIG_ERR;
}
Ejemplo n.º 4
0
int sigdelset(FAR sigset_t *set, int signo)
{
	int ret = ERROR;

	/* Verify the signal */

	if (GOOD_SIGNO(signo)) {
		/* Delete the signal to the set */

		*set &= ~SIGNO2SET(signo);
		ret = OK;
	}

	return ret;
}
Ejemplo n.º 5
0
int sigismember(FAR const sigset_t *set, int signo)
{
  int ret = ERROR;

  /* Verify the signal */

  if (GOOD_SIGNO(signo))
    {
      /* Check if the signal is in the set */

      ret = ((*set & SIGNO2SET(signo)) != 0);
    }

  return ret;
}
Ejemplo n.º 6
0
int sigaddset(FAR sigset_t *set, int signo)
{
  int ret = ERROR;

  /* Verify the signal */

  if (GOOD_SIGNO(signo))
    {
      /* Add the signal to the set */

      *set |= SIGNO2SET(signo);
      ret = OK;
    }

  return ret;
}
Ejemplo n.º 7
0
int sigaddset(FAR sigset_t *set, int signo)
{
  /* Verify the signal */

  if (!GOOD_SIGNO(signo))
    {
      set_errno(EINVAL);
      return ERROR;
    }
  else
    {
      /* Add the signal to the set */

      *set |= SIGNO2SET(signo);
      return OK;
    }
}
Ejemplo n.º 8
0
CODE void (*sigset(int signo, CODE void (*func)(int signo)))(int signo)
{
  _sa_handler_t disposition;
  sigset_t set;
  int ret;

  DEBUGASSERT(GOOD_SIGNO(signo) && func != SIG_ERR);

  (void)sigemptyset(&set);
  (void)sigaddset(&set, signo);

  /* Check if we are being asked to block the signal */

  if (func == SIG_HOLD)
    {
      ret = sigprocmask(SIG_BLOCK, &set, NULL);
      disposition = ret < 0 ? SIG_ERR : SIG_HOLD;
    }

  /* No.. then signal can handle the other cases */

  else
    {
      /* Set the signal handler disposition */

      disposition = signal(signo, func);
      if (disposition != SIG_ERR)
        {
          /* And unblock the signal */

          ret = sigprocmask(SIG_UNBLOCK, &set, NULL);
          if (ret < 0)
            {
              /* Restore the original signal disposition and return and
               * error.
               */

              (void)signal(signo, disposition);
              disposition = SIG_ERR;
            }
        }
    }

  return disposition;
}
Ejemplo n.º 9
0
int sig_mqnotempty(int pid, int signo, void *sival_ptr)
#endif
{
#ifdef CONFIG_SCHED_HAVE_PARENT
  FAR struct tcb_s *rtcb = (FAR struct tcb_s *)g_readytorun.head;
#endif
  siginfo_t info;
  int ret;

#ifdef CONFIG_CAN_PASS_STRUCTS
  sdbg("pid=%p signo=%d value=%d\n", pid, signo, value.sival_int);
#else
  sdbg("pid=%p signo=%d sival_ptr=%p\n", pid, signo, sival_ptr);
#endif

  /* Verify that we can perform the signalling operation */

  if (!GOOD_SIGNO(signo))
    {
      return -EINVAL;
    }

  /* Create the siginfo structure */

  info.si_signo           = signo;
  info.si_code            = SI_MESGQ;
#ifdef CONFIG_CAN_PASS_STRUCTS
  info.si_value           = value;
#else
  info.si_value.sival_ptr = sival_ptr;
#endif
#ifdef CONFIG_SCHED_HAVE_PARENT
  info.si_pid             = rtcb->pid;
  info.si_status          = OK;
#endif

  /* Process the receipt of the signal */

  sched_lock();
  ret = sig_dispatch(pid, &info);
  sched_unlock();

  return ret;
}
Ejemplo n.º 10
0
int sig_mqnotempty (int pid, int signo, void *sival_ptr)
#endif
{
  FAR _TCB *stcb;
  siginfo_t info;
  int       ret = ERROR;

  sched_lock();

  /* Get the TCB of the receiving task */

  stcb = sched_gettcb(pid);

#ifdef CONFIG_CAN_PASS_STRUCTS
  sdbg("TCB=%p signo=%d value=%d\n", stcb, signo, value.sival_int);
#else
  sdbg("TCB=%p signo=%d sival_ptr=%p\n", stcb, signo, sival_ptr);
#endif

  /* Create the siginfo structure */

  info.si_signo           = signo;
  info.si_code            = SI_MESGQ;
#ifdef CONFIG_CAN_PASS_STRUCTS
  info.si_value           = value;
#else
  info.si_value.sival_ptr = sival_ptr;
#endif

  /* Verify that we can perform the signalling operation */

  if ((stcb) && (GOOD_SIGNO(signo)))
   {
     /* Process the receipt of the signal */
     ret = sig_received(stcb, &info);
   }

  sched_unlock();
  return ret;
}
Ejemplo n.º 11
0
static void ft80x_notify(FAR struct ft80x_dev_s *priv,
                         enum ft80x_notify_e event, int arg)
{
  FAR struct ft80x_eventinfo_s *info = &priv->notify[event];
#ifdef CONFIG_CAN_PASS_STRUCTS
  union sigval value;
#endif

  /* Are notifications enabled for this event? */

  if (info->enable)
    {
      DEBUGASSERT(info->signo > 0 && GOOD_SIGNO(info->signo) && info->pid > 0);

      /* Yes.. Signal the client */

#ifdef CONFIG_CAN_PASS_STRUCTS
      value.sival_int = arg;
      (void)nxsig_queue(info->pid, info->signo, value);
#else
      (void)nxsig_queue(info->pid, info->signo, (FAR void *)arg);
#endif
    }
}
Ejemplo n.º 12
0
static int ft80x_ioctl(FAR struct file *filep, int cmd, unsigned long arg)
{
  FAR struct inode *inode;
  FAR struct ft80x_dev_s *priv;
  int ret;

  DEBUGASSERT(filep != NULL);
  inode = filep->f_inode;
  DEBUGASSERT(inode != NULL && inode->i_private != NULL);
  priv  = inode->i_private;

  lcdinfo("cmd: %d arg: %lu\n", cmd, arg);

  /* Get exclusive access to the device structures */

  ret = nxsem_wait(&priv->exclsem);
  if (ret < 0)
    {
      return ret;
    }

  /* Handle built-in ioctl commands */

  switch (cmd)
    {
      /* FT80X_IOC_CREATEDL:
       *   Description:  Write a display list to the FT80x display list memory
       *   Description:  Write a display list to the FT80x display list memory
       *                 starting at offset zero.  This may or may not be the
       *                 entire display list.  Display lists may be created
       *                 incrementally, starting with FT80X_IOC_CREATEDL and
       *                 finishing the display list using FT80XIO_APPENDDL
       *   Argument:     A reference to a display list structure instance.
       *                 See struct ft80x_displaylist_s.
       *   Returns:      None
       */

      case FT80X_IOC_CREATEDL:

        /* Set the file position to zero and fall through to "append" the new
         * display list data at offset 0.
         */

        filep->f_pos = 0;

        /* FALLTHROUGH */

      /* FT80X_IOC_APPENDDL:
       *   Description:  Write additional display list entries to the FT80x
       *                 display list memory at the current display list offset.
       *                 This IOCTL command permits display lists to be completed
       *                 incrementally, starting with FT80X_IOC_CREATEDL and
       *                 finishing the display list using FT80XIO_APPENDDL.
       *   Argument:     A reference to a display list structure instance.  See
       *                 struct ft80x_displaylist_s.
       *   Returns:      None
       */

      case FT80X_IOC_APPENDDL:
        {
          FAR struct ft80x_displaylist_s *dl =
            (FAR struct ft80x_displaylist_s *)((uintptr_t)arg);

          if (dl == NULL || ((uintptr_t)&dl->cmd & 3) != 0 ||
              (dl->dlsize & 3) != 0 ||
              dl->dlsize + filep->f_pos > FT80X_RAM_DL_SIZE)
            {
              ret = -EINVAL;
            }
          else
            {
              /* Check if there is a display list.  It might be useful for
               * the application to issue FT80X_IOC_CREATEDL with no data in
               * order to initialize the display list, then form all of the
               * list entries with FT80X_IOC_APPENDDL.
               */

              if (dl->dlsize > 0)
                {
                  /* This IOCTL command simply copies the display list
                   * provided into the FT80x display list memory.
                   */

                  ft80x_write_memory(priv, FT80X_RAM_DL + filep->f_pos,
                                     &dl->cmd, dl->dlsize);
                  filep->f_pos += dl->dlsize;
                }

              ret = OK;
            }
        }
        break;

      /* FT80X_IOC_GETRAMDL:
       *   Description:  Read a 32-bit value from the display list.
       *   Argument:     A reference to an instance of struct ft80x_relmem_s.
       *   Returns:      The 32-bit value read from the display list.
       */

      case FT80X_IOC_GETRAMDL:
        {
          FAR struct ft80x_relmem_s *ramdl =
            (FAR struct ft80x_relmem_s *)((uintptr_t)arg);

          if (ramdl == NULL || ((uintptr_t)ramdl->offset & 3) != 0 ||
              ramdl->offset >= FT80X_RAM_DL_SIZE)
            {
              ret = -EINVAL;
            }
          else
            {
              ft80x_read_memory(priv, FT80X_RAM_DL + ramdl->offset,
                                ramdl->value, ramdl->nbytes);
              ret = OK;
            }
        }
        break;

      /* FT80X_IOC_PUTRAMG
       *   Description:  Write byte data to FT80x graphics memory (RAM_G)
       *   Argument:     A reference to an instance of struct ft80x_relmem_s.
       *   Returns:      None.
       */

      case FT80X_IOC_PUTRAMG:
        {
          FAR struct ft80x_relmem_s *ramg =
            (FAR struct ft80x_relmem_s *)((uintptr_t)arg);

          if (ramg == NULL ||
             (ramg->offset + ramg->nbytes) >= FT80X_RAM_G_SIZE)
            {
              ret = -EINVAL;
            }
          else
            {
              ft80x_write_memory(priv, FT80X_RAM_G + ramg->offset,
                                 ramg->value, ramg->nbytes);
              ret = OK;
            }
        }
        break;

      /* FT80X_IOC_PUTRAMCMD
       *   Description:  Write 32-bit aligned data to FT80x FIFO (RAM_CMD)
       *   Argument:     A reference to an instance of struct ft80x_relmem_s below.
       *   Returns:      None.
       */

      case FT80X_IOC_PUTRAMCMD:
        {
          FAR struct ft80x_relmem_s *ramcmd =
            (FAR struct ft80x_relmem_s *)((uintptr_t)arg);

          if (ramcmd == NULL || ((uintptr_t)ramcmd->offset & 3) != 0 /* ||
              ramcmd->offset >= FT80X_CMDFIFO_SIZE */ )
            {
              ret = -EINVAL;
            }
          else
            {
              ft80x_write_memory(priv, FT80X_RAM_CMD + ramcmd->offset,
                                ramcmd->value, ramcmd->nbytes);
              ret = OK;
            }
        }
        break;

      /* FT80X_IOC_GETREG8:
       *   Description:  Read an 8-bit register value from the FT80x.
       *   Argument:     A reference to an instance of struct ft80x_register_s.
       *   Returns:      The 8-bit value read from the register.
       */

      case FT80X_IOC_GETREG8:
        {
          FAR struct ft80x_register_s *reg =
            (FAR struct ft80x_register_s *)((uintptr_t)arg);

          if (reg == NULL || ((uintptr_t)reg->addr & 3) != 0)
            {
              ret = -EINVAL;
            }
          else
            {
              reg->value.u8 = ft80x_read_byte(priv, reg->addr);
              ret = OK;
            }
        }
        break;

      /* FT80X_IOC_GETREG16:
       *   Description:  Read a 16-bit register value from the FT80x.
       *   Argument:     A reference to an instance of struct ft80x_register_s.
       *   Returns:      The 16-bit value read from the register.
       */

      case FT80X_IOC_GETREG16:
        {
          FAR struct ft80x_register_s *reg =
            (FAR struct ft80x_register_s *)((uintptr_t)arg);

          if (reg == NULL || ((uintptr_t)reg->addr & 3) != 0)
            {
              ret = -EINVAL;
            }
          else
            {
              reg->value.u16 = ft80x_read_hword(priv, reg->addr);
              ret = OK;
            }
        }
        break;

      /* FT80X_IOC_GETREG32:
       *   Description:  Read a 32-bit register value from the FT80x.
       *   Argument:     A reference to an instance of struct ft80x_register_s.
       *   Returns:      The 32-bit value read from the register.
       */

      case FT80X_IOC_GETREG32:
        {
          FAR struct ft80x_register_s *reg =
            (FAR struct ft80x_register_s *)((uintptr_t)arg);

          if (reg == NULL || ((uintptr_t)reg->addr & 3) != 0)
            {
              ret = -EINVAL;
            }
          else
            {
              reg->value.u32 = ft80x_read_word(priv, reg->addr);
              ret = OK;
            }
        }
        break;

      /* FT80X_IOC_GETREGS:
       *   Description:  Read multiple 32-bit register values from the FT80x.
       *   Argument:     A reference to an instance of struct ft80x_registers_s.
       *   Returns:      The 32-bit values read from the consecutive registers .
       */

      case FT80X_IOC_GETREGS:
        {
          FAR struct ft80x_registers_s *regs =
            (FAR struct ft80x_registers_s *)((uintptr_t)arg);

          if (regs == NULL || ((uintptr_t)regs->addr & 3) != 0)
            {
              ret = -EINVAL;
            }
          else
            {
              ft80x_read_memory(priv, regs->addr, regs->value,
                                (size_t)regs->nregs << 2);
              ret = OK;
            }
        }
        break;

      /* FT80X_IOC_PUTREG8:
       *   Description:  Write an 8-bit register value to the FT80x.
       *   Argument:     A reference to an instance of struct ft80x_register_s.
       *   Returns:      None.
       */

      case FT80X_IOC_PUTREG8:
        {
          FAR struct ft80x_register_s *reg =
            (FAR struct ft80x_register_s *)((uintptr_t)arg);

          if (reg == NULL || ((uintptr_t)reg->addr & 3) != 0)
            {
              ret = -EINVAL;
            }
          else
            {
              ft80x_write_byte(priv, reg->addr, reg->value.u8);
              ret = OK;
            }
        }
        break;

      /* FT80X_IOC_PUTREG16:
       *   Description:  Write a 16-bit  register value to the FT80x.
       *   Argument:     A reference to an instance of struct ft80x_register_s.
       *   Returns:      None.
       */

      case FT80X_IOC_PUTREG16:
        {
          FAR struct ft80x_register_s *reg =
            (FAR struct ft80x_register_s *)((uintptr_t)arg);

          if (reg == NULL || ((uintptr_t)reg->addr & 3) != 0)
            {
              ret = -EINVAL;
            }
          else
            {
              ft80x_write_hword(priv, reg->addr, reg->value.u16);
              ret = OK;
            }
        }
        break;

      /* FT80X_IOC_PUTREG32:
       *   Description:  Write a 32-bit  register value to the FT80x.
       *   Argument:     A reference to an instance of struct ft80x_register_s.
       *   Returns:      None.
       */

      case FT80X_IOC_PUTREG32:
        {
          FAR struct ft80x_register_s *reg =
            (FAR struct ft80x_register_s *)((uintptr_t)arg);

          if (reg == NULL || ((uintptr_t)reg->addr & 3) != 0)
            {
              ret = -EINVAL;
            }
          else
            {
              ft80x_write_word(priv, reg->addr, reg->value.u32);
              ret = OK;
            }
        }
        break;

      /* FT80X_IOC_PUTREGS:
       *   Description:  Write multiple 32-bit register values to the FT80x.
       *   Argument:     A reference to an instance of struct ft80x_registers_s.
       *   Returns:      None.
       */

      case FT80X_IOC_PUTREGS:
        {
          FAR struct ft80x_registers_s *regs =
            (FAR struct ft80x_registers_s *)((uintptr_t)arg);

          if (regs == NULL || ((uintptr_t)regs->addr & 3) != 0)
            {
              ret = -EINVAL;
            }
          else
            {
              ft80x_write_memory(priv, regs->addr, regs->value,
                                 (size_t)regs->nregs << 2);
              ret = OK;
            }
        }
        break;

      /* FT80X_IOC_EVENTNOTIFY:
       *   Description:  Setup to receive a signal when an event occurs.
       *   Argument:     A reference to an instance of struct ft80x_notify_s.
       *   Returns:      None
       */

      case FT80X_IOC_EVENTNOTIFY:
        {
          FAR struct ft80x_notify_s *notify =
            (FAR struct ft80x_notify_s *)((uintptr_t)arg);

          if (notify == NULL || !GOOD_SIGNO(notify->signo) || notify->pid < 0 ||
              (unsigned int)notify->event >= FT80X_INT_NEVENTS)
            {
              ret = -EINVAL;
            }
          else
            {
              FAR struct ft80x_eventinfo_s *info = &priv->notify[notify->event];
              uint32_t regval;

              /* Are we enabling or disabling */

              if (notify->enable)
                {
                  /* Make sure that arguments are valid for the enable */

                  if (notify->signo == 0 || notify->pid == 0)
                    {
                      ret = -EINVAL;
                    }
                  else
                    {
                      /* Setup the new notification information */

                      info->signo  = notify->signo;
                      info->pid    = notify->pid;
                      info->enable = true;

                      /* Enable interrupts associated with the event */

                      regval  = ft80x_read_word(priv, FT80X_REG_INT_MASK);
                      regval |= (1 << notify->event);
                      ft80x_write_word(priv, FT80X_REG_INT_MASK, regval);
                      ret = OK;
                    }
                }
              else
                {
                  /* Disable the notification */

                  info->signo  = 0;
                  info->pid    = 0;
                  info->enable = false;

                  /* Disable interrupts associated with the event */

                  regval  = ft80x_read_word(priv, FT80X_REG_INT_MASK);
                  regval &= ~(1 << notify->event);
                  ft80x_write_word(priv, FT80X_REG_INT_MASK, regval);
                  ret = OK;
                }
            }
        }
        break;

       /* FT80X_IOC_FADE:
        *   Description:  Change the backlight intensity with a controllable
        *                 fade.
        *   Argument:     A reference to an instance of struct ft80x_fade_s.
        *   Returns:      None.
        */

       case FT80X_IOC_FADE:
        {
          FAR const struct ft80x_fade_s *fade =
            (FAR const struct ft80x_fade_s *)((uintptr_t)arg);

          if (fade == NULL || fade->duty > 100 ||
              fade->delay < MIN_FADE_DELAY || fade->delay > MAX_FADE_DELAY)
            {
              ret = -EINVAL;
            }
          else
            {
              ret = ft80x_fade(priv, fade);
            }
        }
        break;

       /* FT80X_IOC_AUDIO:
        *   Description:  Enable/disable an external audio amplifer.
        *   Argument:     0=disable; 1=enable.
        *   Returns:      None.
        */

       case FT80X_IOC_AUDIO:
        {
#if defined(CONFIG_LCD_FT80X_AUDIO_MCUSHUTDOWN)
          /* Amplifier is controlled by an MCU GPIO pin */

          DEBUGASSERT(priv->lower->attach != NULL && priv->lower->audio != NULL);
          DEBUGASSERT(arg == 0 || arg == 1);

          priv->lower->audio(priv->lower, (arg != 0));
          ret = OK;

#elif defined(CONFIG_LCD_FT80X_AUDIO_GPIOSHUTDOWN)
          /* Amplifier is controlled by an FT80x GPIO pin */

          uint8_t regval8;

          DEBUGASSERT(arg == 0 || arg == 1);

          regval8  = ft80x_read_byte(priv, FT80X_REG_GPIO);

          /* Active low logic assumed */

          if (arg == 0)
            {
              regval8 |= (1 << CONFIG_LCD_FT80X_AUDIO_GPIO);
            }
          else
            {
              regval8 &= ~(1 << CONFIG_LCD_FT80X_AUDIO_GPIO);
            }

          ft80x_write_byte(priv, FT80X_REG_GPIO, regval8);
          ret = OK;

#else
          /* Amplifier is not controllable. */

          DEBUGASSERT(arg == 0 || arg == 1);
          return OK;
#endif
        }
        break;

      /* Unrecognized IOCTL command */

      default:
        lcderr("ERROR: Unrecognized cmd: %d arg: %ld\n", cmd, arg);
        ret = -ENOTTY;
        break;
    }

  nxsem_post(&priv->exclsem);
  return ret;
}
Ejemplo n.º 13
0
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;
}
Ejemplo n.º 14
0
int pthread_kill(pthread_t thread, int signo)
{
#ifdef HAVE_GROUP_MEMBERS
    /* If group members are support then pthread_kill() differs from kill().
     * kill(), in this case, must following the POSIX rules for delivery of
     * signals in the group environment.  Otherwise, kill(), like
     * pthread_kill() will just deliver the signal to the thread ID it is
     * requested to use.
     */

#ifdef CONFIG_SCHED_HAVE_PARENT
    FAR struct tcb_s *rtcb = (FAR struct tcb_s *)g_readytorun.head;
#endif
    FAR struct tcb_s *stcb;
    siginfo_t info;
    int ret;

    /* Make sure that the signal is valid */

    if (!GOOD_SIGNO(signo))
    {
        ret = -EINVAL;
        goto errout;
    }

    /* Keep things stationary through the following */

    sched_lock();

    /* Create the siginfo structure */

    info.si_signo           = signo;
    info.si_code            = SI_USER;
    info.si_value.sival_ptr = NULL;
#ifdef CONFIG_SCHED_HAVE_PARENT
    info.si_pid             = rtcb->pid;
    info.si_status          = OK;
#endif

    /* Get the TCB associated with the thread */

    stcb = sched_gettcb((pid_t)thread);
    if (!stcb)
    {
        ret = -ESRCH;
        goto errout_with_lock;
    }

    /* Dispatch the signal to thread, bypassing normal task group thread
     * dispatch rules.
     */

    ret = sig_tcbdispatch(stcb, &info);
    sched_unlock();

    if (ret < 0)
    {
        goto errout;
    }

    return OK;

errout_with_lock:
    sched_unlock();
errout:
    return -ret;

#else
    /* If group members are not supported then pthread_kill is basically the
     * same as kill().
     */

    int ret;

    set_errno(EINVAL);
    ret = kill((pid_t)thread, signo);
    if (ret != OK)
    {
        ret = get_errno();
    }

    return ret;
#endif
}
Ejemplo n.º 15
0
int sigaction(int signo, FAR const struct sigaction *act, FAR struct sigaction *oact)
{
  FAR struct tcb_s *rtcb = (FAR struct tcb_s*)g_readytorun.head;
  FAR sigactq_t *sigact;

  /* Since sigactions can only be installed from the running thread of
   * execution, no special precautions should be necessary.
   */

  /* Verify the signal number */

  if (!GOOD_SIGNO(signo))
    {
      set_errno(EINVAL);
      return ERROR;
    }

  /* Find the signal in the sigactionq */

  sigact = sig_findaction(rtcb, signo);

  /* Return the old sigaction value if so requested */

  if (oact)
    {
      if (sigact)
        {
          COPY_SIGACTION(oact, &sigact->act);
        }
      else
        {
          /* There isn't an old value */

          oact->sa_u._sa_handler = NULL;
          oact->sa_mask = NULL_SIGNAL_SET;
          oact->sa_flags = 0;
        }
    }

  /* If the argument act is a null pointer, signal handling is unchanged;
   * thus, the call can be used to enquire about the current handling of
   * a given signal.
   */

  if (!act)
    {
      return OK;
    }

#if defined(CONFIG_SCHED_HAVE_PARENT) && defined(CONFIG_SCHED_CHILD_STATUS)

  /* Handle a special case.  Retention of child status can be suppressed
   * if signo == SIGCHLD and sa_flags == SA_NOCLDWAIT.
   *
   * POSIX.1 leaves it unspecified whether a SIGCHLD signal is generated
   * when a child process terminates.  In NuttX, a SIGCHLD signal is
   * generated in this case; but in some other implementations, it may not
   * be.
   */

  if (signo == SIGCHLD && (act->sa_flags & SA_NOCLDWAIT) != 0)
    {
      irqstate_t flags;

      /* We do require a critical section to muck with the TCB values that
       * can be modified by the child thread.
       */

      flags = irqsave();

      /* Mark that status should be not be retained */

      rtcb->group->tg_flags |= GROUP_FLAG_NOCLDWAIT;

      /* Free all pending exit status */

      group_removechildren(rtcb->group);
      irqrestore(flags);
    }
#endif

  /* Handle the case where no sigaction is supplied (SIG_IGN) */

  if (act->sa_u._sa_handler == SIG_IGN)
    {
      /* Do we still have a sigaction container from the previous setting? */

      if (sigact)
        {
          /* Yes.. Remove it from sigactionq */

          sq_rem((FAR sq_entry_t*)sigact, &rtcb->sigactionq);

          /* And deallocate it */

          sig_releaseaction(sigact);
        }
    }

  /* A sigaction has been supplied */

  else
    {
      /* Do we still have a sigaction container from the previous setting?
       * If so, then re-use for the new signal action.
       */

      if (!sigact)
        {
          /* No.. Then we need to allocate one for the new action. */

          sigact = sig_allocateaction();

          /* An error has occurred if we could not allocate the sigaction */

          if (!sigact)
           {
              set_errno(ENOMEM);
              return ERROR;
           }

          /* Put the signal number in the queue entry */

          sigact->signo = (uint8_t)signo;

          /* Add the new sigaction to sigactionq */

          sq_addlast((FAR sq_entry_t*)sigact, &rtcb->sigactionq);
        }

      /* Set the new sigaction */

      COPY_SIGACTION(&sigact->act, act);
    }

  return OK;
}
Ejemplo n.º 16
0
FAR char *strsignal(int signum)
{
  /* Handle invalid signals */

  if (!GOOD_SIGNO(signum))
    {
      return (FAR char *)"Invalid Signal";
    }

  /* Handle named signals */

  switch (signum)
    {
      /* Standard signals */

#ifdef SIGUSR1
      case SIGUSR1:
        return (FAR char *)"SIGUSR1";
#endif

#ifdef SIGUSR2
      case SIGUSR2:
        return (FAR char *)"SIGUSR2";
#endif

#ifdef SIGALRM
      case SIGALRM:
        return (FAR char *)"SIGALRM";
#endif

#ifdef SIGCHLD
      case SIGCHLD:
        return (FAR char *)"SIGCHLD";
#endif

#ifdef SIGPOLL
      case SIGPOLL:
        return (FAR char *)"SIGPOLL";
#endif

#ifdef SIGSTOP
      case SIGSTOP:
        return (FAR char *)"SIGSTOP";
#endif

#ifdef SIGSTP
      case SIGSTP:
        return (FAR char *)"SIGSTP";
#endif

#ifdef SIGCONT
      case SIGCONT:
        return (FAR char *)"SIGCONT";
#endif

#ifdef SIGKILL
      case SIGKILL:
        return (FAR char *)"SIGKILL";
#endif

#ifdef SIGINT
      case SIGINT:
        return (FAR char *)"SIGINT";
#endif

      /* Non-standard signals */

#ifdef SIGCONDTIMEDOUT
      case SIGCONDTIMEDOUT:
        return (FAR char *)"SIGCONDTIMEDOUT";
#endif

#ifdef SIGWORK
      case SIGWORK:
        return (FAR char *)"SIGWORK";
#endif

      default:
        break;
    }

  /* Return a string devoid is meaning */

  return (FAR char *)g_default_sigstr[signum];
}
Ejemplo n.º 17
0
int sigaction(int signo, FAR const struct sigaction *act, FAR struct sigaction *oact)
{
  FAR _TCB      *rtcb = (FAR _TCB*)g_readytorun.head;
  FAR sigactq_t *sigact;
  int            ret = ERROR;  /* Assume failure */

  /* Since sigactions can only be installed from the running thread of
   * execution, no special precautions should be necessary.
   */

  /* Verify the signal */

  if (GOOD_SIGNO(signo))
    {
      ret = OK;  /* Assume success */

      /* Find the signal in the sigactionq */

      sigact = sig_findaction(rtcb, signo);

      /* Return the old sigaction value if so requested */

      if (oact)
        {
          if (sigact)
            {
              COPY_SIGACTION(oact, &sigact->act);
            }
          else
            {
              /* There isn't an old value */

              oact->sa_u._sa_handler = NULL;
              oact->sa_mask = NULL_SIGNAL_SET;
              oact->sa_flags = 0;
            }
        }

      /* If no sigaction was found, but one is needed, then
       * allocate one.
       */

      if (!sigact && act && act->sa_u._sa_handler)
        {
          sigact = sig_allocateaction();

          /* An error has occurred if we could not allocate the sigaction */

          if (!sigact)
            {
              ret = ERROR;
            }
          else
            {
              /* Put the signal number in the queue entry */

              sigact->signo = (uint8_t)signo;

              /* Add the new sigaction to sigactionq */

              sq_addlast((FAR sq_entry_t*)sigact, &rtcb->sigactionq);
            }
        }

      /* Set the new sigaction if so requested */

      if ((sigact) && (act))
        {
          /* Check if it is a request to install a new handler */

          if (act->sa_u._sa_handler)
            {
              COPY_SIGACTION(&sigact->act, act);
            }

          /* No.. It is a request to remove the old handler */

          else
            {
              /* Remove the old sigaction from sigactionq */

              sq_rem((FAR sq_entry_t*)sigact, &rtcb->sigactionq);

              /* And deallocate it */

              sig_releaseaction(sigact);
            }
        }
    }

  return ret;
}