|
|
|
@ -3,15 +3,6 @@ |
|
|
|
* ya_freelist.c |
|
|
|
*/ |
|
|
|
|
|
|
|
/* Block layout: |
|
|
|
* |
|
|
|
* -2 -1 0 size-4 size-3 |
|
|
|
* +------+------+-------- - - - - - - - --------+------+------+ |
|
|
|
* | prev | size | data... | size | next | |
|
|
|
* +------+------+-------- - - - - - - - --------+------+------+ |
|
|
|
* |
|
|
|
*/ |
|
|
|
|
|
|
|
/*----------*/ |
|
|
|
/* Includes */ |
|
|
|
/*----------*/ |
|
|
|
@ -35,7 +26,7 @@ intptr_t *fl_end = NULL; // sorted decreasing |
|
|
|
#ifdef YA_DEBUG |
|
|
|
void fl_debug_print() { |
|
|
|
for (intptr_t *block = fl_start; block != NULL; block = fl_next(block)) { |
|
|
|
printf("Free block %p:%ld\n", block, block_size(block)); |
|
|
|
ya_debug("%p:%ld\n", block, block_size(block)); |
|
|
|
} |
|
|
|
} |
|
|
|
#endif |
|
|
|
@ -62,11 +53,15 @@ void fl_alloc(intptr_t *block) { |
|
|
|
/* Adds the freed block to the appropriate in the free list, which is kept |
|
|
|
* in sorted increasing order. */ |
|
|
|
void fl_free(intptr_t *block) { |
|
|
|
intptr_t *next; |
|
|
|
for (next = fl_start; next && block < next; next = fl_next(next)) { |
|
|
|
// *whistle* |
|
|
|
if (!fl_start && !fl_end) { |
|
|
|
// add to empty list |
|
|
|
fl_set_prev(block, NULL); |
|
|
|
fl_set_next(block, NULL); |
|
|
|
fl_start = block; |
|
|
|
fl_end = block; |
|
|
|
return; |
|
|
|
} |
|
|
|
if (next == fl_start) { |
|
|
|
if (block < fl_start) { |
|
|
|
// preprend block to the free list |
|
|
|
fl_set_prev(block, NULL); |
|
|
|
fl_set_next(block, fl_start); |
|
|
|
@ -74,7 +69,7 @@ void fl_free(intptr_t *block) { |
|
|
|
fl_start = block; |
|
|
|
return; |
|
|
|
} |
|
|
|
if (!next) { |
|
|
|
if (block > fl_end) { |
|
|
|
// append block to the free list |
|
|
|
fl_set_prev(block, fl_end); |
|
|
|
fl_set_next(block, NULL); |
|
|
|
@ -83,6 +78,10 @@ void fl_free(intptr_t *block) { |
|
|
|
return; |
|
|
|
} |
|
|
|
// splice the block in the middle of the list |
|
|
|
intptr_t *next; |
|
|
|
for (next = fl_start; next && next < block; next = fl_next(next)) { |
|
|
|
// *whistle* |
|
|
|
} |
|
|
|
intptr_t *prev = fl_prev(next); |
|
|
|
fl_set_prev(block, prev); |
|
|
|
fl_set_next(block, next); |
|
|
|
@ -104,6 +103,47 @@ intptr_t *fl_find(intptr_t min_size) { |
|
|
|
/* Force split of free block [block_size] into [size, block_size - size]. */ |
|
|
|
void fl_split(intptr_t *block, intptr_t size) { |
|
|
|
fl_set_next(block, block+size); |
|
|
|
if (block == fl_end) { |
|
|
|
fl_end = block+size; |
|
|
|
} |
|
|
|
fl_set_prev(block+size, block); |
|
|
|
} |
|
|
|
|
|
|
|
void fl_join_next(intptr_t *block) { |
|
|
|
intptr_t *next = block + block_size(block); |
|
|
|
if (fl_next(block) == next) { |
|
|
|
// skip a block |
|
|
|
ya_debug("fl_join_next: %p:%ld + %p:%ld -> %p:%ld\n", |
|
|
|
block, block_size(block), next, block_size(next), |
|
|
|
block, block_size(block) + block_size(next)); |
|
|
|
fl_set_next(block, fl_next(next)); |
|
|
|
fl_set_prev(next, fl_prev(block)); |
|
|
|
if (fl_next(next) == NULL) { |
|
|
|
fl_end = block; |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
void fl_join_prev(intptr_t *block) { |
|
|
|
intptr_t *free_prev = fl_prev(block); |
|
|
|
if (!free_prev) { |
|
|
|
return; |
|
|
|
} |
|
|
|
// will not segfault because there is at least one block preceding |
|
|
|
intptr_t *prev = block - block[-4]; |
|
|
|
if (prev == free_prev) { |
|
|
|
ya_debug("fl_join_prev: %p:%ld + %p:%ld -> %p:%ld\n", |
|
|
|
block, block_size(block), prev, block_size(prev), |
|
|
|
prev, block_size(block) + block_size(prev)); |
|
|
|
fl_set_prev(block, fl_prev(prev)); |
|
|
|
fl_set_next(prev, fl_next(block)); |
|
|
|
if (fl_next(block) == NULL) { |
|
|
|
fl_end = prev; |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
void fl_join(intptr_t *block) { |
|
|
|
fl_join_next(block); |
|
|
|
fl_join_prev(block); |
|
|
|
} |