heap_align_block.c 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133
  1. #include <assert.h>
  2. #include "private.h"
  3. #include "context.h"
  4. #include "node.h"
  5. /*--------------------------------------------------------- */
  6. static void
  7. lub_heap_free_leading_memory(lub_heap_t * this,
  8. lub_heap_block_t * block, size_t size)
  9. {
  10. lub_heap_block_t *prev_block = lub_heap_block_getprevious(block);
  11. if (prev_block && prev_block->free.tag.free) {
  12. /*
  13. * add the excess bytes to a preceeding free block
  14. */
  15. lub_heap_graft_to_top(this,
  16. prev_block,
  17. block,
  18. (size >> 2), BOOL_FALSE, BOOL_FALSE);
  19. } else {
  20. /*
  21. * convert the excess bytes into a free block
  22. */
  23. lub_heap_init_free_block(this,
  24. block,
  25. size,
  26. block->alloc.tag.segment, BOOL_FALSE);
  27. }
  28. this->stats.alloc_bytes -= size;
  29. }
  30. /*--------------------------------------------------------- */
  31. static void
  32. lub_heap_free_trailing_memory(lub_heap_t * this,
  33. lub_heap_block_t * block, size_t size)
  34. {
  35. bool_t done = BOOL_FALSE;
  36. lub_heap_block_t *next_block = lub_heap_block_getnext(block);
  37. lub_heap_tag_t *tail = lub_heap_block__get_tail(block);
  38. char *ptr = (char *)&tail[1] - size;
  39. if (next_block && next_block->free.tag.free) {
  40. /*
  41. * try and add the excess bytes to a following free block
  42. */
  43. lub_heap_graft_to_bottom(this,
  44. next_block,
  45. ptr,
  46. (size >> 2), BOOL_FALSE, BOOL_FALSE);
  47. done = BOOL_TRUE;
  48. } else if (size >= sizeof(lub_heap_free_block_t)) {
  49. /*
  50. * convert the excess bytes into a free block
  51. */
  52. lub_heap_init_free_block(this,
  53. ptr, size, BOOL_FALSE, tail->segment);
  54. done = BOOL_TRUE;
  55. }
  56. if (done) {
  57. /* correct the word count for the block */
  58. block->alloc.tag.words -= (size >> 2);
  59. tail = lub_heap_block__get_tail(block);
  60. tail->segment = 0;
  61. tail->free = 0;
  62. tail->words = block->alloc.tag.words;
  63. this->stats.alloc_bytes -= size;
  64. }
  65. }
  66. /*--------------------------------------------------------- */
  67. void
  68. lub_heap_align_block(lub_heap_t * this,
  69. lub_heap_align_t alignment, char **ptr, size_t * size)
  70. {
  71. if (*ptr) {
  72. lub_heap_block_t *block = lub_heap_block_from_ptr(*ptr);
  73. lub_heap_block_t *new_block;
  74. lub_heap_tag_t *new_tail;
  75. /* find the second occurance of an alignment boundary */
  76. size_t tmp = (alignment - 1);
  77. char *new_ptr =
  78. (char *)(((size_t) * ptr + tmp + alignment) & ~tmp);
  79. size_t leading_bytes = (new_ptr - *ptr);
  80. size_t trailing_bytes;
  81. /* check this is a allocated block */
  82. assert(0 == block->alloc.tag.free);
  83. /*
  84. * We MUST have left sufficient space to fit a free block and
  85. * leak dection node if necessary.
  86. */
  87. assert(leading_bytes >=
  88. (sizeof(lub_heap_free_block_t) +
  89. sizeof(lub_heap_node_t)));
  90. if ((0 < lub_heap_frame_count) && (0 == this->suppress)) {
  91. /*
  92. * If leak detection is enabled then offset the pointer back by the size of
  93. * a lub_heap_node; which will be filled out by lub_heap_post_realloc()
  94. */
  95. new_ptr -= sizeof(lub_heap_node_t);
  96. leading_bytes -= sizeof(lub_heap_node_t);
  97. }
  98. /*
  99. * Create a new header just before the new pointer
  100. */
  101. new_block = lub_heap_block_from_ptr(new_ptr);
  102. new_block->alloc.tag.free = 0;
  103. new_block->alloc.tag.segment = 0;
  104. new_block->alloc.tag.words =
  105. block->alloc.tag.words - (leading_bytes >> 2);
  106. /* fix the size in the tail */
  107. new_tail = lub_heap_block__get_tail(new_block);
  108. new_tail->words = new_block->alloc.tag.words;
  109. lub_heap_free_leading_memory(this, block, leading_bytes);
  110. /* identify any trailing excess memory */
  111. trailing_bytes =
  112. (new_block->alloc.tag.words << 2) - (*size -
  113. (alignment << 1));
  114. if (trailing_bytes) {
  115. lub_heap_free_trailing_memory(this,
  116. new_block,
  117. trailing_bytes);
  118. }
  119. *size = (new_block->alloc.tag.words << 2); /* size including the lub_heap_alloc_block_t details */
  120. *ptr = new_ptr;
  121. }
  122. }