/* * mm-naive.c - The clear list(LIFO), best fit, coalesce immediately malloc package. */ #include #include "mm.h" #include "memlib.h" 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 size_t (4) or double size_t (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 ADDRESS (sizeof(size_t)) #define CHUNK 1 << 12 #define MIN_BLOCK (2 * ADDRESS + DSIZE) #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) #define POS_PRED(bp) ((byte *)(bp)) #define POS_SUCC(bp) (((byte *)(bp) + ADDRESS)) #define GET_PRED(bp) (*(size_t *)POS_PRED(bp)) #define GET_SUCC(bp) (*(size_t *)POS_SUCC(bp)) 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 * @deprecated useless for clear list */ void *fitted_p = NULL; void *list_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); static void *__coalesce_none(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 * @deprecated I'll use clear list * @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); /** * traverse blank block only and find first fit, then place in * @deprecated for the memory loss * @param size align by 8, excluding head and foot * @return */ static void *_first_fit_of_clear(size_t size); /** * best fit for clear list * @param size align by 8, excluding head and foot * @return */ static void *_best_fit_of_clear(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); /** * just replace in of out in list * @param in the block that in the list * @param out the block that out the list */ static void _fix_list(void *in, void *out); /** * check the number of blank list nums and real blank nums and print * @deprecated */ static void _check(); // 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 = _best_fit_of_clear(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) { #ifdef DEBUG printf("---free---\n"); _check(); printf("----------\n"); #endif 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) { void *next = NEXT(ptr); // remove if (total_size - adjust_size >= MIN_BLOCK) { SET(POS_SUCC(GET_PRED(next)), GET_SUCC(next)); SET(POS_PRED(GET_SUCC(next)), GET_PRED(next)); SET(HEAD(ptr), PACK(total_size, 1)); SET(FOOT(ptr), PACK(total_size, 1)); if (next == list_p) { if (GET_SUCC(next) == (size_t) next) list_p = NULL; else list_p = (void *) GET_SUCC(next); } if (next == tail_p) tail_p = ptr; } else { // replace void *pred = (void *)GET_PRED(next); void *succ = (void *) GET_SUCC(next); SET(HEAD(ptr), PACK(adjust_size, 1)); SET(FOOT(ptr), PACK(adjust_size, 1)); size_t new_size = total_size - adjust_size - DSIZE; void *new = NEXT(ptr); SET(HEAD(new), PACK(new_size, 0)); SET(FOOT(new), PACK(new_size, 0)); if (pred == next) { SET(POS_PRED(new), (size_t)new); SET(POS_SUCC(new), (size_t)new); } else { SET(POS_PRED(succ), (size_t)new); SET(POS_SUCC(pred), (size_t)new); } if (list_p == next) list_p = new; if (next == tail_p) tail_p = new; } return ptr; } 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)); #ifdef DEBUG if (tail_p) { printf("----extend----\n"); _check(); printf("--------------\n"); } #endif // init mark point tail_p = bp; return _coalesce(bp); } static void *_coalesce(void *bp) { // one chunk if (bp == front_p && bp == tail_p) return __coalesce_none(bp); if (bp == front_p || ALLOC(PREV(bp))) { if (bp == tail_p || ALLOC(NEXT(bp))) return __coalesce_none(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; list_p = prev; return prev; } static void *__coalesce_next(void *bp) { void *next = NEXT(bp); // tweak list _fix_list(next, bp); // coalesce 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; list_p = bp; #ifdef DEBUG printf("----coalesce next----\n"); _check(); printf("---------------------\n"); #endif return bp; } static void *__coalesce_all(void *bp) { void *prev = PREV(bp); void *next = NEXT(bp); // tweak list SET(POS_SUCC(GET_PRED(next)), GET_SUCC(next)); SET(POS_PRED(GET_SUCC(next)), GET_PRED(next)); // coalesce 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; list_p = prev; #ifdef DEBUG printf("---coalesce all---\n"); _check(); printf("-------------------\n"); #endif return prev; } static void *__coalesce_none(void *bp) { // tweak list if (list_p == NULL) { list_p = bp; SET(POS_SUCC(list_p), (size_t)list_p); SET(POS_PRED(list_p), (size_t)list_p); } else { // add to list SET(POS_SUCC(bp), GET_SUCC(list_p)); SET(POS_PRED(bp), (size_t)list_p); SET(POS_PRED(GET_SUCC(list_p)), (size_t)bp); SET(POS_SUCC(list_p), (size_t)bp); list_p = bp; } #ifdef DEBUG printf("---coalesce none---\n"); _check(); printf("-------------------\n"); #endif return bp; } 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 *_first_fit_of_clear(size_t size) { void *bp = list_p; if (bp == NULL) return NULL; do { if (SIZE(bp) >= size) { _place(bp, size); return bp; } bp = (void *)GET_SUCC(bp); } while (bp != list_p); return NULL; } static void *_best_fit_of_clear(size_t size) { void *bp = list_p; if (bp == NULL) return NULL; size_t min = 0; void *min_p = NULL; do { if (SIZE(bp) >= size) { if (min_p == NULL || SIZE(bp) < min) { min = SIZE(bp); min_p = bp; } } bp = (void *)GET_SUCC(bp); } while (bp != list_p); 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 >= MIN_BLOCK) { SET(HEAD(ptr), PACK(size, 1)); SET(FOOT(ptr), PACK(size, 1)); // DSIZE adjust size_t adjust_size = p_size - size - DSIZE; void *new_ptr = NEXT(ptr); SET(HEAD(new_ptr), PACK(adjust_size, 0)); SET(FOOT(new_ptr), PACK(adjust_size, 0)); if (ptr == tail_p) tail_p = new_ptr; // tweak list _fix_list(ptr, new_ptr); if (ptr == list_p) list_p = new_ptr; } else { SET(HEAD(ptr), PACK(p_size, 1)); SET(FOOT(ptr), PACK(p_size, 1)); // tweak list // remove SET(POS_SUCC(GET_PRED(ptr)), GET_SUCC(ptr)); SET(POS_PRED(GET_SUCC(ptr)), GET_PRED(ptr)); if (ptr == list_p) { if (GET_SUCC(ptr) == (size_t)ptr) list_p = NULL; else list_p = (void *)GET_SUCC(ptr); } } //#ifdef DEBUG // printf("----place----\n"); // _check(); // printf("-------------\n"); //#endif } static void _fix_list(void *in, void *out) { if (GET_SUCC(in) == (size_t)in) { SET(POS_SUCC(out), (size_t)out); SET(POS_PRED(out), (size_t)out); } else { SET(POS_SUCC(out), GET_SUCC(in)); SET(POS_PRED(out), GET_PRED(in)); SET(POS_SUCC(GET_PRED(in)), (size_t)out); SET(POS_PRED(GET_SUCC(in)), (size_t)out); } } static void _check() { int num1 = 0; int num2 = 0; int num3 = 0; void *bp = front_p; void *after_p = NEXT(tail_p); void *blank_p = NULL; while (bp != after_p) { if (!ALLOC(bp)) { if (blank_p == NULL) blank_p = bp; num1++; } bp = NEXT(bp); } bp = blank_p; do { if (bp != NULL) { bp = (void *)GET_SUCC(bp); num2++; } } while (bp != blank_p); bp = list_p; do { if (bp != NULL) { bp = (void *)GET_SUCC(bp); num3++; } } while (bp != list_p); printf("expect: %d, actual: %d, list_p: %d\n", num1, num2, num3); }