diff --git a/Makefile b/Makefile index 701bc21..f9f8bed 100644 --- a/Makefile +++ b/Makefile @@ -2,8 +2,8 @@ # Students' Makefile for the Malloc Lab # CC = gcc -# CFLAGS = -Wall -O2 -m32 -g03 -pg -CFLAGS = -Wall -O0 -m32 -g03 -pg +CFLAGS = -Wall -O2 -m32 +# CFLAGS = -Wall -O0 -m32 -g03 -pg OBJS = mdriver.o mm.o memlib.o fsecs.o fcyc.o clock.o ftimer.o diff --git a/mm.c b/mm.c index d3b7ee1..1008be2 100644 --- a/mm.c +++ b/mm.c @@ -89,6 +89,7 @@ team_t team = { /* Read and write a word at address p */ #define GET(p) (*(unsigned int *)(p)) #define PUT(p, val) (*(unsigned int *)(p) = (val)) +#define PUTT(p, val) (*(unsigned int *)(p) = (val)) /* Read the size and allocated fields from address p */ #define GET_SIZE(p) (GET(p) & ~0x7) @@ -121,9 +122,7 @@ char* seg_list[LISTSIZE]; ///////////////////////////////// HELPER PREDEF //////////////////////////////// //////////////////////////////////////////////////////////////////////////////// /* Page 856-858, Pearson R. Bryant – D. O’Hallaron. Computer Systems: A Programmer’s Perspective.3rd Edition, Pearson, 2003. */ -static void place(void *bp, size_t asize); -/* Page 856, Pearson R. Bryant – D. O’Hallaron. Computer Systems: A Programmer’s Perspective.3rd Edition, Pearson, 2003. */ -static void* find_fit(size_t asize); +static void* place(void *bp, size_t asize); /* Page 833, Pearson R. Bryant – D. O’Hallaron. Computer Systems: A Programmer’s Perspective.3rd Edition, Pearson, 2003. */ static void* coalesce(void *bp); /* Page 831, Pearson R. Bryant – D. O’Hallaron. Computer Systems: A Programmer’s Perspective.3rd Edition, Pearson, 2003. */ @@ -132,152 +131,174 @@ static void add_free(void* bp, size_t asize); //////////////////////////////////////////////////////////////////////////////// /////////////////////////////// HELPER FUNCTIONS /////////////////////////////// //////////////////////////////////////////////////////////////////////////////// -static int getSzClass(size_t asize) { - for (size_t i = 0; i < LISTSIZE; ++i) { - if (asize == (1 << i)) { - return i; - } - } - return LISTSIZE-1; -} - -static void add_free(void* ptr, size_t size) +static void *extend_heap(size_t size) { - int szClass = getSzClass(size); - void* classPtr = seg_list[szClass]; - - while(classPtr != NULL) - { - classPtr = NXT_PTR(classPtr); - } - PUT_PTR(NXT_PTR(classPtr), ptr); - PUT_PTR(PRV_PTR(ptr), classPtr); - PUT_PTR(NXT_PTR(ptr), NULL); -} - -static void place(void *bp, size_t asize) -{ - 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)); - } -} - -static void remove_free(void* bp) { - int szClass = getSzClass(GET_SIZE(HDRP(bp))); - - if (PRV_BLK(bp) == NULL && NXT_BLK(bp) == NULL) { - seg_list[szClass] = NULL; - } else if (PRV_BLK(bp) != NULL && NXT_BLK(bp) == NULL) { - PUT_PTR(PRV_PTR(PRV_BLK(bp)), NULL); - seg_list[szClass] = PRV_BLK(bp); - } else if (PRV_BLK(bp) == NULL && NXT_BLK(bp) != NULL) { - PUT_PTR(PRV_PTR(NXT_BLK(bp)), NULL); - } if (PRV_BLK(bp) != NULL && NXT_BLK(bp) != NULL) { - PUT_PTR(NXT_PTR(PRV_BLK(bp)), NXT_BLK(bp)); - PUT_PTR(PRV_PTR(NXT_BLK(bp)), PRV_BLK(bp)); - } -} - -static void* best_fit(void* ptr, size_t asize) { - unsigned long left_over = GET_SIZE(ptr) - asize; - void* bestfit = ptr; - unsigned long best_left_over = GET_SIZE(ptr) - asize; - while (NXT_PTR(ptr) != NULL) { - left_over = GET_SIZE(ptr) - asize; - if(left_over 1)) { + size >>= 1; + list++; + } + + // Keep size ascending order and search + search_ptr = seg_list[list]; + while ((search_ptr != NULL) && (size > GET_SIZE(HDRP(search_ptr)))) { + insert_ptr = search_ptr; + search_ptr = PRV_BLK(search_ptr); + } + + // Set predecessor and successor + if (search_ptr != NULL) { + if (insert_ptr != NULL) { + PUT_PTR(PRV_PTR(ptr), search_ptr); + PUT_PTR(NXT_PTR(search_ptr), ptr); + PUT_PTR(NXT_PTR(ptr), insert_ptr); + PUT_PTR(PRV_PTR(insert_ptr), ptr); } else { - return best_fit(classPtr, asize); + PUT_PTR(PRV_PTR(ptr), search_ptr); + PUT_PTR(NXT_PTR(search_ptr), ptr); + PUT_PTR(NXT_PTR(ptr), NULL); + seg_list[list] = ptr; + } + } else { + if (insert_ptr != NULL) { + PUT_PTR(PRV_PTR(ptr), NULL); + PUT_PTR(NXT_PTR(ptr), insert_ptr); + PUT_PTR(PRV_PTR(insert_ptr), ptr); + } else { + PUT_PTR(PRV_PTR(ptr), NULL); + PUT_PTR(NXT_PTR(ptr), NULL); + seg_list[list] = ptr; } } + + return; } -/* Page 833, Pearson R. Bryant – D. O’Hallaron. Computer Systems: A Programmer’s Perspective.3rd Edition, Pearson, 2003. */ -static void *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; - } else if (prev_alloc && !next_alloc) { /* Case 2 */ - remove_free(bp); - remove_free(NEXT_BLKP(bp)); - size += GET_SIZE(HDRP(NEXT_BLKP(bp))); - PUT(HDRP(bp),PACK(size,0)); - PUT(FTRP(bp),PACK(size,0)); - } else if (!prev_alloc && next_alloc) { /* Case 3 */ - remove_free(bp); - remove_free(PREV_BLKP(bp)); - 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 */ - remove_free(bp); - remove_free(PREV_BLKP(bp)); - remove_free(NEXT_BLKP(bp)); - 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); +static void delete_node(void *ptr) { + int list = 0; + size_t size = GET_SIZE(HDRP(ptr)); + + // Select segregated list + while ((list < LISTSIZE - 1) && (size > 1)) { + size >>= 1; + list++; } - - add_free(bp, size); - - return bp; + + if (PRV_BLK(ptr) != NULL) { + if (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 { + PUT_PTR(NXT_PTR(PRV_BLK(ptr)), NULL); + seg_list[list] = PRV_BLK(ptr); + } + } else { + if (NXT_BLK(ptr) != NULL) { + PUT_PTR(PRV_PTR(NXT_BLK(ptr)), NULL); + } else { + seg_list[list] = NULL; + } + } + + return; } -/* Page 831, Pearson R. Bryant – D. O’Hallaron. Computer Systems: A Programmer’s Perspective.3rd Edition, Pearson, 2003. */ -static void *extend_heap(size_t words) + +static void *coalesce(void *ptr) { - char *bp; - size_t size; + 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)); + - /* Allocate an even number of words to maintain alignment */ - size = (words % 2) ? (words+1) * WSIZE : words * WSIZE; - if ((long)(bp = mem_sbrk(size)) == -1) - return NULL; + if (prev_alloc && next_alloc) { // Case 1 + return ptr; + } + else if (prev_alloc && !next_alloc) { // Case 2 + delete_node(ptr); + delete_node(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 + delete_node(ptr); + delete_node(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 + delete_node(ptr); + delete_node(PREV_BLKP(ptr)); + delete_node(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; +} - /* 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 */ - - add_free(bp, size); - - /* Coalesce if the previous block was free */ - return coalesce(bp); +static void *place(void *ptr, size_t asize) +{ + size_t ptr_size = GET_SIZE(HDRP(ptr)); + size_t remainder = ptr_size - asize; + + delete_node(ptr); + + + if (remainder <= DSIZE * 2) { + // Do not split block + PUT(HDRP(ptr), PACK(ptr_size, 1)); + PUT(FTRP(ptr), PACK(ptr_size, 1)); + } + + else if (asize >= 100) { + // Split block + PUT(HDRP(ptr), PACK(remainder, 0)); + PUT(FTRP(ptr), PACK(remainder, 0)); + PUTT(HDRP(NEXT_BLKP(ptr)), PACK(asize, 1)); + PUTT(FTRP(NEXT_BLKP(ptr)), PACK(asize, 1)); + add_free(ptr, remainder); + return NEXT_BLKP(ptr); + + } + + else { + // Split block + PUT(HDRP(ptr), PACK(asize, 1)); + PUT(FTRP(ptr), PACK(asize, 1)); + PUTT(HDRP(NEXT_BLKP(ptr)), PACK(remainder, 0)); + PUTT(FTRP(NEXT_BLKP(ptr)), PACK(remainder, 0)); + add_free(NEXT_BLKP(ptr), remainder); + } + return ptr; } //////////////////////////////////////////////////////////////////////////////// @@ -316,32 +337,54 @@ int mm_init(void) */ void *mm_malloc(size_t size) { - size_t asize; /* Adjusted block size */ + size_t asize; /* Adjusted block size */ size_t extendsize; /* Amount to extend heap if no fit */ - char *bp; /* Pointer */ - - /* Ignore spurious requests */ + void *ptr = NULL; /* Pointer */ + + // Ignore size 0 cases if (size == 0) return NULL; - - /* Adjust block size to include overhead and alignment reqs. */ - if (size <= DSIZE) - asize = 2*DSIZE; - else + + // Align block size + if (size <= DSIZE) { + asize = 2 * DSIZE; + } else { asize = ALIGN(size+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; + + int list = 0; + size_t searchsize = asize; + // Search for free block in segregated list + while (list < LISTSIZE) { + if ((list == LISTSIZE- 1) || ((searchsize <= 1) && (seg_list[list] != NULL))) { + ptr = seg_list[list]; + // Ignore blocks that are too small or marked with the reallocation bit + while ((ptr != NULL) && (asize > GET_SIZE(HDRP(ptr)))) + { + ptr = PRV_BLK(ptr); + } + if (ptr != NULL) + break; + } + + searchsize >>= 1; + list++; + } + + // if free block is not found, extend the heap + if (ptr == NULL) { + extendsize = MAX(asize, CHUNKSIZE); + + if ((ptr = extend_heap(extendsize)) == NULL) + return NULL; + } + + // Place and divide block + ptr = place(ptr, asize); + + + // Return pointer to newly allocated block + return ptr; } /* Page 833, Pearson R. Bryant – D. O’Hallaron. Computer Systems: A Programmer’s Perspective.3rd Edition, Pearson, 2003. */