/* * Requires: * "bp" is the address of a free block that is at least "asize" bytes. * * Effects: * Place a block of "asize" bytes at the start of the free block "bp" and * split that block if the remainder would be at least the minimum block * size. */ static void place(void *bp, size_t asize) { size_t csize = GET_SIZE(HDRP(bp)); if ((csize - asize) >= (2 * WSIZE)) { bool prev_alloc = GET_PREV_ALLOC(HDRP(bp)); if(!prev_alloc) { PUT(HDRP(bp), PACK(asize, 1)); } else { PUT(HDRP(bp), PACK(asize, 3)); } bp = NEXT_BLKP(bp); PUT(HDRP(bp), PACK(csize - asize, 2)); PUT(FTRP(bp), PACK(csize - asize, 2)); } else { bool prev_alloc = GET_PREV_ALLOC(HDRP(bp)); if(!prev_alloc) { PUT(HDRP(bp), PACK(csize, 1)); } else { PUT(HDRP(bp), PACK(csize, 3)); } int *next = NEXT_BLKP(bp); size_t size_next = GET_SIZE(HDRP(next)); bool next_alloc = GET_ALLOC(HDRP(next)); if(!next_alloc) { PUT(HDRP(next),PACK(size_next,2)); PUT(FTRP(next),PACK(size_next,2)); } else { PUT(HDRP(next),PACK(size_next,3)); } } }
/* * free */ void free(void *ptr) { dbg_printf("=== FREE : 0x%lx\n",(size_t)ptr); #if DEBUG if (NEXT_BLKP(ptr)) { if (!GET_PREV_ALLOC(GET_HEADER(NEXT_BLKP(ptr)))) { dbg_printf("0x%lx Fail to inform next block when malloc, or next block fail to update\n", (size_t)ptr); exit(3); } } #endif if(!ptr) return; /* Debug */ if(!in_heap(ptr)) { dbg_printf("ptr is not in heap!\n"); mm_checkheap(63); exit(1); } if (!aligned(ptr)) { dbg_printf("ptr is not aligned!\n"); mm_checkheap(63); exit(1); } size_t bsize = GET_SIZE(GET_HEADER(ptr)); size_t flag = GET_PREV_ALLOC(GET_HEADER(ptr)) ? 0x2 : 0x0; PUT(GET_HEADER(ptr), PACK(bsize, flag)); PUT(GET_FOOTER(ptr), PACK(bsize, flag)); /* Inform the next block that this block is freed */ char *nextbp = NEXT_BLKP(ptr); if (nextbp) { flag = GET(GET_HEADER(nextbp)); flag &= ~0x2; PUT(GET_HEADER(nextbp), flag); /* Only put footer when next block is free */ if (!GET_ALLOC(GET_HEADER(nextbp))) { PUT(GET_FOOTER(nextbp), flag); } } coalesce(ptr); mm_checkheap(CHECK_HEAP); }
inline static void* extend_heap(size_t words) { #else static void* extend_heap(size_t words) { #endif char *bp; size_t size; size_t prev_alloc; dbg1("[IN ] : extend_heap()\n"); /* Allocate an even number of words to maintain alignment */ size = (words % 2) ? (words+1) * WSIZE : words * WSIZE; if ((long)(bp = mem_sbrk(size)) < 0) return NULL; /* remember if previous block is allocated */ prev_alloc = GET_PREV_ALLOC(HDRP(bp)); /* Initialize free block header/footer and the epliogue header */ PUT(HDRP(bp), PACK(size, prev_alloc)); /* free block header */ PUT(FTRP(bp), PACK(size, prev_alloc)); /* free block footer */ PUT(HDRP(NEXT_BLKP(bp)), PACK(0, 1)); /* new epilogue header */ epilogue = (unsigned *)HDRP(NEXT_BLKP(bp)); dbg1("[OUT] : extend_heap()\n"); /* Coalesce if the previous block was free */ return coalesce(bp); }
/* * Requires: * "bp" is either the address of an allocated block or NULL. * * Effects: * Free a block. */ void mm_free(void *bp) { size_t size; /* Ignore spurious requests. */ if (bp == NULL) return; /* Free and coalesce the block. */ size = GET_SIZE(HDRP(bp)); bool prev_alloc = GET_PREV_ALLOC(HDRP(bp)); if(!prev_alloc) { PUT(HDRP(bp), PACK(size, 0)); PUT(FTRP(bp), PACK(size, 0)); } else { PUT(HDRP(bp), PACK(size, 2)); PUT(FTRP(bp), PACK(size, 2)); } int *next = NEXT_BLKP(bp); size_t size_next = GET_SIZE(HDRP(next)); bool next_alloc = GET_ALLOC(HDRP(next)); if(!next_alloc) { PUT(HDRP(next), PACK(size_next, 0)); PUT(FTRP(next), PACK(size_next, 0)); } else { PUT(HDRP(next), PACK(size_next, 1)); } coalesce(bp); }
/* * free - Frees the block and coalesces * (implementation issue: coalescing) * */ void free(void *bp) { size_t size; size_t prev_alloc; size_t temp_value; dbg1("[IN ] : free()\n"); if (!bp) { dbg1("[OUT] : free() - NULL pointer\n"); return; } if (!mm_initialized) mm_init(); size = GET_SIZE(HDRP(bp)); prev_alloc = GET_PREV_ALLOC(HDRP(bp)); /* update header and footer pointers of this block */ PUT(HDRP(bp), PACK(size, prev_alloc)); PUT(FTRP(bp), PACK(size, prev_alloc)); /* tell next block that this block is now free */ temp_value = GET(HDRP(NEXT_BLKP(bp))) & ~0x2; PUT(HDRP(NEXT_BLKP(bp)), temp_value); coalesce(bp); dbg1("[OUT] : free()\n"); }
/** * place - Place block of asize bytes at start of free block bp * and split if remainder would be at least minimum block size * @param bp Block where new block is to be put * @param asize aligned size of new block */ static inline void place(void *bp, size_t asize) { size_t csize = GET_SIZE(HDRP(bp)); int prev_alloc=0,next_alloc=0; delete_free_list(bp); prev_alloc = GET_PREV_ALLOC(PREV_BLKP(bp)); next_alloc = GET_NEXT_ALLOC(NEXT_BLKP(bp)); if ((csize - asize) >= MIN_BLOCK_SIZE) { /* Splice the etc free space */ /* Minimum size to be left for free list is 3*DSIZE=24 */ /* Put allocation in header, for next, previous, current * Bit wise or of the values, is put */ PUT(HDRP(bp), PACK(asize, (next_alloc| prev_alloc| 1))); PUT(FTRP(bp), PACK(asize, (next_alloc| prev_alloc| 1))); /* Splice the Next Block */ bp = NEXT_BLKP(bp); PUT(HDRP(bp), PACK(csize-asize, 0)); PUT(FTRP(bp), PACK(csize-asize, 0)); /*Add the newly spliced block to free list*/ bp = add_free_list_lifo(bp); } else { /* Do the allocation directly */ PUT(HDRP(bp), PACK(csize, (next_alloc| prev_alloc| 1))); PUT(FTRP(bp), PACK(csize, (next_alloc| prev_alloc| 1))); } }
/* * Requires: * "bp" is the address of a newly freed block. * * Effects: * Perform boundary tag coalescing. Returns the address of the coalesced * block. */ static void *coalesce(void *bp) { bool prev_alloc = GET_PREV_ALLOC(HDRP(bp)); bool next_alloc = GET_ALLOC(HDRP(NEXT_BLKP(bp))); size_t size = GET_SIZE(HDRP(bp)); if (prev_alloc && next_alloc) { /* Case 1 */ return (bp); } else if (prev_alloc && !next_alloc) { /* Case 2 */ size += GET_SIZE(HDRP(NEXT_BLKP(bp))); PUT(HDRP(bp), PACK(size, 2)); PUT(FTRP(bp), PACK(size, 2)); } else if (!prev_alloc && next_alloc) { /* Case 3 */ size += GET_SIZE(HDRP(PREV_BLKP(bp))); PUT(FTRP(bp), PACK(size, 2)); PUT(HDRP(PREV_BLKP(bp)), PACK(size, 2)); bp = PREV_BLKP(bp); } else { /* Case 4 */ size += GET_SIZE(HDRP(PREV_BLKP(bp))) + GET_SIZE(FTRP(NEXT_BLKP(bp))); PUT(HDRP(PREV_BLKP(bp)), PACK(size, 2)); PUT(FTRP(NEXT_BLKP(bp)), PACK(size, 2)); bp = PREV_BLKP(bp); } return (bp); }
/* * place - Place block of asize bytes at start of free block bp * and split if remainder would be at least minimum block size * * given a free block, removes free block from list and updates all relevant pointers * */ static void place(void* bp, size_t asize) { size_t old_size = GET_SIZE(HDRP(bp)); size_t prev_alloc = GET_PREV_ALLOC(HDRP(bp)); size_t temp_value; dbg1("[IN ] : place()\n"); /* remove free block from free list */ remove_free_block(bp); /* check to see if block can be split up */ dbg1("old_size=%ld, asize=%ld, compare=%d\n", old_size, asize, (int) OVERHEAD+2*DSIZE); if (old_size - asize >= OVERHEAD + 2*DSIZE) { /* block can be split up */ PUT(HDRP(bp), PACK(asize, prev_alloc | 0x1)); PUT(HDRP(NEXT_BLKP(bp)), PACK( old_size - asize, 0x2 )); PUT(FTRP(NEXT_BLKP(bp)), PACK( old_size - asize, 0x2 )); insert_free_block(NEXT_BLKP(bp)); } else { /* just use entire block */ PUT(HDRP(bp), PACK(old_size, prev_alloc | 0x1)); temp_value = GET(HDRP(NEXT_BLKP(bp))) | 0x2; PUT(HDRP(NEXT_BLKP(bp)), temp_value); } dbg1("[OUT] : place()\n"); }
/* * prev_block - return previous block only when it's a free block */ static inline void *prev_block(void *bp) { /* previous block is allocated */ if (GET_PREV_ALLOC(HEAD(bp))) { return NULL; } /* previous block is free */ return bp - GET_SIZE(bp - DSIZE); }
/* * checkheap - Check the heap for consistency * (iterates all the blocks starting from prologue to epilogue) * */ void _checkheap(void) { char *bp = heap_listp; size_t prev_alloc, curr_alloc; dbg1("\n[CHECK HEAP]\n"); dbg1("\n[verbose=%d]\n", verbose); if (verbose) { printf("Heap (starting address:%p):\n", heap_listp); printf("-prologue-"); printblock(bp); } /* checking prologue block (size, allocate bit) */ if ((GET_SIZE(HDRP(heap_listp)) != DSIZE) || !GET_ALLOC(HDRP(heap_listp))) { printf("Bad prologue header\n"); printf("-prologue-"); printblock(bp); } checkblock(heap_listp); /* alignment, header/footer */ prev_alloc = GET_ALLOC(HDRP(bp)); /* checking allocated/free blocks */ for (bp = NEXT_BLKP(heap_listp); GET_SIZE(HDRP(bp)) > 0; bp = NEXT_BLKP(bp)) { curr_alloc = GET_PREV_ALLOC(HDRP(bp)); if (verbose) printblock(bp); if (!prev_alloc != !curr_alloc) { /* previous block's allocate bit should match current block's prev allocate bit */ printf("prev allocate bit mismatch\n"); printblock(bp); exit(0); } prev_alloc = GET_ALLOC(HDRP(bp)); checkblock(bp); } printf("done\n"); /* checking epilouge block */ if ((GET_SIZE(HDRP(bp)) != 0) || !(GET_ALLOC(HDRP(bp)))){ printf("Bad epilogue header\n"); printf("-epilogue-"); printblock(bp); } checklist(); dbg1("[CHECK DONE]\n\n"); }
/* * coalesce - Boundary tag coalescing. Return ptr to coalesced block */ static block_ptr coalesce(block_ptr bp) { /* * TODO Here is the bug: Do update the bins while doing this. * Tried to fix. Not sure what will happen. */ block_ptr prev, next = NEXT_BLKP(bp); /* Use GET_PREV_ALLOC to judge if prev block is allocated */ size_t prev_alloc = GET_PREV_ALLOC(bp); size_t next_alloc = GET_ALLOC(HDRP(next)); size_t size = GET_SIZE(HDRP(bp)); if (prev_alloc && next_alloc) /* Case 1 */ { return bp; } else if (prev_alloc && !next_alloc) /* Case 2 */ { remove_freed_block(next); size += GET_SIZE(HDRP(next)); PUT(HDRP(bp), PACK(size, 0)); PUT(FTRP(bp), PACK(size, 0)); } else if (!prev_alloc && next_alloc) /* Case 3 */ { prev = PREV_BLKP(bp); remove_freed_block(prev); size += GET_SIZE(HDRP(prev)); PUT(FTRP(bp), PACK(size, 0)); PUT(HDRP(prev), PACK(size, 0)); bp = prev; } else /* Case 4 */ { prev = PREV_BLKP(bp); remove_freed_block(next); remove_freed_block(prev); size += GET_SIZE(HDRP(prev)) + GET_SIZE(FTRP(next)); PUT(HDRP(prev), PACK(size, 0)); PUT(FTRP(next), PACK(size, 0)); bp = prev; } reset_block(bp); // insert_free_block(bp, size); return bp; }
/* * place */ static void place(void *bp, size_t asize) { size_t csize = GET_SIZE(HDRP(bp)); size_t list; size_t previous = GET_PREV_ALLOC(HDRP(bp)); /*splitting has to happen*/ if((csize - asize) >= 16) { /* Remove the current block from its free list */ PUT(CURRENT_PREV_POINTER(NEXT_FREE_BLKP(bp)), GET(CURRENT_PREV_POINTER(bp))); PUT(CURRENT_NEXT_POINTER(PREV_FREE_BLKP(bp)), GET(CURRENT_NEXT_POINTER(bp))); /*The allocated bit is set to 1*/ PUT(HDRP(bp), PACK(asize,previous, 1)); bp= NEXT_BLKP(bp); /* The remainder of the free block is made into a new free block */ PUT(HDRP(bp), PACK(csize-asize,2,0)); PUT(FTRP(bp), csize-asize); /* Call listno to find the list number in which this split block should * be put and insert it right after the root node of that list */ list = listno(csize - asize); if(list >=maxlist) list=maxlist; PUT(CURRENT_NEXT_POINTER(bp),GET(CURRENT_NEXT_POINTER(root + 8*list))); PUT(CURRENT_PREV_POINTER(bp), GET(CURRENT_PREV_POINTER(NEXT_FREE_BLKP(bp)))); PUT(CURRENT_NEXT_POINTER(root + 8*list),(long)bp-(long)heapstart); PUT(CURRENT_PREV_POINTER(NEXT_FREE_BLKP(bp)),(long)bp-(long)heapstart); } /* No splitting */ else { /* Remove the current block from its free list */ PUT(CURRENT_PREV_POINTER(NEXT_FREE_BLKP(bp)), GET(CURRENT_PREV_POINTER(bp))); PUT(CURRENT_NEXT_POINTER(PREV_FREE_BLKP(bp)), GET(CURRENT_NEXT_POINTER(bp))); /* Set the allocated bit of current block */ PUT(HDRP(bp), PACK(csize,previous,1)); /* Set the prev_alloc bit of next block */ SET_PREV_ALLOC(HDRP(NEXT_BLKP(bp))); } }
/* * free */ void free (void *bp) { /*Ignore spurious request*/ if(bp==0) return; size_t size = GET_SIZE(HDRP(bp)); size_t previous = GET_PREV_ALLOC(HDRP(bp)); /*Set the allocated bit to zero*/ PUT(HDRP(bp), PACK(size,previous,0)); PUT(FTRP(bp), size); coalesce(bp); }
/* * Extend_Heap */ static void *extend_heap(size_t words) { char *bp; size_t size; /* Allocate an even number of words to maintain alignement */ size = (words % 2) ? (words+1) * WSIZE : words * WSIZE; if ((long)(bp = mem_sbrk(size)) == -1) return NULL; size_t previous = GET_PREV_ALLOC(HDRP(bp)); /* Initialize free block header/footer and the epilogue header */ PUT(HDRP(bp), PACK(size,previous, 0)); PUT(FTRP(bp), size); epilogueaddr = HDRP(NEXT_BLKP(bp)); PUT(HDRP(NEXT_BLKP(bp)), PACK(0,2,1)); /* Coalesce if the previous block was free */ return coalesce(bp); }
/* * coalesce - Implements boundary-tag coalescing to merge the input block * with any adjacent free blocks in constant time. */ static void *coalesce(void *bp) { size_t prev_alloc = GET_PREV_ALLOC(HDRP(bp)); size_t next_alloc = GET_ALLOC(HDRP(NEXT_BLKP(bp))); size_t size = GET_SIZE(HDRP(bp)); if (prev_alloc && next_alloc) { /* Case 1 */ UNSET_TAG(HDRP(NEXT_BLKP(bp))); add_to_list(find_list(GET_SIZE(HDRP(bp))), bp); return bp; } else if (prev_alloc && !next_alloc) { /* Case 2 */ remove_from_list(find_list(GET_SIZE(HDRP(NEXT_BLKP(bp)))), NEXT_BLKP(bp)); size += GET_SIZE(HDRP(NEXT_BLKP(bp))); PUT(HDRP(bp), PACK(size, 0)); PUT(FTRP(bp), PACK(size,0)); SET_TAG(HDRP(bp)); SET_TAG(FTRP(bp)); } else if (!prev_alloc && next_alloc) { /* Case 3 */ remove_from_list(find_list(GET_SIZE(HDRP(PREV_BLKP(bp)))), PREV_BLKP(bp)); size += GET_SIZE(HDRP(PREV_BLKP(bp))); SET_SIZE(FTRP(bp), size); SET_SIZE(HDRP(PREV_BLKP(bp)), size); bp = PREV_BLKP(bp); } else { /* Case 4 */ remove_from_list(find_list(GET_SIZE(HDRP(PREV_BLKP(bp)))), PREV_BLKP(bp)); remove_from_list(find_list(GET_SIZE(HDRP(NEXT_BLKP(bp)))), NEXT_BLKP(bp)); size += GET_SIZE(HDRP(PREV_BLKP(bp))) + GET_SIZE(FTRP(NEXT_BLKP(bp))); SET_SIZE(HDRP(PREV_BLKP(bp)), size); SET_SIZE(FTRP(NEXT_BLKP(bp)), size); bp = PREV_BLKP(bp); } UNSET_TAG(HDRP(NEXT_BLKP(bp))); add_to_list(find_list(GET_SIZE(HDRP(bp))), bp); return bp; }
static void *extend_heap(int words) { /* last block of heap, size = 0, alloc = 1 */ char *epilogue = (mem_heap_hi() + 1); char *bp; /* block pointer */ int bsize; /* block size to extend */ size_t flag = 0; /* Allocate even number of words to maintain alignment */ bsize = (words % 2) ? ((words + 1) * WSIZE) : (words * WSIZE); dbg_printf("EXTEND_HEAD: words = %d bszie = %d\n", words, bsize); dbg_printf("!!!!!!!!!!!!!!!!!!!!!!!!Before Extend!!!!\n"); mm_checkheap(CHECK_HEAP); /* Record if last block is allocated or not */ flag = GET_PREV_ALLOC(GET_HEADER(epilogue)) ? 0x2 : 0x0; if ((long)(bp = mem_sbrk(bsize)) == -1) return NULL; /* Init free block header/footer and the epilogue header */ PUT(GET_HEADER(bp), PACK(bsize, flag)); PUT(GET_FOOTER(bp), PACK(bsize, flag)); /* Set epilogue to be size = 0, alloc = 1 */ PUT(GET_HEADER(NEXT_BLKP(bp)), PACK(0, 1)); SET_PRED(bp, NULL); SET_SUCC(bp, NULL); mm_checkheap(CHECK_HEAP); return coalesce(bp); }
/* Extends the heap with a new free block. */ static void *extend_heap(size_t words) { char *bp; size_t size; /* single-word alignment */ size = (words + 1) * WSIZE; if ((long)(bp = mem_sbrk(size)) == -1) return NULL; int prev_alloc = GET_PREV_ALLOC(HDRP(bp)); /* Initialize free block header/footer and the epilogue header */ PUT(HDRP(bp), PACK(size, 0)); /* Free block header */ PUT(FTRP(bp), PACK(size, 0)); /* Free block footer */ PUT(HDRP(NEXT_BLKP(bp)), PACK(0, 1)); /* New epilogue header */ if (prev_alloc) { /* Set the tag as the previous block was allocated */ SET_TAG(HDRP(bp)); } /* Coalesce if the previous block was free */ return coalesce(bp); }
/* * Requires: * None. * * Effects: * Extend the heap with a free block and return that block's address. */ static void *extend_heap(size_t words) { void *bp; size_t size; /* Allocate an even number of words to maintain alignment. */ size = (words % 2) ? (words + 1) * WSIZE : words * WSIZE; if ((bp = mem_sbrk(size)) == (void *)-1) return (NULL); bool prev_alloc = GET_PREV_ALLOC(HDRP(bp)); /* Initialize free block header/footer and the epilogue header. */ if(!prev_alloc) { PUT(HDRP(bp), PACK(size, 0)); /* Free block header */ PUT(FTRP(bp), PACK(size, 0)); /* Free block footer */ } else { PUT(HDRP(bp),PACK(size,2)); PUT(FTRP(bp),PACK(size,2)); } PUT(HDRP(NEXT_BLKP(bp)), PACK(0, 1)); /* New epilogue header */ /* Coalesce if the previous block was free. */ return (coalesce(bp)); }
/* * block_prev_alloc - return whether the previous block is allocated */ static inline size_t block_prev_alloc(void *bp) { return GET_PREV_ALLOC(HEAD(bp)); }
/* * Requires: * "ptr" is either the address of an allocated block or NULL. * * Effects: * Reallocates the block "ptr" to a block with at least "size" bytes of * payload, unless "size" is zero. If "size" is zero, frees the block * "ptr" and returns NULL. If the block "ptr" is already a block with at * least "size" bytes of payload, then "ptr" may optionally be returned. * Otherwise, a new block is allocated and the contents of the old block * "ptr" are copied to that new block. Returns the address of this new * block if the allocation was successful and NULL otherwise. */ void *mm_realloc(void *ptr, size_t size) { size_t oldsize; void *newptr; /* If size == 0 then this is just free, and we return NULL. */ if (size == 0) { mm_free(ptr); return (NULL); } /* If oldptr is NULL, then this is just malloc. */ if (ptr == NULL) return (mm_malloc(size)); oldsize = GET_SIZE(HDRP(ptr)); size_t asize; if((size+WSIZE)%DSIZE==0) asize = size+WSIZE; else asize = (((size+WSIZE)/DSIZE+1)*DSIZE); if(oldsize == asize) return ptr; if(oldsize > asize) { if(oldsize-asize<=MINIMUM) return ptr; bool prev_alloc = GET_PREV_ALLOC(HDRP(ptr)); if(!prev_alloc) { PUT(HDRP(ptr),PACK(asize,1)); } else { PUT(HDRP(ptr),PACK(asize,3)); } PUT(HDRP(ptr),PACK(oldsize-asize,2)); PUT(FTRP(ptr),PACK(oldsize-asize,2)); int *next = NEXT_BLKP(ptr); bool next_alloc = GET_ALLOC(HDRP(next)); size_t size_next = GET_SIZE(HDRP(next)); if(!next_alloc) { PUT(HDRP(ptr),PACK(size_next,0)); PUT(FTRP(ptr),PACK(size_next,0)); } else { PUT(HDRP(ptr),PACK(size_next,1)); } } int *next = NEXT_BLKP(ptr); bool next_alloc = GET_ALLOC(HDRP(next)); if(!next_alloc) { size_t size_next = GET_SIZE(HDRP(next)); if((size_next+oldsize)>=asize) { oldsize += size_next; if((oldsize-asize)>=(2*WSIZE)){ bool prev_alloc = GET_PREV_ALLOC(HDRP(ptr)); if(!prev_alloc) { PUT(HDRP(ptr),PACK(asize,1)); } else { PUT(HDRP(ptr),PACK(asize,3)); } int *next = NEXT_BLKP(ptr); PUT(HDRP(next),PACK(oldsize-asize,2)); PUT(FTRP(next),PACK(oldsize-asize,2)); } else { bool prev_alloc = GET_PREV_ALLOC(HDRP(ptr)); if(!prev_alloc) { PUT(HDRP(ptr),PACK(oldsize,1)); } else { PUT(HDRP(ptr),PACK(oldsize,3)); } int *next = NEXT_BLKP(ptr); size_t size_next = GET_SIZE(HDRP(next)); bool next_alloc = GET_ALLOC(HDRP(next)); if(!next_alloc) { PUT(HDRP(next),PACK(size_next,2)); PUT(FTRP(next),PACK(size_next,2)); } else { PUT(HDRP(next),PACK(size_next,3)); } } return ptr; } } newptr = mm_malloc(size); /* If realloc() fails the original block is left untouched */ if (newptr == NULL) return (NULL); /* Copy the old data. */ if (size < oldsize) oldsize = size; memcpy(newptr, ptr, oldsize); /* Free the old block. */ mm_free(ptr); return (newptr); }
static void *coalesce(void *bp) { dbg_printf("=== Coalesce bp = 0x%lx\n", (size_t)bp); void *prevbp = PREV_BLKP(bp); void *nextbp = NEXT_BLKP(bp); /*ONLY use the former alloc flag */ size_t prev_alloc = GET_PREV_ALLOC(GET_HEADER(bp)); /*GET_ALLOC(GET_FOOTER(prevbp));*/ size_t next_alloc = GET_ALLOC(GET_HEADER(nextbp)); size_t bsize = GET_SIZE(GET_HEADER(bp)); size_t flag = 0; int class_idx = 0; /* case 1: make newly freed block to be root */ if (prev_alloc && next_alloc) { dbg_printf("Coalesce Case 1\n"); insert_first(bp); return bp; } /* case 3: next block is free */ else if (prev_alloc && !next_alloc) { dbg_printf("Coalesce Case 3\n"); class_idx = get_class_idx_by_size(GET_SIZE(GET_HEADER(nextbp))); remove_free_block(nextbp, class_idx); /* Telling coalesced free block about if bp's previous allocated */ flag = GET_PREV_ALLOC(GET_HEADER(bp)) ? 0x2 : 0x0; bsize += GET_SIZE(GET_HEADER(nextbp)); PUT(GET_HEADER(bp), PACK(bsize, flag)); PUT(GET_FOOTER(bp), PACK(bsize, flag)); insert_first(bp); return bp; } /* case 2: prev block is free */ else if (!prev_alloc && next_alloc) { dbg_printf("Coalesce Case 2\n"); class_idx = get_class_idx_by_size(GET_SIZE(GET_HEADER(prevbp))); dbg_printf("class_idx = %d, class_address = 0x%lx\n", class_idx, (size_t)GET_CLASS(class_idx)); remove_free_block(prevbp, class_idx); /* Telling coalesced free block about if bp's previous's previous allocated */ flag = GET_PREV_ALLOC(GET_HEADER(prevbp)) ? 0x2 : 0x0; if (flag == 0) { printf("Implies fail coalese: 0x%lx with former\n", (size_t)prevbp); exit(2); } bsize += GET_SIZE(GET_HEADER(prevbp)); PUT(GET_HEADER(prevbp), PACK(bsize, flag)); PUT(GET_FOOTER(prevbp), PACK(bsize, flag)); insert_first(prevbp); return prevbp; } /* case 4: both blocks are free */ else { dbg_printf("Coalesce Case 4\n"); class_idx = get_class_idx_by_size(GET_SIZE(GET_HEADER(nextbp))); remove_free_block(nextbp, class_idx); class_idx = get_class_idx_by_size(GET_SIZE(GET_HEADER(prevbp))); remove_free_block(prevbp, class_idx); /* Telling coalesced free block about if bp's previous's previous allocated */ flag = GET_PREV_ALLOC(GET_HEADER(prevbp)) ? 0x2 : 0x0; if (flag == 0) { printf("Implies fail coalese: 0x%lx with former\n", (size_t)prevbp); exit(2); } bsize += GET_SIZE(GET_HEADER(nextbp)); bsize += GET_SIZE(GET_FOOTER(prevbp)); PUT(GET_HEADER(prevbp), PACK(bsize, flag)); PUT(GET_FOOTER(nextbp), PACK(bsize, flag)); insert_first(prevbp); return prevbp; } dbg_printf("Unable to coalesce!\n"); return NULL; }
/* Place an ADJUSTED sized block in heap */ static void place(void *bp, size_t asize) { #if DEBUG if (NEXT_BLKP(bp)) { if (GET_PREV_ALLOC(GET_HEADER(NEXT_BLKP(bp)))) { dbg_printf("0x%lx: Fail to inform next block when free\n", (size_t)bp); exit(2); } } #endif dbg_printf("=== Place, bp = 0x%lx, adjusted size = %ld \n", (size_t)bp, asize); /* block free size */ size_t csize = GET_SIZE(GET_HEADER(bp)); char *nextbp = NULL; int class_idx = 0; size_t flag = 0; /* Split, say, minimum block size set to 1 WSIZE = 8 byte */ if ((csize - asize) >= (4 * WSIZE)) { class_idx = get_class_idx_by_size(GET_SIZE(GET_HEADER(bp))); /* Include previous block's information */ flag = GET_PREV_ALLOC(GET_HEADER(bp)) ? 0x3 : 0x1; PUT(GET_HEADER(bp), PACK(asize, flag)); PUT(GET_FOOTER(bp), PACK(asize, flag)); nextbp = NEXT_BLKP(bp); PUT(GET_HEADER(nextbp), PACK((csize - asize), 0)); PUT(GET_FOOTER(nextbp), PACK((csize - asize), 0)); /* Inform the next block that this block is allocated */ flag = GET(GET_HEADER(nextbp)); flag |= 0x2; PUT(GET_HEADER(nextbp), flag); PUT(GET_FOOTER(nextbp), flag); split_free_block(bp, nextbp); remove_free_block(bp, class_idx); remove_free_block(nextbp, class_idx); insert_first(nextbp); mm_checkheap(CHECK_HEAP); } else { /* Include previous block's information */ flag = GET_PREV_ALLOC(GET_HEADER(bp)) ? 0x3 : 0x1; PUT(GET_HEADER(bp), PACK(csize, flag)); PUT(GET_FOOTER(bp), PACK(csize, flag)); /* Inform the next block that this block is allocated */ if ((size_t)bp == 0x800004980) { dbg_printf("bp size = %ld\n",GET_SIZE(GET_HEADER(bp))); dbg_printf("NEXT_BLKP(bp); 0x%lx\n",(size_t)NEXT_BLKP(bp)); } nextbp = NEXT_BLKP(bp); if (nextbp) { flag = GET(GET_HEADER(nextbp)); flag |= 0x2; PUT(GET_HEADER(nextbp), flag); /* Only put footer when next block is free */ if (!GET_ALLOC(GET_HEADER(nextbp))) { PUT(GET_FOOTER(nextbp), flag); } } remove_free_block(bp, get_class_idx_by_size(csize)); } }
/* * Coalesce */ static void* coalesce(void *bp) { size_t prev_alloc = GET_PREV_ALLOC(HDRP(bp)); size_t next_alloc = GET_ALLOC(HDRP(NEXT_BLKP(bp))); size_t size = GET_SIZE(HDRP(bp)); size_t list; /* If previous and next blocks are both allocated */ if(prev_alloc && next_alloc) { /* Find the list number in which the block belongs and put it right * after the root node for that list */ list = listno(size); if(list >=maxlist) list=maxlist; PUT(CURRENT_NEXT_POINTER(bp),GET(CURRENT_NEXT_POINTER(root+ 8*list))); PUT(CURRENT_PREV_POINTER(bp), GET(CURRENT_PREV_POINTER(NEXT_FREE_BLKP(bp)))); PUT(CURRENT_NEXT_POINTER(root + 8*list),(long)bp-(long)heapstart); PUT(CURRENT_PREV_POINTER(NEXT_FREE_BLKP(bp)),(long)bp-(long)heapstart); RESET_PREV_ALLOC(HDRP(NEXT_BLKP(bp))); return bp; } /* If only previous block is allocated */ else if(prev_alloc && !next_alloc) { size += GET_SIZE(HDRP(NEXT_BLKP(bp))); list = listno(size); if(list >=maxlist) list=maxlist; /* Remove the next block from its free list */ PUT(CURRENT_PREV_POINTER(NEXT_FREE_BLKP(NEXT_BLKP(bp))), GET(CURRENT_PREV_POINTER(NEXT_BLKP(bp)))); PUT(CURRENT_NEXT_POINTER(PREV_FREE_BLKP(NEXT_BLKP(bp))), GET(CURRENT_NEXT_POINTER(NEXT_BLKP(bp)))); /* Coalesce the current and next block*/ PUT(HDRP(bp), PACK(size,prev_alloc,0)); PUT(FTRP(bp), size); /* Put the newly coalesced block in front of the appropriate root node * depending on its size */ PUT(CURRENT_NEXT_POINTER(bp),GET(CURRENT_NEXT_POINTER(root+ 8*list))); PUT(CURRENT_PREV_POINTER(bp), GET(CURRENT_PREV_POINTER(NEXT_FREE_BLKP(bp)))); PUT(CURRENT_NEXT_POINTER(root+ 8*list),(long)bp-(long)heapstart); PUT(CURRENT_PREV_POINTER(NEXT_FREE_BLKP(bp)),(long)bp-(long)heapstart); return(bp); } /* If only next block is allocated */ else if(!prev_alloc && next_alloc) { size+= GET_SIZE(HDRP(PREV_BLKP(bp))); size_t previous = GET_PREV_ALLOC(HDRP(PREV_BLKP(bp))); list = listno(size); if(list >=maxlist) list=maxlist; /* Remove the prev block from its free list */ PUT(CURRENT_PREV_POINTER(NEXT_FREE_BLKP(PREV_BLKP(bp))), GET(CURRENT_PREV_POINTER(PREV_BLKP(bp)))); PUT(CURRENT_NEXT_POINTER(PREV_FREE_BLKP(PREV_BLKP(bp))), GET(CURRENT_NEXT_POINTER(PREV_BLKP(bp)))); /* Coalesce the current and prev block */ PUT(FTRP(bp), size); PUT(HDRP(PREV_BLKP(bp)),PACK(size,previous,0)); RESET_PREV_ALLOC(HDRP(NEXT_BLKP(PREV_BLKP(bp)))); /* Put the newly coalesced block in front of the appropriate root node * depending on its size */ PUT(CURRENT_NEXT_POINTER(PREV_BLKP(bp)), GET(CURRENT_NEXT_POINTER(root+ 8*list))); PUT(CURRENT_PREV_POINTER(PREV_BLKP(bp)), GET(CURRENT_PREV_POINTER(NEXT_FREE_BLKP(PREV_BLKP(bp))))); PUT(CURRENT_NEXT_POINTER(root+ 8*list), (long)(PREV_BLKP(bp))-(long)heapstart); PUT(CURRENT_PREV_POINTER(NEXT_FREE_BLKP(PREV_BLKP(bp))), (long)(PREV_BLKP(bp))-(long)heapstart); return(PREV_BLKP(bp)); } /* If prev and next blocks both are free */ else { size+= GET_SIZE(HDRP(PREV_BLKP(bp)))+GET_SIZE(FTRP(NEXT_BLKP(bp))); size_t previous = GET_PREV_ALLOC(HDRP(PREV_BLKP(bp))); list = listno(size); if(list >=maxlist) list=maxlist; /* Remove the next block from its free list */ PUT(CURRENT_PREV_POINTER(NEXT_FREE_BLKP(NEXT_BLKP(bp))), GET(CURRENT_PREV_POINTER(NEXT_BLKP(bp)))); PUT(CURRENT_NEXT_POINTER(PREV_FREE_BLKP(NEXT_BLKP(bp))), GET(CURRENT_NEXT_POINTER(NEXT_BLKP(bp)))); /* Remove the previous block from its free list */ PUT(CURRENT_PREV_POINTER(NEXT_FREE_BLKP(PREV_BLKP(bp))), GET(CURRENT_PREV_POINTER(PREV_BLKP(bp)))); PUT(CURRENT_NEXT_POINTER(PREV_FREE_BLKP(PREV_BLKP(bp))), GET(CURRENT_NEXT_POINTER(PREV_BLKP(bp)))); /* Coalesce the current, prev and next block */ PUT(HDRP(PREV_BLKP(bp)),PACK(size,previous,0)); PUT(FTRP(NEXT_BLKP(bp)),size); /* Put the newly coalesced block in front of the appropriate root node * depending on its size */ PUT(CURRENT_NEXT_POINTER(PREV_BLKP(bp)), GET(CURRENT_NEXT_POINTER(root+ 8*list))); PUT(CURRENT_PREV_POINTER(PREV_BLKP(bp)), GET(CURRENT_PREV_POINTER(NEXT_FREE_BLKP(PREV_BLKP(bp))))); PUT(CURRENT_NEXT_POINTER(root+ 8*list), (long)(PREV_BLKP(bp))-(long)heapstart); PUT(CURRENT_PREV_POINTER(NEXT_FREE_BLKP(PREV_BLKP(bp))), (long)(PREV_BLKP(bp))-(long)heapstart); return(PREV_BLKP(bp)); } }
/* * coalesce - boundary tag coalescing. return ptr to coalesced block * */ static void* coalesce(void* bp) { size_t prev_alloc = GET_PREV_ALLOC(HDRP(bp)); size_t next_alloc = GET_ALLOC(HDRP(NEXT_BLKP(bp))); size_t size = GET_SIZE(HDRP(bp)); dbg1("[IN ] : coalesce()\n"); switch (prev_alloc | next_alloc) { case 3: /* neither of the adjacent blocks are free */ insert_free_block(bp); dbg1("[OUT] : coalesce() : neither of the adjacent blocks are free.\n"); return bp; case 2: /* next block is free */ size += GET_SIZE(HDRP(NEXT_BLKP(bp))); /* remove next block from free list */ remove_free_block(NEXT_BLKP(bp)); /* update header and footer pointers */ PUT(HDRP(bp), PACK(size, prev_alloc)); PUT(FTRP(bp), PACK(size, prev_alloc)); /* insert new merged block into free list */ insert_free_block(bp); dbg1("[OUT] : coalesce() : next block is free - merged \n"); return(bp); case 1: /* prev block is free */ size += GET_SIZE(HDRP(PREV_BLKP(bp))); /* remove this block from free list */ remove_free_block(PREV_BLKP(bp)); /* update header and footer pointers */ prev_alloc = GET_PREV_ALLOC(HDRP(PREV_BLKP(bp))); PUT(FTRP(bp), PACK(size, prev_alloc)); PUT(HDRP(PREV_BLKP(bp)), PACK(size, prev_alloc)); /* insert new merged block into free list */ insert_free_block(PREV_BLKP(bp)); dbg1("[OUT] : coalesce() : previous block is free - merged \n"); return(PREV_BLKP(bp)); default: /* both previous and next blocks are free */ size += GET_SIZE(HDRP(PREV_BLKP(bp))) + GET_SIZE(FTRP(NEXT_BLKP(bp))); /* remove next block from free list */ remove_free_block(NEXT_BLKP(bp)); /* remove this block from free list */ remove_free_block(PREV_BLKP(bp)); /* update header and footer pointers */ prev_alloc = GET_PREV_ALLOC(HDRP(PREV_BLKP(bp))); PUT(HDRP(PREV_BLKP(bp)), PACK(size, prev_alloc)); PUT(FTRP(NEXT_BLKP(bp)), PACK(size, prev_alloc)); /* insert new merged block into free list */ insert_free_block(PREV_BLKP(bp)); dbg1("[OUT] : coalesce() : both previous and next blocks are free - merged \n"); return(PREV_BLKP(bp)); } }
inline static size_t get_list_num(size_t size) { #else static size_t get_list_num(size_t size) { #endif if(size <= BLKSIZE) return 0; if(size <= (BLKSIZE << 1)) return 1; if(size <= (BLKSIZE << 2)) return 2; if(size <= (BLKSIZE << 3)) return 3; if(size <= (BLKSIZE << 4)) return 4; if(size <= (BLKSIZE << 5)) return 5; if(size <= (BLKSIZE << 6)) return 6; if(size <= (BLKSIZE << 7)) return 7; return 8; } #endif #ifdef CLASS1 #ifdef INLINE inline static size_t get_nonempty_list_num(size_t size) { #else static size_t get_nonempty_list_num(size_t size) { #endif dbg1("[IN ] : get_nonempty_list_num():request[%ld] - class1\n", size); if(size <= BLKSIZE && GET_FREE_LISTP(0) != NULL) return 0; if((size <= 40) && GET_FREE_LISTP(1) != NULL) return 1; if((size <= 48) && GET_FREE_LISTP(2) != NULL) return 2; if((size <= 56) && GET_FREE_LISTP(3) != NULL) return 3; if(size <= (BLKSIZE << 1) && GET_FREE_LISTP(4) != NULL) return 4; if(size <= (BLKSIZE << 2) && GET_FREE_LISTP(5) != NULL) return 5; if(size <= (BLKSIZE << 3) && GET_FREE_LISTP(6) != NULL) return 6; if(size <= (BLKSIZE << 4) && GET_FREE_LISTP(7) != NULL) return 7; if(size <= (BLKSIZE << 5) && GET_FREE_LISTP(8) != NULL) return 8; if(size <= (BLKSIZE << 6) && GET_FREE_LISTP(9) != NULL) return 9; if(size <= (BLKSIZE << 7) && GET_FREE_LISTP(10) != NULL) return 10; return 11; } #ifdef INLINE inline static size_t get_list_num(size_t size) { #else static size_t get_list_num(size_t size) { #endif if(size <= BLKSIZE) return 0; if(size <= 40) return 1; if(size <= 48) return 2; if(size <= 56) return 3; if(size <= (BLKSIZE << 1)) return 4; if(size <= (BLKSIZE << 2)) return 5; if(size <= (BLKSIZE << 3)) return 6; if(size <= (BLKSIZE << 4)) return 7; if(size <= (BLKSIZE << 5)) return 8; if(size <= (BLKSIZE << 6)) return 9; if(size <= (BLKSIZE << 7)) return 10; return 11; } #endif /* debugging routines */ /* * mm_checkheap - called by mdriver for each operation in the trace file * */ void mm_checkheap(int v) { verbose = v; checkheap(); } #ifdef CHECKHEAP static void printblock(void *bp) { size_t hsize, halloc, hpalloc, fsize, falloc, fpalloc; hsize = GET_SIZE(HDRP(bp)); halloc = GET_ALLOC(HDRP(bp)); hpalloc = GET_PREV_ALLOC(HDRP(bp)); fsize = GET_SIZE(FTRP(bp)); falloc = GET_ALLOC(FTRP(bp)); fpalloc = GET_PREV_ALLOC(HDRP(bp)); if (hsize == 0) { printf("%p: EOL (size=0): header: [%ld:%c:%c]\n", bp, hsize, (hpalloc ? 'a' : 'f'), (halloc ? 'a' : 'f')); return; } printf("%p: header: [%ld:%c:%c] footer: [%ld:%c:%c]\n", bp, hsize, (hpalloc ? 'a' : 'f'), (halloc ? 'a' : 'f'), fsize, (fpalloc ? 'a' : 'f'), (falloc ? 'a' : 'f')); }