heap_align_block.c 5.1 KB

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