static void place(void *bp, size_t asize) { //dbg_printf("place%p\n",bp); size_t csize = GET_SIZE(HDRP(bp)); // void *remain_blk; size_t remain_size=csize-asize; if ((remain_size) >= 16) { void *remain_blk; delete_free_block(bp); // size_t predoff=get_pred_offset(bp); // size_t succoff=get_succ_offset(bp); alloc_block(bp,asize); remain_blk= NEXT_BLKP(bp); PUT(HDRP(remain_blk), PACK(remain_size, 0)); PUT(FTRP(remain_blk), PACK(remain_size, 0)); add_free_block(remain_blk,remain_size); /*size_t re_off=get_offset(remain_blk); set_succ(remain_blk,succoff); set_pred(remain_blk,predoff); // if (predoff){ set_succ(get_addr(predoff),re_off); // } // else free_list=remain_blk; if (succoff){ set_pred(get_addr(succoff),re_off); }*/ } else { delete_free_block(bp); PUT(HDRP(bp), PACK(csize, 1)); PUT(FTRP(bp), PACK(csize, 1)); } }
/* Free the block whose first page (aka block leader) is specified * by "page_idx". return 1 on success and 0 otherwise. */ int free_block(page_idx_t page_idx) { (void)remove_alloc_block(page_idx); lm_page_t* pi = alloc_info->page_info; lm_page_t* page = pi + page_idx; int order = page->order; ASSERT (find_block(page_idx, order, NULL) == 0); /* Consolidate adjacent buddies */ int page_num = alloc_info->page_num; page_id_t page_id = page_idx_to_id(page_idx); int min_page_id = alloc_info->idx_2_id_adj; while (1) { page_id_t buddy_id = page_id ^ (1<<order); if (buddy_id < min_page_id) break; page_idx_t buddy_idx = page_id_to_idx(buddy_id); if (buddy_idx >= page_num || pi[buddy_idx].order != order || !is_page_leader(pi + buddy_idx) || is_allocated_blk(pi + buddy_idx)) { break; } remove_free_block(buddy_idx, order, 0); reset_page_leader(alloc_info->page_info + buddy_idx); page_id = page_id < buddy_id ? page_id : buddy_id; order++; } add_free_block(page_id_to_idx(page_id), order); return 1; }
/* * realloc */ void *realloc(void *ptr, size_t size) { size_t oldsize; void *newptr; /* If size == 0 then this is just free, and we return NULL. */ if(size == 0) { free(ptr); return 0; } /* If oldptr is NULL, then this is just malloc. */ if(ptr == NULL) { return malloc(size); } oldsize=GET_SIZE(HDRP(ptr)); size_t asize=(size+15)&(~0x7); if (asize==oldsize) { return ptr; } else if (asize<oldsize) { size_t free_size=oldsize-asize; if(free_size<16) { newptr=malloc(size); if(!newptr) { return 0; } memcpy(newptr,ptr,size); free(ptr); return newptr; } else { void *free_block=(void*)((char *)ptr+asize); alloc_block(ptr,asize); PUT(HDRP(free_block),PACK(free_size,0)); PUT(FTRP(free_block),PACK(free_size,0)); add_free_block(free_block); return ptr; } } else { newptr = malloc(size); /* If realloc() fails the original block is left untouched */ if(!newptr) { return 0; } /* Copy the old data. */ // oldsize = GET_SIZE(HDRP(ptr)); // if(size < oldsize) oldsize = size; memcpy(newptr, ptr, oldsize); /* Free the old block. */ free(ptr); return newptr; } return newptr; }
static void* coalesce(void *bp) //bp point to header { //dbg_printf("coalesce %p\n",bp); void *prev_blk=PREV_BLKP(bp); void *next_blk=NEXT_BLKP(bp); size_t prev_alloc = GET_ALLOC(FTRP(prev_blk)); size_t next_alloc = GET_ALLOC(HDRP(next_blk)); size_t size = GET_SIZE(HDRP(bp)); if (prev_alloc && next_alloc) { /* Case 1 */ dbg_printf("no coal%p\n",bp); add_free_block(bp,size); return bp; } else if (prev_alloc && !next_alloc) { /* Case 2 */ size += GET_SIZE(HDRP(next_blk)); delete_free_block(next_blk); PUT(HDRP(bp), PACK(size, 0)); PUT(FTRP(bp), PACK(size,0)); } else if (!prev_alloc && next_alloc) { /* Case 3 */ size += GET_SIZE(HDRP(prev_blk)); delete_free_block(prev_blk); PUT(FTRP(bp), PACK(size, 0)); PUT(HDRP(prev_blk), PACK(size, 0)); bp = prev_blk; } else { /* Case 4 */ size += GET_SIZE(HDRP(prev_blk)) + GET_SIZE(FTRP(next_blk)); delete_free_block(prev_blk); delete_free_block(next_blk); PUT(HDRP(prev_blk), PACK(size, 0)); PUT(FTRP(next_blk), PACK(size, 0)); bp = prev_blk; } add_free_block(bp,size); return bp; }
/********************************************************** * place * Mark the block as allocated. * Also create a new free block of the size difference if possible. **********************************************************/ void place(void* bp, size_t asize) { remove_free_block(bp); /* Get the current block size */ size_t bsize = GET_SIZE(HDRP(bp)); // Create a block of the size difference and insert it into the free list. if (bsize - asize > 8*DSIZE) { PUT(HDRP(bp), PACK(asize, 1)); PUT(FTRP(bp), PACK(asize, 1)); PUT(HDRP(NEXT_BLKP(bp)), PACK(bsize-asize, 0)); PUT(FTRP(NEXT_BLKP(bp)), PACK(bsize-asize, 0)); add_free_block(NEXT_BLKP(bp)); } else { PUT(HDRP(bp), PACK(bsize, 1)); PUT(FTRP(bp), PACK(bsize, 1)); } }
/********************************************************** * extend_heap * Extend the heap by "words" words, maintaining alignment * requirements of course. Free the former epilogue block * and reallocate its new header **********************************************************/ void *extend_heap(size_t words) { char *bp; size_t size; /* Allocate an even number of words to maintain alignments */ size = (words % 2) ? (words+1) * WSIZE : words * WSIZE; if ( (bp = mem_sbrk(size)) == (void *)-1 ) return NULL; logg(1, "extend_heap extends words: %zx(h)(size: %zx(h)); new bp: %p", words, size, bp); /* 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 add_free_block(bp); return bp; }
/* $begin coalesce */ static void *coalesce(void *bp) //bp point to header { void *prev_block=prev_blkp(bp); void *next_block=next_blkp(bp); uint32_t prev_alloc = GET_ALLOC(prev_block); uint32_t next_alloc = GET_ALLOC(next_block); uint32_t size = GET_SIZE(bp); if (prev_alloc && next_alloc) { /* Case 1 */ return bp; } else if (prev_alloc && !next_alloc) { /* Case 2 */ size += GET_SIZE(next_block); delete_free_block(next_block); PUT(bp, PACK(size, 0)); PUT(FTRP1(bp), PACK(size,0)); } else if (!prev_alloc && next_alloc) { /* Case 3 */ size += GET_SIZE(prev_block); delete_free_block(prev_block); PUT(FTRP1(bp), PACK(size, 0)); PUT(prev_block, PACK(size, 0)); bp = prev_block; } else { /* Case 4 */ size += GET_SIZE(prev_block) + GET_SIZE(next_block); delete_free_block(prev_block); delete_free_block(next_block); PUT(prev_block, PACK(size, 0)); PUT(FTRP1(next_block), PACK(size, 0)); bp = prev_block; } add_free_block(bp); return bp; }
/********************************************************** * coalesce * Covers the 4 cases discussed in the text: * - both neighbours are allocated * - the next block is available for coalescing * - the previous block is available for coalescing * - both neighbours are available for coalescing **********************************************************/ void *coalesce(void *bp) { logg(4, "============ coalesce() starts =============="); logg(1, "coalesce() called with bp: %p; Previous block: %p header: %zx; Next block: %p header: %zx", bp, PREV_BLKP(bp), GET(HDRP(PREV_BLKP(bp))), NEXT_BLKP(bp), GET(HDRP(NEXT_BLKP(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) { /* Case 1 */ logg(2, "Case 1: Both prev and next blocks are allocated. NO coalescing."); } else if (prev_alloc && !next_alloc) { /* Case 2 */ logg(2, "Case2: Next block is free."); size += GET_SIZE(HDRP(NEXT_BLKP(bp))); remove_free_block(NEXT_BLKP(bp)); PUT(HDRP(bp), PACK(size, 0)); PUT(FTRP(bp), PACK(size, 0)); } else if (!prev_alloc && next_alloc) { /* Case 3 */ logg(2, "Case3: Prev block is free."); size += GET_SIZE(HDRP(PREV_BLKP(bp))); remove_free_block(PREV_BLKP(bp)); bp = PREV_BLKP(bp); // move bp one block ahead PUT(HDRP(bp), PACK(size, 0)); PUT(FTRP(bp), PACK(size, 0)); } else { /* Case 4 */ logg(2, "Case4: Both blocks are free."); size += GET_SIZE(HDRP(PREV_BLKP(bp))) + GET_SIZE(HDRP(NEXT_BLKP(bp))) ; remove_free_block(NEXT_BLKP(bp)); remove_free_block(PREV_BLKP(bp)); bp = PREV_BLKP(bp); PUT(HDRP(bp), PACK(size,0)); PUT(FTRP(bp), PACK(size,0)); } // Add the bp block to the beginning of free list of corresponding size. add_free_block(bp); logg(4, "============ coalesce() ends =============="); return bp; }
static void place(void *bp, size_t asize){ size_t osize=GET_SIZE(bp); size_t remain_size=osize-asize; // size_t old_predaddr=pred_blka(bp); // size_t old_succaddr=succ_blka(bp); void *remain_block=(char *)bp+asize; if (remain_size>=16){ delete_free_block(bp); set_free_block(remain_block,remain_size,0); add_free_block(remain_block); } else{ delete_free_block(bp); } alloc_block(bp,asize); }
static void* coalesce_ex(void *bp) //bp point to header { dbg_printf("coalesce ex %p\n",bp); void *prev_blk=PREV_BLKP(bp); size_t prev_alloc = GET_ALLOC(FTRP(prev_blk)); size_t size = GET_SIZE(HDRP(bp)); if (prev_alloc ) { /* Case 1 */ add_free_block(bp); return bp; } else { /* Case 3 */ size += GET_SIZE(HDRP(prev_blk)); // delete_free_block(prev_blk); PUT(FTRP(bp), PACK(size, 0)); PUT(HDRP(prev_blk), PACK(size, 0)); bp = prev_blk; } //add_free_block(bp); return bp; }
/* Initialize the page allocator, return 1 on success, 0 otherwise. */ int lm_init_page_alloc(lm_chunk_t* chunk, ljmm_opt_t* mm_opt) { if (!chunk) { /* Trunk is not yet allocated */ return 0; } if (alloc_info) { /* This function was succesfully invoked before */ return 1; } int page_num = chunk->page_num; if (unlikely(mm_opt != NULL)) { int pn = mm_opt->dbg_alloc_page_num; if (((pn > 0) && (pn > page_num)) || !pn) return 0; else if (pn > 0) { page_num = pn; } if (!bc_set_parameter(mm_opt->enable_block_cache, mm_opt->blk_cache_in_page)) { return 0; } } int alloc_sz = sizeof(lm_alloc_t) + sizeof(lm_page_t) * (page_num + 1); alloc_info = (lm_alloc_t*) MYMALLOC(alloc_sz); if (!alloc_info) { errno = ENOMEM; return 0; } alloc_info->first_page = chunk->base; alloc_info->page_num = page_num; alloc_info->page_size = chunk->page_size; alloc_info->page_size_log2 = log2_int32(chunk->page_size); /* Init the page-info */ char* p = (char*)(alloc_info + 1); int align = __alignof__(lm_page_t); p = (char*)((((intptr_t)p) + align - 1) & ~align); alloc_info->page_info = (lm_page_t*)p; int i; lm_page_t* pi = alloc_info->page_info; for (i = 0; i < page_num; i++) { pi[i].order = INVALID_ORDER; pi[i].flags = 0; } /* Init the buddy allocator */ int e; rb_tree_t* free_blks = &alloc_info->free_blks[0]; for (i = 0, e = MAX_ORDER; i < e; i++) rbt_init(&free_blks[i]); rbt_init(&alloc_info->alloc_blks); /* Determine the max order */ int max_order = 0; unsigned int bitmask; for (bitmask = 0x80000000/*2G*/, max_order = 31; bitmask; bitmask >>= 1, max_order --) { if (bitmask & page_num) break; } alloc_info->max_order = max_order; /* So, the ID of biggest block's first page is "1 << order". e.g. * Suppose the chunk contains 11 pages, which will be divided into 3 * blocks, eaching containing 1, 2 and 8 pages. The indices of these * blocks are 0, 1, 3 respectively, and their IDs are 5, 6, and 8 * respectively. In this case: * alloc_info->idx_2_id_adj == 5 == page_id(*) - page_idx(*) */ int idx_2_id_adj = (1 << max_order) - (page_num & ((1 << max_order) - 1)); alloc_info->idx_2_id_adj = idx_2_id_adj; /* Divide the chunk into blocks, smaller block first. Smaller blocks * are likely allocated and deallocated frequently. Therefore, they are * better off residing closer to data segment. */ int page_idx = 0; int order = 0; for (bitmask = 1, order = 0; bitmask != 0; bitmask = bitmask << 1, order++) { if (page_num & bitmask) { add_free_block(page_idx, order); page_idx += (1 << order); } } /*init the block cache */ bc_init(); return 1; }
static void* coalesce_free(void *bp) //bp point to header { dbg_printf("coalesce free %p\n",bp); void *prev_blk=PREV_BLKP(bp); void *next_blk=NEXT_BLKP(bp); size_t prev_alloc = GET_ALLOC(FTRP(prev_blk)); size_t next_alloc = GET_ALLOC(HDRP(next_blk)); size_t size = GET_SIZE(HDRP(bp)); if (prev_alloc && next_alloc) { /* Case 1 */ add_free_block(bp); return bp; } else if (prev_alloc && !next_alloc) { /* Case 2 */ size += GET_SIZE(HDRP(next_blk)); //delete_free_block(next_blk); PUT(HDRP(bp), PACK(size, 0)); PUT(FTRP(bp), PACK(size,0)); size_t predoff=get_pred_offset(next_blk); size_t succoff=get_succ_offset(next_blk); set_pred(bp,predoff); set_succ(bp,succoff); if(predoff) { set_succ(get_addr(predoff),get_offset(bp)); } else { free_list=bp; } if(succoff) set_pred(get_addr(succoff),get_offset(bp)); } else if (!prev_alloc && next_alloc) { /* Case 3 */ size += GET_SIZE(HDRP(prev_blk)); // delete_free_block(prev_blk); PUT(FTRP(bp), PACK(size, 0)); PUT(HDRP(prev_blk), PACK(size, 0)); bp = prev_blk; } else { /* Case 4 */ size += GET_SIZE(HDRP(prev_blk)) + GET_SIZE(FTRP(next_blk)); //size_t predoff=get_pred_offset(prev_blk); size_t succoff=get_succ_offset(next_blk); //delete_free_block(prev_blk); //delete_free_block(next_blk); PUT(HDRP(prev_blk), PACK(size, 0)); PUT(FTRP(next_blk), PACK(size, 0)); bp = prev_blk; //set_pred(bp,predoff); set_succ(bp,succoff); //if(predoff){ //set_succ(get_addr(predoff),get_offset(bp)); //free_list=bp; // } if(succoff) set_pred(get_addr(succoff),get_offset(bp)); } // add_free_block(bp); return bp; }