/* * mm-naive.c - The fastest, least memory-efficient malloc package. * * In this naive approach, a block is allocated by simply incrementing * the brk pointer. A block is pure payload. There are no headers or * footers. Blocks are never coalesced or reused. Realloc is * implemented directly using mm_malloc and mm_free. * * NOTE TO STUDENTS: Replace this header comment with your own header * comment that gives a high level description of your solution. */ #include #include #include #include #include #include "mm.h" #include "memlib.h" /********************************************************* * NOTE TO STUDENTS: Before you do anything else, please * provide your team information in the following struct. ********************************************************/ team_t team = { /* Team name */ "anna.schlittenhardt@stud.uni-due.de+tuan-dat.tran@stud.uni-due.de", /* First member's full name */ "Anna Schlittenhardt", /* First member's email address */ "anna.schlittenhardt@stud.uni-due.de", /* Second member's full name (leave blank if none) */ "Tuan-Dat Tran", /* Second member's email address (leave blank if none) */ "tuan-dat.tran@stud.uni-due.de" }; //////////////////////////////////////////////////////////////////////////////// /////////////////////////////////// STRUCTURE ////////////////////////////////// //////////////////////////////////////////////////////////////////////////////// // Filled Blk // 31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0 // +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ // HEADER | SIZE | A| // +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ // BP-> | ALLOCED MEMORY | // +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ // FOOTER | SIZE | A| // +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ // // Empty Blk // 31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0 // +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ // HEADER | SIZE | A| // +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ // BP-> | PTR TO PREV FREE BLK | // +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ // | PTR TO NEXT FREE BLK | // +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ // | UNALLOC MEMORY | // +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ // FOOTER | SIZE | A| // +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ //////////////////////////////////////////////////////////////////////////////// //////////////////////////////////// DEFINES /////////////////////////////////// //////////////////////////////////////////////////////////////////////////////// /* single word (4) or double word (8) alignment */ #define ALIGNMENT 8 /* rounds up to the nearest multiple of ALIGNMENT */ #define ALIGN(size) (((size) + (ALIGNMENT-1)) & ~0x7) #define SIZE_T_SIZE (ALIGN(sizeof(size_t))) /* Page 830, Pearson R. Bryant – D. O’Hallaron. Computer Systems: A Programmer’s Perspective.3rd Edition, Pearson, 2003. */ /* Basic constants and macros */ #define WSIZE 4 /* Word and header/footer size (bytes) */ #define DSIZE 8 /* Double word size (bytes) */ #define CHUNKSIZE (1<<12) /* Extend heap by this amount (bytes) */ #define MAX(x, y) ((x) > (y)? (x) : (y)) #define MIN(x, y) ((x) < (y)? (x) : (y)) /* Pack a size and allocated bit into a word */ #define PACK(size, alloc) ((size) | (alloc)) /* Read and write a word at address p */ #define GET(p) (*(unsigned int *)(p)) #define PUT(p, val) (*(unsigned int *)(p) = (val)) /* Read the size and allocated fields from address p */ #define GET_SIZE(p) (GET(p) & ~0x7) #define GET_ALLOC(p) (GET(p) & 0x1) /* Given block ptr bp, compute address of its header and footer */ #define HDRP(bp) ((char *)(bp) - WSIZE) #define FTRP(bp) ((char *)(bp) + GET_SIZE(HDRP(bp)) - DSIZE) /* Given block ptr bp, compute address of next and previous blocks */ #define NEXT_BLKP(bp) ((char *)(bp) + GET_SIZE(((char *)(bp) - WSIZE))) #define PREV_BLKP(bp) ((char *)(bp) - GET_SIZE(((char *)(bp) - DSIZE))) #define PUT_PTR(p, ptr) (*(unsigned int *)(p) = (unsigned int)(ptr)) #define PRV_PTR(ptr) ((char *)(ptr)) #define NXT_PTR(ptr) ((char *)(ptr) + WSIZE) #define PRV_BLK(ptr) (*(char **)(ptr)) #define NXT_BLK(ptr) (*(char **)(NXT_PTR(ptr))) //////////////////////////////////////////////////////////////////////////////// ////////////////////////////////// GLOBAL VARS ///////////////////////////////// //////////////////////////////////////////////////////////////////////////////// #define LISTSIZE 20 static char* heap_listp; char* seg_list[LISTSIZE]; //////////////////////////////////////////////////////////////////////////////// ///////////////////////////////// HELPER PREDEF //////////////////////////////// //////////////////////////////////////////////////////////////////////////////// static void *extend_heap(size_t size); static void add_free(void *ptr, size_t size); static void remove_free(void *ptr); static void *coalesce(void *ptr); static void *place(void *ptr, size_t asize); //////////////////////////////////////////////////////////////////////////////// /////////////////////////////// HELPER FUNCTIONS /////////////////////////////// //////////////////////////////////////////////////////////////////////////////// static void *extend_heap(size_t size) { size_t asize; asize = ALIGN(size); void *ptr; if ((ptr = mem_sbrk(asize)) == (void *)-1) return NULL; /* Set Header and Footer*/ PUT(HDRP(ptr), PACK(asize, 0)); PUT(FTRP(ptr), PACK(asize, 0)); PUT(HDRP(NEXT_BLKP(ptr)), PACK(0, 1)); add_free(ptr, asize); return coalesce(ptr); } static void add_free(void *ptr, size_t size) { int list = 0; void *searching_ptr = ptr; void *in_ptr = NULL; while ((list < LISTSIZE - 1) && (size > 1)) { size >>= 1; list++; } searching_ptr = seg_list[list]; while ((searching_ptr != NULL) && (size > GET_SIZE(HDRP(searching_ptr)))) { in_ptr = searching_ptr; searching_ptr = PRV_BLK(searching_ptr); } if (searching_ptr != NULL && in_ptr != NULL) { PUT_PTR(NXT_PTR(searching_ptr), ptr); PUT_PTR(NXT_PTR(ptr), in_ptr); PUT_PTR(PRV_PTR(ptr), searching_ptr); PUT_PTR(PRV_PTR(in_ptr), ptr); } else if (searching_ptr != NULL && in_ptr == NULL) { PUT_PTR(PRV_PTR(ptr), searching_ptr); PUT_PTR(NXT_PTR(searching_ptr), ptr); PUT_PTR(NXT_PTR(ptr), NULL); seg_list[list] = ptr; } else if(searching_ptr == NULL && in_ptr != NULL) { PUT_PTR(NXT_PTR(ptr), in_ptr); PUT_PTR(PRV_PTR(ptr), NULL); PUT_PTR(PRV_PTR(in_ptr), ptr); } else { PUT_PTR(NXT_PTR(ptr), NULL); PUT_PTR(PRV_PTR(ptr), NULL); seg_list[list] = ptr; } return; } static void remove_free(void *ptr) { int list = 0; size_t size = GET_SIZE(HDRP(ptr)); while ((list < LISTSIZE - 1) && (size > 1)) { size >>= 1; list++; } if (PRV_BLK(ptr) != NULL && NXT_BLK(ptr) != NULL) { PUT_PTR(NXT_PTR(PRV_BLK(ptr)), NXT_BLK(ptr)); PUT_PTR(PRV_PTR(NXT_BLK(ptr)), PRV_BLK(ptr)); } else if(PRV_BLK(ptr) != NULL && NXT_BLK(ptr) == NULL) { PUT_PTR(NXT_PTR(PRV_BLK(ptr)), NULL); seg_list[list] = PRV_BLK(ptr); } else if(PRV_BLK(ptr) == NULL && NXT_BLK(ptr) != NULL) { PUT_PTR(PRV_PTR(NXT_BLK(ptr)), NULL); } else { seg_list[list] = NULL; } return; } static void *coalesce(void *ptr) { size_t prev_alloc = GET_ALLOC(HDRP(PREV_BLKP(ptr))); size_t next_alloc = GET_ALLOC(HDRP(NEXT_BLKP(ptr))); size_t size = GET_SIZE(HDRP(ptr)); if (prev_alloc && next_alloc) { // Case 1 return ptr; } else if (prev_alloc && !next_alloc) { // Case 2 remove_free(ptr); remove_free(NEXT_BLKP(ptr)); size += GET_SIZE(HDRP(NEXT_BLKP(ptr))); PUT(HDRP(ptr), PACK(size, 0)); PUT(FTRP(ptr), PACK(size, 0)); } else if (!prev_alloc && next_alloc) { // Case 3 remove_free(ptr); remove_free(PREV_BLKP(ptr)); size += GET_SIZE(HDRP(PREV_BLKP(ptr))); PUT(FTRP(ptr), PACK(size, 0)); PUT(HDRP(PREV_BLKP(ptr)), PACK(size, 0)); ptr = PREV_BLKP(ptr); } else { // Case 4 remove_free(ptr); remove_free(PREV_BLKP(ptr)); remove_free(NEXT_BLKP(ptr)); size += GET_SIZE(HDRP(PREV_BLKP(ptr))) + GET_SIZE(HDRP(NEXT_BLKP(ptr))); PUT(HDRP(PREV_BLKP(ptr)), PACK(size, 0)); PUT(FTRP(NEXT_BLKP(ptr)), PACK(size, 0)); ptr = PREV_BLKP(ptr); } add_free(ptr, size); return ptr; } static void *place(void *ptr, size_t asize) { size_t ptr_size = GET_SIZE(HDRP(ptr)); size_t remainder = ptr_size - asize; remove_free(ptr); if (remainder <= DSIZE * 2) { PUT(HDRP(ptr), PACK(ptr_size, 1)); PUT(FTRP(ptr), PACK(ptr_size, 1)); } else if (asize >= 100) { PUT(HDRP(ptr), PACK(remainder, 0)); PUT(FTRP(ptr), PACK(remainder, 0)); PUT(HDRP(NEXT_BLKP(ptr)), PACK(asize, 1)); PUT(FTRP(NEXT_BLKP(ptr)), PACK(asize, 1)); add_free(ptr, remainder); return NEXT_BLKP(ptr); } else { PUT(HDRP(ptr), PACK(asize, 1)); PUT(FTRP(ptr), PACK(asize, 1)); PUT(HDRP(NEXT_BLKP(ptr)), PACK(remainder, 0)); PUT(FTRP(NEXT_BLKP(ptr)), PACK(remainder, 0)); add_free(NEXT_BLKP(ptr), remainder); } return ptr; } //////////////////////////////////////////////////////////////////////////////// ////////////////////////////// MAIN FUNCTIONALITY ////////////////////////////// //////////////////////////////////////////////////////////////////////////////// /* Page 831, Pearson R. Bryant – D. O’Hallaron. Computer Systems: A Programmer’s Perspective.3rd Edition, Pearson, 2003. */ /* * mm_init - initialize the malloc package. */ int mm_init(void) { // Init seg_list for (size_t i = 0; i < LISTSIZE; ++i) { seg_list[i] = NULL; } /* Create the initial empty heap */ if ((heap_listp = mem_sbrk(4*WSIZE)) == (void *)-1) return -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); /* Extend the empty heap with a free block of CHUNKSIZE bytes */ if (extend_heap(CHUNKSIZE/WSIZE) == NULL) return -1; return 0; } /* Page 834, Pearson R. Bryant – D. O’Hallaron. Computer Systems: A Programmer’s Perspective.3rd Edition, Pearson, 2003. */ /* * mm_malloc - Allocate a block by incrementing the brk pointer. * Always allocate a block whose size is a multiple of the alignment. */ void *mm_malloc(size_t size) { size_t asize; /* Adjusted block size */ size_t extendsize; /* Amount to extend heap if no fit */ void *ptr; /* Pointer */ if (size == 0) return NULL; if (size <= DSIZE) { asize = 2 * DSIZE; } else { asize = ALIGN(size+DSIZE); } int list = 0; size_t searchsize = asize; while (list < LISTSIZE) { if ((list == LISTSIZE- 1) || ((searchsize <= 1) && (seg_list[list] != NULL))) { ptr = seg_list[list]; while ((ptr != NULL) && (asize > GET_SIZE(HDRP(ptr)))) { ptr = PRV_BLK(ptr); } if (ptr != NULL) break; } searchsize >>= 1; list++; } if (ptr == NULL) { extendsize = MAX(asize, CHUNKSIZE); if ((ptr = extend_heap(extendsize)) == NULL) return NULL; } return place(ptr, asize); } /* Page 833, Pearson R. Bryant – D. O’Hallaron. Computer Systems: A Programmer’s Perspective.3rd Edition, Pearson, 2003. */ /* * mm_free - Freeing a block does nothing. */ void mm_free(void *ptr) { size_t size = GET_SIZE(HDRP(ptr)); add_free(ptr, size); PUT(HDRP(ptr), PACK(size, 0)); PUT(FTRP(ptr), PACK(size, 0)); coalesce(ptr); } /* * mm_realloc - Implemented simply in terms of mm_malloc and mm_free */ void *mm_realloc(void *ptr, size_t size) { /* * ATTENTION: You do not need to implement realloc for this assignment */ void *oldptr = ptr; void *newptr; size_t copySize; newptr = mm_malloc(size); if (newptr == NULL) return NULL; copySize = *(size_t *)((char *)oldptr - SIZE_T_SIZE); if (size < copySize) copySize = size; memcpy(newptr, oldptr, copySize); mm_free(oldptr); return newptr; }