//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; }
/* * 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; }
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); }
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; }
// 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; }
// 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)); }