All pastes #365632 Raw Edit

Anonymous

public text v1 · immutable
#365632 ·published 2007-02-21 02:41 UTC
rendered paste body
static block_t *coalesce(block_t *bp) {
    /* 
     * ok i'm gonna do a ton of work in the initializing stage here so that
     * later the focus is on the coalescing logic and not pointer fuckery
     */
    /* address of first word in heap */
    unsigned int *lo = (unsigned int *) mem_heap_lo();
    /* address of last word in heap */
    unsigned int *hi = (unsigned int *) (((char *) mem_heap_hi()) - 3);
    /* addresses of prev and next words */
    unsigned int *prev_word = GET_PREV_WORD(bp);
    unsigned int *next_word = GET_NEXT_WORD(bp);
    /* are adjacent words in the heap? */
    int prev_in_range = prev_word >= lo;
    int next_in_range = prev_word <= hi;
    /* are prev and next free blocks that we can coalesce with? */
    int prev_free = prev_in_range ? (*prev_word & 1) : 0;
    int next_free = next_in_range ? (*next_word & 1) : 0;
    /* sizes of bp, prev, and next */
    size_t bp_sz = GET_SZ(bp);
    size_t prev_sz = prev_free ? (*prev_word & 0) : 0;
    size_t next_sz = next_free ? (*next_word & 0) : 0;
    /* pointers to prev, next, and the new coalesced block */
    /* 
     * we already have a ptr to one boundary tag, so only need to move by the
     * block size + 1 word to get to the header of the prev block
     */
    block_t *prev = prev_free ? ((block_t *) (prev_word - prev_sz - 1)) : NULL;
    /* already at the start of the next block */
    block_t *next = next_free ? ((block_t *) next_word) : NULL;
    block_t *new_block;
    
    /* case 1: prev and next both not free or out of range */
    if (!prev && !next) {
        /* don't coalesce anything */
        new_block = bp;
    }
    
    /* case 2: prev free, but next not free or out of range */
    else if (prev && !next) {
        /* take prev out of the list before doing anything */
        remove_blk(prev);
        /*
         * prev and bp will now become one block. its usable space is prev_sz +
         * bp_sz + 2 (former prev ftr and bp hdr)
         */
        SET_SZ_ALLOC(prev, prev_sz + bp_sz + 2, 0);
        /* and this new block starts where prev used to */
        new_block = prev;
        /* also init its ptrs to 0 */
        SET_PRED(new_block, 0);
        SET_SUCC(new_block, 0);
    }
    
    /* case 3: prev not free or out of range, but next free */
    else if (!prev && next) {
        /* take next out of the list before doing anything */
        remove_blk(next);
        /*
         * bp and next will now become one block. its usable space is bp_sz +
         * next_sz + 2 (former bp ftr and next hdr)
         */
        SET_SZ_ALLOC(bp, bp_sz + next_sz + 2, 0);
        /* and this new block starts where bp used to */
        new_block = bp;
        /* also init its ptrs to 0 */
        SET_PRED(new_block, 0);
        SET_SUCC(new_block, 0);
    }
    
    /* case 4: prev and next both free */
    else {
        /* take prev and next out of the list before doing anything */
        remove_blk(prev);
        remove_blk(next);
        /*
         * prev, bp, and next will now become one block. its usable space is 
         * prev_sz + bp_sz + next_sz + 2 (former prev ftr, bp hdr, bp ftr,
         * and next hdr)
         */
        SET_SZ_ALLOC(prev, prev_sz + bp_sz + next_sz + 4, 0);
        /* and this new block starts where prev used to */
        new_block = prev;
        /* also init its ptrs to 0 */
        SET_PRED(new_block, 0);
        SET_SUCC(new_block, 0);
    }
    
    return new_block;
}