Esempio n. 1
0
int up_create_stack(struct tcb_s *tcb, size_t stack_size, uint8_t ttype)
{
    uint32_t *stack_alloc_ptr;
    int ret = ERROR;
    size_t *adj_stack_ptr;

    /* Move up to next even word boundary if necessary */

    size_t adj_stack_size = (stack_size + 3) & ~3;
    size_t adj_stack_words = adj_stack_size >> 2;

    /* Allocate the memory for the stack */

#if defined(CONFIG_NUTTX_KERNEL) && defined(CONFIG_MM_KERNEL_HEAP)
    /* Use the kernel allocator if this is a kernel thread */

    if (ttype == TCB_FLAG_TTYPE_KERNEL) {
        stack_alloc_ptr = (uint32_t *)kmalloc(stack_size);
    } else
#endif
    {
        stack_alloc_ptr = (uint32_t*)kumalloc(adj_stack_size);
    }
    if (stack_alloc_ptr) {
        /* This is the address of the last word in the allocation */

        adj_stack_ptr = &stack_alloc_ptr[adj_stack_words - 1];

        /* Save the values in the TCB */

        tcb->adj_stack_size  = adj_stack_size;
        tcb->stack_alloc_ptr = stack_alloc_ptr;
        tcb->adj_stack_ptr   = (void *)((unsigned int)adj_stack_ptr & ~7);
        ret = OK;
    }
    return ret;
}
Esempio n. 2
0
int apb_alloc(FAR struct audio_buf_desc_s * bufdesc)
{
  uint32_t            bufsize;
  int                 ret;
  struct ap_buffer_s  *pBuf;

  DEBUGASSERT(bufdesc->u.ppBuffer != NULL);

  /* Perform a user mode allocation */

  bufsize = sizeof(struct ap_buffer_s) + bufdesc->numbytes;
  pBuf = kumalloc(bufsize);
  *bufdesc->u.ppBuffer = pBuf;

  /* Test if the allocation was successful or not */

  if (*bufdesc->u.ppBuffer == NULL)
    ret = -ENOMEM;
  else
    {
      /* Populate the buffer contents */

      memset(pBuf, bufsize, 0);
      pBuf->i.channels = 1;
      pBuf->crefs = 1;
      pBuf->nmaxbytes = bufdesc->numbytes;
      pBuf->nbytes = 0;
#ifdef CONFIG_AUDIO_MULTI_SESSION
      pBuf->session = bufdesc->session;
#endif
      sem_init(&pBuf->sem, 0, 1);
      ret = sizeof(struct audio_buf_desc_s);
    }

  return ret;
}
Esempio n. 3
0
int up_create_stack(FAR struct tcb_s *tcb, size_t stack_size, uint8_t ttype)
{
  /* Is there already a stack allocated of a different size?  Because of
   * alignment issues, stack_size might erroneously appear to be of a
   * different size.  Fortunately, this is not a critical operation.
   */

  if (tcb->stack_alloc_ptr && tcb->adj_stack_size != stack_size)
    {
      /* Yes.. Release the old stack */

      up_release_stack(tcb, ttype);
    }

  /* Do we need to allocate a new stack? */
 
  if (!tcb->stack_alloc_ptr)
    {
      /* Allocate the stack.  If DEBUG is enabled (but not stack debug),
       * then create a zeroed stack to make stack dumps easier to trace.
       */

#if defined(CONFIG_NUTTX_KERNEL) && defined(CONFIG_MM_KERNEL_HEAP)
      /* Use the kernel allocator if this is a kernel thread */

      if (ttype == TCB_FLAG_TTYPE_KERNEL)
        {
#if defined(CONFIG_DEBUG) && !defined(CONFIG_DEBUG_STACK)
          tcb->stack_alloc_ptr = (uint32_t *)kzalloc(stack_size);
#else
          tcb->stack_alloc_ptr = (uint32_t *)kmalloc(stack_size);
#endif
        }
      else
#endif
        {
          /* Use the user-space allocator if this is a task or pthread */

#if defined(CONFIG_DEBUG) && !defined(CONFIG_DEBUG_STACK)
          tcb->stack_alloc_ptr = (uint32_t *)kuzalloc(stack_size);
#else
          tcb->stack_alloc_ptr = (uint32_t *)kumalloc(stack_size);
#endif
        }

#ifdef CONFIG_DEBUG
      /* Was the allocation successful? */

      if (!tcb->stack_alloc_ptr)
        {
          sdbg("ERROR: Failed to allocate stack, size %d\n", stack_size);
        }
#endif
    }

  /* Did we successfully allocate a stack? */

  if (tcb->stack_alloc_ptr)
    {
      size_t top_of_stack;

      /* Yes.. If stack debug is enabled, then fill the stack with a
       * recognizable value that we can use later to test for high
       * water marks.
       */

#if defined(CONFIG_DEBUG) && defined(CONFIG_DEBUG_STACK)
      memset(tcb->stack_alloc_ptr, 0xaa, stack_size);
#endif

      /* The AVR uses a push-down stack:  the stack grows toward lower
       * addresses in memory.  The stack pointer register, points to the
       * lowest, valid work address (the "top" of the stack).  Items on the
       * stack are referenced as positive word offsets from sp.
       */

      top_of_stack = (size_t)tcb->stack_alloc_ptr + stack_size - 1;

      /* Save the adjusted stack values in the struct tcb_s */

      tcb->adj_stack_ptr  = (FAR void *)top_of_stack;
      tcb->adj_stack_size = stack_size;

      up_ledon(LED_STACKCREATED);
      return OK;
    }

   return ERROR;
}
FAR struct file_struct *fs_fdopen(int fd, int oflags, FAR struct tcb_s *tcb)
{
  FAR struct streamlist *slist;
  FAR FILE              *stream;
  int                    err = OK;
  int                    ret;
  int                    i;

  /* Check input parameters */

  if (fd < 0)
    {
      err = EBADF;
      goto errout;
    }

  /* A NULL TCB pointer means to use this threads TCB.  This is a little
   * hack the let's this function be called from user-space (via a syscall)
   * without having access to the TCB.
   */

  if (!tcb)
    {
      tcb = sched_self();
    }

  DEBUGASSERT(tcb && tcb->group);

  /* Verify that this is a valid file/socket descriptor and that the
   * requested access can be support.
   *
   * Is this fd in the range of valid file descriptors?  Socket descriptors
   * lie in a different range.
   */
 
#if CONFIG_NFILE_DESCRIPTORS > 0
  if ((unsigned int)fd >= CONFIG_NFILE_DESCRIPTORS)
#endif
    {
      /* No.. If networking is enabled then this might be a socket
       * descriptor.
       */

#if defined(CONFIG_NET) && CONFIG_NSOCKET_DESCRIPTORS > 0
      ret = net_checksd(fd, oflags);
#else
      /* No networking... it is just a bad descriptor */

      err = EBADF;
      goto errout;
#endif
    }

  /* The descriptor is in a valid range to file descriptor... perform some more checks */

#if CONFIG_NFILE_DESCRIPTORS > 0
  else
    {
      ret = fs_checkfd(tcb, fd, oflags);
    }
#endif

  /* Do we have a good descriptor of some sort? */

  if (ret < 0)
    {
      /* No... return the reported error */

      err = -ret;
      goto errout;
    }

  /* Get the stream list from the TCB */

#if defined(CONFIG_NUTTX_KERNEL) && defined(CONFIG_MM_KERNEL_HEAP)
  slist = tcb->group->tg_streamlist;
#else
  slist = &tcb->group->tg_streamlist;
#endif

  /* Find an unallocated FILE structure in the stream list */

  ret = sem_wait(&slist->sl_sem);
  if (ret != OK)
    {
      goto errout_with_errno;
    }

  for (i = 0 ; i < CONFIG_NFILE_STREAMS; i++)
    {
      stream = &slist->sl_streams[i];
      if (stream->fs_fd < 0)
        {
          /* Zero the structure */

#if CONFIG_STDIO_BUFFER_SIZE > 0
          memset(stream, 0, sizeof(FILE));
#elif CONFIG_NUNGET_CHARS > 0
          stream->fs_nungotten = 0;
#endif

#if CONFIG_STDIO_BUFFER_SIZE > 0
          /* Initialize the semaphore the manages access to the buffer */

          (void)sem_init(&stream->fs_sem, 0, 1);

          /* Allocate the IO buffer */

          stream->fs_bufstart = kumalloc(CONFIG_STDIO_BUFFER_SIZE);
          if (!stream->fs_bufstart)
            {
              err = ENOMEM;
              goto errout_with_sem;
            }

          /* Set up pointers */

          stream->fs_bufend  = &stream->fs_bufstart[CONFIG_STDIO_BUFFER_SIZE];
          stream->fs_bufpos  = stream->fs_bufstart;
          stream->fs_bufpos  = stream->fs_bufstart;
          stream->fs_bufread = stream->fs_bufstart;
#endif
          /* Save the file description and open flags.  Setting the
           * file descriptor locks this stream.
           */

          stream->fs_fd      = fd;
          stream->fs_oflags  = (uint16_t)oflags;

          sem_post(&slist->sl_sem);
          return stream;
        }
    }

  /* No free stream available.. report ENFILE */

  err = ENFILE;

#if CONFIG_STDIO_BUFFER_SIZE > 0
errout_with_sem:
#endif
  sem_post(&slist->sl_sem);

errout:
  set_errno(err);
errout_with_errno:
  return NULL;
}
Esempio n. 5
0
int up_create_stack(FAR struct tcb_s *tcb, size_t stack_size, uint8_t ttype)
{
  /* Is there already a stack allocated of a different size?  Because of
   * alignment issues, stack_size might erroneously appear to be of a
   * different size.  Fortunately, this is not a critical operation.
   */

  if (tcb->stack_alloc_ptr && tcb->adj_stack_size != stack_size)
    {
      /* Yes.. Release the old stack */

      up_release_stack(tcb, ttype);
    }

  /* Do we need to allocate a new stack? */
 
  if (!tcb->stack_alloc_ptr)
    {
      /* Allocate the stack.  If DEBUG is enabled (but not stack debug),
       * then create a zeroed stack to make stack dumps easier to trace.
       */

#if defined(CONFIG_NUTTX_KERNEL) && defined(CONFIG_MM_KERNEL_HEAP)
      /* Use the kernel allocator if this is a kernel thread */

      if (ttype == TCB_FLAG_TTYPE_KERNEL)
        {
#if defined(CONFIG_DEBUG) && !defined(CONFIG_DEBUG_STACK)
          tcb->stack_alloc_ptr = (uint32_t *)kzalloc(stack_size);
#else
          tcb->stack_alloc_ptr = (uint32_t *)kmalloc(stack_size);
#endif
        }
      else
#endif
        {
          /* Use the user-space allocator if this is a task or pthread */

#if defined(CONFIG_DEBUG) && !defined(CONFIG_DEBUG_STACK)
          tcb->stack_alloc_ptr = (uint32_t *)kuzalloc(stack_size);
#else
          tcb->stack_alloc_ptr = (uint32_t *)kumalloc(stack_size);
#endif
        }

#ifdef CONFIG_DEBUG
      /* Was the allocation successful? */

      if (!tcb->stack_alloc_ptr)
        {
          sdbg("ERROR: Failed to allocate stack, size %d\n", stack_size);
        }
#endif
    }

  /* Did we successfully allocate a stack? */

  if (tcb->stack_alloc_ptr)
    {
      size_t top_of_stack;
      size_t size_of_stack;

      /* The ARM uses a push-down stack:  the stack grows toward lower
       * addresses in memory.  The stack pointer register, points to
       * the lowest, valid work address (the "top" of the stack).  Items
       * on the stack are referenced as positive word offsets from sp.
       */

      top_of_stack = (uint32_t)tcb->stack_alloc_ptr + stack_size - 4;

      /* The ARM stack must be aligned; 4 byte alignment for OABI and
       * 8-byte alignment for EABI. If necessary top_of_stack must be
       * rounded down to the next boundary
       */

      top_of_stack = STACK_ALIGN_DOWN(top_of_stack);

      /* The size of the stack in bytes is then the difference between
       * the top and the bottom of the stack (+4 because if the top
       * is the same as the bottom, then the size is one 32-bit element).
       * The size need not be aligned.
       */

      size_of_stack = top_of_stack - (uint32_t)tcb->stack_alloc_ptr + 4;

      /* Save the adjusted stack values in the struct tcb_s */

      tcb->adj_stack_ptr  = (uint32_t*)top_of_stack;
      tcb->adj_stack_size = size_of_stack;

      /* If stack debug is enabled, then fill the stack with a
       * recognizable value that we can use later to test for high
       * water marks.
       */

#if defined(CONFIG_DEBUG) && defined(CONFIG_DEBUG_STACK)
      memset32(tcb->stack_alloc_ptr, 0xdeadbeef, tcb->adj_stack_size/4);
#endif

      up_ledon(LED_STACKCREATED);
      return OK;
    }

   return ERROR;
}
Esempio n. 6
0
int setenv(FAR const char *name, FAR const char *value, int overwrite)
{
  FAR struct tcb_s *rtcb;
  FAR struct task_group_s *group;
  FAR char *pvar;
  FAR char *newenvp;
  int newsize;
  int varlen;
  int ret = OK;

  /* Verify input parameter */

  if (!name)
    {
      ret = EINVAL;
      goto errout;
    }

  /* if no value is provided, then this is the same as unsetenv (unless
   * overwrite is false)
   */

  if (!value || *value == '\0')
    {
      /* If overwite is set then this is the same as unsetenv */

      if (overwrite)
        {
          return unsetenv(name);
        }
      else
        {
          /* Otherwise, it is a request to remove a variable without altering it? */

          return OK;
        }
    }

  /* Get a reference to the thread-private environ in the TCB. */

  sched_lock();
  rtcb  = (FAR struct tcb_s*)g_readytorun.head;
  group = rtcb->group;
  DEBUGASSERT(group);

  /* Check if the variable already exists */

  if (group->tg_envp && (pvar = env_findvar(group, name)) != NULL)
    {
      /* It does! Do we have permission to overwrite the existing value? */

      if (!overwrite)
        {
          /* No.. then just return success */

          sched_unlock();
          return OK;
        }

      /* Yes.. just remove the name=value pair from the environment.  It will
       * be added again below.  Note that we are responsible for reallocating
       * the environment buffer; this will happen below.
       */

      (void)env_removevar(group, pvar);
    }

  /* Get the size of the new name=value string.  The +2 is for the '=' and for
   * null terminator
   */

  varlen = strlen(name) + strlen(value) + 2;

  /* Then allocate or reallocate the environment buffer */

  if (group->tg_envp)
    {
      newsize = group->tg_envsize + varlen;
      newenvp = (FAR char *)kurealloc(group->tg_envp, newsize);
      if (!newenvp)
        {
          ret = ENOMEM;
          goto errout_with_lock;
        }

      pvar = &newenvp[group->tg_envsize];
    }
  else
    {
      newsize = varlen;
      newenvp = (FAR char *)kumalloc(varlen);
      if (!newenvp)
        {
          ret = ENOMEM;
          goto errout_with_lock;
        }

      pvar = newenvp;
    }

  /* Save the new buffer and size */

  group->tg_envp    = newenvp;
  group->tg_envsize = newsize;

  /* Now, put the new name=value string into the environment buffer */

  sprintf(pvar, "%s=%s", name, value);
  sched_unlock();
  return OK;

errout_with_lock:
  sched_unlock();
errout:
  errno = ret;
  return ERROR;
}