diff --git a/mdriver b/mdriver index e7a57c7..36aaaf0 100755 Binary files a/mdriver and b/mdriver differ diff --git a/mm.c b/mm.c index 0f4b275..1136b44 100644 --- a/mm.c +++ b/mm.c @@ -44,61 +44,390 @@ team_t team = { #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) { - return 0; + 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 incrementing the brk pointer. - * Always allocate a block whose size is a multiple of the alignment. + * 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 newsize = ALIGN(size + SIZE_T_SIZE); - void *p = mem_sbrk(newsize); - if (p == (void *)-1) + 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; - else { - *(size_t *)p = size; - return (void *)((char *)p + SIZE_T_SIZE); - } } /* - * mm_free - Freeing a block does nothing. + * 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 - Implemented simply in terms of mm_malloc and mm_free + * mm_realloc - 直接用malloc和free组合实现 */ void *mm_realloc(void *ptr, size_t size) { - 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; -} + 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; +} diff --git a/mm.o b/mm.o index ec88a7a..6f2a8c7 100644 Binary files a/mm.o and b/mm.o differ