コード例 #1
0
ファイル: pipe_common.c プロジェクト: a1ien/nuttx
FAR struct pipe_dev_s *pipecommon_allocdev(size_t bufsize)
{
  FAR struct pipe_dev_s *dev;

  DEBUGASSERT(bufsize <= CONFIG_DEV_PIPE_MAXSIZE);

  /* Allocate a private structure to manage the pipe */

  dev = (FAR struct pipe_dev_s *)kmm_malloc(sizeof(struct pipe_dev_s));
  if (dev)
    {
      /* Initialize the private structure */

      memset(dev, 0, sizeof(struct pipe_dev_s));
      sem_init(&dev->d_bfsem, 0, 1);
      sem_init(&dev->d_rdsem, 0, 0);
      sem_init(&dev->d_wrsem, 0, 0);

     /* The read/write wait semaphores are used for signaling and, hence,
      * should not have priority inheritance enabled.
      */

     sem_setprotocol(&dev->d_rdsem, SEM_PRIO_NONE);
     sem_setprotocol(&dev->d_wrsem, SEM_PRIO_NONE);

      dev->d_bufsize = bufsize;
    }

  return dev;
}
コード例 #2
0
ファイル: local_conn.c プロジェクト: a1ien/nuttx
FAR struct local_conn_s *local_alloc(void)
{
  FAR struct local_conn_s *conn =
    (FAR struct local_conn_s *)kmm_zalloc(sizeof(struct local_conn_s));

  if (conn)
    {
      /* Initialize non-zero elements the new connection structure */

      conn->lc_infd  = -1;
      conn->lc_outfd = -1;

#ifdef CONFIG_NET_LOCAL_STREAM
      /* This semaphore is used for signaling and, hence, should not have
       * priority inheritance enabled.
       */

      sem_init(&conn->lc_waitsem, 0, 0);
      sem_setprotocol(&conn->lc_waitsem, SEM_PRIO_NONE);

#ifdef HAVE_LOCAL_POLL
      memset(conn->lc_accept_fds, 0, sizeof(conn->lc_accept_fds));
#endif
#endif
    }

  return conn;
}
コード例 #3
0
ファイル: pwm.c プロジェクト: a1ien/nuttx
int pwm_register(FAR const char *path, FAR struct pwm_lowerhalf_s *dev)
{
  FAR struct pwm_upperhalf_s *upper;

  /* Allocate the upper-half data structure */

  upper = (FAR struct pwm_upperhalf_s *)kmm_zalloc(sizeof(struct pwm_upperhalf_s));
  if (!upper)
    {
      pwmerr("Allocation failed\n");
      return -ENOMEM;
    }

  /* Initialize the PWM device structure (it was already zeroed by kmm_zalloc()) */

  sem_init(&upper->exclsem, 0, 1);
#ifdef CONFIG_PWM_PULSECOUNT
  sem_init(&upper->waitsem, 0, 0);

  /* The wait semaphore is used for signaling and, hence, should not have priority
   * inheritance enabled.
   */

  sem_setprotocol(&upper->waitsem, SEM_PRIO_NONE);
#endif

  upper->dev = dev;

  /* Register the PWM device */

  pwminfo("Registering %s\n", path);
  return register_driver(path, &g_pwmops, 0666, upper);
}
コード例 #4
0
ファイル: stm32l4_rng.c プロジェクト: a1ien/nuttx
static ssize_t stm32l4_rngread(struct file *filep, char *buffer, size_t buflen)
{
  if (sem_wait(&g_rngdev.rd_devsem) != OK)
    {
      return -errno;
    }
  else
    {
      /* We've got the device semaphore, proceed with reading */

      /* Initialize the operation semaphore with 0 for blocking until the
       * buffer is filled from interrupts.  The waitsem semaphore is used
       * for signaling and, hence, should not have priority inheritance
       * enabled.
       */

      sem_init(&g_rngdev.rd_readsem, 0, 0);
      sem_setprotocol(&g_rngdev.rd_readsem, SEM_PRIO_NONE);

      g_rngdev.rd_buflen = buflen;
      g_rngdev.rd_buf = buffer;

      /* Enable RNG with interrupts */

      stm32l4_rngenable();

      /* Wait until the buffer is filled */

      sem_wait(&g_rngdev.rd_readsem);

      /* Done with the operation semaphore */

      sem_destroy(&g_rngdev.rd_readsem);

      /* Free RNG via the device semaphore for next use */

      sem_post(&g_rngdev.rd_devsem);

      return buflen;
    }
}
コード例 #5
0
ファイル: max11802.c プロジェクト: a1ien/nuttx
int max11802_register(FAR struct spi_dev_s *spi,
                      FAR struct max11802_config_s *config, int minor)
{
  FAR struct max11802_dev_s *priv;
  char devname[DEV_NAMELEN];
#ifdef CONFIG_MAX11802_MULTIPLE
  irqstate_t flags;
#endif
  int ret;

  iinfo("spi: %p minor: %d\n", spi, minor);

  /* Debug-only sanity checks */

  DEBUGASSERT(spi != NULL && config != NULL && minor >= 0 && minor < 100);

  /* Create and initialize a MAX11802 device driver instance */

#ifndef CONFIG_MAX11802_MULTIPLE
  priv = &g_max11802;
#else
  priv = (FAR struct max11802_dev_s *)kmm_malloc(sizeof(struct max11802_dev_s));
  if (!priv)
    {
      ierr("ERROR: kmm_malloc(%d) failed\n", sizeof(struct max11802_dev_s));
      return -ENOMEM;
    }
#endif

  /* Initialize the MAX11802 device driver instance */

  memset(priv, 0, sizeof(struct max11802_dev_s));
  priv->spi     = spi;               /* Save the SPI device handle */
  priv->config  = config;            /* Save the board configuration */
  priv->wdog    = wd_create();       /* Create a watchdog timer */
  priv->threshx = INVALID_THRESHOLD; /* Initialize thresholding logic */
  priv->threshy = INVALID_THRESHOLD; /* Initialize thresholding logic */

  /* Initialize semaphores */

  sem_init(&priv->devsem,  0, 1);    /* Initialize device structure semaphore */
  sem_init(&priv->waitsem, 0, 0);    /* Initialize pen event wait semaphore */

  /* The pen event semaphore is used for signaling and, hence, should not
   * have priority inheritance enabled.
   */

  sem_setprotocol(&priv->waitsem, SEM_PRIO_NONE);

  /* Make sure that interrupts are disabled */

  config->clear(config);
  config->enable(config, false);

  /* Attach the interrupt handler */

  ret = config->attach(config, max11802_interrupt);
  if (ret < 0)
    {
      ierr("ERROR: Failed to attach interrupt\n");
      goto errout_with_priv;
    }

  iinfo("Mode: %d Bits: 8 Frequency: %d\n",
        CONFIG_MAX11802_SPIMODE, CONFIG_MAX11802_FREQUENCY);

  /* Lock the SPI bus so that we have exclusive access */

  max11802_lock(spi);

  /* Configure MAX11802 registers */

  SPI_SELECT(priv->spi, SPIDEV_TOUCHSCREEN, true);
  (void)SPI_SEND(priv->spi, MAX11802_CMD_MODE_WR);
  (void)SPI_SEND(priv->spi, MAX11802_MODE);
  SPI_SELECT(priv->spi, SPIDEV_TOUCHSCREEN, false);

  SPI_SELECT(priv->spi, SPIDEV_TOUCHSCREEN, true);
  (void)SPI_SEND(priv->spi, MAX11802_CMD_AVG_WR);
  (void)SPI_SEND(priv->spi, MAX11802_AVG);
  SPI_SELECT(priv->spi, SPIDEV_TOUCHSCREEN, false);

  SPI_SELECT(priv->spi, SPIDEV_TOUCHSCREEN, true);
  (void)SPI_SEND(priv->spi, MAX11802_CMD_TIMING_WR);
  (void)SPI_SEND(priv->spi, MAX11802_TIMING);
  SPI_SELECT(priv->spi, SPIDEV_TOUCHSCREEN, false);

  SPI_SELECT(priv->spi, SPIDEV_TOUCHSCREEN, true);
  (void)SPI_SEND(priv->spi, MAX11802_CMD_DELAY_WR);
  (void)SPI_SEND(priv->spi, MAX11802_DELAY);
  SPI_SELECT(priv->spi, SPIDEV_TOUCHSCREEN, false);

  /* Test that the device access was successful. */

  SPI_SELECT(priv->spi, SPIDEV_TOUCHSCREEN, true);
  (void)SPI_SEND(priv->spi, MAX11802_CMD_MODE_RD);
  ret = SPI_SEND(priv->spi, 0);
  SPI_SELECT(priv->spi, SPIDEV_TOUCHSCREEN, false);

  /* Unlock the bus */

  max11802_unlock(spi);

  if (ret != MAX11802_MODE)
  {
    ierr("ERROR: max11802 mode readback failed: %02x\n", ret);
    goto errout_with_priv;
  }

  /* Register the device as an input device */

  (void)snprintf(devname, DEV_NAMELEN, DEV_FORMAT, minor);
  iinfo("Registering %s\n", devname);

  ret = register_driver(devname, &max11802_fops, 0666, priv);
  if (ret < 0)
    {
      ierr("ERROR: register_driver() failed: %d\n", ret);
      goto errout_with_priv;
    }

  /* If multiple MAX11802 devices are supported, then we will need to add
   * this new instance to a list of device instances so that it can be
   * found by the interrupt handler based on the recieved IRQ number.
   */

#ifdef CONFIG_MAX11802_MULTIPLE
  flags          = enter_critical_section();
  priv->flink    = g_max11802list;
  g_max11802list = priv;
  leave_critical_section(flags);
#endif

  /* Schedule work to perform the initial sampling and to set the data
   * availability conditions.
   */

  ret = work_queue(HPWORK, &priv->work, max11802_worker, priv, 0);
  if (ret != 0)
    {
      ierr("ERROR: Failed to queue work: %d\n", ret);
      goto errout_with_priv;
    }

  /* And return success (?) */

  return OK;

errout_with_priv:
  sem_destroy(&priv->devsem);
#ifdef CONFIG_MAX11802_MULTIPLE
  kmm_free(priv);
#endif
  return ret;
}
コード例 #6
0
ファイル: usbmsc.c プロジェクト: drashti304/TizenRT
int usbmsc_configure(unsigned int nluns, void **handle)
{
	FAR struct usbmsc_alloc_s *alloc;
	FAR struct usbmsc_dev_s *priv;
	FAR struct usbmsc_driver_s *drvr;
	int ret;

#ifdef CONFIG_DEBUG
	if (nluns > 15) {
		usbtrace(TRACE_CLSERROR(USBMSC_TRACEERR_TOOMANYLUNS), 0);
		return -EDOM;
	}
#endif

	/* Allocate the structures needed */

	alloc = (FAR struct usbmsc_alloc_s *)kmm_malloc(sizeof(struct usbmsc_alloc_s));
	if (!alloc) {
		usbtrace(TRACE_CLSERROR(USBMSC_TRACEERR_ALLOCDEVSTRUCT), 0);
		return -ENOMEM;
	}

	/* Initialize the USB storage driver structure */

	priv = &alloc->dev;
	memset(priv, 0, sizeof(struct usbmsc_dev_s));

	/* Initialize semaphores */
	sem_init(&priv->thsynch, 0, 0);
	sem_init(&priv->thlock, 0, 1);
	sem_init(&priv->thwaitsem, 0, 0);

	/*
	 * The thsynch and thwaitsem semaphores are used for signaling and,
	 * hence, should not have priority inheritance enabled.
	 */
	sem_setprotocol(&priv->thsynch, SEM_PRIO_NONE);
	sem_setprotocol(&priv->thwaitsem, SEM_PRIO_NONE);

	sq_init(&priv->wrreqlist);

	priv->nluns = nluns;

	/* Allocate the LUN table */

	priv->luntab = (FAR struct usbmsc_lun_s *)
				   kmm_malloc(priv->nluns * sizeof(struct usbmsc_lun_s));

	if (!priv->luntab) {
		ret = -ENOMEM;
		goto errout;
	}

	memset(priv->luntab, 0, priv->nluns * sizeof(struct usbmsc_lun_s));

	/* Initialize the USB class driver structure */

	drvr = &alloc->drvr;
#ifdef CONFIG_USBDEV_DUALSPEED
	drvr->drvr.speed = USB_SPEED_HIGH;
#else
	drvr->drvr.speed = USB_SPEED_FULL;
#endif
	drvr->drvr.ops = &g_driverops;
	drvr->dev = priv;

	/* Return the handle and success */

	*handle = (FAR void *)alloc;
	return OK;

errout:
	usbmsc_uninitialize(alloc);
	return ret;
}
コード例 #7
0
ファイル: icmpv6_autoconfig.c プロジェクト: a1ien/nuttx
static int icmpv6_send_message(FAR struct net_driver_s *dev, bool advertise)
{
  struct icmpv6_router_s state;
  int ret;

  /* Initialize the state structure. This is done with interrupts
   * disabled
   */

  /* This semaphore is used for signaling and, hence, should not have
   * priority inheritance enabled.
   */

  (void)sem_init(&state.snd_sem, 0, 0); /* Doesn't really fail */
  sem_setprotocol(&state.snd_sem, SEM_PRIO_NONE);

#ifdef CONFIG_NETDEV_MULTINIC
  /* Remember the routing device name */

  strncpy((FAR char *)state.snd_ifname, (FAR const char *)dev->d_ifname,
          IFNAMSIZ);
#endif

  /* Allocate resources to receive a callback.  This and the following
   * initialization is performed with the network lock because we don't
   * want anything to happen until we are ready.
   */

  state.snd_cb = icmpv6_callback_alloc(dev);
  if (!state.snd_cb)
    {
      nerr("ERROR: Failed to allocate a cllback\n");
      ret = -ENOMEM;
      goto errout_with_semaphore;
    }

  /* Arm the callback */

  state.snd_sent      = false;
  state.snd_result    = -EBUSY;
  state.snd_advertise = advertise;
  state.snd_cb->flags = (ICMPv6_POLL | NETDEV_DOWN);
  state.snd_cb->priv  = (FAR void *)&state;
  state.snd_cb->event = icmpv6_router_interrupt;

  /* Notify the device driver that new TX data is available. */

  dev->d_txavail(dev);

  /* Wait for the send to complete or an error to occur: NOTES: (1)
   * net_lockedwait will also terminate if a signal is received, (2)
   * interrupts may be disabled! They will be re-enabled while the
   * task sleeps and automatically re-enabled when the task restarts.
   */

  do
    {
      (void)net_lockedwait(&state.snd_sem);
    }
  while (!state.snd_sent);

  ret = state.snd_result;
  icmpv6_callback_free(dev, state.snd_cb);

errout_with_semaphore:
  sem_destroy(&state.snd_sem);
  return ret;
}
コード例 #8
0
ファイル: slip.c プロジェクト: a1ien/nuttx
int slip_initialize(int intf, FAR const char *devname)
{
  FAR struct slip_driver_s *priv;
  char buffer[8];
  FAR char *argv[2];

  /* Get the interface structure associated with this interface number. */

  DEBUGASSERT(intf < CONFIG_NET_SLIP_NINTERFACES);
  priv = &g_slip[intf];

  /* Initialize the driver structure */

  memset(priv, 0, sizeof(struct slip_driver_s));
  priv->dev.d_ifup    = slip_ifup;     /* I/F up (new IP address) callback */
  priv->dev.d_ifdown  = slip_ifdown;   /* I/F down callback */
  priv->dev.d_txavail = slip_txavail;  /* New TX data callback */
#ifdef CONFIG_NET_IGMP
  priv->dev.d_addmac  = slip_addmac;   /* Add multicast MAC address */
  priv->dev.d_rmmac   = slip_rmmac;    /* Remove multicast MAC address */
#endif
  priv->dev.d_private = priv;          /* Used to recover private state from dev */

  /* Open the device */

  priv->fd            = open(devname, O_RDWR, 0666);
  if (priv->fd < 0)
    {
      nerr("ERROR: Failed to open %s: %d\n", devname, errno);
      return -errno;
    }

  /* Initialize the wait semaphore */

  sem_init(&priv->waitsem, 0, 0);
  sem_setprotocol(&priv->waitsem, SEM_PRIO_NONE);

  /* Put the interface in the down state.  This usually amounts to resetting
   * the device and/or calling slip_ifdown().
   */

  slip_ifdown(&priv->dev);

  /* Start the SLIP receiver task */

  snprintf(buffer, 8, "%d", intf);
  argv[0] = buffer;
  argv[1] = NULL;

  priv->rxpid = task_create("rxslip", CONFIG_NET_SLIP_DEFPRIO,
                            CONFIG_NET_SLIP_STACKSIZE, (main_t)slip_rxtask,
                            (FAR char * const *)argv);
  if (priv->rxpid < 0)
    {
      nerr("ERROR: Failed to start receiver task\n");
      return -errno;
    }

  /* Wait and make sure that the receive task is started. */

  slip_semtake(priv);

  /* Start the SLIP transmitter task */

  priv->txpid = task_create("txslip", CONFIG_NET_SLIP_DEFPRIO,
                            CONFIG_NET_SLIP_STACKSIZE, (main_t)slip_txtask,
                            (FAR char * const *)argv);
  if (priv->txpid < 0)
    {
      nerr("ERROR: Failed to start receiver task\n");
      return -errno;
    }

  /* Wait and make sure that the transmit task is started. */

  slip_semtake(priv);

  /* Bump the semaphore count so that it can now be used as a mutex */

  slip_semgive(priv);

  /* Register the device with the OS so that socket IOCTLs can be performed */

  (void)netdev_register(&priv->dev, NET_LL_SLIP);

  /* When the RX and TX tasks were created, the TTY file descriptor was
   * dup'ed for each task.  This task no longer needs the file descriptor
   * and we can safely close it.
   */

  close(priv->fd);
  return OK;
}
コード例 #9
0
ファイル: udp_psock_sendto.c プロジェクト: a1ien/nuttx
ssize_t psock_udp_sendto(FAR struct socket *psock, FAR const void *buf,
                         size_t len, int flags, FAR const struct sockaddr *to,
                         socklen_t tolen)
{
  FAR struct udp_conn_s *conn;
  FAR struct net_driver_s *dev;
  struct sendto_s state;
  int ret;

#if defined(CONFIG_NET_ARP_SEND) || defined(CONFIG_NET_ICMPv6_NEIGHBOR)
#ifdef CONFIG_NET_ARP_SEND
#ifdef CONFIG_NET_ICMPv6_NEIGHBOR
  if (psock->s_domain == PF_INET)
#endif
    {
      FAR const struct sockaddr_in *into;

      /* Make sure that the IP address mapping is in the ARP table */

      into = (FAR const struct sockaddr_in *)to;
      ret = arp_send(into->sin_addr.s_addr);
    }
#endif /* CONFIG_NET_ARP_SEND */

#ifdef CONFIG_NET_ICMPv6_NEIGHBOR
#ifdef CONFIG_NET_ARP_SEND
  else
#endif
    {
      FAR const struct sockaddr_in6 *into;

      /* Make sure that the IP address mapping is in the Neighbor Table */

      into = (FAR const struct sockaddr_in6 *)to;
      ret = icmpv6_neighbor(into->sin6_addr.s6_addr16);
    }
#endif /* CONFIG_NET_ICMPv6_NEIGHBOR */

  /* Did we successfully get the address mapping? */

  if (ret < 0)
    {
      nerr("ERROR: Peer not reachable\n");
      return -ENETUNREACH;
    }
#endif /* CONFIG_NET_ARP_SEND || CONFIG_NET_ICMPv6_NEIGHBOR */

  /* Set the socket state to sending */

  psock->s_flags = _SS_SETSTATE(psock->s_flags, _SF_SEND);

  /* Initialize the state structure.  This is done with interrupts
   * disabled because we don't want anything to happen until we
   * are ready.
   */

  net_lock();
  memset(&state, 0, sizeof(struct sendto_s));

  /* This semaphore is used for signaling and, hence, should not have
   * priority inheritance enabled.
   */

  sem_init(&state.st_sem, 0, 0);
  sem_setprotocol(&state.st_sem, SEM_PRIO_NONE);

  state.st_buflen = len;
  state.st_buffer = buf;

#if defined(CONFIG_NET_SENDTO_TIMEOUT) || defined(NEED_IPDOMAIN_SUPPORT)
  /* Save the reference to the socket structure if it will be needed for
   * asynchronous processing.
   */

  state.st_sock = psock;
#endif

#ifdef CONFIG_NET_SENDTO_TIMEOUT
  /* Set the initial time for calculating timeouts */

  state.st_time = clock_systimer();
#endif

  /* Setup the UDP socket.  udp_connect will set the remote address in the
   * connection structure.
   */

  conn = (FAR struct udp_conn_s *)psock->s_conn;
  DEBUGASSERT(conn);

  ret = udp_connect(conn, to);
  if (ret < 0)
    {
      nerr("ERROR: udp_connect failed: %d\n", ret);
      goto errout_with_lock;
    }

  /* Get the device that will handle the remote packet transfers.  This
   * should never be NULL.
   */

  dev = udp_find_raddr_device(conn);
  if (dev == NULL)
    {
      nerr("ERROR: udp_find_raddr_device failed\n");
      ret = -ENETUNREACH;
      goto errout_with_lock;
   }

  /* Set up the callback in the connection */

  state.st_cb = udp_callback_alloc(dev, conn);
  if (state.st_cb)
    {
      state.st_cb->flags   = (UDP_POLL | NETDEV_DOWN);
      state.st_cb->priv    = (FAR void *)&state;
      state.st_cb->event   = sendto_interrupt;

      /* Notify the device driver of the availability of TX data */

      netdev_txnotify_dev(dev);

      /* Wait for either the receive to complete or for an error/timeout to occur.
       * NOTES:  (1) net_lockedwait will also terminate if a signal is received, (2)
       * interrupts may be disabled!  They will be re-enabled while the task sleeps
       * and automatically re-enabled when the task restarts.
       */

      net_lockedwait(&state.st_sem);

      /* Make sure that no further interrupts are processed */

      udp_callback_free(dev, conn, state.st_cb);
    }

  /* The result of the sendto operation is the number of bytes transferred */

  ret = state.st_sndlen;

errout_with_lock:
  /* Release the semaphore */

  sem_destroy(&state.st_sem);

  /* Set the socket state back to idle */

  psock->s_flags = _SS_SETSTATE(psock->s_flags, _SF_IDLE);

  /* Unlock the network and return the result of the sendto() operation */

  net_unlock();
  return ret;
}
コード例 #10
0
ファイル: group_create.c プロジェクト: a1ien/nuttx
int group_allocate(FAR struct task_tcb_s *tcb, uint8_t ttype)
{
  FAR struct task_group_s *group;
  int ret;

  DEBUGASSERT(tcb && !tcb->cmn.group);

  /* Allocate the group structure and assign it to the TCB */

  group = (FAR struct task_group_s *)kmm_zalloc(sizeof(struct task_group_s));
  if (!group)
    {
      return -ENOMEM;
    }

#if CONFIG_NFILE_STREAMS > 0 && (defined(CONFIG_BUILD_PROTECTED) || \
    defined(CONFIG_BUILD_KERNEL)) && defined(CONFIG_MM_KERNEL_HEAP)
  /* If this group is being created for a privileged thread, then all elements
   * of the group must be created for privileged access.
   */

  if ((ttype & TCB_FLAG_TTYPE_MASK) == TCB_FLAG_TTYPE_KERNEL)
    {
      group->tg_flags |= GROUP_FLAG_PRIVILEGED;
    }

  /* In a flat, single-heap build.  The stream list is allocated with the
   * group structure.  But in a kernel build with a kernel allocator, it
   * must be separately allocated using a user-space allocator.
   */

  group->tg_streamlist = (FAR struct streamlist *)
    group_zalloc(group, sizeof(struct streamlist));

  if (!group->tg_streamlist)
    {
      kmm_free(group);
      return -ENOMEM;
    }

#endif

  /* Attach the group to the TCB */

  tcb->cmn.group = group;

#if defined(HAVE_GROUP_MEMBERS) || defined(CONFIG_ARCH_ADDRENV)
  /* Assign the group a unique ID.  If g_gidcounter were to wrap before we
   * finish with task creation, that would be a problem.
   */

  group_assigngid(group);
#endif

  /* Duplicate the parent tasks environment */

  ret = env_dup(group);
  if (ret < 0)
    {
#if CONFIG_NFILE_STREAMS > 0 && (defined(CONFIG_BUILD_PROTECTED) || \
    defined(CONFIG_BUILD_KERNEL)) && defined(CONFIG_MM_KERNEL_HEAP)
      group_free(group, group->tg_streamlist);
#endif
      kmm_free(group);
      tcb->cmn.group = NULL;
      return ret;
    }

#ifndef CONFIG_DISABLE_PTHREAD
  /* Initialize the pthread join semaphore */

  (void)sem_init(&group->tg_joinsem, 0, 1);
#endif

#if defined(CONFIG_SCHED_WAITPID) && !defined(CONFIG_SCHED_HAVE_PARENT)
  /* Initialize the exit/wait semaphores
   *
   * This semaphore is used for signaling and, hence, should not have
   * priority inheritance enabled.
   */

  (void)sem_init(&group->tg_exitsem, 0, 0);
  (void)sem_setprotocol(&group->tg_exitsem, SEM_PRIO_NONE);
#endif

  return OK;
}
コード例 #11
0
ファイル: pty.c プロジェクト: a1ien/nuttx
int pty_register(int minor)
{
  FAR struct pty_devpair_s *devpair;
  int pipe_a[2];
  int pipe_b[2];
  char devname[16];
  int ret;

  /* Allocate a device instance */

  devpair = kmm_zalloc(sizeof(struct pty_devpair_s));
  if (devpair == NULL)
    {
      return -ENOMEM;
    }

  /* Initialize semaphores */

  sem_init(&devpair->pp_slavesem, 0, 0);
  sem_init(&devpair->pp_exclsem, 0, 1);

  /* The pp_slavesem semaphore is used for signaling and, hence, should not
   * have priority inheritance enabled.
   */

  sem_setprotocol(&devpair->pp_slavesem, SEM_PRIO_NONE);

#ifndef CONFIG_DISABLE_PSEUDOFS_OPERATIONS
  devpair->pp_minor             = minor;
#endif
  devpair->pp_locked            = true;
  devpair->pp_master.pd_devpair = devpair;
  devpair->pp_master.pd_master  = true;
  devpair->pp_slave.pd_devpair  = devpair;

  /* Create two pipes:
   *
   *   pipe_a:  Master source, slave sink (TX, slave-to-master)
   *   pipe_b:  Master sink, slave source (RX, master-to-slave)
   */

  ret = pipe2(pipe_a, CONFIG_PSEUDOTERM_TXBUFSIZE);
  if (ret < 0)
    {
      goto errout_with_devpair;
    }

  ret = pipe2(pipe_b, CONFIG_PSEUDOTERM_RXBUFSIZE);
  if (ret < 0)
    {
      goto errout_with_pipea;
    }

  /* Detach the pipe file descriptors (closing them in the process)
   *
   *  fd[0] is for reading;
   *  fd[1] is for writing.
   */

  ret = file_detach(pipe_a[0], &devpair->pp_master.pd_src);
  if (ret < 0)
    {
      goto errout_with_pipeb;
    }

  pipe_a[0] = -1;

  ret = file_detach(pipe_a[1], &devpair->pp_slave.pd_sink);
  if (ret < 0)
    {
      goto errout_with_pipeb;
    }

  pipe_a[1] = -1;

  ret = file_detach(pipe_b[0], &devpair->pp_slave.pd_src);
  if (ret < 0)
    {
      goto errout_with_pipeb;
    }

  pipe_b[0] = -1;

  ret = file_detach(pipe_b[1], &devpair->pp_master.pd_sink);
  if (ret < 0)
    {
      goto errout_with_pipeb;
    }

  pipe_b[1] = -1;

  /* Register the slave device
   *
   * BSD style (deprecated): /dev/ttypN
   * SUSv1 style:  /dev/pts/N
   *
   * Where N is the minor number
   */

#ifdef CONFIG_PSEUDOTERM_BSD
  snprintf(devname, 16, "/dev/ttyp%d", minor);
#else
  snprintf(devname, 16, "/dev/pts/%d", minor);
#endif

  ret = register_driver(devname, &g_pty_fops, 0666, &devpair->pp_slave);
  if (ret < 0)
    {
      goto errout_with_pipeb;
    }

  /* Register the master device
   *
   * BSD style (deprecated):  /dev/ptyN
   * SUSv1 style: Master: /dev/ptmx (multiplexor, see ptmx.c)
   *
   * Where N is the minor number
   */

  snprintf(devname, 16, "/dev/pty%d", minor);

  ret = register_driver(devname, &g_pty_fops, 0666, &devpair->pp_master);
  if (ret < 0)
    {
      goto errout_with_slave;
    }

  return OK;

errout_with_slave:
#ifdef CONFIG_PSEUDOTERM_BSD
  snprintf(devname, 16, "/dev/ttyp%d", minor);
#else
  snprintf(devname, 16, "/dev/pts/%d", minor);
#endif
  (void)unregister_driver(devname);

errout_with_pipeb:
  if (pipe_b[0] >= 0)
    {
      close(pipe_b[0]);
    }
  else
    {
      (void)file_close_detached(&devpair->pp_master.pd_src);
    }

  if (pipe_b[1] >= 0)
    {
      close(pipe_b[1]);
    }
  else
    {
      (void)file_close_detached(&devpair->pp_slave.pd_sink);
    }

errout_with_pipea:
  if (pipe_a[0] >= 0)
    {
      close(pipe_a[0]);
    }
  else
    {
      (void)file_close_detached(&devpair->pp_slave.pd_src);
    }

  if (pipe_a[1] >= 0)
    {
      close(pipe_a[1]);
    }
  else
    {
      (void)file_close_detached(&devpair->pp_master.pd_sink);
    }

errout_with_devpair:
   sem_destroy(&devpair->pp_exclsem);
   sem_destroy(&devpair->pp_slavesem);
   kmm_free(devpair);
   return ret;
}