123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132 |
- /*
- * heap_add_segment.c
- */
- #include <stdlib.h>
- #include <string.h>
- #include "private.h"
- #include "context.h"
- #include "lub/bintree.h"
- typedef struct
- {
- const lub_heap_segment_t *segment;
- } lub_heap_segment_key_t;
- /*--------------------------------------------------------- */
- static int
- lub_heap_segment_compare(const void *clientnode,
- const void *clientkey)
- {
- const lub_heap_segment_t * segment = clientnode;
- const lub_heap_segment_key_t * key = clientkey;
-
- return ((long)segment - (long)key->segment);
- }
- /*--------------------------------------------------------- */
- /* we simply use the segment address as the index */
- static void
- lub_heap_segment_getkey(const void *clientnode,
- lub_bintree_key_t *key)
- {
- lub_heap_segment_key_t clientkey;
- clientkey.segment = clientnode;
- memcpy(key,&clientkey,sizeof(lub_heap_segment_key_t));
- }
- /*--------------------------------------------------------- */
- static void
- lub_heap_segment_meta_init()
- {
- static bool_t initialised = BOOL_FALSE;
-
- if(BOOL_FALSE == initialised)
- {
- lub_heap_leak_t *leak = lub_heap_leak_instance();
- initialised = BOOL_TRUE;
- /* initialise the segment tree */
- lub_bintree_init(&leak->m_segment_tree,
- offsetof(lub_heap_segment_t,bt_node),
- lub_heap_segment_compare,
- lub_heap_segment_getkey);
- lub_heap_leak_release(leak);
- }
- }
- /*--------------------------------------------------------- */
- const lub_heap_segment_t *
- lub_heap_segment_findnext(const void *address)
- {
- lub_heap_segment_t *segment;
- lub_heap_segment_key_t key;
- lub_heap_leak_t *leak = lub_heap_leak_instance();
- key.segment = address;
-
- segment = lub_bintree_findnext(&leak->m_segment_tree,&key);
- lub_heap_leak_release(leak);
- return segment;
- }
- /*--------------------------------------------------------- */
- /*
- * as an optimisation this could be modified to merge
- * adjacent segments together
- */
- void
- lub_heap_add_segment(lub_heap_t *this,
- void *start,
- size_t size)
- {
- lub_heap_segment_t *segment;
-
- /* check for simple adjacent segment as produced by sbrk() type behaviour */
- if(this->first_segment.words)
- {
- lub_heap_tag_t *tail;
- char *ptr = (char*)&this[1];
- ptr += (this->first_segment.words << 2);
- if(ptr == start)
- {
- /* simply extend the current first segment */
- this->first_segment.words += (size >> 2);
- tail = &((lub_heap_tag_t*)start)[-1];
- tail->segment = BOOL_FALSE; /* no longer last block in segment */
- /* convert the new memory into a free block... */
- lub_heap_init_free_block(this,start,size,BOOL_FALSE,BOOL_TRUE);
- /* try and merge with the previous block */
- lub_heap_merge_with_previous(this,start);
- this->stats.segs_bytes += size;
- return;
- }
- }
- /* adjust the size which can be used */
- size -= sizeof(lub_heap_segment_t);
- /* set up the linked list of segments */
- segment = start;
-
- /* update the stats */
- ++this->stats.segs;
- this->stats.segs_bytes += size;
- this->stats.segs_overhead += sizeof(lub_heap_segment_t);
-
- if(segment != &this->first_segment)
- {
- /* maintain the list of segments */
- segment->next = this->first_segment.next;
- this->first_segment.next = segment;
- }
- segment->words = (size >> 2);
-
- lub_heap_init_free_block(this,&segment[1],size,BOOL_TRUE,BOOL_TRUE);
-
- /* add this segment to the tree */
- lub_heap_segment_meta_init();
- lub_bintree_node_init(&segment->bt_node);
- {
- lub_heap_leak_t *leak = lub_heap_leak_instance();
- lub_bintree_insert(&leak->m_segment_tree,segment);
- lub_heap_leak_release(leak);
- }
- }
- /*--------------------------------------------------------- */
|