/* 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); }
/* Free the block referenced by ptr. */ void mm_free (void *ptr) { size_t payloadSize; BlockInfo * blockInfo; BlockInfo * followingBlock; // Implement mm_free. You can change or remove the declaraions // above. They are included as minor hints. blockInfo = (BlockInfo*)POINTER_SUB(ptr, WORD_SIZE); payloadSize = SIZE(blockInfo->sizeAndTags); followingBlock = (BlockInfo*)POINTER_ADD(blockInfo, payloadSize); // update the status in the current block: reset TAG_USED in both head and boundary tag size_t precedingBlockUseTag = blockInfo->sizeAndTags & TAG_PRECEDING_USED; blockInfo->sizeAndTags = payloadSize | precedingBlockUseTag; *((size_t*)POINTER_ADD(blockInfo, payloadSize - WORD_SIZE)) = payloadSize | precedingBlockUseTag; // update the status in the following block: reset TAG_PRECEDING_USED size_t followingBlockSize = SIZE(followingBlock->sizeAndTags); size_t followingBlockUsed = followingBlock->sizeAndTags & TAG_USED; followingBlock->sizeAndTags = followingBlockSize | followingBlockUsed; // if the following block is free, also update its boundary tag if ((followingBlock->sizeAndTags & TAG_USED) != TAG_USED) { *((size_t*)POINTER_ADD(followingBlock, followingBlockSize - WORD_SIZE)) = followingBlock->sizeAndTags; } insertFreeBlock(blockInfo); coalesceFreeBlock(blockInfo); }
/* Free the block referenced by ptr. */ void mm_free (void *ptr) { size_t payloadSize; BlockInfo * blockInfo; BlockInfo * followingBlock; // Implement mm_free. You can change or remove the declaraions // above. They are included as minor hints. // Casts void pointer into BlockInfo, subtracts pointer by Wsize blockInfo = (BlockInfo*)POINTER_SUB(ptr, WORD_SIZE); // Checks if block wasn't freed if(((blockInfo->sizeAndTags) & TAG_USED)==0){ return; } // Marks it as free, adds to free list and coalesces the free blocks together. blockInfo->sizeAndTags = blockInfo->sizeAndTags & (~TAG_USED); insertFreeBlock(blockInfo); coalesceFreeBlock(blockInfo); // unmarks the next block's preced used tag payloadSize = SIZE(blockInfo->sizeAndTags); followingBlock = (BlockInfo*)POINTER_ADD(blockInfo, payloadSize); followingBlock->sizeAndTags = followingBlock->sizeAndTags & (~TAG_PRECEDING_USED); }
/* Free the block referenced by ptr. */ void mm_free (void *ptr) { size_t payloadSize; BlockInfo * blockInfo; BlockInfo * followingBlock; size_t bitMask; // Implement mm_free. You can change or remove the declaraions // above. They are included as minor hints. // set BlockInfo pointer to include header blockInfo = (BlockInfo*) POINTER_SUB(ptr, WORD_SIZE); payloadSize = SIZE(blockInfo->sizeAndTags) - WORD_SIZE; followingBlock = (BlockInfo*) POINTER_ADD(ptr, payloadSize + WORD_SIZE); // set header (first tags, then size) bitMask = ~0 << 1; blockInfo->sizeAndTags &= bitMask; /* preserves all bits, except sets lowest to 0 (unsetting used tag) */ // copy header into footer *((size_t*) POINTER_ADD(blockInfo, payloadSize)) = blockInfo->sizeAndTags; // set preceding use tag for following block bitMask = (~0 << 2) | 1; followingBlock->sizeAndTags &= bitMask; /* preserves all bits except 2nd lowest bit */ // insert into free list and coalesce insertFreeBlock(blockInfo); coalesceFreeBlock(blockInfo); }
/* Free the block referenced by ptr. */ void mm_free (void *ptr) { size_t payloadSize; BlockInfo * blockInfo; BlockInfo * followingBlock; blockInfo = (BlockInfo *)UNSCALED_POINTER_SUB(ptr, WORD_SIZE);//header of chosen block to free blockInfo->sizeAndTags = blockInfo->sizeAndTags & (~TAG_USED);//turn off the tag used tag payloadSize = SIZE(blockInfo->sizeAndTags);//get the payload of the block soon to be freed followingBlock = (BlockInfo *)UNSCALED_POINTER_ADD(blockInfo, payloadSize + WORD_SIZE);//move to the block that follows the block to be freed followingBlock->sizeAndTags = (followingBlock->sizeAndTags) & (~TAG_PRECEDING_USED);//turn off its preceding tag used flag insertFreeBlock(blockInfo);//insert block that was freed back to the list coalesceFreeBlock(blockInfo);//coalesce, if possible }
/* Free the block referenced by ptr. */ void mm_free (void *ptr) { size_t payloadSize; BlockInfo * blockInfo; BlockInfo * nextBlock; // Implement mm_free. You can change or remove the declaraions // above. They are included as minor hints. blockInfo = (BlockInfo* )POINTER_SUB(ptr, WORD_SIZE); payloadSize = SIZE(blockInfo->sizeAndTags); blockInfo->sizeAndTags = blockInfo->sizeAndTags & ~TAG_USED; *((size_t*)POINTER_ADD(blockInfo, payloadSize- WORD_SIZE)) = blockInfo->sizeAndTags; nextBlock = (BlockInfo* )POINTER_ADD(blockInfo, payloadSize); nextBlock->sizeAndTags = nextBlock->sizeAndTags & ~TAG_PRECEDING_USED; insertFreeBlock(blockInfo); coalesceFreeBlock(blockInfo); }
/* Free the block referenced by ptr. */ void mm_free (void *ptr) { printf("Begin free\n"); size_t payloadSize; BlockInfo * blockInfo; BlockInfo * footer; BlockInfo * nextBlock; size_t precedingBlockUseTag; blockInfo = (BlockInfo *) UNSCALED_POINTER_SUB(ptr, WORD_SIZE); payloadSize = SIZE(blockInfo->sizeAndTags); precedingBlockUseTag = blockInfo->sizeAndTags & TAG_PRECEDING_USED; blockInfo->sizeAndTags = (payloadSize & ~TAG_USED) | precedingBlockUseTag; footer = (BlockInfo *) UNSCALED_POINTER_ADD(blockInfo, payloadSize - WORD_SIZE); footer->sizeAndTags = blockInfo->sizeAndTags; nextBlock = (BlockInfo *) UNSCALED_POINTER_ADD(ptr, payloadSize); set_next_block(nextBlock, precedingBlockUseTag); insertFreeBlock(blockInfo); coalesceFreeBlock(blockInfo); }
void split_block(BlockInfo * ptrFreeBlock, size_t totalSize, size_t precedingBlockUseTag){ printf("Splitting\n"); BlockInfo * splitBlock = NULL; BlockInfo * splitBlockFooter = NULL; BlockInfo * nextBlock = NULL; size_t splitBlockSize; size_t ptrFreeBlockSize; ptrFreeBlockSize = SIZE(ptrFreeBlock->sizeAndTags); splitBlock = (BlockInfo *) UNSCALED_POINTER_ADD(ptrFreeBlock, ptrFreeBlockSize); splitBlockSize = totalSize - ptrFreeBlockSize; splitBlock->sizeAndTags = splitBlockSize | TAG_PRECEDING_USED; splitBlockFooter = (BlockInfo *) UNSCALED_POINTER_ADD((void*)splitBlock, splitBlockSize - WORD_SIZE); splitBlockFooter->sizeAndTags = splitBlock->sizeAndTags; nextBlock = (BlockInfo *) UNSCALED_POINTER_ADD((void *) splitBlock, splitBlockSize); set_next_block(nextBlock, 0); insertFreeBlock(splitBlock); coalesceFreeBlock(splitBlock); examine_heap(); }
//changes the size allocated to a block, if possible void* mm_realloc(void* ptr, size_t size) { size_t oldsize; BlockInfo * blockInfo,*block; void * copyptr; if(ptr == NULL && (size > 0)){ copyptr = mm_malloc(size); mm_free(ptr); } if(size == 0){ mm_free(ptr); copyptr = NULL; } //code for iterating through the freelist. upon each call of realloc, search the freelist, and coalesce all unused blocks //likely inefficent, but sufficient for the project. prevents us from getting a multitude of free blocks that are too big //to be used, which causes mem_sbrk to fail and the program to quit. for(block = (BlockInfo *)UNSCALED_POINTER_ADD(mem_heap_lo(), WORD_SIZE); /* first block on heap */ SIZE(block->sizeAndTags) != 0 && block < mem_heap_hi(); block = (BlockInfo *)UNSCALED_POINTER_ADD(block, SIZE(block->sizeAndTags))) { /* and allocated/free specific data */ if ((block->sizeAndTags & TAG_USED) == 0) { coalesceFreeBlock(block); } } copyptr = mm_malloc(size);//call to mm_malloc for the requested size blockInfo = (BlockInfo *)UNSCALED_POINTER_SUB(ptr,WORD_SIZE); //pointer to the header of ptr oldsize = SIZE(blockInfo->sizeAndTags);//get the size of ptr if(size < oldsize){//if the size of ptr is greater than requested oldsize = size;// change the value of bytes to be copied to the requested size } memcpy(copyptr, ptr, oldsize); //copy "n = oldsize" bytes from ptr to copyptr mm_free(ptr); //return ptr to the freelist return copyptr; // return copyptr }