/* ** Merge as possible the next block or/and ** the previous block with the current parameter. ** Return the new address of the current block. */ t_ptr heap_merge(t_ptr block) { size_t size; size_t prev_state; size_t next_state; assert(!IS_B_ALLOC(block)); size = GET_B_SIZE(block); prev_state = IS_B_ALLOC(GET_PREV(block)); next_state = IS_B_ALLOC(GET_NEXT(block)); if (!prev_state) { size += GET_B_SIZE(GET_PREV(block)); if (!next_state) size += GET_B_SIZE(GET_NEXT(block)); SET(GET_HEAD(GET_PREV(block)), PACK(size, 0)); SET(GET_FOOT(GET_PREV(block)), PACK(size, 0)); block = GET_PREV(block); } else if (!next_state) { size += GET_B_SIZE(GET_NEXT(block)); SET(GET_HEAD(block), PACK(size, 0)); SET(GET_FOOT(block), PACK(size, 0)); } return (block); }
/* * place block */ void *place(void *bp, size_t size){ void *free_bp; size_t full_size = GET_SIZE(bp); //size of the free block before place /* not split the free block for small allocation or small space left */ if ((full_size - size) < FSIZE || size < FSIZE ){ /* reset hdr/ftr the alloc bit */ PUT(HDRP(bp), PACK(full_size, 1)); PUT(FTRP(bp), PACK(full_size, 1)); /* delete from free list */ SET_NEXT(GET_PREV(bp), GET_NEXT(bp)); SET_PREV(GET_NEXT(bp), GET_PREV(bp)); return bp; } /* after alloc size bytes, * the original free block still have bytes in the tail, * split the free block into two parts: |alloc one|free one| */ free_bp = bp + size; /* reset ftr/hdr of the new free block*/ PUT(HDRP(free_bp), PACK(full_size-size, 0)); PUT(FTRP(free_bp), PACK(full_size-size, 0)); /* add it to free list, also delete the original free block from list */ SET_NEXT(free_bp, GET_NEXT(bp)); SET_PREV(free_bp, GET_PREV(bp)); SET_NEXT(GET_PREV(bp), free_bp); SET_PREV(GET_NEXT(bp), free_bp); /* set hdr/ftr of alloc block */ PUT(HDRP(bp), PACK(size, 1)); PUT(FTRP(bp), PACK(size, 1)); return bp; }
/* remove an element from the freelist */ void fl_remove(void* ptr) { void** freelist = (void**)(master->ptr+WSIZE); unsigned int size = GETSIZE(ptr); int idx = log_two(size) - 4; /* void* curr = freelist[idx]; void* prev = NULL; while ((curr- ptr)!=0 && (curr != NULL)) { prev = curr; curr = GET_NEXT(curr); } */ //if (curr == NULL) return; //shouldn't really happen if (GET_NEXT(ptr) != NULL) PUT_PREV(GET_NEXT(ptr),GET_PREV(ptr)); if (GET_PREV(ptr) == NULL) //ptr is the first element { freelist[idx] = GET_NEXT(ptr); } else { PUT_NEXT(GET_PREV(ptr), GET_NEXT(ptr)); } //return; }
int validFreeList(char *bp) { #ifdef DEBUG char *hdr ; int prevOffset ; // int offset = (int)(((long)(HDRP(firstFBP))) - (long)(heapStart)) ; // offset between first block and heap start char * curr = firstFBP ; if(curr == NULL) return 1 ; //int nextOffset = DEREF_NEXT(curr) ; while(curr != heapStart) //curr == heapStart if next field is NULL/0 { hdr = HDRP(curr) ; if(GETALLOC(hdr)) return 0 ; // block is not free if(!isValidBlock(curr)) return 0 ; prevOffset = DEREF_PREV(curr) ; if((prevOffset != 0 && GETALLOC(HDRP(GET_PREV(curr)))) || (DEREF_NEXT(curr) != 0 && GETALLOC(HDRP(GET_NEXT(curr))))) { // if prev or next is not free return 0 ; } ASSERT((GET_NEXT(curr)==heapStart) || GET_PREV(GET_NEXT(curr)) == curr) ; curr = GET_NEXT(curr) ; // dbg_printf("Curr->next = %d \n", DEREF_NEXT(curr)) ; // nextOffset = DEREF_NEXT(curr) ; //no effect if curr == heapStart } return 1 ; #else return 1 ; #endif }
/* * coalesce next block with current block * this method only called by coalesce, * pre-condistion is bp block is free and its next block in heap is free too, * so we merge them */ void coalesce_next(void *bp){ size_t size = GET_SIZE(bp); void *next_bp = NEXT_BLKP(bp); /* delete next_bp from free list */ SET_NEXT(GET_PREV(next_bp), GET_NEXT(next_bp)); SET_PREV(GET_NEXT(next_bp), GET_PREV(next_bp)); /* reset hdr/ftr of the new free block */ size += GET_SIZE(NEXT_BLKP(bp)); PUT(HDRP(bp), PACK(size, 0)); PUT(FTRP(bp), PACK(size, 0)); }
static buddy_block_t *buddy_remove_free(buddy_ctxt_t *buddy, int index, int order) { buddy_block_t *block = buddy->all + index; int index_next = GET_NEXT(block); int index_prev = GET_PREV(block); buddy_block_t *next = buddy->all + index_next; buddy_block_t *prev = buddy->all + index_prev; /* adjust next/prev index + free list */ if(index_prev == index) { if(index_next == index) { buddy->free[order] = -1; } else { buddy->free[order] = index_next; next->prev = (next->prev & MASK_ORDER) | index_next; } } else { if(index_next == index) { prev->next = (prev->next & MASK_ORDER) | index_prev; } else { next->prev = (next->prev & MASK_ORDER) | index_prev; prev->next = (prev->next & MASK_ORDER) | index_next; } } return block; }
void buddy_dump(buddy_ctxt_t *buddy) { int i; printf(" <BUDDY BASE=%x MAX=%d ORDER=%d>\n", buddy->base, buddy->index_max, buddy->order); for(i = 0; i < buddy->order; i++) { int next, index = buddy->free[i]; if(index != -1) { printf(" <ORDER %d>\n", i); for(;;) { buddy_block_t *block = buddy->all + index; if(index < 0 || index >= buddy->index_max) { printf(" <BLOCK *** ERROR index=%d ***>", index); } else { addr_t start = buddy->base + (index<< buddy->page_bits); addr_t end = start + (1UL << (GET_ORDER(block) + buddy->page_bits)); printf(" <BLOCK %s A=%x-%x ORDER=%d ME=%d NEXT=%d PREV=%d>\n", IS_FREE(block) ? "free" : "in use", start, end, GET_ORDER(block), index, GET_NEXT(block), GET_PREV(block) ); } next = GET_NEXT(block); if(index == next) break; index = next; } } } }
static void FL_remove(char *bp) //remove block from free list given free block bp { ASSERT(bp != NULL) ; ASSERT(GETALLOC(bp) == 0) ; ASSERT(bp != epilogue && bp != prologue && bp != heapStart) ; if(bp == NULL) return ; else if(DEREF_NEXT(bp) == 0 && DEREF_PREV(bp) == 0) { // if list has only 1 element make list empty firstFBP = NULL ; return ; } char *next_bp = GET_NEXT(bp) ; char *prev_bp = GET_PREV(bp) ; if(next_bp == heapStart && prev_bp == heapStart) { firstFBP = NULL ; // empty free list return ; } else if(next_bp == heapStart) { //prev_bp != heapStart SET_NEXT(prev_bp, 0) ; //if bp is end node in free list next->prev = 0 return ; } else if (prev_bp == heapStart) { SET_PREV(next_bp, 0) ; // if bp is start node, next->prev = 0 firstFBP = next_bp ; // change firstFBP to point to new bp ASSERT(DEREF_PREV(firstFBP) == 0) ; return ; } // normal case SET_PREV(next_bp, DEREF_PREV(bp)) ; SET_NEXT(prev_bp, DEREF_NEXT(bp)) ; // prev->next = curr->next return ; }
static void rm_free(void *bp) { //bp->prev->next = bp->next; //bp->next->prev = bp->prev; size_t *prev = GET_PREV(bp); size_t *next = GET_NEXT(bp); if(prev) SET_NEXT(prev, next); else free_listp = next; if(next) SET_PREV(next, prev); }
static void *coalesce(void *bp) { size_t size = GET_SIZE(bp); size_t prev_alloc = GET_PRE_ALLOC_INFO(bp); size_t next_alloc = GET_ALLOC( GET_NEXT(bp) ); if ( prev_alloc && next_alloc ){ /* Case 0 */ return bp; } else if ( !prev_alloc && next_alloc ) { /* Case 1*/ void * prev = (void *)GET_PREV(bp); size_t sign = 0 | GET_PRE_ALLOC_INFO(prev) | GET_PRE_8_INFO(prev); delete_node(prev); size += GET_SIZE( prev ); PUT_HDRP( prev, PACK(size, sign) ); PUT_FTRP( prev, PACK(size, sign) ); return prev; } else if ( prev_alloc && !next_alloc ) { /* Case 2 */ size += GET_SIZE( GET_NEXT(bp) ); delete_node( GET_NEXT(bp) ); size_t sign = 0 | GET_PRE_ALLOC_INFO(bp) | GET_PRE_8_INFO(bp); PUT_HDRP( bp, PACK(size,sign) ); PUT_FTRP( bp, PACK(size,sign) ); return bp; } else { /* Case 3 */ void * prev = (void *)GET_PREV(bp); void * next = (void *)GET_NEXT(bp); size += GET_SIZE( prev ) + GET_SIZE( next ); delete_node( prev ); delete_node( next ); size_t sign = 0 | GET_PRE_ALLOC_INFO(bp) | GET_PRE_8_INFO(bp); PUT_HDRP( prev, PACK(size,sign) ); PUT_FTRP( prev, PACK(size,sign) ); return prev; } }
void LLrem(char *bp) { unsigned int next = GET_NEXT(bp); unsigned int prev = GET_PREV(bp); if(prev == 0)// bp is head of list { free_list = (char *) next; if(next != 0) { SET_PREV((char *)next, NULL); } } else { SET_NEXT((char *) prev, next); if(next != 0) { SET_PREV((char *) next, prev); } } }
/* * mm_checkheap */ void mm_checkheap(int lineno) { void *bp = heap_listp; int last_free = 0; int count = 0; //how many free blocks /* check prologue */ if (GET(bp) != PACK(DSIZE, 1)){ printf("wrong prologue, at line: %d\n",lineno); } while (1){ if (GET_SIZE(bp) == 0 && GET_ALLOC(bp) == 1){ /* reach epilogue */ if (bp-1 != mem_heap_hi()){ printf("wrong epilogue,%d\n",lineno); } break; }else{ /* check aligned */ if (!aligned(bp)){ printf("not aligned, at line: %d!\n", lineno); } /* check ftr == hdr */ if (GET(HDRP(bp)) != GET(FTRP(bp))){ printf("hdr != ftr, at line: %d!\n", lineno); } /* check no consecutive free block */ if (last_free && GET_ALLOC(bp) == 0){ printf("consecutive free blocks, at line: %d!\n", lineno); } last_free = !GET_ALLOC(bp); count += last_free; bp = NEXT_BLKP(bp); } } /* check blocks in explicit free list are all free */ bp = free_listp; while(1){ bp = GET_NEXT(bp); /* check if reach end */ if (GET_NEXT(bp) == 0){ break; }else{ /* check free */ if (GET_ALLOC(bp)){ printf("allocated block in free list! at line: %d!\n", lineno); } /* check cur.next.prev == cur and cur.prev.next == cur */ if (GET_PREV(GET_NEXT(bp)) != bp || GET_NEXT(GET_PREV(bp)) != bp){ printf("inconsistent pointers! at line: %d!\n", lineno); } if (!in_heap(bp)){ printf("not in heap! at line: %d\n", lineno); } count--; } } /* check free block numbers are the same through two traversing methods */ if (count){ printf("inconsistent free block numbers in two checks!, at line: %d\n", lineno); } }