Esempio n. 1
0
FAR void *group_malloc(FAR struct task_group_s *group, size_t nbytes)
{
  /* A NULL group pointer means the current group */

  if (!group)
    {
      FAR struct tcb_s *tcb = this_task();
      DEBUGASSERT(tcb && tcb->group);
      group = tcb->group;
    }

  /* Check the group type */

  if ((group->tg_flags & GROUP_FLAG_PRIVILEGED) != 0)
    {
      /* It is a privileged group... use the kernel mode memory allocator */

      return kmm_malloc(nbytes);
    }
  else
    {
      /* This is an unprivileged group... use the user mode memory
       * allocator.
       */

      return kumm_malloc(nbytes);
    }
}
Esempio n. 2
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_BUILD_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 *)kmm_malloc(stack_size);
    } else
#endif
    {
        stack_alloc_ptr = (uint32_t*)kumm_malloc(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. 3
0
FAR void *rammap(int fd, size_t length, off_t offset)
{
  FAR struct fs_rammap_s *map;
  FAR uint8_t *alloc;
  FAR uint8_t *rdbuffer;
  ssize_t nread;
  off_t fpos;
  int errcode;
  int ret;

  /* There is a major design flaw that I have not yet thought of fix for:
   * The goal is to have a single region of memory that represents a single
   * file and can be shared by many threads.  That is, given a filename a
   * thread should be able to open the file, get a file descriptor, and
   * call mmap() to get a memory region.  Different file descriptors opened
   * with the same file path should get the same memory region when mapped.
   *
   * The design flaw is that I don't have sufficient knowledge to know that
   * these different file descriptors map to the same file.  So, for the time
   * being, a new memory region is created each time that rammap() is called.
   * Not very useful!
   */

  /* Allocate a region of memory of the specified size */

  alloc = (FAR uint8_t *)kumm_malloc(sizeof(struct fs_rammap_s) + length);
  if (!alloc)
    {
      ferr("ERROR: Region allocation failed, length: %d\n", (int)length);
      errcode = ENOMEM;
      goto errout;
    }

  /* Initialize the region */

  map         = (FAR struct fs_rammap_s *)alloc;
  memset(map, 0, sizeof(struct fs_rammap_s));
  map->addr   = alloc + sizeof(struct fs_rammap_s);
  map->length = length;
  map->offset = offset;

  /* Seek to the specified file offset */

  fpos = lseek(fd, offset,  SEEK_SET);
  if (fpos == (off_t)-1)
    {
      /* Seek failed... errno has already been set, but EINVAL is probably
       * the correct response.
       */

      ferr("ERROR: Seek to position %d failed\n", (int)offset);
      errcode = EINVAL;
      goto errout_with_region;
    }

  /* Read the file data into the memory region */

  rdbuffer = map->addr;
  while (length > 0)
    {
      nread = read(fd, rdbuffer, length);
      if (nread < 0)
        {
          /* Handle the special case where the read was interrupted by a
           * signal.
           */

          errcode = get_errno();
          if (errcode != EINTR)
            {
              /* All other read errors are bad.  errno is already set.
               * (but maybe should be forced to EINVAL?).  NOTE that if
               * FS DEBUG is enabled, then the following ferr() macro will
               * destroy the errno value.
               */

              ferr("ERROR: Read failed: offset=%d errno=%d\n",
                   (int)offset, errcode);
#ifdef CONFIG_DEBUG_FS
              goto errout_with_region;
#else
              goto errout_with_errno;
#endif
             }
        }

      /* Check for end of file. */

      if (nread == 0)
        {
          break;
        }

      /* Increment number of bytes read */

      rdbuffer += nread;
      length   -= nread;
    }

  /* Zero any memory beyond the amount read from the file */

  memset(rdbuffer, 0, length);

  /* Add the buffer to the list of regions */

  rammap_initialize();
  ret = sem_wait(&g_rammaps.exclsem);
  if (ret < 0)
    {
      goto errout_with_errno;
    }

  map->flink  = g_rammaps.head;
  g_rammaps.head = map;

  sem_post(&g_rammaps.exclsem);
  return map->addr;

errout_with_region:
  kumm_free(alloc);
errout:
  set_errno(errcode);
  return MAP_FAILED;

errout_with_errno:
  kumm_free(alloc);
  return MAP_FAILED;
}
Esempio n. 4
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_BUILD_KERNEL) && defined(CONFIG_MM_KERNEL_HEAP)
      /* Use the kernel allocator if this is a kernel thread */

      if (ttype == TCB_FLAG_TTYPE_KERNEL)
        {
          tcb->stack_alloc_ptr = (uint32_t *)kmm_malloc(stack_size);
        }
      else
#endif
        {
          /* Use the user-space allocator if this is a task or pthread */

          tcb->stack_alloc_ptr = (uint32_t *)kumm_malloc(stack_size);
        }

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

      if (!tcb->stack_alloc_ptr)
        {
          serr("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;

      /* 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.
       */

#ifdef CONFIG_STACK_COLORATION
      memset(tcb->stack_alloc_ptr, 0xaa, stack_size);
#endif

      /* The SH family uses a push-down stack:  the stack grows
       * toward loweraddresses 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 SH stack must be aligned at word (4 byte)
       * boundaries. If necessary top_of_stack must be rounded
       * down to the next boundary
       */

      top_of_stack &= ~3;
      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;

      board_autoled_on(LED_STACKCREATED);
      return OK;
    }

   return ERROR;
}
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.
       */

      tcb->stack_alloc_ptr = (uint32_t *)kumm_malloc(stack_size);

#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.
       */

#ifdef CONFIG_STACK_COLORATION
      memset(tcb->stack_alloc_ptr, STACK_COLOR, 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;

#if defined(ARCH_HAVE_LEDS)
      board_autoled_on(LED_STACKCREATED);
#endif
      return OK;
    }

  return ERROR;
}
Esempio n. 6
0
int up_create_stack(FAR struct tcb_s *tcb, size_t stack_size, uint8_t ttype)
{
  static bool first_task = true;

  /* 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.
       */

#ifdef HAVE_KERNEL_HEAP
      /* Use the kernel allocator if this is a kernel thread */

      if (ttype == TCB_FLAG_TTYPE_KERNEL)
        {
          tcb->stack_alloc_ptr = (uint32_t *)kmm_malloc(stack_size);
        }
      else
#endif
        {
          /* Use the user-space allocator if this is a task or pthread */

          tcb->stack_alloc_ptr = (uint32_t *)kumm_malloc(stack_size);
        }

#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.
       */

#ifdef CONFIG_STACK_COLORATION
      up_stack_color(tcb->stack_alloc_ptr, tcb->adj_stack_size);
#endif

      if (first_task)
        {
          board_led_on(LED_STACKCREATED);
          first_task = false;
        }

      return OK;
    }

   return ERROR;
}
int elf_loaddtors(FAR struct elf_loadinfo_s *loadinfo)
{
  FAR Elf32_Shdr *shdr;
  size_t dtorsize;
  int dtoridx;
  int ret;
  int i;

  DEBUGASSERT(loadinfo->dtors == NULL);

  /* Allocate an I/O buffer if necessary.  This buffer is used by
   * elf_sectname() to accumulate the variable length symbol name.
   */

  ret = elf_allocbuffer(loadinfo);
  if (ret < 0)
    {
      bdbg("elf_allocbuffer failed: %d\n", ret);
      return -ENOMEM;
    }

  /* Find the index to the section named ".dtors."  NOTE:  On old ABI system,
   * .dtors is the name of the section containing the list of destructors;
   * On newer systems, the similar section is called .fini_array.  It is
   * expected that the linker script will force the section name to be ".dtors"
   * in either case.
   */

  dtoridx = elf_findsection(loadinfo, ".dtors");
  if (dtoridx < 0)
    {
      /* This may not be a failure.  -ENOENT indicates that the file has no
       * static destructor section.
       */

      bvdbg("elf_findsection .dtors section failed: %d\n", dtoridx);
      return ret == -ENOENT ? OK : ret;
    }

  /* Now we can get a pointer to the .dtor section in the section header
   * table.
   */

  shdr = &loadinfo->shdr[dtoridx];

  /* Get the size of the .dtor section and the number of destructors that
   * will need to be called.
   */

  dtorsize         = shdr->sh_size;
  loadinfo->ndtors = dtorsize / sizeof(binfmt_dtor_t);

  bvdbg("dtoridx=%d dtorsize=%d sizeof(binfmt_dtor_t)=%d ndtors=%d\n",
        dtoridx, dtorsize,  sizeof(binfmt_dtor_t), loadinfo->ndtors);

  /* Check if there are any destructors.  It is not an error if there
   * are none.
   */

  if (loadinfo->ndtors > 0)
    {
      /* Check an assumption that we made above */

      DEBUGASSERT(shdr->sh_size == loadinfo->ndtors * sizeof(binfmt_dtor_t));

      /* In the old ABI, the .dtors section is not allocated.  In that case,
       * we need to allocate memory to hold the .dtors and then copy the
       * from the file into the allocated memory.
       *
       * SHF_ALLOC indicates that the section requires memory during
       * execution.
       */

      if ((shdr->sh_flags & SHF_ALLOC) == 0)
        {
          /* Allocate memory to hold a copy of the .dtor section */

          loadinfo->ctoralloc = (binfmt_dtor_t*)kumm_malloc(dtorsize);
          if (!loadinfo->ctoralloc)
            {
              bdbg("Failed to allocate memory for .dtors\n");
              return -ENOMEM;
            }

          loadinfo->dtors = (binfmt_dtor_t *)loadinfo->ctoralloc;

          /* Read the section header table into memory */

          ret = elf_read(loadinfo, (FAR uint8_t*)loadinfo->dtors, dtorsize,
                         shdr->sh_offset);
          if (ret < 0)
            {
              bdbg("Failed to allocate .dtors: %d\n", ret);
              return ret;
            }

          /* Fix up all of the .dtor addresses.  Since the addresses
           * do not lie in allocated memory, there will be no relocation
           * section for them.
           */

          for (i = 0; i < loadinfo->ndtors; i++)
            {
              FAR uintptr_t *ptr = (uintptr_t *)((FAR void *)(&loadinfo->dtors)[i]);

              bvdbg("dtor %d: %08lx + %08lx = %08lx\n",
                    i, *ptr, (unsigned long)loadinfo->textalloc,
                    (unsigned long)(*ptr + loadinfo->textalloc));

              *ptr += loadinfo->textalloc;
            }
        }
      else
        {

          /* Save the address of the .dtors (actually, .init_array) where it was
           * loaded into memory.  Since the .dtors lie in allocated memory, they
           * will be relocated via the normal mechanism.
           */

          loadinfo->dtors = (binfmt_dtor_t*)shdr->sh_addr;
        }
    }

  return OK;
}