Пример #1
0
/** Free a memory block
 *
 * @param addr The address of the block.
 *
 */
void free(const void *addr)
{
	if (addr == NULL)
		return;
	
	futex_down(&malloc_futex);
	
	/* Calculate the position of the header. */
	heap_block_head_t *head
	    = (heap_block_head_t *) (addr - sizeof(heap_block_head_t));
	
	block_check(head);
	malloc_assert(!head->free);
	
	heap_area_t *area = head->area;
	
	area_check(area);
	malloc_assert((void *) head >= (void *) AREA_FIRST_BLOCK_HEAD(area));
	malloc_assert((void *) head < area->end);
	
	/* Mark the block itself as free. */
	head->free = true;
	
	/* Look at the next block. If it is free, merge the two. */
	heap_block_head_t *next_head
	    = (heap_block_head_t *) (((void *) head) + head->size);
	
	if ((void *) next_head < area->end) {
		block_check(next_head);
		if (next_head->free)
			block_init(head, head->size + next_head->size, true, area);
	}
	
	/* Look at the previous block. If it is free, merge the two. */
	if ((void *) head > (void *) AREA_FIRST_BLOCK_HEAD(area)) {
		heap_block_foot_t *prev_foot =
		    (heap_block_foot_t *) (((void *) head) - sizeof(heap_block_foot_t));
		
		heap_block_head_t *prev_head =
		    (heap_block_head_t *) (((void *) head) - prev_foot->size);
		
		block_check(prev_head);
		
		if (prev_head->free)
			block_init(prev_head, prev_head->size + head->size, true,
			    area);
	}
	
	heap_shrink(area);
	
	futex_up(&malloc_futex);
}
Пример #2
0
/** Reallocate memory block
 *
 * @param addr Already allocated memory or NULL.
 * @param size New size of the memory block.
 *
 * @return Reallocated memory or NULL.
 *
 */
void *realloc(const void *addr, const size_t size)
{
	if (addr == NULL)
		return malloc(size);
	
	futex_down(&malloc_futex);
	
	/* Calculate the position of the header. */
	heap_block_head_t *head =
	    (heap_block_head_t *) (addr - sizeof(heap_block_head_t));
	
	block_check(head);
	malloc_assert(!head->free);
	
	heap_area_t *area = head->area;
	
	area_check(area);
	malloc_assert((void *) head >= (void *) AREA_FIRST_BLOCK_HEAD(area));
	malloc_assert((void *) head < area->end);
	
	void *ptr = NULL;
	bool reloc = false;
	size_t real_size = GROSS_SIZE(ALIGN_UP(size, BASE_ALIGN));
	size_t orig_size = head->size;
	
	if (orig_size > real_size) {
		/* Shrink */
		if (orig_size - real_size >= STRUCT_OVERHEAD) {
			/*
			 * Split the original block to a full block
			 * and a trailing free block.
			 */
			block_init((void *) head, real_size, false, area);
			block_init((void *) head + real_size,
			    orig_size - real_size, true, area);
			heap_shrink(area);
		}
		
		ptr = ((void *) head) + sizeof(heap_block_head_t);
	} else {
		/*
		 * Look at the next block. If it is free and the size is
		 * sufficient then merge the two. Otherwise just allocate
		 * a new block, copy the original data into it and
		 * free the original block.
		 */
		heap_block_head_t *next_head =
		    (heap_block_head_t *) (((void *) head) + head->size);
		
		if (((void *) next_head < area->end) &&
		    (head->size + next_head->size >= real_size) &&
		    (next_head->free)) {
			block_check(next_head);
			block_init(head, head->size + next_head->size, false, area);
			split_mark(head, real_size);
			
			ptr = ((void *) head) + sizeof(heap_block_head_t);
			next_fit = NULL;
		} else
			reloc = true;
	}
	
	futex_up(&malloc_futex);
	
	if (reloc) {
		ptr = malloc(size);
		if (ptr != NULL) {
			memcpy(ptr, addr, NET_SIZE(orig_size));
			free(addr);
		}
	}
	
	return ptr;
}
Пример #3
0
/*
 * Return an element from the heap, located at the given index
 */
static HeapElement *
heap_delete(Heap * h,int idx)
{
    HeapElement *he,*helast;
    int		 pidx;
    HeapInternCmp cmp_func;

    DBG(debug("heap_delete(h=%p,idx=%d)\n",h,idx));

    LLOG(HSIZE(h));

    if (idx < 0 || idx >= HSIZE(h))
	{ LLOG(idx); return NULL; }

    if (h->hpMode == HEAP_MAXIMIZE)
	cmp_func = heap_larger;
    else 
    	cmp_func = heap_smaller;

    /* Remember the current element */
    he = HARRAY(h,idx);
    /* Remember the last element */
    helast = HLAST(h);

    h->hpFilled--;

    if (idx == HSIZE(h))
    	/* This is the last element */
	goto end_label;

    /* Put the last element in the position of the current */

    HARRAY(h,idx) = helast;

    if (h->hpChgFunc)
	h->hpChgFunc(HARRAY(h,idx)->heData,idx);

    /* Heapify the new subtree. Then if the root of the subtree 
     * is larger than its parent, propagate it up the tree until
     * it finds is proper location */
    heap_heapify(h,idx);

    pidx = HPARENT(idx);
    LLOG(pidx);

    if (idx > 0)
    {
	while (cmp_func(h,HARRAY(h,idx),HARRAY(h,pidx)))
	{
	    heap_swap(h,idx,pidx);
	    idx = pidx;
	    if (idx == 0)
		break;
	    pidx = HPARENT(idx);
	}
    }

end_label:


    if (NEEDS2SHRINK(h))
    	heap_shrink(h);

    return he;
}