heap_add_segment.c 4.0 KB

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