/* * 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) = (size_t)(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 //////////////////////////////// //////////////////////////////////////////////////////////////////////////////// /** @brief Extends the memory of the heap by the specified amount. @param[in] size amount of memory to extend heap by @result Pointer to the newly allocated memory area. */ static void *extend_heap(size_t size); /** @brief Adds a free memory location to the segregated list. @param[in] ptr Pointer of the memory location to be added @param[in] size size of the area that would be occupied */ static void add_free(void *ptr, size_t size); /** @brief Removes a free memory location to the segregated list. @param[in] ptr Pointer of the memory location to be removed */ static void remove_free(void *ptr); /** @brief Coalesce memory areas around the given pointer, given that they're free. @param[in] ptr Memory area to look into. */ static void *coalesce(void *ptr); /** @brief Places The header and footer for our memory blocks. @param[in] ptr pointer to the memory block that's allocated @param[in] asize size of memory to allocate */ static void *place(void *ptr, size_t asize); /** @brief Get the size class of the given size inside of the segregated list @param[in] asize size class to look for in segregated list @result Size class (i.e. index of segregated list) */ static inline int getSzClass(size_t asize); //////////////////////////////////////////////////////////////////////////////// /////////////////////////////// HELPER FUNCTIONS /////////////////////////////// //////////////////////////////////////////////////////////////////////////////// static inline int getSzClass(size_t asize) { int i; int size = asize; for (i = 0; i < LISTSIZE-1; ++i) { if (size > 1) break; size >>= 1; } return i; } 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 szClass = getSzClass(size); void* class_ptr = seg_list[szClass]; void *pre_ptr = NULL; while ((class_ptr != NULL) && (size > GET_SIZE(HDRP(class_ptr)))) { pre_ptr = class_ptr; class_ptr = PRV_BLK(class_ptr); } if (class_ptr != NULL && pre_ptr != NULL) { PUT_PTR(NXT_PTR(class_ptr), ptr); PUT_PTR(NXT_PTR(ptr), pre_ptr); PUT_PTR(PRV_PTR(ptr), class_ptr); PUT_PTR(PRV_PTR(pre_ptr), ptr); } else if (class_ptr != NULL && pre_ptr == NULL) { PUT_PTR(PRV_PTR(ptr), class_ptr); PUT_PTR(NXT_PTR(class_ptr), ptr); PUT_PTR(NXT_PTR(ptr), NULL); seg_list[szClass] = ptr; } else if(class_ptr == NULL && pre_ptr != NULL) { PUT_PTR(NXT_PTR(ptr), pre_ptr); PUT_PTR(PRV_PTR(ptr), NULL); PUT_PTR(PRV_PTR(pre_ptr), ptr); } else { PUT_PTR(NXT_PTR(ptr), NULL); PUT_PTR(PRV_PTR(ptr), NULL); seg_list[szClass] = ptr; } return; } static void remove_free(void *ptr) { size_t size = GET_SIZE(HDRP(ptr)); int szClass = getSzClass(size); 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[szClass] = PRV_BLK(ptr); } else if(PRV_BLK(ptr) == NULL && NXT_BLK(ptr) != NULL) { PUT_PTR(PRV_PTR(NXT_BLK(ptr)), NULL); } else { seg_list[szClass] = 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 rest = ptr_size - asize; remove_free(ptr); if (rest <= DSIZE * 2) { PUT(HDRP(ptr), PACK(ptr_size, 1)); PUT(FTRP(ptr), PACK(ptr_size, 1)); } else { PUT(HDRP(ptr), PACK(rest, 0)); PUT(FTRP(ptr), PACK(rest, 0)); PUT(HDRP(NEXT_BLKP(ptr)), PACK(asize, 1)); PUT(FTRP(NEXT_BLKP(ptr)), PACK(asize, 1)); add_free(ptr, rest); return NEXT_BLKP(ptr); } 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); } size_t sz = asize; for (int i = 0;i < LISTSIZE; ++i) { if ((i == LISTSIZE-1) || ((sz < 2) && (seg_list[i] != NULL))) { ptr = seg_list[i]; while (!((ptr == NULL) || (asize <= GET_SIZE(HDRP(ptr))))) { ptr = PRV_BLK(ptr); } if (ptr != NULL) break; } sz >>= 1; } 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; }