/* * mm_check - check basic heap consistency. * * Check 1 : Is every block in the free list marked as free? * Check 2 : Are there any contiguous free blocks that somehow escaped coalescing? * Check 3 : Is every free block except 8byte actually in the free list? * */ int mm_check() { int flag = 0; //printf("Heap Consistency Checker : starts checking\n"); // Check 1 : Is every block in the free list marked as free? // 1-1 Checking for 16-list FREE prev = NULL; FREE iter = address_list; while(iter) { if(!checkMarkedAsFree(iter)) { printf("Heap Consistency Checker : %x is not marked as free though it's in free-list(16Byte)\n", (size_t)iter); int size = FSIZE(iter); printf("Heap Consistency Checker : Value of Header = %x, Value of Footer = %x\n", *(size_t*)iter, *(size_t*)((char *)iter+size-HEADER_SIZE)); flag=1; } iter=right(iter); } // 1-2 Checking for tree flag=flag|checkTreeMakredAsFree(address_tree); // Check 2 : Are there any contiguous free blocks that somehow escaped coalescing? iter=getLeftBlock((FREE)((char*)mem_heap_hi()+1)); while(iter) { if (prev&&checkMarkedAsFree(prev)&&checkMarkedAsFree(iter)) { printf("Heap Consistency Checker : %x and %x are contigous free block\n", (size_t)prev, (size_t)iter); flag=1; } prev=iter; iter=getLeftBlock(iter); } // Check 3 : Is every free block except 8byte actually in the free list? iter=getLeftBlock((FREE)((char*)mem_heap_hi()+1)); while(iter) { if (checkMarkedAsFree(iter) && FSIZE(iter) != 2 * HEADER_SIZE) { if (!checkContainedInList(iter)&&!checkContainedInTree(iter)) { printf("Heap Consistency Checker : %x : %08x is not contained in any list or tree\n", (size_t)iter, (size_t)FSIZE(iter)); flag = 1; } } iter=getLeftBlock(iter); } return flag; }
/* * mm_checkheap */ int mm_checkheap(int verbose) { char *bp = first_block; size_t* low = mem_heap_lo(); size_t* high = mem_heap_hi(); if (!GET_ALLOC(HDRP(first_block)) || (GET_SIZE(HDRP(first_block)) != WSIZE)) { if (verbose) printf("Error[%p]: Incorrect prologue header\n", bp); return -1; } if (GET_ALLOC(HDRP(bp)) && (GET_SIZE(HDRP(bp)) != GET_SIZE(FTRP(bp)))) { if (verbose) printf("Error[%p]: Header and footer does not match\n", bp); return -1; } assert(low == mem_heap_lo()); assert(high == mem_heap_hi()); for (bp = NEXT_BLKP(first_block); GET_SIZE(HDRP(bp)) > 0; bp = NEXT_BLKP(bp)) { if ((size_t)bp > (size_t)high || (size_t)bp < (size_t)low) { if (verbose) printf("Error[%p]: Out of heap boundaries\n", bp); return -1; } if ((size_t)bp % 8) { if (verbose) printf("Error[%p]: Not doubleword aligned\n", bp); return -1; } if (!GET_ALLOC(HDRP(bp)) && (GET_SIZE(HDRP(bp)) != GET_SIZE(FTRP(bp)))) { if (verbose) printf("Error[%p]: Header and footer does not match\n", bp); return -1; } if (GET_ALLOC(HDRP(bp)) == 0 && GET_ALLOC(HDRP(NEXT_BLKP(bp))) == 0) { if (verbose){ printf("Error: Free Blocks are not coalesced correctly [%p] and [%p] \n", bp, NEXT_BLKP(bp)); } return -1; } } if (!(GET_ALLOC(HDRP(bp))) || (GET_SIZE(HDRP(bp)) != 0)) { if (verbose) printf("Error[%p]: Incorrect epilogue header\n", bp); return -1; } return 0; }
/* * add_range - As directed by request opnum in trace tracenum, * we've just called the student's mm_malloc to allocate a block of * size bytes at addr lo. After checking the block for correctness, * we create a range struct for this block and add it to the range list. */ static int add_range(range_t **ranges, char *lo, int size, int tracenum, int opnum) { char *hi = lo + size - 1; range_t *p; char msg[MAXLINE]; assert(size > 0); /* Payload addresses must be ALIGNMENT-byte aligned */ if (!IS_ALIGNED(lo)) { sprintf(msg, "Payload address (%p) not aligned to %d bytes", lo, ALIGNMENT); malloc_error(tracenum, opnum, msg); return 0; } /* The payload must lie within the extent of the heap */ if ((lo < (char *)mem_heap_lo()) || (lo > (char *)mem_heap_hi()) || (hi < (char *)mem_heap_lo()) || (hi > (char *)mem_heap_hi())) { sprintf(msg, "Payload (%p:%p) lies outside heap (%p:%p)", lo, hi, mem_heap_lo(), mem_heap_hi()); malloc_error(tracenum, opnum, msg); return 0; } /* The payload must not overlap any other payloads */ for (p = *ranges; p != NULL; p = p->next) { if ((lo >= p->lo && lo <= p-> hi) || (hi >= p->lo && hi <= p->hi)) { sprintf(msg, "Payload (%p:%p) overlaps another payload (%p:%p)\n", lo, hi, p->lo, p->hi); malloc_error(tracenum, opnum, msg); return 0; } } /* * Everything looks OK, so remember the extent of this block * by creating a range struct and adding it the range list. */ if ((p = (range_t *)malloc(sizeof(range_t))) == NULL) unix_error("malloc error in add_range"); p->next = *ranges; p->lo = lo; p->hi = hi; *ranges = p; return 1; }
/* * create_space_at_endHeap - create new MALLOC chunk at end. * if last chunk is free, then delete that and use to malloc chunk. * */ void *create_space_at_endHeap(size_t size) { FREE last; int lastSize = *((size_t*)((char*)mem_heap_hi()+1-HEADER_SIZE)); if(lastSize&1) { last = (FREE)((char*)mem_heap_hi()+1-(lastSize&-2)); delete_free(last); mem_sbrk(size - FSIZE(last)); return last; } return mem_sbrk(size); }
/* * mm_check - Does not currently check anything */ static int mm_check(void) { int i; //Check free blocks. for (i = 0; i < NUM; i++) { int *bp = (int*) heap_st + i; while (1) { if (*bp == 0) break; //Check if the address pointed is valid. if ((int) (*bp) < (int) heap_st) { printf("The number 0x%x is not a valid heap address.\n", (int) *bp); return -1; } //Check 8 bytes alignment. if ((int) (*bp) % 8 != 0) { printf("The block 0x%x is not 8 bytes aligned.\n", (int) *bp); return -1; } bp = (int*) GET(HDRP(bp)); } } //Get the data content. int *bp = (int *) heap_st + NUM; while (1) { bp = (int*) bp + DSIZE; if (bp >= (int*) mem_heap_hi()) break; if (GET(HDRP(bp)) == 0) bp = (int*) bp + DSIZE; if (bp >= (int*) mem_heap_hi()) break; //Check 8 bytes alignment. if (((int) bp) % 8 != 0) { printf("The block 0x%x is not 8 byte aligned.\n", (int) bp); return -1; } //Check if the block size is valid. size_t size = GET_SIZE(HDRP(bp)); bp = (int*) bp + size; if ((int) *bp != 0) { printf("The size of block 0x%x is invalid.\n", (int) ((int*) bp - size)); return -1; } } return 0; }
/* Coalesce - Merge free blocks together */ int coalesce(listBlock *ptr) { listBlock *upperBlock = (listBlock *)(((char *)ptr) + ptr->header); if (upperBlock < (listBlock *)mem_heap_hi()) { // don't try to coalesce out of bounds if ((upperBlock->header & 0x1) == 0) { // if upperBlock is Free ptr->header = ptr->header + upperBlock->header; // absorb it into ptr int *footer = (int *)(((char *)ptr) + ptr->header - WORD_SIZE); *footer = ptr->header; upperBlock->next->prev = upperBlock->prev; // splite out the upperBlock from the free list upperBlock->prev->next = upperBlock->next; } } int *lowerFooter = (int *)(((char *)ptr) - WORD_SIZE); listBlock *lowerBlock = (listBlock *)(((char *)ptr) - (*lowerFooter & ~0x1)); if ((lowerBlock->header & 0x1) == 0) { // if previous block is free if (lowerBlock != (listBlock *)mem_heap_lo()) { // don't coalesce with the dummy block because we don't want it to ever get allocated lowerBlock->header = lowerBlock->header + ptr->header; int *footer = (int *)(((char *)lowerBlock) + lowerBlock->header - WORD_SIZE); *footer = lowerBlock->header; return 0; } } return 1; }
/*extend_heap function is used when the heap is firstly initialized, or there isn't enough space when invoking the malloc or realloc. The extend_heap when judge whether there is space left in the tail of the former block, it is a method to enhance the space utility.*/ void *extend_heap(size_t size_) { void *bp; void *end = mem_heap_hi() - 3; int size = size_; if( !PRE_ALLOC_INFO(end) ){ if(PRE_8_INFO(end)) size -= BLOCK_8; else size -= SIZE(end - 4); } if(size <= 0) return NULL; size = MAX(CHUNKSIZE, size); if((long)(bp = mem_sbrk(size)) == -1) return NULL; /* Initialize free block HDRPer/FTRPer and the epilogue HDRPer */ size_t sign = 0 | GET_PRE_ALLOC_INFO(bp) | GET_PRE_8_INFO(bp); PUT_HDRP(bp, PACK(size,sign) ); /* free block HDRPer */ PUT_FTRP(bp, PACK(size,sign) ); /* free block FTRPer */ PUT_HDRP(GET_NEXT(bp), PACK(0,1) ); /* new epilogue HDRPer */ insert_node(coalesce(bp)); return (void *)bp; }
/* Print the heap by iterating through it as an implicit free list. */ static void examine_heap() { BlockInfo *block; fprintf(stderr, "FREE_LIST_HEAD: %p\n", (void *)FREE_LIST_HEAD); for(block = (BlockInfo*)POINTER_ADD(mem_heap_lo(), WORD_SIZE); /* first block on heap */ SIZE(block->sizeAndTags) != 0 && block < mem_heap_hi(); block = (BlockInfo*)POINTER_ADD(block, SIZE(block->sizeAndTags))) { /* print out common block attributes */ fprintf(stderr, "%p: %ld %ld %ld\t", (void*)block, SIZE(block->sizeAndTags), block->sizeAndTags & TAG_PRECEDING_USED, block->sizeAndTags & TAG_USED); /* and allocated/free specific data */ if (block->sizeAndTags & TAG_USED) { fprintf(stderr, "ALLOCATED\n"); } else { fprintf(stderr, "FREE\tnext: %p, prev: %p\n", (void*)block->next, (void*)block->prev); } } fprintf(stderr, "END OF HEAP\n\n"); }
/* * mm_check - heap consistency checker. return 0 if something is wrong, 1 otherwise. */ int mm_check(void) { void *cur, *end; if(!rb_check_preorder()){ return 0; } cur = mem_heap_lo() + MIN_BLOCK_SIZE; end = mem_heap_hi() - 3; while(cur < end){ if(CUR_FREE(cur)){ // cur is free block if(PREV_FREE(cur)){ // contiguous free block printf("%p, %p are consecutive, but both are free.\n", PREV_BLOCK(cur, CUR_SIZE_MASKED(cur)), cur); return 0; } if(IS_IN_RB(cur) && !rb_find_exact(cur)){ // cur is not in Red-black tree printf("%p is free block, but is not in Red-black tree.\n", cur); return 0; } }else{ // cur is allocated block } cur = NEXT_BLOCK(cur, CUR_SIZE_MASKED(cur)); } return 1; }
/* * mm_realloc - Implemented simply in terms of mm_malloc and mm_free, * but with one added optimization. * * The optimization is that if the block is already at the end of the heap, * sbrk only the extra required size and update the header and footer. * No memcpy call is required and return the pointer that was passed in. */ void *mm_realloc(void *ptr, size_t size) { unsigned blkSize = GET_SIZE(HDRP(ptr)); if (realloc_size(size, 0) < blkSize) { return ptr; } // coalesce with sbrk if (NEXT_BLKP(ptr) == ADD_PTR(mem_heap_hi(), 1)) { unsigned allocSize = realloc_size(size, OVERHEAD) - blkSize; mem_sbrk(allocSize); alloc_ptr(ptr, realloc_size(size, OVERHEAD)); // set allocation before the last block PUT_INT(HDRP(NEXT_BLKP(ptr)), 1); return ptr; } /* // allocate coalesce with next free block // allocate coalesce with prev free block */ void *newptr = mm_malloc((unsigned)size); if (newptr == NULL) return NULL; unsigned cpysize = MIN(blkSize - OVERHEAD, (unsigned)size); memcpy_8(newptr, ptr, cpysize); mm_free(ptr); return newptr; }
/* Initialize the allocator. */ int mm_init () { // Head of the free list. BlockInfo *firstFreeBlock; // Initial heap size: WORD_SIZE byte header (stores pointer to head // of free list), MIN_BLOCK_SIZE bytes of space, WORD_SIZE byte footer. int initsize = WORD_SIZE+MIN_BLOCK_SIZE+WORD_SIZE; int totalSize; void* mem_sbrk_result = mem_sbrk(initsize); // printf("mem_sbrk returned %p\n", mem_sbrk_result); if ((int)mem_sbrk_result == -1) { printf("ERROR: mem_sbrk failed in mm_init, returning %p\n", mem_sbrk_result); exit(1); } firstFreeBlock = (BlockInfo*)POINTER_ADD(mem_heap_lo(), WORD_SIZE); // total usable size is full size minus header and footer words. totalSize = initsize - WORD_SIZE - WORD_SIZE; // initialize the free block firstFreeBlock->sizeAndTags = totalSize | TAG_PRECEDING_USED; firstFreeBlock->next = NULL; firstFreeBlock->prev = NULL; // boundary tag *((int*)POINTER_ADD(firstFreeBlock, totalSize - WORD_SIZE)) = totalSize | TAG_PRECEDING_USED; // Tag "useless" word at end of heap as used. *((int*)POINTER_SUB(mem_heap_hi(), 3)) = TAG_USED; // set the head of the free list to this new free block. FREE_LIST_HEAD = firstFreeBlock; return 0; }
static void checkblock(void *bp) { size_t halloc = GET_ALLOC(HDRP(bp)); // check if free block is inside heap if ((bp < mem_heap_lo()) || (mem_heap_hi() < bp)) { printf("mm_check: block pointer %p outside of heap\n",bp); fflush(stdout); exit(0); } // alignment check if ((size_t)bp % 8) { printf("Error: %p is not doubleword aligned\n", bp); exit(0); } // allocated block does not have footer if (!halloc) { if (GET(HDRP(bp)) != GET(FTRP(bp))) { printf("Error: header does not match footer\n"); exit(0); } } }
/** * extend_heap - Extend the heap by number of bytes adjusted_size. * * This differs from the example extend_heap function in that the parameter * passed is in BYTES rather than WORDS. Constantly converting between the two * is confusing and unnecessary. * * Furthermore, it should be a size already adjusted to fit byte and header * alignment. This function merely sets header/footer/successor as needed. */ static void *extend_heap(size_t adjusted_size) { char *bp; size_t prev_alloc; TRACE("Entering extend_heap(adjusted_size=%u)\n", adjusted_size); if ((long)(bp = mem_sbrk(adjusted_size)) == -1) return NULL; /* Initialize free block header/footer and the epilogue header. heap_end points to one byte before the next payload, so reading the PREVALLOC field of heap_end + 1 will yield the actual prev-alloc for the block just before the end of the heap. */ prev_alloc = GET_PREVALLOC(heap_end + 1); /* Free block header */ PUTW(GET_BLOCKHDR(bp), PACK(adjusted_size, prev_alloc)); /* Free block header */ PUTW(GET_BLOCKFTR(bp), PACK(adjusted_size, prev_alloc)); /* New epilogue header */ PUTW(GET_BLOCKHDR(GET_NEXTBLOCK(bp)), PACK(0xEA7F00D0, THISALLOC)); heap_end = mem_heap_hi(); TRACE("<<<---Leaving extend_heap() with a call to coalesce()\n"); /* Coalesce if the previous block was free */ return coalesce(bp); /* coalesce handles adding block to free list */ }
/* * mm_realloc - Change the size of a block. */ void *mm_realloc(void *ptr, size_t size) { #ifdef MM_CHECK if (!ptr) return mm_malloc(size); if (!size) return mm_free(ptr); #endif void *now = mm_restore_header(ptr); void *dest; size_t now_size = MM(now)->size; size_t need_size = MM_HEADER_SIZE + ALIGN(size); // try to merge useable blocks while (now_size < need_size && mm_merge(now, &now_size)); if (now_size >= need_size) { // the block can be locally extensed and splitting is possible return mm_split(now, now_size, need_size); } else { if ((now + now_size - 1) == mem_heap_hi()) { // the block is the last block and it can be extensed return mm_break(now, now_size, need_size); } else { // need to allocate a new block and copy data to it dest = mm_malloc(size); memcpy(dest, ptr, MM(now)->size - MM_HEADER_SIZE); mm_free(ptr); return dest; } } }
/* * getRightBlock - returns a block on the right side of target * returns NULL if doens't exists. * */ void* getRightBlock(void* target) { void* rightBlock = (FREE)((void*)target+FSIZE(target)); if (rightBlock<mem_heap_hi()+1) { return rightBlock; } return NULL; }
void print_heap() { hblock *bp = mem_heap_lo(); while(bp < (hblock *) mem_heap_hi()) { printf("%s block at %p, size %d\n", GET_ALLOC(bp) ? "allocated":"free", bp, GET_SIZE(bp)); bp = (hblock *) NEXT_BLKP(bp); } }
void print_the_heap() // printing the information related to blocks in the heap { blockHdr *bp = mem_heap_lo(); while(bp<(blockHdr *)mem_heap_hi()){ printf("%s block at: %p,size: %d\n",(bp->size&1)?"allocated":"free",bp ,(int)(bp->size & ~1)); bp = (blockHdr *)((char *)bp +(bp->size & ~1)); } }
/* * checkBlock - Checks a block for consistency * Checks prev and next pointers to see if they are within heap boundaries. * Checks for 8-byte alignment. * Checks header and footer for consistency. * * This function takes a block pointer (to a block for examinination) as a * parameter. */ static void checkBlock(void *bp) { // Reports if the next and prev pointers are within heap bounds if (NEXT_FREEP(bp)< mem_heap_lo() || NEXT_FREEP(bp) > mem_heap_hi()) printf("Error: next pointer %p is not within heap bounds \n" , NEXT_FREEP(bp)); if (PREV_FREEP(bp)< mem_heap_lo() || PREV_FREEP(bp) > mem_heap_hi()) printf("Error: prev pointer %p is not within heap bounds \n" , PREV_FREEP(bp)); /* Reports if there isn't 8-byte alignment by checking if the block pointer * is divisible by 8. */ if ((size_t)bp % 8) printf("Error: %p is not doubleword aligned\n", bp); // Reports if the header information does not match the footer information if (GET(HDRP(bp)) != GET(FTRP(bp))) printf("Error: header does not match footer\n"); }
void *coalesce(size_t *bp) { size_t *next = (size_t *)((char *)bp + (*bp & ~1L)); size_t *prev = (size_t *)((char *)bp - ((*(size_t *)((char *)bp - SIZE_T_SIZE)) & ~1L)); int prev_alloc, next_alloc; blockHdr *head = (blockHdr *)mem_heap_lo(); blockHdr *v = (blockHdr *)bp; if (prev > (size_t *)mem_heap_lo()) { prev_alloc = *prev & 1; } else { prev_alloc = 1; } if (next < ((size_t *)mem_heap_hi())) { next_alloc = *next & 1; } else { next_alloc = 1; } if (prev_alloc && next_alloc) { v->next_p = head->next_p; v->prior_p = head; head->next_p = v; v->next_p->prior_p = v; return v; } else if (!prev_alloc && next_alloc) {//if previous free *prev += (*bp & ~1); //bp is not yet freed *(size_t *) ((char *)bp + (*bp & ~1) - SIZE_T_SIZE) = *prev; return prev; } else if (prev_alloc && !next_alloc) { //if next free *bp += (*next & ~1); *(size_t *) ((char *)next + (*next & ~1) - SIZE_T_SIZE) = *bp; v->next_p = ((blockHdr *) next)->next_p; v->prior_p = ((blockHdr *) next)->prior_p; v->prior_p->next_p = v; v->next_p->prior_p = v; return v; } else if (!prev_alloc && !next_alloc) { *prev += (*next & ~1) + (*bp & ~1); *(size_t *) ((char *)next + (*next & ~1) - SIZE_T_SIZE) = *prev; /*((blockHdr *) prev)->next_p = ((blockHdr *) next)->next_p; ((blockHdr *) prev)->next_p->prior_p = (blockHdr *) prev;*/ ((blockHdr*)next)->prior_p->next_p = ((blockHdr *)next)->next_p; ((blockHdr*)next)->next_p->prior_p = ((blockHdr *)next)->prior_p; return prev; } return NULL; }
/********************************************************** * is_in_heap * Checks if the block pointer is in heap. Prints an error * message if the block is outside the heap **********************************************************/ int is_in_heap(void *bp) { if (bp < mem_heap_lo() || bp > mem_heap_hi()) { PRINTDBG (("The block is not on the heap\n")); return 0; } return 1; }
void print_heap() { blockHdr *bp = mem_heap_lo(); while (bp < (blockHdr *)mem_heap_hi()) { printf("%s block at %p, size %d\n", (bp->size&1)?"allocated":"free", bp, (int)(bp->size & ~1)); bp = (blockHdr *)((char *)bp + (bp->size & ~1)); } }
void print_heap(){ blockHdr *bp = mem_heap_lo(); int i = 0; while (bp < (blockHdr *) mem_heap_hi()) { printf("%d. %s block at %p, size %ld + \n", i, (bp->size&1)?"allocated":"free", bp, (long) (bp->size & ~1)); bp = (blockHdr *) ((char *) bp + (bp->size & ~1)); i++; } }
/* * mm_malloc - Allocate a block * * If there exists a free block where the request fits, get the smallest one, segment it and allocate. * If there is no such block, increase brk. */ void* mm_malloc(size_t size) { size_t block_size, next_block_size; void *free_block, *next_block; block_size = ALIGN(HEADER_SIZE + size); block_size = block_size < MIN_BLOCK_SIZE ? MIN_BLOCK_SIZE : block_size; free_block = rb_find(block_size); if(free_block == rb_null){ // proper free block not found /* set free_block to the end of last block in heap */ free_block = mem_heap_hi() - 3; if(PREV_FREE(free_block)){ // if the last block is free /* set free_block to the last block */ free_block -= PREV_SIZE_MASKED(free_block); if(IS_IN_RB(free_block)){ rb_delete(free_block); } /* this block is smaller than request, so increase brk */ mem_sbrk(block_size - CUR_SIZE_MASKED(free_block)); }else{ // if the last block is not free mem_sbrk(block_size); } }else{ /* will be allocated, so delete from tree first */ rb_delete(free_block); /* if the block is bigger than request, segment it */ if((next_block_size = CUR_SIZE_MASKED(free_block) - block_size) > 0){ next_block = NEXT_BLOCK(free_block, block_size); CUR_SIZE(next_block) = PREV_SIZE(NEXT_BLOCK(next_block, next_block_size)) = next_block_size | 1; if(IS_IN_RB(next_block)){ rb_insert(next_block); } } } CUR_SIZE(free_block) = PREV_SIZE(NEXT_BLOCK(free_block, block_size)) = block_size; #ifdef DEBUG printf("mm_malloc(%u) called\n", size); printf("free_block = %p\n", free_block); rb_print_preorder(); printf("\n"); #endif /* DEBUG */ #ifdef CHECK if(!mm_check()){ rb_print_preorder(); exit(0); } #endif /* CHECK */ return USER_BLOCK(free_block); }
/* * checkFreeNodes - function that checks correctness of the blocks in * the free list */ static void checkFreeNodes(void *bp) { /* Seperate condition for free_listp since it does not have a * previous pointer. */ if(bp == free_listp) { /* Checking that free_listp indeed points to a free block. */ if(GET_ALLOC(HDRP(bp))) printf("Error: Freelistp points to an allocated block.\n"); /* Free_listp must point to a valid block and must not be * out of bounds */ if(!(bp > mem_heap_lo() && bp < mem_heap_hi())) printf("Error: Free list pointer out of heap bounds.\n"); /* Previous pointer of free_listp * must point nowhere (nil). */ if(PREV_FREE(bp) != 0 ) printf("Error: Free pointer is not null.\n"); return; } /* Checking that bp is indeed pointing to a free block */ if(GET_ALLOC(HDRP(bp)) != 0) printf("Error: There exists an allocated block in the free list.\n"); /* Check that next and prev pointers in consecutive blocks are consistent * Next pointer of previous block points to current block and previous pointer * of next block points to current block */ // Split one print statement into 2 to not cross the 80 character limit. if(PREV_FREE(bp) && NEXT_FREE(PREV_FREE(bp)) != bp) { printf("Error: Next pointer of previous free block "); printf("not pointing to current block.\n"); } if(NEXT_FREE(bp) && PREV_FREE(NEXT_FREE(bp)) != bp) { printf("Error: Previous pointer of next free block "); printf("not pointing to current block.\n"); } /* Check that coalescing was correct at the free block pointed to by bp. The previous and next blocks must both be allocated.*/ if(!GET_ALLOC(HDRP(NEXT_BLKP(bp))) || !GET_ALLOC(HDRP(PREV_BLKP(bp)))) printf("Error: Contiguous free blocks in the heap\n"); }
void checklist(void) { void* bp = heap_listp; void* prev_ptr; //int prev_alloc = 1; int i; dbg1("[IN ] : checklist\n"); /* go through each segregated free list */ for ( i = 0; i <= MAXCLASS; i++ ) { if (verbose) printlist(i); bp = GET_FREE_LISTP(i); prev_ptr = NULL; while( bp != NULL) { /* see if pointer is within heap */ if ((bp < mem_heap_lo()) || (mem_heap_hi() < bp)) { printf("mm_check: free block pointer %p outside of heap\n",bp); fflush(stdout); exit(0); } /* make sure block is truly free */ if (GET_ALLOC(HDRP(bp))) { printf("mm_check: free block list %d has allocated block\n", i); fflush(stdout); exit(0); } /* make sure block is not smaller than min block */ if (GET_SIZE(HDRP(bp)) < OVERHEAD + 2*DSIZE) { printf("mm_check: block too small in list %d with block at %p\n", i, bp); printf("mm_check: %x\n", GET_SIZE(HDRP(bp))); fflush(stdout); exit(0); } /* make sure previous pointer is correct */ if (PREV_FREE_BLKP(bp) != prev_ptr) { printf("mm_check: previous block ptr in list %d does not point to previous block\n", i); fflush(stdout); exit(0); } /* go to next free block */ prev_ptr = bp; bp = (void*)NEXT_FREE_BLKP(bp); } } dbg1("[OUT] : checklist\n"); return; }
/* * checkblock - checks basic invariants of a block in the heap list */ static void checkblock(void *bp) { /* Checking for double word alignment */ if ((size_t)bp % 8) printf("Error: %p is not doubleword aligned\n", bp); /* Header must match footer for allocation bit and size */ if (GET(HDRP(bp)) != GET(FTRP(bp))) printf("Error: header does not match footer\n"); /* Block pointer must be within the heap boundaries */ if(bp > mem_heap_hi() || bp < mem_heap_lo()) printf("Error: block pointer not within heap boundaries.\n"); }
/* * mm_merge - Try to merge with next free block. */ inline int mm_merge(void *ptr, size_t *p_size) { void *next = ptr + *p_size; size_t next_size = MM(next)->size; // if the next block can be merged if ((next - 1) != mem_heap_hi() && SIGN_CHECK(next_size)) { *p_size += SIGN_MARK(next_size); mm_put_header(ptr, SIGN_MARK(*p_size)); return -1; } else { return 0; } }
/* * mm_exit - finalize the malloc package. */ void mm_exit(void) { void *cur, *end; cur = mem_heap_lo() + MIN_BLOCK_SIZE; end = mem_heap_hi() - 3; while(cur < end){ /* check if there are allocated blocks remaining */ if(!CUR_FREE(cur)){ printf("memory leak at %p is detected.\n", cur); mm_free(cur + HEADER_SIZE); } cur = NEXT_BLOCK(cur, CUR_SIZE_MASKED(cur)); } }
/* * mm_print - Print block list for debug purpose. */ void mm_print(void) { void *now = mem_heap_lo(); size_t now_size = 0; printf("\n"); // scan the block list while ((now - 1) != mem_heap_hi()) { now_size = MM(now)->size; printf("pos: %x - head: %x\n", (unsigned) now, now_size); // visit the next block now += SIGN_CHECK(now_size) ? SIGN_MARK(now_size) : now_size; } }
static void print_blk(char *cur_blk) { cur_blk = cur_blk; dbg_printf("\n address: %d\n", (unsigned long)cur_blk); dbg_printf(" hdr-size: %d\n", GET_SIZE(HDRP(cur_blk))); dbg_printf(" hdr-alloc: %d\n", GET_ALLOC(HDRP(cur_blk))); dbg_printf(" ftr-size: %d\n", GET_SIZE(FTRP(cur_blk))); dbg_printf(" ftr-alloc: %d\n", GET_ALLOC(FTRP(cur_blk))); if (GET_ALLOC(HDRP(cur_blk)) == 0) { dbg_printf(" pred: %d\n", (unsigned long)REAL_ADDR(GET(PRED(cur_blk)))); dbg_printf(" succ: %d\n", (unsigned long)REAL_ADDR(GET(SUCC(cur_blk)))); } dbg_printf(" heap_end: %d\n", (unsigned long)(mem_heap_hi() + 1)); dbg_printf("****************************\n"); }