123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133 |
- #include <assert.h>
- #include "private.h"
- #include "context.h"
- #include "node.h"
- /*--------------------------------------------------------- */
- static void
- lub_heap_free_leading_memory(lub_heap_t * this,
- lub_heap_block_t * block, size_t size)
- {
- lub_heap_block_t *prev_block = lub_heap_block_getprevious(block);
- if (prev_block && prev_block->free.tag.free) {
- /*
- * add the excess bytes to a preceeding free block
- */
- lub_heap_graft_to_top(this,
- prev_block,
- block,
- (size >> 2), BOOL_FALSE, BOOL_FALSE);
- } else {
- /*
- * convert the excess bytes into a free block
- */
- lub_heap_init_free_block(this,
- block,
- size,
- block->alloc.tag.segment, BOOL_FALSE);
- }
- this->stats.alloc_bytes -= size;
- }
- /*--------------------------------------------------------- */
- static void
- lub_heap_free_trailing_memory(lub_heap_t * this,
- lub_heap_block_t * block, size_t size)
- {
- bool_t done = BOOL_FALSE;
- lub_heap_block_t *next_block = lub_heap_block_getnext(block);
- lub_heap_tag_t *tail = lub_heap_block__get_tail(block);
- char *ptr = (char *)&tail[1] - size;
- if (next_block && next_block->free.tag.free) {
- /*
- * try and add the excess bytes to a following free block
- */
- lub_heap_graft_to_bottom(this,
- next_block,
- ptr,
- (size >> 2), BOOL_FALSE, BOOL_FALSE);
- done = BOOL_TRUE;
- } else if (size >= sizeof(lub_heap_free_block_t)) {
- /*
- * convert the excess bytes into a free block
- */
- lub_heap_init_free_block(this,
- ptr, size, BOOL_FALSE, tail->segment);
- done = BOOL_TRUE;
- }
- if (done) {
- /* correct the word count for the block */
- block->alloc.tag.words -= (size >> 2);
- tail = lub_heap_block__get_tail(block);
- tail->segment = 0;
- tail->free = 0;
- tail->words = block->alloc.tag.words;
- this->stats.alloc_bytes -= size;
- }
- }
- /*--------------------------------------------------------- */
- void
- lub_heap_align_block(lub_heap_t * this,
- lub_heap_align_t alignment, char **ptr, size_t * size)
- {
- if (*ptr) {
- lub_heap_block_t *block = lub_heap_block_from_ptr(*ptr);
- lub_heap_block_t *new_block;
- lub_heap_tag_t *new_tail;
- /* find the second occurance of an alignment boundary */
- size_t tmp = (alignment - 1);
- char *new_ptr =
- (char *)(((size_t) * ptr + tmp + alignment) & ~tmp);
- size_t leading_bytes = (new_ptr - *ptr);
- size_t trailing_bytes;
- /* check this is a allocated block */
- assert(0 == block->alloc.tag.free);
- /*
- * We MUST have left sufficient space to fit a free block and
- * leak dection node if necessary.
- */
- assert(leading_bytes >=
- (sizeof(lub_heap_free_block_t) +
- sizeof(lub_heap_node_t)));
- if ((0 < lub_heap_frame_count) && (0 == this->suppress)) {
- /*
- * If leak detection is enabled then offset the pointer back by the size of
- * a lub_heap_node; which will be filled out by lub_heap_post_realloc()
- */
- new_ptr -= sizeof(lub_heap_node_t);
- leading_bytes -= sizeof(lub_heap_node_t);
- }
- /*
- * Create a new header just before the new pointer
- */
- new_block = lub_heap_block_from_ptr(new_ptr);
- new_block->alloc.tag.free = 0;
- new_block->alloc.tag.segment = 0;
- new_block->alloc.tag.words =
- block->alloc.tag.words - (leading_bytes >> 2);
- /* fix the size in the tail */
- new_tail = lub_heap_block__get_tail(new_block);
- new_tail->words = new_block->alloc.tag.words;
- lub_heap_free_leading_memory(this, block, leading_bytes);
- /* identify any trailing excess memory */
- trailing_bytes =
- (new_block->alloc.tag.words << 2) - (*size -
- (alignment << 1));
- if (trailing_bytes) {
- lub_heap_free_trailing_memory(this,
- new_block,
- trailing_bytes);
- }
- *size = (new_block->alloc.tag.words << 2); /* size including the lub_heap_alloc_block_t details */
- *ptr = new_ptr;
- }
- }
|