/* * 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 */ "team", /* First member's full name */ "GentleCold", /* First member's email address */ "1952173800@qq.com", /* Second member's full name (leave blank if none) */ "", /* Second member's email address (leave blank if none) */ "" }; /* 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) // My define #define WSIZE 4 #define DSIZE 8 #define FSIZE 16 #define CHUNK 1 << 10 #define MAX(a, b) ((a) > (b) ? (a) : (b)) #define PARSE(v) ((v) & ~0x7) #define PACK(v, a) ((v) | (a)) #define HEAD(bp) ((byte *)(bp) - WSIZE) #define FOOT(bp) ((byte *)(bp) + SIZE(bp)) #define SIZE(bp) (PARSE(GET(HEAD(bp)))) #define ALLOC(bp) (GET(HEAD(bp)) & 0x1) #define GET(p) (*(word *)(p)) #define SET(p, v) (*(word *)(p) = (v)) #define NEXT(bp) (FOOT(bp) + DSIZE) #define PREV(bp) ((byte *)(bp) - PARSE(GET((bp) - DSIZE)) - DSIZE) typedef unsigned int word; typedef char byte; // mark the front and tail pos void *front_p = NULL; void *tail_p = NULL; // used for next fit, updated by mm_init, mm_malloc, _coalesce void *fitted_p = NULL; // My func /** * add a blank chunk and coalesce * will update tail_p * @param size align by 8, excluding head and foot * @return new bp */ static void *_extend(size_t size); /** * coalesce blank chunk before and after bp * @param bp loaded point * @return bp after coalesce */ static void *_coalesce(void *bp); static void *__coalesce_prev(void *bp); static void *__coalesce_next(void *bp); static void *__coalesce_all(void *bp); /** * traverse and find first fit, then place in * @deprecated too slow * @param size align by 8, excluding head and foot * @return */ static void *_first_fit(size_t size); /** * find next fit, then place in * @param size align by 8, excluding head and foot * @return */ static void *_next_fit(size_t size); /** * find next fit, then place in, if from beginning, use best fit * @deprecated thru loss * @param size align by 8, excluding head and foot * @return */ static void *_next_best_fit(size_t size); /** * allocate the block and cut sometimes * @param size align by 8, excluding head and foot */ static void _place(void *ptr, size_t size); // end /** * initialize the malloc package. * get a new chunk, set front_p and tail_p */ int mm_init(void) { if ((front_p = mem_sbrk(WSIZE)) == (void *) - 1) return -1; // blank front_p += DSIZE; // first chunk fitted_p = front_p; // init fitted_p if (!_extend(CHUNK)) return -1; return 0; } /** * find first fit or extend */ void *mm_malloc(size_t size) { size_t adjust_size = ALIGN(size); size_t extend_size; void *bp; if ((bp = _next_fit(adjust_size)) != NULL) { fitted_p = bp; return bp; } else { extend_size = adjust_size; if (!ALLOC(tail_p)) { extend_size -= (SIZE(tail_p) + DSIZE); } bp = _extend(MAX(extend_size, CHUNK)); if (bp == NULL) return bp; _place(bp, adjust_size); fitted_p = bp; return bp; } } /** * free a block and coalesce immediately */ void mm_free(void *ptr) { size_t size = SIZE(ptr); SET(HEAD(ptr), PACK(size, 0)); SET(FOOT(ptr), PACK(size, 0)); _coalesce(ptr); } /** * implemented simply in terms of mm_malloc and mm_free * compare adjust_size and total_size step by step */ void *mm_realloc(void *ptr, size_t size) { if (ptr == NULL) return mm_malloc(size); if (size == 0) return NULL; void *new_ptr; size_t adjust_size = ALIGN(size); size_t old_size = SIZE(ptr); if (adjust_size <= old_size) { // just return, for the memory lost is little return ptr; } size_t next_size = (ptr != tail_p && !ALLOC(NEXT(ptr))) ? SIZE(NEXT(ptr)) + DSIZE : 0; size_t total_size = old_size + next_size; if (adjust_size <= total_size) { __coalesce_next(ptr); _place(ptr, adjust_size); // just cut return ptr; } size_t prev_size = (ptr != front_p && !ALLOC(PREV(ptr))) ? SIZE(PREV(ptr)) + DSIZE : 0; total_size += prev_size; if (adjust_size <= total_size) { // coalesce prev or all new_ptr = _coalesce(ptr); memmove(new_ptr, ptr, old_size); _place(new_ptr, adjust_size); } else { if ((new_ptr = mm_malloc(size)) == NULL) return NULL; memmove(new_ptr, ptr, old_size); mm_free(ptr); } return new_ptr; } // my func static void *_extend(size_t size) { void *bp; if ((bp = mem_sbrk(size + DSIZE)) == (void *) - 1) return NULL; // init chunk SET(bp, PACK(size, 0)); bp += WSIZE; SET(FOOT(bp), PACK(size, 0)); // init mark point tail_p = bp; return _coalesce(bp); } static void *_coalesce(void *bp) { // one chunk if (bp == front_p && bp == tail_p) return bp; if (bp == front_p || ALLOC(PREV(bp))) { if (bp == tail_p || ALLOC(NEXT(bp))) return bp; return __coalesce_next(bp); } else if (bp == tail_p || ALLOC(NEXT(bp))) { return __coalesce_prev(bp); } else { return __coalesce_all(bp); } } static void *__coalesce_prev(void *bp) { void *prev = PREV(bp); size_t new_size = SIZE(prev) + SIZE(bp) + DSIZE; SET(HEAD(prev), PACK(new_size, 0)); SET(FOOT(bp), PACK(new_size, 0)); if (bp == tail_p) tail_p = prev; if (bp == fitted_p) fitted_p = prev; return prev; } static void *__coalesce_next(void *bp) { void *next = NEXT(bp); size_t new_size = SIZE(next) + SIZE(bp) + DSIZE; SET(HEAD(bp), PACK(new_size, 0)); SET(FOOT(next), PACK(new_size, 0)); if (next == tail_p) tail_p = bp; // should also change if (next == fitted_p) fitted_p = bp; return bp; } static void *__coalesce_all(void *bp) { void *prev = PREV(bp); void *next = NEXT(bp); size_t new_size = SIZE(prev) + SIZE(bp) + SIZE(next) + FSIZE; SET(HEAD(prev), PACK(new_size, 0)); SET(FOOT(next), PACK(new_size, 0)); if (next == tail_p) tail_p = prev; if (next == fitted_p || bp == fitted_p) fitted_p = prev; return prev; } static void *_first_fit(size_t size) { void *bp = front_p; void *after_p = NEXT(tail_p); while (bp != after_p) { if (!ALLOC(bp) && SIZE(bp) >= size) { _place(bp, size); return bp; } bp = NEXT(bp); } return NULL; } static void *_next_fit(size_t size) { void *bp = fitted_p; void *after_p = NEXT(tail_p); while (bp != after_p) { if (!ALLOC(bp) && SIZE(bp) >= size) { _place(bp, size); return bp; } bp = NEXT(bp); } bp = front_p; while (bp != fitted_p) { if (!ALLOC(bp) && SIZE(bp) >= size) { _place(bp, size); return bp; } bp = NEXT(bp); } return NULL; } static void *_next_best_fit(size_t size) { void *bp = fitted_p; void *after_p = NEXT(tail_p); while (bp != after_p) { if (!ALLOC(bp) && SIZE(bp) >= size) { _place(bp, size); return bp; } bp = NEXT(bp); } bp = front_p; size_t min = 0; void *min_p = NULL; while (bp != fitted_p) { if (!ALLOC(bp) && SIZE(bp) >= size) { if (min_p == NULL || SIZE(bp) < min) { min = SIZE(bp); min_p = bp; } } bp = NEXT(bp); } if (min_p == NULL) return NULL; _place(min_p, size); return min_p; } static void _place(void *ptr, size_t size) { size_t p_size = SIZE(ptr); if (p_size - size >= FSIZE) { SET(HEAD(ptr), PACK(size, 1)); SET(FOOT(ptr), PACK(size, 1)); // DSIZE adjust size_t adjust_size = p_size - size - DSIZE; SET(HEAD(NEXT(ptr)), PACK(adjust_size, 0)); SET(FOOT(NEXT(ptr)), PACK(adjust_size, 0)); if (ptr == tail_p) tail_p = NEXT(ptr); } else { SET(HEAD(ptr), PACK(p_size, 1)); SET(FOOT(ptr), PACK(p_size, 1)); } }