|
|
- /*
- * mm-naive.c - The clear list, first fit malloc package.
- */
- #include <string.h>
-
- #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 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 ADDRESS (sizeof(unsigned long))
- #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) (*(word *)POS_PRED(bp))
- #define GET_SUCC(bp) (*(word *)POS_SUCC(bp))
-
- typedef unsigned long 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
- * @param size align by 8, excluding head and foot
- * @return
- */
- static void *_first_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 = _first_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
- SET(POS_SUCC(GET_PRED(next)), GET_SUCC(next));
- SET(POS_PRED(GET_SUCC(next)), GET_PRED(next));
- if (next == list_p) {
- if (GET_SUCC(next) == (word)next) list_p = NULL;
- else list_p = (void *)GET_SUCC(next);
- }
- SET(HEAD(ptr), PACK(total_size, 1));
- SET(FOOT(ptr), PACK(total_size, 1));
- if (next == tail_p) tail_p = ptr;
- 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), (word)list_p);
- SET(POS_PRED(list_p), (word)list_p);
- } else {
- // add to list
- SET(POS_SUCC(bp), GET_SUCC(list_p));
- SET(POS_PRED(bp), (word)list_p);
- SET(POS_PRED(GET_SUCC(list_p)), (word)bp);
- SET(POS_SUCC(list_p), (word)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 _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) == (word)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) == (word)in) {
- SET(POS_SUCC(out), (word)out);
- SET(POS_PRED(out), (word)out);
- } else {
- SET(POS_SUCC(out), GET_SUCC(in));
- SET(POS_PRED(out), GET_PRED(in));
- SET(POS_SUCC(GET_PRED(in)), (word)out);
- SET(POS_PRED(GET_SUCC(in)), (word)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);
- }
|