int elf_addrenv_alloc(FAR struct elf_loadinfo_s *loadinfo, size_t textsize,
                      size_t datasize)
{
#ifdef CONFIG_ARCH_ADDRENV
    FAR void *vtext;
    FAR void *vdata;
    int ret;

    /* Create an address environment for the new ELF task */

    ret = up_addrenv_create(textsize, datasize, &loadinfo->addrenv);
    if (ret < 0)
    {
        bdbg("ERROR: up_addrenv_create failed: %d\n", ret);
        return ret;
    }

    /* Get the virtual address associated with the start of the address
     * environment.  This is the base address that we will need to use to
     * access the ELF image (but only if the address environment has been
     * selected.
     */

    ret = up_addrenv_vtext(&loadinfo->addrenv, &vtext);
    if (ret < 0)
    {
        bdbg("ERROR: up_addrenv_vtext failed: %d\n", ret);
        return ret;
    }

    ret = up_addrenv_vdata(&loadinfo->addrenv, textsize, &vdata);
    if (ret < 0)
    {
        bdbg("ERROR: up_adup_addrenv_vdatadrenv_vtext failed: %d\n", ret);
        return ret;
    }

    loadinfo->textalloc = (uintptr_t)vtext;
    loadinfo->dataalloc = (uintptr_t)vdata;
    return OK;
#else
    /* Allocate memory to hold the ELF image */

    loadinfo->textalloc = (uintptr_t)kuzalloc(textsize + datasize);
    if (!loadinfo->textalloc)
    {
        return -ENOMEM;
    }

    loadinfo->dataalloc = loadinfo->textalloc + textsize;
    return OK;
#endif
}
Example #2
0
int elf_addrenv_alloc(FAR struct elf_loadinfo_s *loadinfo, size_t envsize)
{
#ifdef CONFIG_ADDRENV
  FAR void *vaddr;
  int ret;

  /* Create an address environment for the new ELF task */

  ret = up_addrenv_create(envsize, &loadinfo->addrenv);
  if (ret < 0)
    {
      bdbg("ERROR: up_addrenv_create failed: %d\n", ret);
      return ret;
    }

  /* Get the virtual address associated with the start of the address
   * environment.  This is the base address that we will need to use to
   * access the ELF image (but only if the address environment has been
   * selected.
   */

  ret = up_addrenv_vaddr(loadinfo->addrenv, &vaddr);
  if (ret < 0)
    {
      bdbg("ERROR: up_addrenv_vaddr failed: %d\n", ret);
      return ret;
    }

  loadinfo->elfalloc = (uintptr_t)vaddr;
  return OK;
#else
  /* Allocate memory to hold the ELF image */

  loadinfo->elfalloc = (uintptr_t)kuzalloc(envsize);
  if (!loadinfo->elfalloc)
    {
      return -ENOMEM;
    }

  return OK;
#endif
}
Example #3
0
NXHANDLE nx_open(FAR NX_DRIVERTYPE *dev)
{
  FAR struct nxfe_state_s *fe;
  int ret;

  /* Sanity checking */

#ifdef CONFIG_DEBUG
  if (!dev)
    {
      errno = EINVAL;
      return NULL;
    }
#endif

  /* Allocate the NX state structure.  The user-space allocator is used
   * (if available) for compatibility with the multi-user implementation.
   */

  fe = (FAR struct nxfe_state_s *)kuzalloc(sizeof(struct nxfe_state_s));
  if (!fe)
    {
      errno = ENOMEM;
      return NULL;
    }

  /* Initialize and configure the server */

  ret = nxsu_setup(dev, fe);
  if (ret < 0)
    {
      return NULL; /* nxsu_setup sets errno */
    }

  /* Fill the initial background window */

  nxbe_fill(&fe->be.bkgd, &fe->be.bkgd.bounds, fe->be.bgcolor);
  return (NXHANDLE)fe;
}
int group_allocate(FAR struct task_tcb_s *tcb)
{
  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 *)kzalloc(sizeof(struct task_group_s));
  if (!group)
    {
      return -ENOMEM;
    }

#if CONFIG_NFILE_STREAMS > 0 && defined(CONFIG_NUTTX_KERNEL) && \
    defined(CONFIG_MM_KERNEL_HEAP)

  /* 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 *)
    kuzalloc(sizeof(struct streamlist));

  if (!group->tg_streamlist)
    {
      kfree(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_NUTTX_KERNEL) && \
    defined(CONFIG_MM_KERNEL_HEAP)
      kufree(group->tg_streamlist);
#endif
      kfree(group);
      tcb->cmn.group = NULL;
      return ret;
    }

  /* Initialize the pthread join semaphore */

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

  return OK;
}
Example #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;

      /* 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;
}
Example #6
0
FAR DIR *opendir(FAR const char *path)
{
  FAR struct inode *inode = NULL;
  FAR struct fs_dirent_s *dir;
  FAR const char *relpath;
  bool isroot = false;
  int ret;

  /* If we are given 'nothing' then we will interpret this as
   * request for the root inode.
   */

  inode_semtake();
  if (!path || *path == 0 || strcmp(path, "/") == 0)
    {
      inode   = root_inode;
      isroot = true;
      relpath = NULL;
    }
  else
    {
      /* We don't know what to do with relative pathes */

      if (*path != '/')
        {
          ret = -ENOTDIR;
          goto errout_with_semaphore;
        }

      /* Find the node matching the path. */

      inode = inode_search(&path, (FAR struct inode**)NULL, (FAR struct inode**)NULL, &relpath);
    }

  /* Did we get an inode? */

  if (!inode)
    {
      /* 'path' is not a does not exist.*/

      ret = ENOTDIR;
      goto errout_with_semaphore;
    }

  /* Allocate a type DIR -- which is little more than an inode
   * container.
   */

  dir = (FAR struct fs_dirent_s *)kuzalloc(sizeof(struct fs_dirent_s));
  if (!dir)
    {
      /* Insufficient memory to complete the operation.*/

      ret = ENOMEM;
      goto errout_with_semaphore;
    }

  /* Populate the DIR structure and return it to the caller.  The way that
   * we do this depends on whenever this is a "normal" pseudo-file-system
   * inode or a file system mountpoint.
   */

  dir->fd_position = 0;      /* This is the position in the read stream */

  /* First, handle the special case of the root inode.  This must be
   * special-cased here because the root inode might ALSO be a mountpoint.
   */

  if (isroot)
    {
      /* Whatever payload the root inode carries, the root inode is always
       * a directory inode in the pseudo-file system
       */

      open_pseudodir(inode, dir);
    }

  /* Is this a node in the pseudo filesystem? Or a mountpoint?  If the node
   * is the root (isroot == TRUE), then this is a special case.
   */

#ifndef CONFIG_DISABLE_MOUNTPOINT
   else if (INODE_IS_MOUNTPT(inode))
     {
       /* Yes, the node is a file system mountpoint */

      dir->fd_root = inode;  /* Save the inode where we start */

      /* Open the directory at the relative path */

      ret = open_mountpoint(inode, relpath, dir);
      if (ret != OK)
        {
           goto errout_with_direntry;
        }
    }
#endif
  else
    {
      /* The node is part of the root pseudo file system.  Does the inode
       * have a child? If so that the child would be the 'root' of a list
       * of nodes under the directory.
       */

      FAR struct inode *child = inode->i_child;
      if (child)
        {
          /* It looks we have a valid pseudo-filesystem directory node. */

          open_pseudodir(child, dir);
        }
      else if (!inode->u.i_ops)
        {
          /* This is a dangling node with no children and no operations. Set
           * up to enumerate an empty directory.
           */

          open_emptydir(dir);
        }
      else
        {
          ret = ENOTDIR;
          goto errout_with_direntry;
        }
    }

  inode_semgive();
  return ((DIR*)dir);

  /* Nasty goto's make error handling simpler */

errout_with_direntry:
  kufree(dir);

errout_with_semaphore:
  inode_semgive();
  set_errno(ret);
  return NULL;
}
Example #7
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;
}
Example #8
0
int nxflat_addrenv_alloc(FAR struct nxflat_loadinfo_s *loadinfo, size_t envsize)
{
  FAR struct dspace_s *dspace;
#ifdef CONFIG_ADDRENV
  FAR void *vaddr;
  hw_addrenv_t oldenv;
  int ret;
#endif

  DEBUGASSERT(!loadinfo->dspace);

  /* Allocate the struct dspace_s container for the D-Space allocation */

  dspace = (FAR struct dspace_s *)kmalloc(sizeof(struct dspace_s));
  if (dspace == 0)
    {
      bdbg("ERROR: Failed to allocate DSpace\n");
      return -ENOMEM;
    }

#ifdef CONFIG_ADDRENV
  /* Create a D-Space address environment for the new NXFLAT task */

  ret = up_addrenv_create(envsize, &loadinfo->addrenv);
  if (ret < 0)
    {
      bdbg("ERROR: up_addrenv_create failed: %d\n", ret);
      goto errout_with_dspace;
    }

  /* Get the virtual address associated with the start of the address
   * environment.  This is the base address that we will need to use to
   * access the D-Space region (but only if the address environment has been
   * selected.
   */

  ret = up_addrenv_vaddr(loadinfo->addrenv, &vaddr);
  if (ret < 0)
    {
      bdbg("ERROR: up_addrenv_vaddr failed: %d\n", ret);
      goto errout_with_addrenv;
    }

  /* Clear all of the allocated D-Space memory.  We have to temporarily
   * selected the D-Space address environment to do this.
   */

  ret = up_addrenv_select(loadinfo->addrenv, &oldenv);
  if (ret < 0)
    {
      bdbg("ERROR: up_addrenv_select failed: %d\n", ret);
      goto errout_with_addrenv;
    }

  memset(vaddr, 0, envsize);

  ret = up_addrenv_restore(oldenv);
  if (ret < 0)
    {
      bdbg("ERROR: up_addrenv_restore failed: %d\n", ret);
      goto errout_with_addrenv;
    }

  /* Success... save the fruits of our labor */

  loadinfo->dspace = dspace;
  dspace->crefs    = 1;  
  dspace->region   = (FAR uint8_t *)vaddr;
  return OK;

errout_with_addrenv:
  (void)up_addrenv_destroy(loadinfo->addrenv);
  loadinfo->addrenv = 0;

errout_with_dspace:
  kfree(dspace);
  return ret;
#else
  /* Allocate (and zero) memory to hold the ELF image */

  dspace->region = (FAR uint8_t *)kuzalloc(envsize);
  if (!dspace->region)
    {
      kfree(dspace);
      return -ENOMEM;
    }

  loadinfo->dspace = dspace;
  dspace->crefs    = 1;  
  return OK;
#endif
}