heap_add_segment.c 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126
  1. /*
  2. * heap_add_segment.c
  3. */
  4. #include <stdlib.h>
  5. #include <string.h>
  6. #include "private.h"
  7. #include "context.h"
  8. #include "lub/bintree.h"
  9. typedef struct {
  10. const lub_heap_segment_t *segment;
  11. } lub_heap_segment_key_t;
  12. /*--------------------------------------------------------- */
  13. static int
  14. lub_heap_segment_compare(const void *clientnode, const void *clientkey)
  15. {
  16. const lub_heap_segment_t *segment = clientnode;
  17. const lub_heap_segment_key_t *key = clientkey;
  18. return ((long)segment - (long)key->segment);
  19. }
  20. /*--------------------------------------------------------- */
  21. /* we simply use the segment address as the index */
  22. static void
  23. lub_heap_segment_getkey(const void *clientnode, lub_bintree_key_t * key)
  24. {
  25. lub_heap_segment_key_t clientkey;
  26. clientkey.segment = clientnode;
  27. memcpy(key, &clientkey, sizeof(lub_heap_segment_key_t));
  28. }
  29. /*--------------------------------------------------------- */
  30. static void lub_heap_segment_meta_init()
  31. {
  32. static bool_t initialised = BOOL_FALSE;
  33. if (BOOL_FALSE == initialised) {
  34. lub_heap_leak_t *leak = lub_heap_leak_instance();
  35. initialised = BOOL_TRUE;
  36. /* initialise the segment tree */
  37. lub_bintree_init(&leak->m_segment_tree,
  38. offsetof(lub_heap_segment_t, bt_node),
  39. lub_heap_segment_compare,
  40. lub_heap_segment_getkey);
  41. lub_heap_leak_release(leak);
  42. }
  43. }
  44. /*--------------------------------------------------------- */
  45. const lub_heap_segment_t *lub_heap_segment_findnext(const void *address)
  46. {
  47. lub_heap_segment_t *segment;
  48. lub_heap_segment_key_t key;
  49. lub_heap_leak_t *leak = lub_heap_leak_instance();
  50. key.segment = address;
  51. segment = lub_bintree_findnext(&leak->m_segment_tree, &key);
  52. lub_heap_leak_release(leak);
  53. return segment;
  54. }
  55. /*--------------------------------------------------------- */
  56. /*
  57. * as an optimisation this could be modified to merge
  58. * adjacent segments together
  59. */
  60. void lub_heap_add_segment(lub_heap_t * this, void *start, size_t size)
  61. {
  62. lub_heap_segment_t *segment;
  63. /* check for simple adjacent segment as produced by sbrk() type behaviour */
  64. if (this->first_segment.words) {
  65. lub_heap_tag_t *tail;
  66. char *ptr = (char *)&this[1];
  67. ptr += (this->first_segment.words << 2);
  68. if (ptr == start) {
  69. /* simply extend the current first segment */
  70. this->first_segment.words += (size >> 2);
  71. tail = &((lub_heap_tag_t *) start)[-1];
  72. tail->segment = BOOL_FALSE; /* no longer last block in segment */
  73. /* convert the new memory into a free block... */
  74. lub_heap_init_free_block(this, start, size, BOOL_FALSE,
  75. BOOL_TRUE);
  76. /* try and merge with the previous block */
  77. lub_heap_merge_with_previous(this, start);
  78. this->stats.segs_bytes += size;
  79. return;
  80. }
  81. }
  82. /* adjust the size which can be used */
  83. size -= sizeof(lub_heap_segment_t);
  84. /* set up the linked list of segments */
  85. segment = start;
  86. /* update the stats */
  87. ++this->stats.segs;
  88. this->stats.segs_bytes += size;
  89. this->stats.segs_overhead += sizeof(lub_heap_segment_t);
  90. if (segment != &this->first_segment) {
  91. /* maintain the list of segments */
  92. segment->next = this->first_segment.next;
  93. this->first_segment.next = segment;
  94. }
  95. segment->words = (size >> 2);
  96. lub_heap_init_free_block(this, &segment[1], size, BOOL_TRUE, BOOL_TRUE);
  97. /* add this segment to the tree */
  98. lub_heap_segment_meta_init();
  99. lub_bintree_node_init(&segment->bt_node);
  100. {
  101. lub_heap_leak_t *leak = lub_heap_leak_instance();
  102. lub_bintree_insert(&leak->m_segment_tree, segment);
  103. lub_heap_leak_release(leak);
  104. }
  105. }
  106. /*--------------------------------------------------------- */