/* 
 * 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);
}
Beispiel #3
0
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);
}
Beispiel #5
0
/*
 * 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");
}
Beispiel #6
0
/**
 * 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);
}
Beispiel #8
0
/*
 * 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");

}
Beispiel #9
0
/*
 * 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);
}
Beispiel #10
0
/*
 * 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");
}
Beispiel #11
0
/*
 * 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;
}
Beispiel #12
0
/*
 * 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)));
	}
}
Beispiel #13
0
/*
 * 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);
}
Beispiel #14
0
/*
 * 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));
}
Beispiel #19
0
/*
 * 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));
    }
}
Beispiel #23
0
/*
 * 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));
	}
}
Beispiel #24
0
/* 
 * 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));
	}
}
Beispiel #25
0
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'));
}