// k_heap_compress - Merge free blocks // This function "compresses" the linked list, consolidating as many adjacent free blocks as possible, to reduce fragmentation. int k_heap_compress() { k_heap_blk* blk = heap.start; k_heap_blk* next = NULL; int blks_deleted = 0; __dynmem_lock.lock_cli(); while((blk != NULL) && (blk->next != NULL)) { // Don't compress the first or last block in the heap. next = blk->next; if(blk->prev != NULL) { if(!blk->used && !blk->prev->used) { // If both the current block and the one before it are free... // ...then _delete_ this block. k_heap_delete(blk); blks_deleted++; } } blk = next; } if((heap.end->prev != NULL) && (!heap.end->prev->used)) { k_heap_delete(heap.end); blks_deleted++; } __dynmem_lock.unlock_cli(); return blks_deleted; }
// k_heap_add_at_offset - Add a new heap block // This function places a new heap block in memory, linked to an "origin" block. void k_heap_add_at_offset(k_heap_blk* origin_blk, int block_offset) { __dynmem_lock.lock_cli(); k_heap_blk* blk = (k_heap_blk*)((size_t)origin_blk+(block_offset*HEAP_BLK_SIZE)); blk->prev = origin_blk; blk->next = origin_blk->next; blk->magic = HEAP_MAGIC_NUMBER; blk->prev->next = blk; if(blk->next != NULL) blk->next->prev = blk; else heap.end = blk; __dynmem_lock.unlock_cli(); }
// k_heap_delete - Unlink a block // This function removes a block from the linked list, effectively "deleting" it. void k_heap_delete(k_heap_blk* blk) { __dynmem_lock.lock_cli(); if(blk == NULL) { panic("dynmem: Attempted to delete NULL block!"); } if(blk->prev != NULL) { blk->prev->next = blk->next; } else { return; // can't delete the first block } if(blk->next != NULL) { blk->next->prev = blk->prev; } else { heap.end = blk->prev; } blk->next = NULL; blk->prev = NULL; blk->magic = 0; blk->used = false; __dynmem_lock.unlock_cli(); }