/* Get more heap space of size at least reqSize. */ static void requestMoreSpace(size_t reqSize) { size_t pagesize = mem_pagesize(); size_t numPages = (reqSize + pagesize - 1) / pagesize; BlockInfo *newBlock; size_t totalSize = numPages * pagesize; size_t prevLastWordMask; void* mem_sbrk_result = mem_sbrk(totalSize); if ((size_t)mem_sbrk_result == -1) { printf("ERROR: mem_sbrk failed in requestMoreSpace\n"); exit(0); } newBlock = (BlockInfo*)UNSCALED_POINTER_SUB(mem_sbrk_result, WORD_SIZE); /* initialize header, inherit TAG_PRECEDING_USED status from the previously useless last word however, reset the fake TAG_USED bit */ printf("newBlock: %p\n", (void *) newBlock); prevLastWordMask = newBlock->sizeAndTags & TAG_PRECEDING_USED; newBlock->sizeAndTags = totalSize | prevLastWordMask; // Initialize boundary tag. ((BlockInfo*)UNSCALED_POINTER_ADD(newBlock, totalSize - WORD_SIZE))->sizeAndTags = totalSize | prevLastWordMask; /* initialize "new" useless last word the previous block is free at this moment but this word is useless, so its use bit is set This trick lets us do the "normal" check even at the end of the heap and avoid a special check to see if the following block is the end of the heap... */ *((size_t*)UNSCALED_POINTER_ADD(newBlock, totalSize)) = TAG_USED; // Add the new block to the free list and immediately coalesce newly // allocated memory space insertFreeBlock(newBlock); coalesceFreeBlock(newBlock); }
/** * mm_init - Initialize the malloc package. */ int mm_init(void) { TRACE(">>>Entering mm_init()\n"); mem_init(); #ifdef DO_MM_CHECK /* initialize the ENTIRE heap provided by memlib to 0x00 */ memset(mem_heap_lo(), 0, MAX_HEAP); #endif /*Each element in free_lists starts off as the empty head of a linked list*/ memset(free_lists, (int)NULL, sizeof(free_lists)); /* Initialize write-once variables */ PAGE_SIZE = mem_pagesize(); ADJUSTED_PAGESIZE = ADJUST_BYTESIZE((PAGE_SIZE*2)); /* Initially allocate 1 page of memory plus room for the prologue and epilogue blocks and free block header */ if((heap_start = mem_sbrk(ADJUSTED_PAGESIZE + (4 * WSIZE))) == NULL) return -1; heap_end = mem_heap_hi(); /* Alignment word */ PUTW(heap_start, 0x8BADF00D); /* Prologue header */ PUTW(heap_start + (1 * WSIZE), PACK(DSIZE, THISALLOC | PREVALLOC)); PUTW(heap_start + (2 * WSIZE), PACK(DSIZE, THISALLOC | PREVALLOC)); /* Epilogue header */ PUTW(heap_start + ADJUSTED_PAGESIZE + 3 * WSIZE, PACK(0xEA7F00D0, THISALLOC)); /* Setup initial free block */ PUTW(heap_start + (3 * WSIZE), PACK(ADJUSTED_PAGESIZE, PREVALLOC)); PUTW((heap_end - WSIZE + 1) - WSIZE, PACK(ADJUSTED_PAGESIZE, PREVALLOC)); add_to_list(heap_start + (4 * WSIZE), calc_list_index(ADJUSTED_PAGESIZE)); RUN_MM_CHECK(); TRACE("<<<---Leaving mm_init()\n"); return 0; }
/********************************************************** * mm_check * Check the consistency of the memory heap * Return nonzero if the heap is consistant. *********************************************************/ int mm_check(void) { #ifdef DEBUG_BUILD int i; dlist *current; void *bp; //To point at the start of the heap size_t size = 0; //To measure the total size of blocks on the heap // Check if every block in free list is actually marked free. // If a allocated block is in the free list then it may result in segmentation faults // while accessing the prev and next pointers. It will also result in the allocater manipulating // memory allocated to user which will be nasty! for(i = 0; i < NUM_SEG_LIST; i++) { current = sep_list_head[i]; while (current != NULL) { // Check if block is in heap if (is_in_heap((void*)current) == 0) return 0; if (GET_ALLOC(HDRP((void*)current))) { PRINTDBG (("block (%p) in free list is allocated!\n", current)); return 0; } current = current->next; } } // Check if there exist any free blocks that may have escaped coalescing. // If found, these cases result in internal fragmentation. for (bp = heap_listp; GET_SIZE(HDRP(bp)) > 0; bp = NEXT_BLKP(bp)) { // Check if the current block is free and the next block is also free // Since this is done in a sequential manner, we don't need to check the previous blk if (!GET_ALLOC(HDRP(bp)) && (!GET_ALLOC(HDRP(NEXT_BLKP(bp))))) { PRINTDBG (("Consecutive blocks (%p, %p) have escaped coalescing!\n", bp, NEXT_BLKP(bp))); return 0; } } for (bp = heap_listp; GET_SIZE(HDRP(bp)) > 0; bp = NEXT_BLKP(bp)) { if (bp < mem_heap_lo() || bp > mem_heap_hi()) { PRINTDBG (("Block is outside the heap.\n")); return 0; } else { size += GET_SIZE(HDRP(bp)); //Add the size of the current block to the total size of the calculated blocks on the heap so far } } if (size == mem_heapsize()) PRINTDBG (("The total size of all blocks on the heap match the heap size.\n")); if (mem_heapsize() > mem_pagesize()) //Check if heap size exceeded systems page size PRINTDBG (("Heap size is more than page size. TLB misses might occur\n")); char c; scanf("%c\n", &c); #endif return 1; }