#include<stdio.h>#include<string.h>#include<stdlib.h>#include"mm.h"#include"memlib.h"/* $begin mallocmacros *//* Basic constants and macros */#define WSIZE 4 /* Word and header/footer size (bytes) *///line:vm:mm:beginconst#define DSIZE 8 /* Double word size (bytes) */#define CHUNKSIZE (1<<12) /* Extend heap by this amount (bytes) *///line:vm:mm:endconst#define MAX(x, y) ((x) > (y)? (x) : (y))/* Pack a size and allocated bit into a word */#define PACK(size, alloc) ((size) | (alloc)) //line:vm:mm:pack/* Read and write a word at address p */#define GET(p) (*(unsigned int *)(p)) //line:vm:mm:get#define PUT(p, val) (*(unsigned int *)(p) = (val)) //line:vm:mm:put/* Read the size and allocated fields from address p */#define GET_SIZE(p) (GET(p) & ~0x7) //line:vm:mm:getsize#define GET_ALLOC(p) (GET(p) & 0x1) //line:vm:mm:getalloc/* Given block ptr bp, compute address of its header and footer */#define HDRP(bp) ((char *)(bp) - WSIZE) //line:vm:mm:hdrp#define FTRP(bp) ((char *)(bp) + GET_SIZE(HDRP(bp)) - DSIZE) //line:vm:mm:ftrp/* Given block ptr bp, compute address of next and previous blocks */#define NEXT_BLKP(bp) ((char *)(bp) + GET_SIZE(((char *)(bp) - WSIZE))) //line:vm:mm:nextblkp#define PREV_BLKP(bp) ((char *)(bp) - GET_SIZE(((char *)(bp) - DSIZE))) //line:vm:mm:prevblkp/* $end mallocmacros *//* Global variables */staticchar*heap_listp =0;/* Pointer to first block */staticchar*rover;/* Next fit rover *//* Function prototypes for internal helper routines */staticvoid*extend_heap(size_t words);staticvoidplace(void*bp, size_t asize);staticvoid*find_fit(size_t asize);staticvoid*coalesce(void*bp);staticvoidprintblock(void*bp);staticvoidcheckheap(int verbose);staticvoidcheckblock(void*bp);/*
* mm_init - Initialize the memory manager
*//* $begin mminit */intmm_init(void){mem_init();/* Create the initial empty heap */if((heap_listp =mem_sbrk(4*WSIZE))==(void*)-1)//line:vm:mm:begininitreturn-1;PUT(heap_listp,0);/* Alignment padding */PUT(heap_listp +(1*WSIZE),PACK(DSIZE,1));/* Prologue header */PUT(heap_listp +(2*WSIZE),PACK(DSIZE,1));/* Prologue footer */PUT(heap_listp +(3*WSIZE),PACK(0,1));/* Epilogue header */
heap_listp +=(2*WSIZE);//line:vm:mm:endinit/* $end mminit */
rover = heap_listp;/* $begin mminit *
/* Extend the empty heap with a free block of CHUNKSIZE bytes */if(extend_heap(CHUNKSIZE/WSIZE)==NULL)return-1;return0;}/* $end mminit *//*
* mm_malloc - Allocate a block with at least size bytes of payload
*//* $begin mmmalloc */void*mm_malloc(size_t size){
size_t asize;/* Adjusted block size */
size_t extendsize;/* Amount to extend heap if no fit */char*bp;/* $end mmmalloc */if(heap_listp ==0){mm_init();}/* $begin mmmalloc *//* Ignore spurious requests */if(size ==0)returnNULL;/* Adjust block size to include overhead and alignment reqs. */if(size <= DSIZE)//line:vm:mm:sizeadjust1
asize =2*DSIZE;//line:vm:mm:sizeadjust2else
asize = DSIZE *((size +(DSIZE)+(DSIZE-1))/ DSIZE);//line:vm:mm:sizeadjust3/* Search the free list for a fit */if((bp =find_fit(asize))!=NULL){//line:vm:mm:findfitcallplace(bp, asize);//line:vm:mm:findfitplacereturn bp;}/* No fit found. Get more memory and place the block */
extendsize =MAX(asize,CHUNKSIZE);//line:vm:mm:growheap1if((bp =extend_heap(extendsize/WSIZE))==NULL)returnNULL;//line:vm:mm:growheap2place(bp, asize);//line:vm:mm:growheap3return bp;}/* $end mmmalloc *//*
* mm_free - Free a block
*//* $begin mmfree */voidmm_free(void*bp){/* $end mmfree */if(bp ==0)return;/* $begin mmfree */
size_t size =GET_SIZE(HDRP(bp));/* $end mmfree */if(heap_listp ==0){mm_init();}/* $begin mmfree */PUT(HDRP(bp),PACK(size,0));PUT(FTRP(bp),PACK(size,0));coalesce(bp);}/* $end mmfree *//*
* coalesce - Boundary tag coalescing. Return ptr to coalesced block
*//* $begin mmfree */staticvoid*coalesce(void*bp){
size_t prev_alloc =GET_ALLOC(FTRP(PREV_BLKP(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 */return bp;}elseif(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));}elseif(!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));
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,0));PUT(FTRP(NEXT_BLKP(bp)),PACK(size,0));
bp =PREV_BLKP(bp);}/* $end mmfree *//* Make sure the rover isn't pointing into the free block *//* that we just coalesced */if((rover >(char*)bp)&&(rover <NEXT_BLKP(bp)))
rover = bp;/* $begin mmfree */return bp;}/* $end mmfree *//*
* mm_realloc - Naive implementation of realloc
*/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);return0;}/* If oldptr is NULL, then this is just malloc. */if(ptr ==NULL){returnmm_malloc(size);}
newptr =mm_malloc(size);/* If realloc() fails the original block is left untouched */if(!newptr){return0;}/* Copy the old data. */
oldsize =GET_SIZE(HDRP(ptr));if(size < oldsize) oldsize = size;memcpy(newptr, ptr, oldsize);/* Free the old block. */mm_free(ptr);return newptr;}/*
* mm_checkheap - Check the heap for correctness
*/voidmm_checkheap(int verbose){checkheap(verbose);}/*
* The remaining routines are internal helper routines
*//*
* extend_heap - Extend heap with free block and return its block pointer
*//* $begin mmextendheap */staticvoid*extend_heap(size_t words){char*bp;
size_t size;/* Allocate an even number of words to maintain alignment */
size =(words %2)?(words+1)* WSIZE : words * WSIZE;//line:vm:mm:beginextendif((long)(bp =mem_sbrk(size))==-1)returnNULL;//line:vm:mm:endextend/* Initialize free block header/footer and the epilogue header */PUT(HDRP(bp),PACK(size,0));/* Free block header *///line:vm:mm:freeblockhdrPUT(FTRP(bp),PACK(size,0));/* Free block footer *///line:vm:mm:freeblockftrPUT(HDRP(NEXT_BLKP(bp)),PACK(0,1));/* New epilogue header *///line:vm:mm:newepihdr/* Coalesce if the previous block was free */returncoalesce(bp);//line:vm:mm:returnblock}/* $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 */staticvoidplace(void*bp, size_t asize)/* $end mmplace-proto */{
size_t csize =GET_SIZE(HDRP(bp));if((csize - asize)>=(2*DSIZE)){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 */staticvoid*find_fit(size_t asize)/* $end mmfirstfit-proto */{/* $end mmfirstfit *//* Next fit search */char*oldrover = rover;/* Search from the rover to the end of list */for(;GET_SIZE(HDRP(rover))>0; rover =NEXT_BLKP(rover))if(!GET_ALLOC(HDRP(rover))&&(asize <=GET_SIZE(HDRP(rover))))return rover;/* search from start of list to old rover */for(rover = heap_listp; rover < oldrover; rover =NEXT_BLKP(rover))if(!GET_ALLOC(HDRP(rover))&&(asize <=GET_SIZE(HDRP(rover))))return rover;returnNULL;/* no fit found */}/* $end mmfirstfit */staticvoidprintblock(void*bp){
size_t hsize, halloc, fsize, falloc;checkheap(0);
hsize =GET_SIZE(HDRP(bp));
halloc =GET_ALLOC(HDRP(bp));
fsize =GET_SIZE(FTRP(bp));
falloc =GET_ALLOC(FTRP(bp));if(hsize ==0){printf("%p: EOL\n", bp);return;}printf("%p: header: [%ld:%c] footer: [%ld:%c]\n", bp,
hsize,(halloc ?'a':'f'),
fsize,(falloc ?'a':'f'));}staticvoidcheckblock(void*bp){if((size_t)bp %8)printf("Error: %p is not doubleword aligned\n", bp);if(GET(HDRP(bp))!=GET(FTRP(bp)))printf("Error: header does not match footer\n");}/*
* checkheap - Minimal check of the heap for consistency
*/voidcheckheap(int verbose){char*bp = heap_listp;if(verbose)printf("Heap (%p):\n", heap_listp);if((GET_SIZE(HDRP(heap_listp))!= DSIZE)||!GET_ALLOC(HDRP(heap_listp)))printf("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))))printf("Bad epilogue header\n");}
P18
#include<stdio.h>#include<string.h>#include<stdlib.h>#include"mm.h"#include"memlib.h"/* $begin mallocmacros *//* Basic constants and macros */#define WSIZE 4 /* Word and header/footer size (bytes) *///line:vm:mm:beginconst#define DSIZE 8 /* Double word size (bytes) */#define CHUNKSIZE (1<<12) /* Extend heap by this amount (bytes) *///line:vm:mm:endconst#define MAX(x, y) ((x) > (y)? (x) : (y))/* Pack a size and allocated bit into a word */#define PACK(size, alloc, prev_alloc) ((size) | (alloc) | (prev_alloc << 1)) //line:vm:mm:pack/* Read and write a word at address p */#define GET(p) (*(unsigned int *)(p)) //line:vm:mm:get#define PUT(p, val) (*(unsigned int *)(p) = (val)) //line:vm:mm:put/* Read the size and allocated fields from address p */#define GET_SIZE(p) (GET(p) & ~0x7) //line:vm:mm:getsize#define GET_ALLOC(p) (GET(p) & 0x1) //line:vm:mm:getalloc#define GET_PREV_ALLOC(p) ((GET(p) >> 1) & 0x1)/* Given block ptr bp, compute address of its header and footer */#define HDRP(bp) ((char *)(bp) - WSIZE) //line:vm:mm:hdrp#define FTRP(bp) ((char *)(bp) + GET_SIZE(HDRP(bp)) - DSIZE) //line:vm:mm:ftrp/* Given block ptr bp, compute address of next and previous blocks */#define NEXT_BLKP(bp) ((char *)(bp) + GET_SIZE(((char *)(bp) - WSIZE))) //line:vm:mm:nextblkp#define PREV_BLKP(bp) ((char *)(bp) - GET_SIZE(((char *)(bp) - DSIZE))) //line:vm:mm:prevblkp/* $end mallocmacros *//* Global variables */staticchar*heap_listp =0;/* Pointer to first block *//* Function prototypes for internal helper routines */staticvoid*extend_heap(size_t words);staticvoidplace(void*bp, size_t asize);staticvoid*find_fit(size_t asize);staticvoid*coalesce(void*bp);staticvoidprintblock(void*bp);staticvoidcheckheap(int verbose);staticvoidcheckblock(void*bp);/*
* mm_init - Initialize the memory manager
*//* $begin mminit */intmm_init(void){mem_init();/* Create the initial empty heap */if((heap_listp =mem_sbrk(4*WSIZE))==(void*)-1)//line:vm:mm:begininitreturn-1;PUT(heap_listp,0);/* Alignment padding */PUT(heap_listp +(1*WSIZE),PACK(DSIZE,1,1));/* Prologue header */PUT(heap_listp +(2*WSIZE),PACK(DSIZE,1,1));/* Prologue footer */PUT(heap_listp +(3*WSIZE),PACK(0,1,1));/* Epilogue header */
heap_listp +=(2*WSIZE);//line:vm:mm:endinit/* $end mminit *//* $begin mminit *//* Extend the empty heap with a free block of CHUNKSIZE bytes */if(extend_heap(CHUNKSIZE/WSIZE)==NULL)return-1;return0;}/* $end mminit *//*
* mm_malloc - Allocate a block with at least size bytes of payload
*//* $begin mmmalloc */void*mm_malloc(size_t size){
size_t asize;/* Adjusted block size */
size_t extendsize;/* Amount to extend heap if no fit */char*bp;/* $end mmmalloc */if(heap_listp ==0){mm_init();}/* $begin mmmalloc *//* Ignore spurious requests */if(size ==0)returnNULL;/* Adjust block size to include overhead and alignment reqs. */if(size <= WSIZE)
asize = DSIZE;else
asize = DSIZE *((size +(WSIZE)+(DSIZE-1))/ DSIZE);//line:vm:mm:sizeadjust3/* Search the free list for a fit */if((bp =find_fit(asize))!=NULL){//line:vm:mm:findfitcallplace(bp, asize);//line:vm:mm:findfitplacereturn bp;}/* No fit found. Get more memory and place the block */
extendsize =MAX(asize,CHUNKSIZE);//line:vm:mm:growheap1if((bp =extend_heap(extendsize/WSIZE))==NULL)returnNULL;//line:vm:mm:growheap2place(bp, asize);//line:vm:mm:growheap3return bp;}/* $end mmmalloc *//*
* mm_free - Free a block
*//* $begin mmfree */voidmm_free(void*bp){/* $end mmfree */if(bp ==0)return;/* $begin mmfree */
size_t size =GET_SIZE(HDRP(bp));/* $end mmfree */if(heap_listp ==0){mm_init();}/* $begin mmfree */PUT(HDRP(bp),PACK(size,0,GET_PREV_ALLOC(HDRP(bp))));PUT(FTRP(bp),PACK(size,0,GET_PREV_ALLOC(HDRP(bp))));if(GET_ALLOC(HDRP(NEXT_BLKP(bp))))PUT(HDRP(NEXT_BLKP(bp)),PACK(GET_SIZE(HDRP(NEXT_BLKP(bp))),1,0));else{PUT(HDRP(NEXT_BLKP(bp)),PACK(GET_SIZE(HDRP(NEXT_BLKP(bp))),0,0));PUT(FTRP(NEXT_BLKP(bp)),PACK(GET_SIZE(HDRP(NEXT_BLKP(bp))),0,0));}coalesce(bp);}/* $end mmfree *//*
* coalesce - Boundary tag coalescing. Return ptr to coalesced block
*//* $begin mmfree */staticvoid*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 */return bp;}elseif(prev_alloc &&!next_alloc){/* Case 2 */
size +=GET_SIZE(HDRP(NEXT_BLKP(bp)));PUT(HDRP(bp),PACK(size,0,1));PUT(FTRP(bp),PACK(size,0,1));}elseif(!prev_alloc && next_alloc){/* Case 3 */
size +=GET_SIZE(HDRP(PREV_BLKP(bp)));PUT(FTRP(bp),PACK(size,0,1));PUT(HDRP(PREV_BLKP(bp)),PACK(size,0,1));
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,0,1));PUT(FTRP(NEXT_BLKP(bp)),PACK(size,0,1));
bp =PREV_BLKP(bp);}/* $end mmfree *//* $begin mmfree */return bp;}/* $end mmfree *//*
* mm_realloc - Naive implementation of realloc
*/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);return0;}/* If oldptr is NULL, then this is just malloc. */if(ptr ==NULL){returnmm_malloc(size);}
newptr =mm_malloc(size);/* If realloc() fails the original block is left untouched */if(!newptr){return0;}/* Copy the old data. */
oldsize =GET_SIZE(HDRP(ptr));if(size < oldsize) oldsize = size;memcpy(newptr, ptr, oldsize);/* Free the old block. */mm_free(ptr);return newptr;}/*
* mm_checkheap - Check the heap for correctness
*/voidmm_checkheap(int verbose){checkheap(verbose);}/*
* The remaining routines are internal helper routines
*//*
* extend_heap - Extend heap with free block and return its block pointer
*//* $begin mmextendheap */staticvoid*extend_heap(size_t words){char*bp;
size_t size;/* Allocate an even number of words to maintain alignment */
size =(words %2)?(words+1)* WSIZE : words * WSIZE;//line:vm:mm:beginextendif((long)(bp =mem_sbrk(size))==-1)returnNULL;//line:vm:mm:endextend/* Initialize free block header/footer and the epilogue header */PUT(HDRP(bp),PACK(size,0,GET_PREV_ALLOC(HDRP(bp))));/* Free block header *///line:vm:mm:freeblockhdrPUT(FTRP(bp),PACK(size,0,GET_PREV_ALLOC(HDRP(bp))));/* Free block footer *///line:vm:mm:freeblockftrPUT(HDRP(NEXT_BLKP(bp)),PACK(0,1,0));/* New epilogue header *///line:vm:mm:newepihdr/* Coalesce if the previous block was free */returncoalesce(bp);//line:vm:mm:returnblock}/* $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 */staticvoidplace(void*bp, size_t asize)/* $end mmplace-proto */{
size_t csize =GET_SIZE(HDRP(bp));if((csize - asize)>=(2*DSIZE)){PUT(HDRP(bp),PACK(asize,1,1));
bp =NEXT_BLKP(bp);PUT(HDRP(bp),PACK(csize-asize,0,1));PUT(FTRP(bp),PACK(csize-asize,0,1));}else{PUT(HDRP(bp),PACK(csize,1,1));PUT(HDRP(NEXT_BLKP(bp)),PACK(csize,1,1));}}/* $end mmplace *//*
* find_fit - Find a fit for a block with asize bytes
*//* $begin mmfirstfit *//* $begin mmfirstfit-proto */staticvoid*find_fit(size_t asize)/* $end mmfirstfit-proto */{/* $end mmfirstfit *//* $begin mmfirstfit *//* First-fit search */void*bp;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;}}returnNULL;/* No fit */}/* $end mmfirstfit */staticvoidprintblock(void*bp){
size_t hsize, halloc, fsize, falloc;checkheap(0);
hsize =GET_SIZE(HDRP(bp));
halloc =GET_ALLOC(HDRP(bp));
fsize =GET_SIZE(FTRP(bp));
falloc =GET_ALLOC(FTRP(bp));if(hsize ==0){printf("%p: EOL\n", bp);return;}printf("%p: header: [%ld:%c] footer: [%ld:%c]\n", bp,
hsize,(halloc ?'a':'f'),
fsize,(falloc ?'a':'f'));}staticvoidcheckblock(void*bp){if((size_t)bp %8)printf("Error: %p is not doubleword aligned\n", bp);if(GET(HDRP(bp))!=GET(FTRP(bp)))printf("Error: header does not match footer\n");}/*
* checkheap - Minimal check of the heap for consistency
*/voidcheckheap(int verbose){char*bp = heap_listp;if(verbose)printf("Heap (%p):\n", heap_listp);if((GET_SIZE(HDRP(heap_listp))!= DSIZE)||!GET_ALLOC(HDRP(heap_listp)))printf("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))))printf("Bad epilogue header\n");}