Ejemplo n.º 1
0
/**
 * @brief   Allocates a block of memory from the heap by using the first-fit
 *          algorithm.
 * @details The allocated block is guaranteed to be properly aligned for a
 *          pointer data type (@p stkalign_t).
 *
 * @param[in] heapp     pointer to a heap descriptor or @p NULL in order to
 *                      access the default heap.
 * @param[in] size      the size of the block to be allocated. Note that the
 *                      allocated block may be a bit bigger than the requested
 *                      size for alignment and fragmentation reasons.
 * @return              A pointer to the allocated block.
 * @retval NULL         if the block cannot be allocated.
 *
 * @api
 */
void *chHeapAlloc(memory_heap_t *heapp, size_t size) {
  union heap_header *qp, *hp, *fp;

  if (heapp == NULL) {
    heapp = &default_heap;
  }

  size = MEM_ALIGN_NEXT(size);
  qp = &heapp->h_free;

  H_LOCK(heapp);
  while (qp->h.u.next != NULL) {
    hp = qp->h.u.next;
    if (hp->h.size >= size) {
      if (hp->h.size < (size + sizeof(union heap_header))) {
        /* Gets the whole block even if it is slightly bigger than the
           requested size because the fragment would be too small to be
           useful.*/
        qp->h.u.next = hp->h.u.next;
      }
      else {
        /* Block bigger enough, must split it.*/
        /*lint -save -e9087 [11.3] Safe cast.*/
        fp = (void *)((uint8_t *)(hp) + sizeof(union heap_header) + size);
        /*lint -restore*/
        fp->h.u.next = hp->h.u.next;
        fp->h.size = (hp->h.size - sizeof(union heap_header)) - size;
        qp->h.u.next = fp;
        hp->h.size = size;
      }
      hp->h.u.heap = heapp;
      H_UNLOCK(heapp);

      /*lint -save -e9087 [11.3] Safe cast.*/
      return (void *)(hp + 1);
      /*lint -restore*/
    }
    qp = hp;
  }
  H_UNLOCK(heapp);

  /* More memory is required, tries to get it from the associated provider
     else fails.*/
  if (heapp->h_provider != NULL) {
    hp = heapp->h_provider(size + sizeof(union heap_header));
    if (hp != NULL) {
      hp->h.u.heap = heapp;
      hp->h.size = size;
      hp++;

      /*lint -save -e9087 [11.3] Safe cast.*/
      return (void *)hp;
      /*lint -restore*/
    }
  }

  return NULL;
}
Ejemplo n.º 2
0
void chHeapFree(void *p) {

  chDbgCheck(p != NULL, "chHeapFree");

  H_LOCK();
  free(p);
  H_UNLOCK();
}
Ejemplo n.º 3
0
void *chHeapAlloc(MemoryHeap *heapp, size_t size) {
  void *p;

  chDbgCheck(heapp == NULL, "chHeapAlloc");

  H_LOCK();
  p = malloc(size);
  H_UNLOCK();
  return p;
}
Ejemplo n.º 4
0
/**
 * @brief   Reports the heap status.
 * @note    This function is meant to be used in the test suite, it should
 *          not be really useful for the application code.
 * @note    This function is not implemented when the @p CH_USE_MALLOC_HEAP
 *          configuration option is used (it always returns zero).
 *
 * @param[in] heapp     pointer to a heap descriptor or @p NULL in order to
 *                      access the default heap.
 * @param[in] sizep     pointer to a variable that will receive the total
 *                      fragmented free space
 * @return              The number of fragments in the heap.
 *
 * @api
 */
size_t chHeapStatus(MemoryHeap *heapp, size_t *sizep) {
  union heap_header *qp;
  size_t n, sz;

  if (heapp == NULL)
    heapp = &default_heap;

  H_LOCK(heapp);

  sz = 0;
  for (n = 0, qp = &heapp->h_free; qp->h.u.next; n++, qp = qp->h.u.next)
    sz += qp->h.u.next->h.size;
  if (sizep)
    *sizep = sz;

  H_UNLOCK(heapp);
  return n;
}
Ejemplo n.º 5
0
/**
 * @brief   Frees a previously allocated memory block.
 *
 * @param[in] p         pointer to the memory block to be freed
 *
 * @api
 */
void chHeapFree(void *p) {
  union heap_header *qp, *hp;
  MemoryHeap *heapp;

  chDbgCheck(p != NULL, "chHeapFree");

  hp = (union heap_header *)p - 1;
  heapp = hp->h.u.heap;
  qp = &heapp->h_free;
  H_LOCK(heapp);

  while (TRUE) {
    chDbgAssert((hp < qp) || (hp >= LIMIT(qp)),
                "chHeapFree(), #1",
                "within free block");

    if (((qp == &heapp->h_free) || (hp > qp)) &&
        ((qp->h.u.next == NULL) || (hp < qp->h.u.next))) {
      /* Insertion after qp.*/
      hp->h.u.next = qp->h.u.next;
      qp->h.u.next = hp;
      /* Verifies if the newly inserted block should be merged.*/
      if (LIMIT(hp) == hp->h.u.next) {
        /* Merge with the next block.*/
        hp->h.size += hp->h.u.next->h.size + sizeof(union heap_header);
        hp->h.u.next = hp->h.u.next->h.u.next;
      }
      if ((LIMIT(qp) == hp)) {
        /* Merge with the previous block.*/
        qp->h.size += hp->h.size + sizeof(union heap_header);
        qp->h.u.next = hp->h.u.next;
      }
      break;
    }
    qp = qp->h.u.next;
  }

  H_UNLOCK(heapp);
  return;
}
Ejemplo n.º 6
0
/**
 * @brief   Frees a previously allocated memory block.
 *
 * @param[in] p         pointer to the memory block to be freed
 *
 * @api
 */
void chHeapFree(void *p) {
  union heap_header *qp, *hp;
  memory_heap_t *heapp;

  chDbgCheck(p != NULL);

  /*lint -save -e9087 [11.3] Safe cast.*/
  hp = (union heap_header *)p - 1;
  /*lint -restore*/
  heapp = hp->h.u.heap;
  qp = &heapp->h_free;

  H_LOCK(heapp);
  while (true) {
    chDbgAssert((hp < qp) || (hp >= LIMIT(qp)), "within free block");

    if (((qp == &heapp->h_free) || (hp > qp)) &&
        ((qp->h.u.next == NULL) || (hp < qp->h.u.next))) {
      /* Insertion after qp.*/
      hp->h.u.next = qp->h.u.next;
      qp->h.u.next = hp;
      /* Verifies if the newly inserted block should be merged.*/
      if (LIMIT(hp) == hp->h.u.next) {
        /* Merge with the next block.*/
        hp->h.size += hp->h.u.next->h.size + sizeof(union heap_header);
        hp->h.u.next = hp->h.u.next->h.u.next;
      }
      if ((LIMIT(qp) == hp)) {
        /* Merge with the previous block.*/
        qp->h.size += hp->h.size + sizeof(union heap_header);
        qp->h.u.next = hp->h.u.next;
      }
      break;
    }
    qp = qp->h.u.next;
  }
  H_UNLOCK(heapp);

  return;
}
Ejemplo n.º 7
0
/**
 * @brief   Reports the heap status.
 * @note    This function is meant to be used in the test suite, it should
 *          not be really useful for the application code.
 *
 * @param[in] heapp     pointer to a heap descriptor or @p NULL in order to
 *                      access the default heap.
 * @param[in] sizep     pointer to a variable that will receive the total
 *                      fragmented free space
 * @return              The number of fragments in the heap.
 *
 * @api
 */
size_t chHeapStatus(memory_heap_t *heapp, size_t *sizep) {
  union heap_header *qp;
  size_t n, sz;

  if (heapp == NULL) {
    heapp = &default_heap;
  }

  H_LOCK(heapp);
  sz = 0;
  n = 0;
  qp = &heapp->h_free;
  while (qp->h.u.next != NULL) {
    sz += qp->h.u.next->h.size;
    n++;
    qp = qp->h.u.next;
  }
  if (sizep != NULL) {
    *sizep = sz;
  }
  H_UNLOCK(heapp);

  return n;
}