/* * Place the block and potentially split the block * Return: Nothing */ static void place(void *block, unsigned int awords) { REQUIRES(awords >= 2 && awords % 2 == 0); REQUIRES(block != NULL); REQUIRES(in_heap(block)); REQUIRES(in_list(block)); unsigned int cwords = block_size(block); //the size of the given freeblock block_delete(block); // delete block from the seg list ENSURES(!in_list(block)); if ((cwords - awords) >= 4) { set_size(block, awords); block_mark(block, ALLOCATED); block = block_next(block); set_size(block, cwords - awords - 2); block_mark(block, FREE); block_insert(block); ENSURES(in_list(block)); } else { set_size(block, cwords); block_mark(block, ALLOCATED); } }
/* * 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; }
// Returns a pointer if block of sufficient size is available // will allocate a new block if none are free static void* find_free_block(int index, size_t size){ REQUIRES(0 <= index && index < NUM_FREE_LISTS); void* block; void* current; int new_index = index; while(new_index < NUM_FREE_LISTS){ current = free_lists[new_index]; while(current != NULL){ if(block_size(current) >= size){ // if(new_index > index){ // block = split_block(new_index); // block_mark(block, 0); // return block; // } block = current; block_mark(block, 0); remove_block_from_list(new_index, block); } current = block_next(current); } new_index++; } assert(aligned(block)); block = allocate_block(size); ENSURES(block != NULL); return block; }
/* * free */ void free (void *ptr) { if (ptr == NULL) { return; } block_mark(get_header(ptr), 0); coalesce(ptr); }
/* * Extends the heap with a new free block * Return: the pointer to the new free block * NULL on error. */ static void *extend_heap(unsigned int words) { REQUIRES(words > 4); uint32_t *block; uint32_t *next; /* Ask for 2 more words for header and footer */ words = (words % 2) ? (words + 1) : words; if (VERBOSE) printf("Extend Words = %d bytes\n", words * 4); if ((long)(block = mem_sbrk(words * WSIZE)) == -1) return NULL; block--; // back step 1 since the last one is the epi block set_size(block, words - 2); block_mark(block, FREE); ENSURES(block != NULL); // New eqilogue block next = block_next(block); set_size(next, 0); *next |= 0x40000000; //block_mark(block_next(block), ALLOCATED); ENSURES(!block_free(next)); ENSURES(block_size(next) == 0); block = coalesce(block); // Coalesce if necessary ENSURES(in_list(block)); return block; }
/* * free */ void free (void *ptr) { /* If ptr is NULL, no operation is performed. */ if (ptr == NULL) return; uint32_t* block = block_block(ptr); block_mark(block, FREE); coalesce(block); }
static void* allocate_block(size_t size){ void* block; block = mem_sbrk(size); if(block == NULL) return NULL; set_size(block, size); set_prev_pointer(block, NULL); set_next_pointer(block, NULL); block_mark(block, 0); return block; }
/* * free */ void free (void *ptr) { size_t size; void* block; int index; checkheap(1); if (ptr == NULL) { return; } if(heap_start == 0) mm_init(); block = block_from_ptr(ptr); index = coalesce(block, &size); block_mark(block, 1); //set_prev_pointer(block, NULL); //set_next_pointer(block, NULL); add_block_to_list(index, block); checkheap(1); return; }
/* * Initialize: return -1 on error, 0 on success. */ int mm_init(void) { /* Initialize the seg_list with NULL */ seg_list = mem_sbrk(SEG_LIST_SIZE * sizeof(uint32_t *)); for (int i = 0; i < SEG_LIST_SIZE; ++i) { seg_list[i] = NULL; } if ((heap_listp = mem_sbrk(4 * WSIZE)) == (void *)-1) return -1; set_size(heap_listp, 0); // Allignment padding set_size(heap_listp + 1, 0); // Pro of 0 size set_size(heap_listp + 3, 0); // Epi of 0 size (heap_listp + 3)[0] |= 0x40000000; // Mark epi as allocated block_mark(heap_listp + 1, ALLOCATED); // Mark prologue as allocated heap_listp += 1; /* Extend the empty heap with a free block of CHUNKSIZE bytes * extend_heap would ask for 2 more words */ if (extend_heap(CHUNKSIZE + 2) == NULL) return -1; return 0; }
/* * realloc - you may want to look at mm-naive.c */ void *realloc(void *oldptr, size_t size) { if (oldptr == NULL) // if oldptr is NULL, this works as malloc(size) return malloc(size); if (size == 0) { // if size is 0, this works as free(oldptr) free(oldptr); return NULL; } uint32_t *block = block_block(oldptr); REQUIRES(in_heap(block)); REQUIRES(!block_free(block)); unsigned int words = block_size(block); // old size in words unsigned int nwords; // new size in words uint32_t * ptr; // temp ptr /* Adjust size to include alignment and convert to multipes of 4 bytes */ if (size <= DSIZE) nwords = 2; else nwords = (((size) + (DSIZE-1)) & ~0x7) / WSIZE; /* if new size is the same as old size or the old size is larger but no larger * than 4 words, return oldptr without spliting */ //printf("RE, words = %d, nwords = %d\n", words, nwords); if (nwords == words || (words > nwords && words - nwords < 4)) return oldptr; else if (nwords < words) { /* if old size is at least 4 words larger than new size * return oldptr with spliting */ set_size(block, nwords); block_mark(block, ALLOCATED); ptr = block_next(block); ENSURES(words - nwords - 2 < words); set_size(ptr, words - nwords - 2); block_mark(ptr, FREE); block_insert(ptr); return oldptr; } else { /* if old size is smaller than new size, look for more space */ ptr = block_next(block); if (block_free(ptr)) { ENSURES(in_list(ptr)); // if next block is free unsigned int owords = block_size(ptr); //size of next blockdd int remain = owords + 2 - (nwords - words); if (remain >= 4) { // the next free block is enough large to split block_delete(ptr); set_size(block, nwords); block_mark(block, ALLOCATED); ptr = block_next(block); set_size(ptr, owords - (nwords - words)); block_mark(ptr, FREE); block_insert(ptr); return oldptr; } else if (remain >= 0) { // the next free block can not split block_delete(ptr); set_size(block, words + owords + 2); block_mark(block, ALLOCATED); return oldptr; } } /* the next free block is too small, or * next block is not free, malloc whole new one. */ ptr = malloc(size); /* Copy the old data. */ memcpy(ptr, oldptr, block_size(block) * WSIZE); /* Free the old block. */ free(oldptr); return ptr; } }