Beispiel #1
0
//Coalesce free blocks if possible
static void *coalesce(void *bp) {
    size_t prev_alloc = block_free(block_prev(get_header(bp)));
    size_t next_alloc = block_free(block_next(get_header(bp)));
    size_t size = block_size(get_header(bp));

    if(prev_alloc && next_alloc)
	return bp;
    else if(prev_alloc && !next_alloc) {
	size += block_size(block_next(get_header(bp)));
	PUT(get_header(bp), PACK(size, 0));
	PUT(get_footer(bp), PACK(size, 0));
    }
    else if(!prev_alloc && next_alloc) {
	size += block_size(block_prev(get_header(bp)));
	PUT(get_header(prev_bp(bp)), PACK(size, 0));
	PUT(get_footer(bp), PACK(size, 0));
	bp = prev_bp(bp);
    }
    else if(!prev_alloc && !next_alloc) {
	size += block_size(block_next(get_header(bp))) + block_size(block_prev(get_header(bp)));
	PUT(get_header(prev_bp(bp)), PACK(size, 0));
	PUT(get_footer(next_bp(bp)), PACK(size, 0));
	bp = prev_bp(bp);
    }
    checkheap(1);
    return bp;
}
Beispiel #2
0
/*
 * Merge block with adjacent free blocks
 * Return: the pointer to the new free block 
 */
static void *coalesce(void *block) {
    REQUIRES(block != NULL);
    REQUIRES(in_heap(block));

    uint32_t *prev_block = block_prev(block);
    uint32_t *next_block = block_next(block);
    int prev_free = block_free(prev_block);
    int next_free = block_free(next_block);
    unsigned int words = block_size(block);
    

    if (prev_free && next_free) {       // Case 4, both free

        block_delete(prev_block);
        block_delete(next_block);

        words += block_size(prev_block) + block_size(next_block) + 4;
        set_size(prev_block, words);
        block_mark(prev_block, FREE);
        block = (void *)prev_block;

        block_insert(block);
        ENSURES(in_list(block));    
    }

    else if (!prev_free && next_free) { // Case 2, next if free

        block_delete(next_block);

        words += block_size(next_block) + 2;
        set_size(block, words);
        block_mark(block, FREE);  

        block_insert(block);
        ENSURES(in_list(block));      
    }

    else if (prev_free && !next_free) { // Case 3, prev is free
        block_delete(prev_block);

        words += block_size(prev_block) + 2;
        set_size(prev_block, words);
        block_mark(prev_block, FREE);
        block = (void *)prev_block;

        block_insert(block);
        ENSURES(in_list(block));
    }

    else {                              // Case 1, both unfree
        block_insert(block);
        ENSURES(in_list(block));
        return block;
    }
    return block;
 } 
Beispiel #3
0
static void remove_block_from_list(int index, void* block){
    REQUIRES(0 <= index && index < NUM_FREE_LISTS);

    void* next = block_next(block);
    void* prev = block_prev(block);

    if(free_lists[index] == block) free_lists[index] = next;

    if(prev != NULL) set_next_pointer(prev, next);
    if(next != NULL) set_prev_pointer(next, prev);

    set_next_pointer(block, NULL);
    set_prev_pointer(block, NULL);
}
Beispiel #4
0
static int coalesce(void* block, size_t* size){
    REQUIRES(block != NULL);
    REQUIRES(in_heap(block));

    //uint64_t* left_block;
    void* right_block;
    size_t new_size;
    int index;

    void* next;
    void* prev;

    *size = block_size(block);
    new_size = (*size) * 2;
    index = get_free_list_index(*size);

    if(new_size > MAX_SIZE) return index;

    right_block = ((uint64_t*)block)+(block_size(block)/sizeof(uint64_t*));

    // if(in_heap(left_block) && block_free(left_block)){
    //     if(block_size(left_block) == size){
    //         set_size(left_block, size*2);
    //         add_block_to_list(get_free_list_index(size*2), left_block);
    //     }
    // }
    
    if(in_heap(right_block) && block_free((uint32_t*)right_block)){
        if(block_size(right_block) == new_size/2){

            next = block_next(right_block);
            prev = block_prev(right_block);

            if(free_lists[index] == right_block) free_lists[index] = next;
            if(prev != NULL) set_next_pointer(prev, next);
            if(next != NULL) set_prev_pointer(next, prev);

            set_size(block, new_size);
            *size = new_size;
            index++;
        }
    }
    return index;
}
Beispiel #5
0
// Returns 0 if no errors were found, otherwise returns the error
int mm_checkheap(int verbose) {
    
    uint32_t *block = heap_listp;
    int count_iter = 0;
    int count_list = 0;
    
    //Check prologue blocks.
    if (block_size(block) != 0) {
        if (verbose)
            printf("Pro block should be zero size, header = %x\n", block[0]);
        return -1;         
    }

    if(block_free(block)) {
        if (verbose)
            printf("Pro block should not be free, header = %x\n", block[0]);
        return -1;
    }       

    for (block = heap_listp + 2; block_size(block) > 0; block = block_next(block)) {
        //printf("header = %x %d\n", block[0], block[0]);
        //Check each block’s address alignment.
        if (align(block + 1, 8) != block + 1) {
            if (verbose)
                printf("Block address alignment error\n");
            return -1;
        }

        //Check heap boundaries.
        if (!in_heap(block)) {
            if (verbose)
                printf("Block isn't in heap\n");
            return -1;
        }
        
        /* Check each block’s header and footer: 
        size (minimum size, alignment), previous/next allocate/
        free bit consistency, header and footer matching each other. */

        unsigned int words = block_size(block);
        if (words < 2) {
            if (verbose)
                printf("Block size is less then 8 bytes\n");
            return -1;
        }
        if (words % 2 != 0) {
            if (verbose)
                printf("Header %x, size %d is not a multiples of 8 bytes\n",
                      block[0],
                      words);
            return -1;
        }

        unsigned int next = block_size(block) + 1;        
        if (block[next] != block[0]) {
            if (verbose)
                printf("Header and footer should be identical\n");
            return -1;
        }

        //Check coalescing: no two consecutive free blocks in the heap.
        if (block_free(block)) {
            count_iter++;
            if (!in_list(block)) {
                if (verbose)
                    printf("This free block is in heap but not in list, size = %d\n",
                           block_size(block));
            }



            if (block_free(block_prev(block)) || block_free(block_next(block))) {
                if (verbose)
                    printf("There should be no consecutive free blocks\n");
                return -1;
            }
        }
    }

    if (block_free(block)) {
        if (verbose)
            printf("Epi block should not be free\n");
        return -1;
    }

    for (int i = 0; i < SEG_LIST_SIZE; ++i) {        
        if (seg_list[i] == NULL)
            continue;

        for (block = seg_list[i]; block != NULL; block = block_succ(block)) {
            count_list++;
            
            /*All next/previous pointers are consistent 
             * (if A’s next pointer points to B, B’s previous pointer
             * should point to A). */
            uint32_t *pred = block_pred(block);
            uint32_t *succ = block_succ(block);
            if (pred != NULL) {
                if (block != block_succ(pred)) {
                    if (verbose)
                        printf("List pointer is not consistent\n");
                    return -1;
                }
            }

            if (succ != NULL) {
                if (block != block_pred(succ)) {
                    if (verbose)
                        printf("List pointer is not consistent\n");
                    return -1;
                }
            }

            //All free list pointers points between mem heap lo() and hi()
            if (!in_heap(block)) {
                if (verbose)
                    printf("Block isn't in heap\n");
                return -1;
            }

            //All blocks in each list bucket fall within bucket size range
            if (find_index(block_size(block)) != i) {
                if (verbose)
                    printf("Blocks size should fall within bucket size range\n");
                return -1;                    
            }            
        }
    }

    /* Count free blocks by iterating through every block and 
     * traversing free list by pointers and see if they match. */
    //dbg_printf("Number of free blocks should be the same, "
                   //"iter = %d, list = %d;\n", count_iter, count_list);
    if (count_list != count_iter) {
    //if (1) { 
        if (verbose)
            printf("Number of free blocks should be the same, "
                   "iter = %d, list = %d;\n", count_iter, count_list);
        return -1;                    
    }

    return 0;
}
Beispiel #6
0
// Return the pointer to the last block in the heap.
static inline uint32_t * last_block() {
    return block_prev((uint32_t *)((char *)mem_heap_hi() - 3));
}