示例#1
0
void coalesceWithNextBlock(void* newAddr, uint32_t newSize, struct freeBlockLinks *successorBlockLinks) 
{
	struct blockHeader *newBlock = newAddr;
	newBlock->attribute = newSize;

	// Update links to freenodes.
	void* blockLinks = ADDRESS_PLUS_OFFSET(newAddr, blockHeader);
	struct freeBlockLinks *newBlockLinks = INIT_STRUCT(freeBlockLinks, blockLinks);
	PREV_BLOCK(newBlockLinks) = PREV_BLOCK(successorBlockLinks);
	NEXT_BLOCK(newBlockLinks) = NEXT_BLOCK(successorBlockLinks);

	// Prev block.
	void* prevLinks = ADDRESS_PLUS_OFFSET(PREV_BLOCK(newBlockLinks), blockHeader);
	struct freeBlockLinks *prevBlockLinks = INIT_STRUCT(freeBlockLinks, prevLinks);
	NEXT_BLOCK(prevBlockLinks) = newAddr;

	// Next block.
	void* nextLinks = ADDRESS_PLUS_OFFSET(NEXT_BLOCK(newBlockLinks), blockHeader);
	struct freeBlockLinks *nextBlockLinks = INIT_STRUCT(freeBlockLinks, nextLinks);
	PREV_BLOCK(prevBlockLinks) = newAddr;

	uint64_t sizeOffset = WORDS_TO_BYTES(newSize);
	setFooterBlockOnCoalescing(newAddr, sizeOffset, newSize);
	updateNextBlockOnCoalescing(newAddr, sizeOffset);
}
示例#2
0
// Remove allocated block from free list.
void removeAllocatedBlock(struct freeBlockLinks *blockToBeRemovedLinks) 
{
	void* prevBlock = PREV_BLOCK(blockToBeRemovedLinks);
	void* prevLinks = ADDRESS_PLUS_OFFSET(prevBlock, blockHeader);
	struct freeBlockLinks *prevBlockLinks = INIT_STRUCT(freeBlockLinks, prevLinks);
	NEXT_BLOCK(prevBlockLinks) = NEXT_BLOCK(blockToBeRemovedLinks);

	void* nextBlock = NEXT_BLOCK(blockToBeRemovedLinks);
	void* nextLinks = ADDRESS_PLUS_OFFSET(nextBlock, blockHeader);
	struct freeBlockLinks *nextBlockLinks = INIT_STRUCT(freeBlockLinks, nextLinks);
	PREV_BLOCK(nextBlockLinks) = PREV_BLOCK(blockToBeRemovedLinks);
}
示例#3
0
// Insert new free block into the free list
void insertFreeBlock(void* newBlock, struct freeBlockLinks *prevBlockLinks) 
{
	void* usableArea = ADDRESS_PLUS_OFFSET(newBlock, blockHeader);
	struct freeBlockLinks *newBlockLinks = INIT_STRUCT(freeBlockLinks, usableArea);

	void* next = NEXT_BLOCK(newBlockLinks) + sizeof(blockHeader);
	struct freeBlockLinks *nextBlock = INIT_STRUCT(freeBlockLinks, next);
	PREV_BLOCK(nextBlock) = newBlock;

	void* prev = PREV_BLOCK(newBlockLinks) + sizeof(blockHeader);
	struct freeBlockLinks *prevBlock = INIT_STRUCT(freeBlockLinks, prev);
	NEXT_BLOCK(prevBlock) = newBlock;
	
}
示例#4
0
/*
 * 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;
}
示例#5
0
// size in words.
// Flag one means block is free.
void initialiseFreeBlock(void* freeRegion, uint32_t size, void* prevFreeRegion, 
	void* nextFreeRegion, bool flag, bool setHeader) 
{	
	totalFreeSpace += WORDS_TO_BYTES(size); // Stats

	 // Update largest free region.
	if (size > largestFreeBlock) {
		largestFreeBlock = WORDS_TO_BYTES(size);
	}

	if (setHeader) {
		struct blockHeader *header = INIT_STRUCT(blockHeader, freeRegion);
		header->attribute = size; // Set size. Size is max 2^30. Flag is 0 by default.
		if (flag)
			header->attribute |= MSB_TO_ONE; // Set flag to 1.
	}

	void* usableArea = ADDRESS_PLUS_OFFSET(freeRegion, blockHeader);
	struct freeBlockLinks *blockLinks = INIT_STRUCT(freeBlockLinks, usableArea);
	PREV_BLOCK(blockLinks) = prevFreeRegion; 
	NEXT_BLOCK(blockLinks) = nextFreeRegion;

	// Set footer free region.
	uint64_t sizeOffset = WORDS_TO_BYTES(size);
	void* footer = ADDRESS_MINUS_OFFSET(usableArea + sizeOffset, freeBlockFooter);
	struct freeBlockFooter *blockFooter = INIT_STRUCT(freeBlockFooter, footer);
	blockFooter->size = size;
}
示例#6
0
// Split a large block into two sub-blocks.
// spaceLeft and size are in words
void *splitFreeBlock(void* blockToSplit, uint64_t spaceLeft,
		uint32_t size, void* currentFreeBlock, 
		struct freeBlockLinks *currentBlockLinks) 
{
	// Reinitialise header of first sub-block.
	void* block = ADDRESS_MINUS_OFFSET(blockToSplit, blockHeader);
	struct blockHeader *allocatedBlock = INIT_STRUCT(blockHeader, block);
	allocatedBlock->attribute = size;

	// Create and initialise new node.
	uint32_t sizeNewNode = spaceLeft - BYTES_TO_WORDS(sizeof(blockHeader));
 
 	uint64_t sizeOffset =  WORDS_TO_BYTES(size);
	void* endUserRequestedBlock = blockToSplit + sizeOffset;
	// initialise new block.
	void* prevBlock = PREV_BLOCK(currentBlockLinks);

	totalFreeSpace -= WORDS_TO_BYTES(spaceLeft);
	totalFreeSpace -= WORDS_TO_BYTES(size); // Stats

	initialiseFreeBlock(endUserRequestedBlock, sizeNewNode, 
		prevBlock, currentFreeBlock, false, true);
	insertFreeBlock(endUserRequestedBlock, currentBlockLinks);

	return endUserRequestedBlock;
}
示例#7
0
// size free region in bytes
void initialiseFreeMmapRegion(void* beginningFreeRegion, uint64_t sizeFreeRegion) 
{
	uint32_t sizeFreeRegionInWords = BYTES_TO_WORDS(sizeFreeRegion); // headerMmapsize in words.
	if(!freeList) {
		freeList = beginningFreeRegion; // Initialise the free list.
		initialiseFreeBlock(beginningFreeRegion, sizeFreeRegionInWords, 
			beginningFreeRegion, beginningFreeRegion, false, true);
	} else {
		// Add to free list.
		void *currentBlock = freeList;
		void* links = ADDRESS_PLUS_OFFSET(currentBlock, blockHeader);
		struct freeBlockLinks *currentBlockLinks = INIT_STRUCT(freeBlockLinks, links);

		void* prevBlock = PREV_BLOCK(currentBlockLinks);
		initialiseFreeBlock(beginningFreeRegion, sizeFreeRegionInWords, 
			prevBlock, currentBlock, false, true); 

		// Tell next block that its previous one is NOW free. 
		uint64_t sizeOffset = WORDS_TO_BYTES(sizeFreeRegionInWords);
		updateNextBlockOnCoalescing(beginningFreeRegion, sizeFreeRegion);

		insertFreeBlock(beginningFreeRegion, currentBlockLinks);
	}
}
示例#8
0
/* TBD: Make this function force inline */
static inline void prvInsertBlockIntoFreeList( xBlockLink * pxBlockToInsert )
{
	xBlockLink *pxIterator;
	xBlockLink *xBlockToMerge;
	size_t xBlockSize;

	ASSERT(IS_FREE_BLOCK(pxBlockToInsert));

	/* We have a block which we are about to declare as a free block. 
	  *  Lets find out if there is a free block in front of us and back
	  *  of us  
	  */ 

	/*
	TRACE("pxBlockToInsert->pxNextFreeBlock: %x ->pxPrev = %x\n\r",
	      pxBlockToInsert->pxNextFreeBlock, pxBlockToInsert->pxPrev);
	*/
	
        /* Check for front merge */
	if ( !IS_LAST_BLOCK( pxBlockToInsert ) ) { 
		if ( IS_FREE_BLOCK(NEXT_BLOCK( pxBlockToInsert ) ) ) {
			xBlockToMerge = NEXT_BLOCK( pxBlockToInsert );

			/*  Find out xBlockToMerge's location on the free list.*/
			for( pxIterator = &xStart;
			     pxIterator->pxNextFreeBlock != xBlockToMerge &&
				     pxIterator->pxNextFreeBlock != NULL;
			     pxIterator = pxIterator->pxNextFreeBlock ) {}

#ifdef DEBUG_HEAP
			if(! ( pxIterator->pxNextFreeBlock == xBlockToMerge ) ) {
				/*
				 * This is not a good situation. The
				 * problem is that data structures here are
				 * showing that the next block is free. But
				 * ths free block could not be found in the
				 * free list.
				 */
				ATRACE("Target block dump :\n\r");
				ATRACE("pxNextFreeBlock : 0x%x\n\r", 
				      xBlockToMerge->pxNextFreeBlock);
				ATRACE("pxPrev          : 0x%x\n\r", 
				      xBlockToMerge->pxPrev);
				ATRACE("xBlockSize      : %d (0x%x)\n\r", 
				      xBlockToMerge->xBlockSize, xBlockToMerge->xBlockSize);
#ifdef DEBUG_HEAP_EXTRA
				ATRACE("xActualBlockSize: %d\n\r", 
				      xBlockToMerge->xActualBlockSize);
#endif /* DEBUG_HEAP_EXTRA */
				ATRACE("Panic\n\r");
				while(1) {}
			}
#endif /* DEBUG_HEAP */
			ASSERT( pxIterator->pxNextFreeBlock == xBlockToMerge );
			
			//TRACE("Merge: F\n\r");
			/* Delete node from Free list */
			pxIterator->pxNextFreeBlock = xBlockToMerge->pxNextFreeBlock;
			
			/* Delete xBlockToMerge node from Serial List */
			if( ! IS_LAST_BLOCK( xBlockToMerge ) )
				NEXT_BLOCK( xBlockToMerge )->pxPrev = pxBlockToInsert;

			/* Update node size */
			pxBlockToInsert->xBlockSize += BLOCK_SIZE( xBlockToMerge );
			/* Now forget about xBlockToMerge */
		}
	}

	/* Check for back merge */
	if ( ! IS_FIRST_BLOCK(pxBlockToInsert) ) {
		if ( IS_FREE_BLOCK( PREV_BLOCK(pxBlockToInsert ))) {

			xBlockToMerge = PREV_BLOCK(pxBlockToInsert);

			/* Find out xBlockToMerge's location on the free list  */
			for( pxIterator = &xStart; 
			     pxIterator->pxNextFreeBlock != xBlockToMerge &&
				     pxIterator->pxNextFreeBlock != NULL;
			     pxIterator = pxIterator->pxNextFreeBlock ) {}
			
			ASSERT( pxIterator->pxNextFreeBlock == xBlockToMerge );
			//TRACE("Merge: R\n\r");
			/* Delete xBlockToMerge node from Free list */
			pxIterator->pxNextFreeBlock = xBlockToMerge->pxNextFreeBlock;
				
			/* Delete _ pxBlockToInsert _ node from Serial List */
			if( ! IS_LAST_BLOCK( pxBlockToInsert ) )
				NEXT_BLOCK( pxBlockToInsert )->pxPrev = xBlockToMerge;

			/* Update node size */
			xBlockToMerge->xBlockSize += BLOCK_SIZE( pxBlockToInsert );
				
			/* Now forget about pxBlockToInsert */
			pxBlockToInsert = xBlockToMerge;
		}
	}       

	xBlockSize = pxBlockToInsert->xBlockSize;

	
	
	/* Iterate through the list until a block is found that has a larger size */
	/* than the block we are inserting. */
	for( pxIterator = &xStart; pxIterator->pxNextFreeBlock->xBlockSize < xBlockSize;
	     pxIterator = pxIterator->pxNextFreeBlock )
	{
		/* There is nothing to do here - just iterate to the correct position. */
	}

	/* Update the list to include the block being inserted in the correct */
	/* position. */
	pxBlockToInsert->pxNextFreeBlock = pxIterator->pxNextFreeBlock;
	pxIterator->pxNextFreeBlock = pxBlockToInsert;
}
示例#9
0
/*
 * mm_free - Coalesce with surrounding blocks, and put it to Red-black tree
 */
void mm_free(void *ptr)
{
    size_t size, new_size;
    void *prev, *cur, *next, *new_block;

    cur = ptr - HEADER_SIZE;

    /* double free */
    if(CUR_FREE(cur)){
        printf("try to free a freed memory block(%p) is detected.\n", cur);
        return ;
    }

    new_block = cur;
    new_size = CUR_SIZE_MASKED(cur);

    /* coalesce with the previous block if free */
    if(PREV_FREE(cur)){
        size = PREV_SIZE_MASKED(cur);
        prev = PREV_BLOCK(cur, size);
        if(IS_IN_RB(prev)){
            rb_delete(prev);
        }
        new_block = prev;
        new_size += size;
    }

    /* coalesce with the next block if exists and free */
    size = CUR_SIZE_MASKED(cur);
    next = NEXT_BLOCK(cur, size);
    if(next + 4 <= mem_heap_hi() && CUR_FREE(next)){
        size = CUR_SIZE_MASKED(next);
        if(IS_IN_RB(next)){
            rb_delete(next);
        }
        new_size += size;
    }

    /* new free block setting */
    CUR_SIZE(new_block) = PREV_SIZE(NEXT_BLOCK(new_block, new_size)) = new_size | 1;
    if(IS_IN_RB(new_block)){
        rb_insert(new_block);
    }
    
#ifdef DEBUG
    printf("mm_free(%p) called\n", ptr);
    printf("new_block = %p\n", new_block);
    rb_print_preorder();
    printf("\n");
#endif /* DEBUG */

#ifdef CHECK
    if(!mm_check()){
        rb_print_preorder();
        exit(0);
    }
#endif /* CHECK */

    /* DON't MODIFY THIS STAGE AND LEAVE IT AS IT WAS */
    if (gl_ranges)
        remove_range(gl_ranges, ptr);
}
示例#10
0
void coalescingAndFree(void* block) 
{
	struct blockHeader *header = INIT_STRUCT(blockHeader, block);
	uint32_t size = GET_SIZE(header->attribute); // in words
	uint32_t flag = GET_FLAG(header->attribute);

	NEIGHBOUR_BLOCKS state = NEIGHBOUR_BLOCKS_NOT_FREE; 

	struct freeBlockLinks *successorBlockLinks = NULL; // update only if necessary

	// Initialise addr and size for no change. 
	void* newAddr = block; 
	uint32_t newSize = size;
	uint64_t sizeOffset;
	// Is precedent block free? 
	if (flag == MSB_TO_ONE) {
		state = NEIGHBOUR_BLOCKS_PRECEDENT_FREE;
		// In this case it's just about updating the size of the prev free block 
		// and removing the successive one if free.
		void* footer = ADDRESS_MINUS_OFFSET(block, freeBlockFooter);
		struct freeBlockFooter *prevBlockFooter = INIT_STRUCT(freeBlockFooter, footer);
		sizeOffset = WORDS_TO_BYTES(prevBlockFooter->size); // Footer has no flag.
		newAddr = block - sizeOffset - sizeof(blockHeader);
		newSize = prevBlockFooter->size + BYTES_TO_WORDS(sizeof(blockHeader)) + size;
	}

	// Is successive block free? 
	sizeOffset = WORDS_TO_BYTES(size);
	void* nextBlock = ADDRESS_PLUS_OFFSET(block + sizeOffset, blockHeader);
	struct blockHeader *nextHeader = INIT_STRUCT(blockHeader, nextBlock);
	if (nextHeader->attribute != MSB_TO_ZERO) { // check if next block is mmap footer or not.
		uint32_t nextSize = GET_SIZE(nextHeader->attribute);
		sizeOffset = WORDS_TO_BYTES(nextSize);
		void* nextNextBlock =  ADDRESS_PLUS_OFFSET(nextBlock + sizeOffset, blockHeader);

		struct blockHeader *nextNextHeader = INIT_STRUCT(blockHeader, nextNextBlock);
		if (nextNextHeader->attribute != MSB_TO_ZERO) {
			flag = GET_FLAG(nextNextHeader->attribute);
			if (flag == MSB_TO_ONE) {
				if (!state) {
					state = NEIGHBOUR_BLOCKS_SUCCESSIVE_FREE;
					// Do not change address, but Increase size
					newSize = size + BYTES_TO_WORDS(sizeof(blockHeader)) + nextSize;
				} else {
					state = NEIGHBOUR_BLOCKS_BOTH_FREE;
					newSize = newSize + BYTES_TO_WORDS(sizeof(blockHeader)) + nextSize;
				}
				successorBlockLinks = nextBlock + sizeof(blockHeader);
				// IF NO PREV block is free:
				// Just update the pointers of the prev and next blocks 
				// relative to this block AND the size.
			}
		}
	} // Otherwise it's next block is the mmap footer.

	switch(state)
	{
		case NEIGHBOUR_BLOCKS_NOT_FREE: 
		{
			void *currentBlock = freeList;
			struct freeBlockLinks *currentBlockLinks = ADDRESS_PLUS_OFFSET(currentBlock, blockHeader);

			void* prevBlock = PREV_BLOCK(currentBlockLinks);
			initialiseFreeBlock(newAddr, newSize, 
				prevBlock, currentBlock, false, false);

			// Tell next block that its previous one is NOW free.
			sizeOffset = WORDS_TO_BYTES(size);
			updateNextBlockOnCoalescing(newAddr, sizeOffset);

			insertFreeBlock(newAddr, currentBlockLinks);
			numberFreeBlocks++;
			break;
		}
		case NEIGHBOUR_BLOCKS_PRECEDENT_FREE: 
		{
			coalesceWithPrevBlock(newAddr, newSize);
			break;
		}
		case NEIGHBOUR_BLOCKS_SUCCESSIVE_FREE: 
		{
			coalesceWithNextBlock(newAddr, newSize, successorBlockLinks);
			break;
		}
		case NEIGHBOUR_BLOCKS_BOTH_FREE: 
		{
			coalesceWithNeighbours(newAddr, newSize, successorBlockLinks);
			break;
		}
		default:
		{
			fprintf(stderr, "memoryManagement.coalescingAndFree - NEIGHBOUR_BLOCKS state unknown\n");
			exit(-1);
		}
	} // end switch

	// Update total free space
	// When state == 0, the totalFreeSpace is updated when the block is initialised.
	totalFreeSpace += WORDS_TO_BYTES(size); // Stats
	if (state != NEIGHBOUR_BLOCKS_NOT_FREE)
		totalFreeSpace += sizeof(blockHeader); 
	
	// Largest free region
	if (newSize > largestFreeBlock)
		largestFreeBlock = newSize;

	freeList = newAddr;
}