Пример #1
0
/*!
 * \brief Add a new memory region to the heap.
 *
 * This function can be called more than once to manage non-continous
 * memory regions. It is automatically called by Nut/OS during
 * initialization.
 *
 * \param addr Start address of the memory region.
 * \param size Number of bytes of the memory region.
 */
void NutHeapRootAdd(HEAPNODE ** root, void *addr, size_t size)
{
    HEAPNODE *node = (HEAPNODE *) NUTMEM_TOP_ALIGN((uintptr_t) addr);

    node->hn_size = NUTMEM_BOTTOM_ALIGN(size - ((uintptr_t) node - (uintptr_t) addr));
#ifdef NUTDEBUG_HEAP
    NutHeapDebugRootFree(root, PrepareUserArea(node), NULL, 0);
#else
    NutHeapRootFree(root, PrepareUserArea(node));
#endif
}
Пример #2
0
/*!
 * \brief Return a block to heap memory.
 *
 * This function simply calls NutHeapFree(). It overrides the function
 * of the runtime library, when the application is linked with nutcrt or
 * nutcrtf.
 *
 * \param p Points to a memory block previously allocated
 *          through a call to malloc().
 */
void dbg_free(void *p, CONST char *file, int line)
{
    NutHeapDebugRootFree(&heapFreeList, p, file, line);
}
Пример #3
0
void *NutHeapRootRealloc(HEAPNODE ** root, void *block, size_t size)
#endif
{
    HEAPNODE *node;
    HEAPNODE **npp;
    HEAPNODE *fnode;
    void *newmem;

#ifdef NUTDEBUG_HEAP
    /* With NULL pointer the call is equivalent to alloc. */
    if (block == NULL) {
        return NutHeapDebugRootAlloc(root, size, file, line);
    }
    /* With zero size the call is equivalent to free. */
    if (size == 0) {
        if (NutHeapDebugRootFree(root, block, file, line)) {
            return NULL;
        }
        return block;
    }

    /* Revive our node pointer. */
    fnode = (HEAPNODE *) ((uintptr_t) block - (NUT_HEAP_OVERHEAD + NUTMEM_GUARD_BYTES));

    /* Sanity check. */
    if (DebugValidateUserArea(fnode, file, line)) {
        return NULL;
    }
#else
    if (block == NULL) {
        return NutHeapRootAlloc(root, size);
    }
    if (size == 0) {
        if (NutHeapRootFree(root, block)) {
            return NULL;
        }
        return block;
    }
    fnode = (HEAPNODE *) ((uintptr_t) block - (NUT_HEAP_OVERHEAD + NUTMEM_GUARD_BYTES));
    if (ValidateUserArea(fnode)) {
        return NULL;
    }
#endif

    /* Determine the minimum size. Add optional guard and alignment bytes.
       Make sure that a HEAPNODE structure fits. */
    size += NUT_HEAP_OVERHEAD + NUTMEM_GUARD_BYTES * 2;
    if (size < sizeof(HEAPNODE)) {
        size = sizeof(HEAPNODE);
    }
    size = NUTMEM_TOP_ALIGN(size);

    /*
     * Expansion.
     */
    if (size > fnode->hn_size) {
        size_t size_miss = size - fnode->hn_size;

        /* Find the free node following next. */
        node = *root;
        npp = root;
        while (node && node < fnode) {
            npp = &node->hn_next;
            node = node->hn_next;
        }

        /* If we found a node and if this node is large enough and
           if it directly follows without a gap, then use it. */
        if (node && node->hn_size >= size_miss &&       /* */
            (uintptr_t) fnode + fnode->hn_size == (uintptr_t) node) {
            /* Check if the following node is large enough to be split. */
            if (node->hn_size - size_miss >= NUTMEM_HEAPNODE_MIN) {
                /* Adjust the allocated size. */
                fnode->hn_size += size_miss;
                /* Insert the remaining part into the free list. */
                *npp = (HEAPNODE *) ((uintptr_t) node + size_miss);
                /* Due to possible overlapping it is important to set
                   the pointer first, then the size. */
                (*npp)->hn_next = node->hn_next;
                (*npp)->hn_size = node->hn_size - size_miss;
                PrepareUserArea(fnode);
            } else {
                /* Adjust the allocated size. */
                fnode->hn_size += node->hn_size;
                PrepareUserArea(fnode);
                /* Remove the merged node from the free list. */
                *npp = node->hn_next;
            }
            /* Return the original pointer. */
            return block;
        }

        /* Relocate if no sufficiently large block follows. */
#ifdef NUTDEBUG_HEAP
        newmem = NutHeapDebugRootAlloc(root, size, file, line);
#else
        newmem = NutHeapRootAlloc(root, size);
#endif
        if (newmem) {
            memcpy(newmem, block,
                fnode->hn_size - NUT_HEAP_OVERHEAD - 2 * NUTMEM_GUARD_BYTES);
#ifdef NUTDEBUG_HEAP
            NutHeapDebugRootFree(root, block, file, line);
#else
            NutHeapRootFree(root, block);
#endif
        }
        return newmem;
    }

    /*
     * Reduction.
     */
    if (size < fnode->hn_size - NUTMEM_HEAPNODE_MIN) {
        /* Release the remaining part to the free list. */
        node = (HEAPNODE *) ((uintptr_t) fnode + size);
        node->hn_size = fnode->hn_size - size;
#ifdef NUTDEBUG_HEAP
        NutHeapDebugRootFree(root, PrepareUserArea(node), NULL, 0);
#else
        NutHeapRootFree(root, PrepareUserArea(node));
#endif
        /* Adjust the allocated size. */
        fnode->hn_size = size;
        PrepareUserArea(fnode);
    }
    return block;
}