/* * mm_init - Initialize the malloc package. Construct prologue and epilogue * blocks. */ int mm_init(void) { int list; // List counter char *heap_start; // Pointer to beginning of heap /* Initialize array of pointers to segregated free lists */ for (list = 0; list < LISTS; list++) { free_lists[list] = NULL; } /* Allocate memory for the initial empty heap */ if ((long)(heap_start = mem_sbrk(4 * WSIZE)) == -1) return -1; PUT_NOTAG(heap_start, 0); /* Alignment padding */ PUT_NOTAG(heap_start + (1 * WSIZE), PACK(DSIZE, 1)); /* Prologue header */ PUT_NOTAG(heap_start + (2 * WSIZE), PACK(DSIZE, 1)); /* Prologue footer */ PUT_NOTAG(heap_start + (3 * WSIZE), PACK(0, 1)); /* Epilogue header */ prologue_block = heap_start + DSIZE; /* Extend the empty heap */ if (extend_heap(CHUNKSIZE) == NULL) return -1; /* Variables for checking function line_count = LINE_OFFSET; skip = 0; */ return 0; }
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)); PUT_NOTAG(HDRP(NEXT_BLKP(ptr)), PACK(asize, 1)); PUT_NOTAG(FTRP(NEXT_BLKP(ptr)), PACK(asize, 1)); insert_node(ptr, remainder); return NEXT_BLKP(ptr); } else { // Split block PUT(HDRP(ptr), PACK(asize, 1)); PUT(FTRP(ptr), PACK(asize, 1)); PUT_NOTAG(HDRP(NEXT_BLKP(ptr)), PACK(remainder, 0)); PUT_NOTAG(FTRP(NEXT_BLKP(ptr)), PACK(remainder, 0)); insert_node(NEXT_BLKP(ptr), remainder); } return ptr; }
/* * mm_realloc - Reallocate a block in place, extending the heap if necessary. * The new block is padded with a buffer to guarantee that the * next reallocation can be done without extending the heap, * assuming that the block is expanded by a constant number of bytes * per reallocation. * * If the buffer is not large enough for the next reallocation, * mark the next block with the reallocation tag. Free blocks * marked with this tag cannot be used for allocation or * coalescing. The tag is cleared when the marked block is * consumed by reallocation, when the heap is extended, or when * the reallocated block is freed. */ void *mm_realloc(void *ptr, size_t size) { void *new_ptr = ptr; /* Pointer to be returned */ size_t new_size = size; /* Size of new block */ int remainder; /* Adequacy of block sizes */ int extendsize; /* Size of heap extension */ int block_buffer; /* Size of block buffer */ /* Filter invalid block size */ if (size == 0) return NULL; /* Adjust block size to include boundary tag and alignment requirements */ if (new_size <= DSIZE) { new_size = 2 * DSIZE; } else { new_size = DSIZE * ((new_size + (DSIZE) + (DSIZE - 1)) / DSIZE); } /* Add overhead requirements to block size */ new_size += BUFFER; /* Calculate block buffer */ block_buffer = GET_SIZE(HEAD(ptr)) - new_size; /* Allocate more space if overhead falls below the minimum */ if (block_buffer < 0) { /* Check if next block is a free block or the epilogue block */ if (!GET_ALLOC(HEAD(NEXT(ptr))) || !GET_SIZE(HEAD(NEXT(ptr)))) { remainder = GET_SIZE(HEAD(ptr)) + GET_SIZE(HEAD(NEXT(ptr))) - new_size; if (remainder < 0) { extendsize = MAX(-remainder, CHUNKSIZE); if (extend_heap(extendsize) == NULL) return NULL; remainder += extendsize; } delete_node(NEXT(ptr)); // Do not split block PUT_NOTAG(HEAD(ptr), PACK(new_size + remainder, 1)); /* Block header */ PUT_NOTAG(FOOT(ptr), PACK(new_size + remainder, 1)); /* Block footer */ } else { new_ptr = mm_malloc(new_size - DSIZE); //line_count--; memmove(new_ptr, ptr, MIN(size, new_size)); mm_free(ptr); //line_count--; } block_buffer = GET_SIZE(HEAD(new_ptr)) - new_size; } /* Tag the next block if block overhead drops below twice the overhead */ if (block_buffer < 2 * BUFFER) SET_TAG(HEAD(NEXT(new_ptr))); /* // Check heap for consistency line_count++; if (CHECK && CHECK_REALLOC) { mm_check('r', ptr, size); } */ /* Return reallocated block */ return new_ptr; }
/* * mm_realloc - Implemented simply in terms of mm_malloc and mm_free * * Role : The mm_realloc routine returns a pointer to an allocated * region of at least size bytes with constraints. * * I used https://github.com/htian/malloc-lab/blob/master/mm.c source idea to maximize utilization * by using reallocation tags * in reallocation cases (realloc-bal.rep, realloc2-bal.rep) */ void *mm_realloc(void *ptr, size_t size) { void *new_ptr = ptr; /* Pointer to be returned */ size_t new_size = size; /* Size of new block */ int remainder; /* Adequacy of block sizes */ int extendsize; /* Size of heap extension */ int block_buffer; /* Size of block buffer */ // Ignore size 0 cases if (size == 0) return NULL; // Align block size if (new_size <= DSIZE) { new_size = 2 * DSIZE; } else { new_size = ALIGN(size+DSIZE); } /* Add overhead requirements to block size */ new_size += REALLOC_BUFFER; /* Calculate block buffer */ block_buffer = GET_SIZE(HDRP(ptr)) - new_size; /* Allocate more space if overhead falls below the minimum */ if (block_buffer < 0) { /* Check if next block is a free block or the epilogue block */ if (!GET_ALLOC(HDRP(NEXT_BLKP(ptr))) || !GET_SIZE(HDRP(NEXT_BLKP(ptr)))) { remainder = GET_SIZE(HDRP(ptr)) + GET_SIZE(HDRP(NEXT_BLKP(ptr))) - new_size; if (remainder < 0) { extendsize = MAX(-remainder, CHUNKSIZE); if (extend_heap(extendsize) == NULL) return NULL; remainder += extendsize; } delete_node(NEXT_BLKP(ptr)); // Do not split block PUT_NOTAG(HDRP(ptr), PACK(new_size + remainder, 1)); PUT_NOTAG(FTRP(ptr), PACK(new_size + remainder, 1)); } else { new_ptr = mm_malloc(new_size - DSIZE); memcpy(new_ptr, ptr, MIN(size, new_size)); mm_free(ptr); } block_buffer = GET_SIZE(HDRP(new_ptr)) - new_size; } // Tag the next block if block overhead drops below twice the overhead if (block_buffer < 2 * REALLOC_BUFFER) SET_RATAG(HDRP(NEXT_BLKP(new_ptr))); // Return the reallocated block return new_ptr; }
//////////////////////////////////////// Helper functions ////////////////////////////////////////////////////////// static void *extend_heap(size_t size) { void *ptr; size_t asize; // Adjusted size asize = ALIGN(size); if ((ptr = mem_sbrk(asize)) == (void *)-1) return NULL; // Set headers and footer PUT_NOTAG(HDRP(ptr), PACK(asize, 0)); PUT_NOTAG(FTRP(ptr), PACK(asize, 0)); PUT_NOTAG(HDRP(NEXT_BLKP(ptr)), PACK(0, 1)); insert_node(ptr, asize); return coalesce(ptr); }
/* * extend_heap - Extend the heap with a system call. Insert the newly * requested free block into the appropriate list. */ static void *extend_heap(size_t size) { void *ptr; /* Pointer to newly allocated memory */ size_t words = size / WSIZE; /* Size of extension in words */ size_t asize; /* Adjusted size */ /* Allocate an even number of words to maintain alignment */ asize = (words % 2) ? (words + 1) * WSIZE : words * WSIZE; /* Extend the heap */ if ((long)(ptr = mem_sbrk(asize)) == -1) return NULL; /* Set headers and footer */ PUT_NOTAG(HEAD(ptr), PACK(asize, 0)); /* Free block header */ PUT_NOTAG(FOOT(ptr), PACK(asize, 0)); /* Free block footer */ PUT_NOTAG(HEAD(NEXT(ptr)), PACK(0, 1)); /* Epilogue header */ /* Insert new block into appropriate list */ insert_node(ptr, asize); /* Coalesce if the previous block was free */ return coalesce(ptr); }
/* * place - Set headers and footers for newly allocated blocks. Split blocks * if enough space is remaining. */ static void place(void *ptr, size_t asize) { size_t ptr_size = GET_SIZE(HEAD(ptr)); size_t remainder = ptr_size - asize; /* Remove block from list */ delete_node(ptr); if (remainder >= MINSIZE) { /* Split block */ PUT(HEAD(ptr), PACK(asize, 1)); /* Block header */ PUT(FOOT(ptr), PACK(asize, 1)); /* Block footer */ PUT_NOTAG(HEAD(NEXT(ptr)), PACK(remainder, 0)); /* Next header */ PUT_NOTAG(FOOT(NEXT(ptr)), PACK(remainder, 0)); /* Next footer */ insert_node(NEXT(ptr), remainder); } else { /* Do not split block */ PUT(HEAD(ptr), PACK(ptr_size, 1)); /* Block header */ PUT(FOOT(ptr), PACK(ptr_size, 1)); /* Block footer */ } return; }
/* * mm_init - initialize the malloc package. * Before calling mm_malloc, mm_realloc, or mm_free, * the application program calls mm_init to perform any necessary initializations, * such as allocating the initial heap area. * * Return value : -1 if there was a problem, 0 otherwise. */ int mm_init(void) { int list; char *heap_start; // Pointer to beginning of heap // Initialize segregated free lists for (list = 0; list < LISTLIMIT; list++) { segregated_free_lists[list] = NULL; } // Allocate memory for the initial empty heap if ((long)(heap_start = mem_sbrk(4 * WSIZE)) == -1) return -1; PUT_NOTAG(heap_start, 0); /* Alignment padding */ PUT_NOTAG(heap_start + (1 * WSIZE), PACK(DSIZE, 1)); /* Prologue header */ PUT_NOTAG(heap_start + (2 * WSIZE), PACK(DSIZE, 1)); /* Prologue footer */ PUT_NOTAG(heap_start + (3 * WSIZE), PACK(0, 1)); /* Epilogue header */ if (extend_heap(INITCHUNKSIZE) == NULL) return -1; return 0; }