Beispiel #1
0
/*
    memmap_free_t* merge_block(memmap_free_t* mmap_left, memmap_free_t* mmap_right)

    Merges two contiguous block of free memory.

*/
memmap_free_t* merge_block(memmap_free_t* mmap_left, memmap_free_t* mmap_right) {
    memmap_t* mmap_left_alloc = (memmap_t*) mmap_left;
    memmap_t* mmap_right_alloc = (memmap_t*) mmap_right;
    if(is_last_in_memory(mmap_right_alloc)) {
        set_next_block(mmap_left_alloc, mmap_left_alloc);
    }
    else {
        set_next_block(mmap_left_alloc, get_next_block(mmap_right_alloc));
        set_prev_block(get_next_block(mmap_right_alloc), mmap_left_alloc);
    }

#ifdef DEBUG_MEMORY
    printf("Left: %d, right: %d ,", get_block_size(mmap_left_alloc),
           get_block_size(mmap_right_alloc));
#endif

    remove_free_block(mmap_right);
    remove_free_block(mmap_left);
    set_block_size(mmap_left_alloc, get_block_size(mmap_left_alloc) +
                   get_block_size(mmap_right_alloc));

#ifdef DEBUG_MEMORY
    printf("new left:  %d\n", get_block_size(mmap_left_alloc));
#endif

    return mmap_left;
}
Beispiel #2
0
static void place(hblock *bp, size_t newsize)
{  
    size_t csize = GET_SIZE(bp->header);

    if ((csize - newsize) >= 24) {
        bp->header = newsize | 0x1;
        bp->footer = bp->header;
        remove_free_block(bp);
        bp = (hblock *) NEXT_BLKP(bp);
        bp->header = (csize-newsize) | 0x0;
        bp->footer = bp->header; 
        coalesce(bp);
    }


    else {
        bp->header = csize | 0x1;
        bp->footer = bp->header;
        remove_free_block(bp);
    }
    /* Set the allocated bit of the header and footer */
    //bp->header |= 0x1;
    //bp->footer = bp->header;

    /* Set up the link for the free list */  
    //remove_free_block(bp);

    return;
}
/**********************************************************
 * 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)
{
	//printf("IN COALESCE\n");
	//printf("coalescing block ptr %p\n",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));
	//printf("sizeof size_t %08p\n",sizeof(size_t));

	if (prev_alloc && next_alloc) {       /* Case 1 */
		//printf("case 1\n");
		add_to_free_list(bp);	//add to the free list
		//print_ptr(bp);
		return bp;
	}
	else if (prev_alloc && !next_alloc) { /* Case 2 */

		//printf("case 2\n");
		size += GET_SIZE(HDRP(NEXT_BLKP(bp)));

		remove_free_block(NEXT_BLKP(bp)); //remove the free block from the free list
		PUT(HDRP(bp), PACK(size, 0));
		PUT(FTRP(bp), PACK(size, 0));
		add_to_free_list(bp);
		return (bp);
	}
	else if (!prev_alloc && next_alloc) { /* Case 3 */
		//printf("case 3\n");
		size += GET_SIZE(HDRP(PREV_BLKP(bp)));

		remove_free_block(PREV_BLKP(bp));
		PUT(FTRP(bp), PACK(size, 0));
		PUT(HDRP(PREV_BLKP(bp)), PACK(size, 0));
		add_to_free_list(PREV_BLKP(bp));
		//print_ptr(PREV_BLKP(bp));
		//print_ptr(bp);
		return (PREV_BLKP(bp));
	}
	else {            /* Case 4 */
		//printf("case 4\n");
		size += GET_SIZE(HDRP(PREV_BLKP(bp)))+GET_SIZE(FTRP(NEXT_BLKP(bp)));
		remove_free_block(PREV_BLKP(bp));
		remove_free_block(NEXT_BLKP(bp));
		PUT(HDRP(PREV_BLKP(bp)), PACK(size,0));
		PUT(FTRP(NEXT_BLKP(bp)), PACK(size,0));
		add_to_free_list(PREV_BLKP(bp));
		//print_ptr(bp);

		return (PREV_BLKP(bp));
	}
}
Beispiel #4
0
/*
 * place - Place block of asize bytes at start of free block bp
 *         and split if remainder would be at least minimum block size
 *         
 *  given a free block, removes free block from list and updates all relevant pointers 
 *
 */
static void place(void* bp, size_t asize) {

	size_t old_size = GET_SIZE(HDRP(bp));
	size_t prev_alloc = GET_PREV_ALLOC(HDRP(bp));
	size_t temp_value;

	dbg1("[IN ] : place()\n");

	/* remove free block from free list */
	remove_free_block(bp);

	/* check to see if block can be split up */

	dbg1("old_size=%ld, asize=%ld, compare=%d\n", old_size, asize, (int) OVERHEAD+2*DSIZE);
	
	if (old_size - asize >= OVERHEAD + 2*DSIZE) {

		/* block can be split up */
		PUT(HDRP(bp), PACK(asize, prev_alloc | 0x1));
		PUT(HDRP(NEXT_BLKP(bp)), PACK( old_size - asize, 0x2 ));
		PUT(FTRP(NEXT_BLKP(bp)), PACK( old_size - asize, 0x2 ));

		insert_free_block(NEXT_BLKP(bp));
	}
	else {
		/* just use entire block */
		PUT(HDRP(bp), PACK(old_size, prev_alloc | 0x1));
		temp_value = GET(HDRP(NEXT_BLKP(bp))) | 0x2;
		PUT(HDRP(NEXT_BLKP(bp)), temp_value);
	}

	dbg1("[OUT] : place()\n");

}
Beispiel #5
0
/* 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;
}
Beispiel #6
0
/**********************************************************
 * 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 int
 locate_group_section(struct pic32_section *s,
                        struct memory_region_struct *region) {

  struct pic32_memory *b;
  bfd_vma len = group_section_size(s);
  bfd_vma addr = s->sec->lma;
  int result = 0;

  /* DEBUG */
  if (pic32_debug)
    printf("  group section \"%s\", total size = %lx\n",
           s->sec->name, len);

  /* look for tricky user error */
  if (PIC32_IS_ABSOLUTE_ATTR(s->sec) && ACROSS_REGION(addr, len, region))
        einfo(_(" Link Warning: absolute section \'%s\' crosses"
                " the boundary of region %s.\n"),
              s->sec->name, region->name_list.name);

  if (len == 0)
    update_group_section_info(0,s,region); /* trivial case */
  else if (PIC32_IS_ABSOLUTE_ATTR(s->sec) &&
           OUTSIDE_REGION(addr, len, region)) {
    update_group_section_info(addr, s, region);  /* falls outside region */
  }
  else {                          /* locate using free_blocks list */
    b = select_free_block(s, len);
    if (b) {
      addr = b->addr + b->offset;
      update_group_section_info(addr,s,region);
      create_remainder_blocks(free_blocks,b,len);
      remove_free_block(b);
    } else {
      if (locate_options != NO_LOCATE_OPTION) {
        if (pic32_debug)
          printf("    \"%s\" location declined\n", s->sec->name);
        return 0;
      }
      result |= 1;
    }
  }

  if (pic32_debug)
    printf("    removing group from allocation list\n");
  pic32_remove_group_from_section_list(alloc_section_list);

  return result;
} /* locate_group_section() */
Beispiel #8
0
/**********************************************************
 * 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));
    }
}
/**********************************************************
 * mm_malloc
 * Allocate a block of size bytes.
 * The type of search is determined by find_fit
 * The decision of splitting the block, or not is determined
 *   in place(..)
 * If no block satisfies the request, the heap is extended
 **********************************************************/
void *mm_malloc(size_t size)
{
	//mm_check();
	//print_seg(0);
//	printf("IN MALLOC\n");
    size_t asize; /* adjusted block size */
    size_t extendsize; /* amount to extend heap if no fit */
    char * bp;

    /* Ignore spurious requests */
    if (size == 0)
        return NULL;

    /* Adjust block size to include overhead and alignment reqs. */
    if (size <= DSIZE)
        asize = 2 * DSIZE;
    else
        asize = DSIZE * ((size + (DSIZE) + (DSIZE-1))/ DSIZE);

    /* Search the free list for a fit */
    if ((bp = find_segregated_best_fit(asize)) != NULL) {

    	//printf("free size found, bp is %p\n",bp);
    	remove_free_block(bp);
        place(bp, asize);
        return bp;
    };

    /* No fit found. Get more memory and place the block */
    extendsize = MAX(asize, CHUNKSIZE);
    if ((bp = extend_heap(extendsize/WSIZE)) == NULL)
    {
        return NULL;
    }
    place(bp, asize);
    return bp;

}
static void *coalesce(void *bp) {
    
    dbg_printf("=== Coalesce bp = 0x%lx\n", (size_t)bp);
    
    void *prevbp = PREV_BLKP(bp);
    void *nextbp = NEXT_BLKP(bp);
    
    /*ONLY use the former alloc flag  */
    size_t prev_alloc = GET_PREV_ALLOC(GET_HEADER(bp)); /*GET_ALLOC(GET_FOOTER(prevbp));*/
    size_t next_alloc = GET_ALLOC(GET_HEADER(nextbp));
    size_t bsize = GET_SIZE(GET_HEADER(bp));
    size_t flag = 0;
    
    int class_idx = 0;
    
    /* case 1: make newly freed block to be root */
    if (prev_alloc && next_alloc) {
        
        dbg_printf("Coalesce Case 1\n");
        
        insert_first(bp);
        
        return bp;
        
    }
    /* case 3: next block is free */
    else if (prev_alloc && !next_alloc) {
        
        dbg_printf("Coalesce Case 3\n");
        
        class_idx = get_class_idx_by_size(GET_SIZE(GET_HEADER(nextbp)));
        remove_free_block(nextbp, class_idx);
        
        /* Telling coalesced free block about if bp's previous allocated */
        flag = GET_PREV_ALLOC(GET_HEADER(bp)) ? 0x2 : 0x0;
        
        bsize += GET_SIZE(GET_HEADER(nextbp));
        PUT(GET_HEADER(bp), PACK(bsize, flag));
        PUT(GET_FOOTER(bp), PACK(bsize, flag));
        
        insert_first(bp);
        
        return bp;
        
    }
    /* case 2: prev block is free */
    else if (!prev_alloc && next_alloc) {
        
        dbg_printf("Coalesce Case 2\n");
        
        class_idx = get_class_idx_by_size(GET_SIZE(GET_HEADER(prevbp)));
        
        dbg_printf("class_idx = %d, class_address = 0x%lx\n", class_idx, (size_t)GET_CLASS(class_idx));
        
        remove_free_block(prevbp, class_idx);
        
        /* Telling coalesced free block about if bp's previous's previous allocated */
        flag = GET_PREV_ALLOC(GET_HEADER(prevbp)) ? 0x2 : 0x0;
        
        if (flag == 0) {
            printf("Implies fail coalese: 0x%lx with former\n", (size_t)prevbp);
            exit(2);
        }
        
        bsize += GET_SIZE(GET_HEADER(prevbp));
        PUT(GET_HEADER(prevbp), PACK(bsize, flag));
        PUT(GET_FOOTER(prevbp), PACK(bsize, flag));
        
        insert_first(prevbp);
        
        return prevbp;
    }
    /* case 4: both blocks are free */
    else {
        
        dbg_printf("Coalesce Case 4\n");
        
        class_idx = get_class_idx_by_size(GET_SIZE(GET_HEADER(nextbp)));
        remove_free_block(nextbp, class_idx);
        class_idx = get_class_idx_by_size(GET_SIZE(GET_HEADER(prevbp)));
        remove_free_block(prevbp, class_idx);
        
        /* Telling coalesced free block about if bp's previous's previous allocated */
        flag = GET_PREV_ALLOC(GET_HEADER(prevbp)) ? 0x2 : 0x0;
        
        if (flag == 0) {
            printf("Implies fail coalese: 0x%lx with former\n", (size_t)prevbp);
            exit(2);
        }
        
        bsize += GET_SIZE(GET_HEADER(nextbp));
        bsize += GET_SIZE(GET_FOOTER(prevbp));
        PUT(GET_HEADER(prevbp), PACK(bsize, flag));
        PUT(GET_FOOTER(nextbp), PACK(bsize, flag));
        
        insert_first(prevbp);
        
        return prevbp;
    }
    
    dbg_printf("Unable to coalesce!\n");
    return NULL;
}
/* Place an ADJUSTED sized block in heap */
static void place(void *bp, size_t asize) {
    
#if DEBUG
    if (NEXT_BLKP(bp)) {
        if (GET_PREV_ALLOC(GET_HEADER(NEXT_BLKP(bp)))) {
            dbg_printf("0x%lx: Fail to inform next block when free\n", (size_t)bp);
            exit(2);
        }
    }
#endif
    
    dbg_printf("=== Place, bp = 0x%lx, adjusted size = %ld \n", (size_t)bp, asize);
    
    /* block free size */
    size_t csize = GET_SIZE(GET_HEADER(bp));
    char *nextbp = NULL;
    int class_idx = 0;
    size_t flag = 0;
    
    /* Split, say, minimum block size set to 1 WSIZE = 8 byte */
    if ((csize - asize) >= (4 * WSIZE)) {
        
        class_idx = get_class_idx_by_size(GET_SIZE(GET_HEADER(bp)));
        
        /* Include previous block's information */
        flag = GET_PREV_ALLOC(GET_HEADER(bp)) ? 0x3 : 0x1;
        
        PUT(GET_HEADER(bp), PACK(asize, flag));
        PUT(GET_FOOTER(bp), PACK(asize, flag));
        
        nextbp = NEXT_BLKP(bp);
        
        PUT(GET_HEADER(nextbp), PACK((csize - asize), 0));
        PUT(GET_FOOTER(nextbp), PACK((csize - asize), 0));
        
        /* Inform the next block that this block is allocated */
        flag = GET(GET_HEADER(nextbp));
        flag |= 0x2;
        PUT(GET_HEADER(nextbp), flag);
        PUT(GET_FOOTER(nextbp), flag);
        
        split_free_block(bp, nextbp);
        remove_free_block(bp, class_idx);
        
        remove_free_block(nextbp, class_idx);
        insert_first(nextbp);
        
        mm_checkheap(CHECK_HEAP);
        
    }
    else {
        /* Include previous block's information */
        flag = GET_PREV_ALLOC(GET_HEADER(bp)) ? 0x3 : 0x1;
        
        PUT(GET_HEADER(bp), PACK(csize, flag));
        PUT(GET_FOOTER(bp), PACK(csize, flag));
        
        /* Inform the next block that this block is allocated */
        if ((size_t)bp == 0x800004980) {
            dbg_printf("bp size = %ld\n",GET_SIZE(GET_HEADER(bp)));
            dbg_printf("NEXT_BLKP(bp); 0x%lx\n",(size_t)NEXT_BLKP(bp));
        }
        nextbp = NEXT_BLKP(bp);
        if (nextbp) {
            flag = GET(GET_HEADER(nextbp));
            flag |= 0x2;
            PUT(GET_HEADER(nextbp), flag);
            /* Only put footer when next block is free */
            if (!GET_ALLOC(GET_HEADER(nextbp))) {
                PUT(GET_FOOTER(nextbp), flag);
            }
            
        }
        
        remove_free_block(bp, get_class_idx_by_size(csize));
    }
}
Beispiel #12
0
/* 
 * coalesce - boundary tag coalescing. return ptr to coalesced block
 *
 */
static void* coalesce(void* bp) {

	size_t prev_alloc = GET_PREV_ALLOC(HDRP(bp));
	size_t next_alloc = GET_ALLOC(HDRP(NEXT_BLKP(bp)));
	size_t size = GET_SIZE(HDRP(bp));

	dbg1("[IN ] : coalesce()\n");

	switch (prev_alloc | next_alloc)
	{
		case 3:
			/* neither of the adjacent blocks are free */
			insert_free_block(bp);
			dbg1("[OUT] : coalesce() : neither of the adjacent blocks are free.\n");
			return bp;
		case 2:
			/* next block is free */
			size += GET_SIZE(HDRP(NEXT_BLKP(bp)));

			/* remove next block from free list */
			remove_free_block(NEXT_BLKP(bp));

			/* update header and footer pointers */
			PUT(HDRP(bp), PACK(size, prev_alloc));
			PUT(FTRP(bp), PACK(size, prev_alloc));

			/* insert new merged block into free list */
			insert_free_block(bp);
			dbg1("[OUT] : coalesce() : next block is free - merged \n");
			return(bp);
		case 1:
			/* prev block is free */
			size += GET_SIZE(HDRP(PREV_BLKP(bp)));

			/* remove this block from free list */
			remove_free_block(PREV_BLKP(bp));

			/* update header and footer pointers */
			prev_alloc = GET_PREV_ALLOC(HDRP(PREV_BLKP(bp)));
			PUT(FTRP(bp), PACK(size, prev_alloc));
			PUT(HDRP(PREV_BLKP(bp)), PACK(size, prev_alloc));

			/* insert new merged block into free list */
			insert_free_block(PREV_BLKP(bp));
			dbg1("[OUT] : coalesce() : previous block is free - merged \n");
			return(PREV_BLKP(bp));
		default:
			/* both previous and next blocks are free */
			size += GET_SIZE(HDRP(PREV_BLKP(bp))) + GET_SIZE(FTRP(NEXT_BLKP(bp)));

			/* remove next block from free list */
			remove_free_block(NEXT_BLKP(bp));

			/* remove this block from free list */
			remove_free_block(PREV_BLKP(bp));

			/* update header and footer pointers */
			prev_alloc = GET_PREV_ALLOC(HDRP(PREV_BLKP(bp)));
			PUT(HDRP(PREV_BLKP(bp)), PACK(size, prev_alloc));
			PUT(FTRP(NEXT_BLKP(bp)), PACK(size, prev_alloc));

			/* insert new merged block into free list */
			insert_free_block(PREV_BLKP(bp));

			dbg1("[OUT] : coalesce() : both previous and next blocks are free - merged \n");
			
			return(PREV_BLKP(bp));
	}
}
Beispiel #13
0
/* To extend the given exiting allocated block such that it can accommodate
 * at least new_sz bytes.
 */
int
extend_alloc_block(page_idx_t block_idx, size_t new_sz) {
    rb_tree_t* rbt = &alloc_info->alloc_blks;
    intptr_t alloc_sz;
    int res = rbt_search(rbt, block_idx, &alloc_sz);
#ifdef DEBUG
    ASSERT(res);
#else
    (void)res;
#endif

    int page_sz = alloc_info->page_size;
    int page_sz_log2 = alloc_info->page_size_log2;
    int min_page_num = (new_sz + page_sz - 1) >> page_sz_log2;

    page_id_t blk_id = page_idx_to_id(block_idx);
    int order = alloc_info->page_info[block_idx].order;

    /* step 1: The in-place block extension is done by merging its *following*
     *  free buddy to a form bigger block. The extension process repeats until
     *  we find a block bigger enough to accommodate the <new_sz> bytes.
     */
    int succ = 0;
    int ord;
    for (ord = order; ord <= alloc_info->max_order; ord++) {
        if (min_page_num <= (1 << ord)) {
            succ = 1;
            break;
        }

        page_id_t buddy_id = blk_id ^ (1 << ord);
        if (buddy_id < blk_id) {
            /* The buddy block must reside at higher address. */
            break;
        }

        int buddy_idx = page_id_to_idx(buddy_id);
        if (!rbt_search(&alloc_info->free_blks[ord], buddy_idx, NULL)) {
            /* bail out if the buddy is not available */
            break;
        }
    }

    /* This function is not supposed to shrink the existing block; therefore,
     * if the existing block is big enough to accommodate allocation request,
     * it need to return 0 to inform the caller that something fishy is
     * happening.
     */
    if (!succ || ord == order)
        return 0;

    /* Step 2: The previous step is merely a 'dry-run' of extension. This
     *  step is to perform real transformation.
     */
    int t;
    for (t = order; t < ord; t++) {
        page_id_t buddy_id = blk_id ^ (1 << t);
        int buddy_idx = page_id_to_idx(buddy_id);
        remove_free_block(buddy_idx, t, 0);
        reset_page_leader(alloc_info->page_info + buddy_idx);
    }

    migrade_alloc_block(block_idx, order, ord, new_sz);

    return 1;
}