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; }