/* * 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 */ "ateam", /* First member's full name */ "Deng Bohao", /* First member's email address */ "10225501432@stu.ecnu.edu.cn", /* Second member's full name (leave blank if none) */ "Deng Bohao", /* Second member's email address (leave blank if none) */ "10225501432@stu.ecnu.edu.cn" }; /* 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))) /* 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)) /* Pack a size and allocated bit into 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 and write a pointer at address p */ #define GET_PTR(p) ((unsigned int *)(long)(GET(p))) #define PUT_PTR(p, ptr) (*(unsigned int *)(p) = ((long)ptr)) /* 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))) /* 每个free list中块的大小范围 */ #define SIZE1 (1<<4) #define SIZE2 (1<<5) #define SIZE3 (1<<6) #define SIZE4 (1<<7) #define SIZE5 (1<<8) #define SIZE6 (1<<9) #define SIZE7 (1<<10) /* 1 KB */ #define SIZE8 (1<<11) #define SIZE9 (1<<12) #define SIZE10 (1<<13) #define SIZE11 (1<<14) #define SIZE12 (1<<15) #define SIZE13 (1<<16) #define SIZE14 (1<<17) #define SIZE15 (1<<18) #define SIZE16 (1<<19) #define SIZE17 (1<<20) /* 1 MB */ #define LISTS_NUM 18 /* free list 的数量 */ /* Globe var */ static char *heap_listp; /* 函数声明 */ static void *extend_heap(size_t words); static void *coalesce(void *bp); static void *find_fit(size_t asize); static void place(void *bp, size_t asize); static void insert_list(void *bp); int getListOffset(size_t size); void delete_list(void *bp); /* * mm_init - initialize the malloc package. */ int mm_init(void) { char *bp; int i; if ((heap_listp = mem_sbrk((LISTS_NUM + 4) * WSIZE)) == (void *)-1) { return -1; } PUT(heap_listp + LISTS_NUM * WSIZE, 0); PUT(heap_listp + (1 + LISTS_NUM) * WSIZE, PACK(DSIZE, 1)); PUT(heap_listp + (2 + LISTS_NUM) * WSIZE, PACK(DSIZE, 1)); PUT(heap_listp + (3 + LISTS_NUM) * WSIZE, PACK(0, 1)); for (i = 0; i < LISTS_NUM; i++) { PUT_PTR(heap_listp + WSIZE * i, NULL); } /* Extend the empty heap with a free block of CHUNKSIZE bytes */ if ((bp = extend_heap(CHUNKSIZE / WSIZE)) == NULL) { return -1; } return 0; } /* * 扩展heap的大小 */ void *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); if ((long)(bp = mem_sbrk(size)) == -1) { return NULL; } /* 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 */ /* Coalesce if the previous block was free */ return coalesce(bp); } /* * 合并free block */ 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) { /* 前后都分配了 */ bp = bp; } else if (prev_alloc && !next_alloc) { /* 前分配, 后未分配 */ delete_list(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) { /* 前未分配, 后分配 */ delete_list(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 { /* 前后都未分配 */ delete_list(NEXT_BLKP(bp)); delete_list(PREV_BLKP(bp)); size = size + GET_SIZE(HDRP(PREV_BLKP(bp))) + GET_SIZE(HDRP(NEXT_BLKP(bp))); PUT(HDRP(PREV_BLKP(bp)), PACK(size, 0)); PUT(FTRP(NEXT_BLKP(bp)), PACK(size, 0)); bp = PREV_BLKP(bp); } insert_list(bp); return bp; } /* * mm_malloc - Allocate a block by searching the free list. * 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 */ char *bp; /* Igore spurious requests */ if (0 == size) { return NULL; } /* Adjusted block size to include overhead and alignment reqs */ if (size <= DSIZE) { asize = 2 * DSIZE; } else { asize = DSIZE * ((size + (DSIZE) + (DSIZE - 1)) / 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; } /* * getListOffset - 得到大小为size的块应该在哪个list中 */ int getListOffset(size_t size) { if (size <= SIZE1) { return 0; } else if (size <= SIZE2) { return 1; } else if (size <= SIZE3) { return 2; } else if (size <= SIZE4) { return 3; } else if (size <= SIZE5) { return 4; } else if (size <= SIZE6) { return 5; } else if (size <= SIZE7) { return 6; } else if (size <= SIZE8) { return 7; } else if (size <= SIZE9) { return 8; } else if (size <= SIZE10) { return 9; } else if (size <= SIZE11) { return 10; } else if (size <= SIZE12) { return 11; } else if (size <= SIZE13) { return 12; } else if (size <= SIZE14) { return 13; } else if (size <= SIZE15) { return 14; } else if (size <= SIZE16) { return 15; } else if (size <= SIZE17) { return 16; } else { return 17; } } /* * insert_list - 将free block插入到相应大小的free list中, 插入位置为表头 */ void insert_list(void *bp) { int index; size_t size; size = GET_SIZE(HDRP(bp)); index = getListOffset(size); if (GET_PTR(heap_listp + WSIZE * index) == NULL) { PUT_PTR(heap_listp + WSIZE * index, bp); PUT_PTR(bp, NULL); PUT_PTR((unsigned int *)bp + 1, NULL); } else { PUT_PTR(bp, GET_PTR(heap_listp + WSIZE * index)); PUT_PTR(GET_PTR(heap_listp + WSIZE * index) + 1, bp); /* 修改前一个位置 */ PUT_PTR((unsigned int *)bp + 1, NULL); PUT_PTR(heap_listp + WSIZE * index, bp); } } /* * delete_list - 删除链表结点 */ void delete_list(void *bp) { int index; size_t size; size = GET_SIZE(HDRP(bp)); index = getListOffset(size); if (GET_PTR(bp) == NULL && GET_PTR((unsigned int *)bp + 1) == NULL) { /* 链表中唯一结点 */ PUT_PTR(heap_listp + WSIZE * index, NULL); } else if (GET_PTR(bp) == NULL && GET_PTR((unsigned int *)bp + 1) != NULL) { /* 链表中最后一个结点, 不是唯一一个 */ PUT_PTR(GET_PTR((unsigned int *)bp + 1), NULL); } else if (GET_PTR(bp) != NULL && GET_PTR((unsigned int *)bp + 1) == NULL){ /* 链表中第一个结点, 不是唯一一个 */ PUT_PTR(heap_listp + WSIZE * index, GET_PTR(bp)); PUT_PTR(GET_PTR(bp) + 1, NULL); } else if (GET_PTR(bp) != NULL && GET_PTR((unsigned int *)bp + 1) != NULL) { /* 链表中的中间结点 */ PUT_PTR(GET_PTR((unsigned int *)bp + 1), GET_PTR(bp)); PUT_PTR(GET_PTR(bp) + 1, GET_PTR((unsigned int*)bp + 1)); } } /* * find_fit - Search the free list for a fit */ void *find_fit(size_t asize) { int index; index = getListOffset(asize); unsigned int *ptr; /* 小的class内找不到就到大的class内找 */ while (index < 18) { ptr = GET_PTR(heap_listp + 4 * index); while (ptr != NULL) { if (GET_SIZE(HDRP(ptr)) >= asize) { return (void *)ptr; } ptr = GET_PTR(ptr); } index++; } return NULL; } /* * place - place the requested block at the beginning of the free block */ void place(void *bp, size_t asize) { size_t csize = GET_SIZE(HDRP(bp)); delete_list(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)); insert_list(bp); } else { PUT(HDRP(bp), PACK(csize, 1)); PUT(FTRP(bp), PACK(csize, 1)); } } /* * mm_free - Freeing a block. */ void mm_free(void *ptr) { size_t size = GET_SIZE(HDRP(ptr)); PUT(HDRP(ptr), PACK(size, 0)); PUT(FTRP(ptr), PACK(size, 0)); coalesce(ptr); } /* * mm_realloc - 直接用malloc和free组合实现 */ void *mm_realloc(void *ptr, size_t size) { size_t asize; void *oldptr = ptr; void *newptr; /* free */ if (0 == size) { free(oldptr); return NULL; } if (size <= DSIZE) { asize = 2 * DSIZE; } else { asize = DSIZE * ((size + (DSIZE) + (DSIZE - 1)) / DSIZE); } if (asize == GET_SIZE(HDRP(oldptr))) { return oldptr; } /* 缩小空间 */ if (asize < GET_SIZE(HDRP(oldptr))) { newptr = mm_malloc(size); memmove(newptr, oldptr, size); mm_free(oldptr); return newptr; } newptr = mm_malloc(size); if (NULL == newptr) return NULL; memmove(newptr, oldptr, size); mm_free(oldptr); return newptr; }