📄 mm_malloc.c
字号:
/* * Simple allocator based on implicit free lists with boundary * tag coalescing. Each block has header and footer of the form: * * 31 3 2 1 0 * ----------------------------------- * | s s s s ... s s s 0 0 a/f * ----------------------------------- * * where s are the meaningful size bits and a/f is set * iff the block is allocated. The list has the following form: * * begin end * heap heap * ----------------------------------------------------------------- * | pad | hdr(8:a) | ftr(8:a) | zero or more usr blks | hdr(8:a) | * ----------------------------------------------------------------- * | prologue | | epilogue | * | block | | block | * * The allocated prologue and epilogue blocks are overhead that * eliminate edge conditions during coalescing. */#include "mm_malloc.h"#include <memlib.h>#include <string.h>#include <stdio.h>/* The only global variable is a pointer to the first block */static char *heap_listp; /* function prototypes for internal helper routines */static void *extend_heap(int words);static void place(void *bp, int asize);static void *find_fit(int asize);static void *coalesce(void *bp);static void printblock(void *bp); static void checkblock(void *bp);/* inline helper function */static inline unsigned intmin( unsigned int x, unsigned int y ){ return ( x < y ? x : y );}/* * mm_init - Initialize the memory manager *//* $begin mminit */int mm_init(void) { /* create the initial empty heap */ mem_init(0xffffffff); if ((int)(heap_listp = mem_sbrk(4*WSIZE)) < 0) return -1; PUT(heap_listp, 0); /* alignment padding */ PUT(heap_listp+WSIZE, PACK(OVERHEAD, 1)); /* prologue header */ PUT(heap_listp+DSIZE, PACK(OVERHEAD, 1)); /* prologue footer */ PUT(heap_listp+WSIZE+DSIZE, PACK(0, 1)); /* epilogue header */ heap_listp += DSIZE; /* Extend the empty heap with a free block of CHUNKSIZE bytes */ if (extend_heap(CHUNKSIZE/WSIZE) == NULL) return -1; return 0;}/* $end mminit *//* * mm_malloc - Allocate a block with at least size bytes of payload *//* $begin mmmalloc */void *mm_malloc(int size) { int asize; /* adjusted block size */ int extendsize; /* amount to extend heap if no fit */ char *bp; /* Ignore spurious requests */ if (size <= 0) { return NULL; } /* Adjust block size to include overhead and alignment reqs. */ if (size <= DSIZE) asize = DSIZE + OVERHEAD; else asize = DSIZE * ((size + (OVERHEAD) + (DSIZE-1)) / DSIZE); /* Search the free list for a fit */ if ((bp = find_fit(asize)) != NULL) { place(bp, asize); return bp; } /* No fit found. Get more memory and place the block */ extendsize = MAX(asize,CHUNKSIZE); if ((bp = extend_heap(extendsize/WSIZE)) == NULL) { return NULL; } place(bp, asize); return bp;} /* $end mmmalloc *//* * mm_free - Free a block *//* $begin mmfree */void mm_free(void *bp){ int size; size = GET_SIZE(HDRP(bp)); PUT(HDRP(bp), PACK(size, 0)); PUT(FTRP(bp), PACK(size, 0)); coalesce(bp);}/* $end mmfree *//* Not implemented. For consistency with 15-213 malloc driver */void *mm_realloc(void *ptr, int size){ unsigned int old_size; unsigned int *new_chunk; new_chunk = mm_malloc( size ); if( !new_chunk ) { return NULL; } if( ptr ) { old_size = GET_SIZE( HDRP(ptr) ); memcpy( new_chunk, ptr, min( old_size, size ) ); mm_free( ptr ); } return new_chunk;}/* * mm_checkheap - Check the heap for consistency */void mm_checkheap(int verbose) { char *bp = heap_listp; if (verbose) lprintf("Heap (0x%x):\n", heap_listp); if ((GET_SIZE(HDRP(heap_listp)) != DSIZE) || !GET_ALLOC(HDRP(heap_listp))) lprintf("Bad prologue header\n"); checkblock(heap_listp); for (bp = heap_listp; GET_SIZE(HDRP(bp)) > 0; bp = NEXT_BLKP(bp)) { if (verbose) printblock(bp); checkblock(bp); } if (verbose) printblock(bp); if ((GET_SIZE(HDRP(bp)) != 0) || !(GET_ALLOC(HDRP(bp)))) lprintf("Bad epilogue header\n");}/* The remaining routines are internal helper routines *//* * extend_heap - Extend heap with free block and return its block pointer *//* $begin mmextendheap */static void *extend_heap(int words) { char *bp; int size; /* Allocate an even number of words to maintain alignment */ size = (words % 2) ? (words+1) * WSIZE : words * WSIZE; if ((int)(bp = mem_sbrk(size)) < 0) return NULL; /* 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 */ /* Coalesce if the previous block was free */ return coalesce(bp);}/* $end mmextendheap *//* * place - Place block of asize bytes at start of free block bp * and split if remainder would be at least minimum block size *//* $begin mmplace *//* $begin mmplace-proto */static void place(void *bp, int asize)/* $end mmplace-proto */{ int csize = GET_SIZE(HDRP(bp)); if ((csize - asize) >= (DSIZE + OVERHEAD)) { PUT(HDRP(bp), PACK(asize, 1)); PUT(FTRP(bp), PACK(asize, 1)); bp = NEXT_BLKP(bp); PUT(HDRP(bp), PACK(csize-asize, 0)); PUT(FTRP(bp), PACK(csize-asize, 0)); } else { PUT(HDRP(bp), PACK(csize, 1)); PUT(FTRP(bp), PACK(csize, 1)); }}/* $end mmplace *//* * find_fit - Find a fit for a block with asize bytes *//* $begin mmfirstfit *//* $begin mmfirstfit-proto */static void *find_fit(int asize)/* $end mmfirstfit-proto */{ void *bp; /* first fit search */ for (bp = heap_listp; GET_SIZE(HDRP(bp)) > 0; bp = NEXT_BLKP(bp)) { if (!GET_ALLOC(HDRP(bp)) && (asize <= GET_SIZE(HDRP(bp)))) { return bp; } } return NULL; /* no fit */}/* $end mmfirstfit *//* * coalesce - boundary tag coalescing. Return ptr to coalesced block *//* $begin mmfree */static void *coalesce(void *bp) { int prev_alloc = GET_ALLOC(FTRP(PREV_BLKP(bp))); int next_alloc = GET_ALLOC(HDRP(NEXT_BLKP(bp))); int 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, 0)); PUT(FTRP(bp), PACK(size,0)); return(bp); } else if (!prev_alloc && next_alloc) { /* Case 3 */ size += GET_SIZE(HDRP(PREV_BLKP(bp))); PUT(FTRP(bp), PACK(size, 0)); PUT(HDRP(PREV_BLKP(bp)), PACK(size, 0)); return(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, 0)); PUT(FTRP(NEXT_BLKP(bp)), PACK(size, 0)); return(PREV_BLKP(bp)); }}/* $end mmfree */void printblock(void *bp) { int hsize, halloc, fsize, falloc; hsize = GET_SIZE(HDRP(bp)); halloc = GET_ALLOC(HDRP(bp)); fsize = GET_SIZE(FTRP(bp)); falloc = GET_ALLOC(FTRP(bp)); if (hsize == 0) { lprintf("0x%x: EOL\n", bp); return; } lprintf("0x%x: header: [%d:%c] footer: [%d:%c]\n", bp, hsize, (halloc ? 'a' : 'f'), fsize, (falloc ? 'a' : 'f')); }static void checkblock(void *bp) { if ((int)bp % 8) lprintf("Error: %p is not doubleword aligned\n", bp); if (GET(HDRP(bp)) != GET(FTRP(bp))) lprintf("Error: header does not match footer\n");}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -