123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415 |
- #include <stdio.h>
- #include <string.h>
- #include "cache.h"
- /*--------------------------------------------------------- */
- size_t
- lub_heap_cache__get_max_free(lub_heap_cache_t *this)
- {
- size_t size = 0;
- /* get the size from the cache */
- lub_heap_cache_bucket_t **ptr;
- for(ptr = this->m_bucket_start;
- ptr < this->m_bucket_end;
- ++ptr)
- {
- lub_blockpool_stats_t stats;
- lub_blockpool__get_stats(&(*ptr)->m_blockpool,&stats);
- if(stats.free_blocks && ((stats.block_size - sizeof(lub_heap_cache_bucket_t*)) > size))
- {
- size = stats.block_size - sizeof(lub_heap_cache_bucket_t*);
- }
- }
- return size;
- }
- /*--------------------------------------------------------- */
- static lub_heap_cache_bucket_t *
- _lub_heap_cache_find_bucket_from_size(lub_heap_cache_t *this,
- size_t size)
- {
- lub_heap_cache_bucket_t **ptr = this->m_bucket_start;
- /* leave space to put the bucket reference into place */
- size += sizeof(lub_heap_cache_bucket_t*);
- /* place powers of two into the correct bucket */
- --size;
- /* ignore sizes of 1,2 and 4 bytes */
- size >>= 3;
- for(;
- (ptr < this->m_bucket_end) && size;
- ++ptr)
- {
- size >>= 1;
- }
- return (ptr == this->m_bucket_end) ? 0 : *ptr;
- }
- /*--------------------------------------------------------- */
- static size_t
- lub_heap_cache_num_buckets(lub_heap_align_t max_block_size)
- {
- unsigned num_buckets = 0;
- /* count the number of buckets to be created */
- max_block_size >>= 3; /* ignore buckets of size 1,2 and 4 bytes */
- while(max_block_size)
- {
- ++num_buckets;
- max_block_size >>= 1;
- }
- return num_buckets;
- }
- /*--------------------------------------------------------- */
- size_t
- lub_heap_cache_overhead_size(lub_heap_align_t max_block_size,
- size_t num_max_blocks)
- {
- size_t overhead = 0;
- if(num_max_blocks && max_block_size)
- {
- /*
- * account for the cache overheads
- */
- size_t num_buckets = lub_heap_cache_num_buckets(max_block_size);
-
- /* cache control block */
- overhead += sizeof(lub_heap_cache_t);
-
- /* array of bucket pointers (-1 because one is contained in control block) */
- overhead += sizeof(lub_heap_cache_bucket_t*) * (num_buckets-1);
-
- /* fast size lookup array */
- overhead += sizeof(lub_heap_cache_bucket_t*) * max_block_size;
-
- /* buckets themselves */
- overhead += num_buckets * offsetof(lub_heap_cache_bucket_t,m_memory_start);
- }
- return overhead;
- }
- /*--------------------------------------------------------- */
- size_t
- lub_heap_overhead_size(lub_heap_align_t max_block_size,
- size_t num_max_blocks)
- {
- /* heap control block */
- size_t overhead = sizeof(lub_heap_t);
-
- /* need at least one free blocks worth */
- overhead += sizeof(lub_heap_free_block_t);
- if(max_block_size && num_max_blocks)
- {
- size_t num_buckets = lub_heap_cache_num_buckets(max_block_size);
- size_t bucket_size = max_block_size * num_max_blocks;
- /* now add any cache overhead contribution */
- overhead += lub_heap_cache_overhead_size(max_block_size,num_max_blocks);
- /* add the bucket contents */
- overhead += (num_buckets * bucket_size);
- }
- return overhead;
- }
- /*--------------------------------------------------------- */
- lub_heap_status_t
- lub_heap_cache_init(lub_heap_t *this,
- lub_heap_align_t max_block_size,
- size_t num_max_blocks)
- {
- lub_heap_status_t status = LUB_HEAP_FAILED;
- do
- {
- size_t bucket_size = (max_block_size * num_max_blocks);
- unsigned num_buckets = lub_heap_cache_num_buckets(max_block_size);
- size_t block_size = 8;
- lub_heap_cache_t *cache;
- lub_heap_cache_bucket_t **ptr;
- int i;
- /* cannot call this multiple times */
- if(this->cache) break;
-
- /* allocate a cache control block */
- cache = this->cache = lub_heap_static_alloc(this,
- sizeof(lub_heap_cache_t) + sizeof(lub_heap_cache_bucket_t*)*(num_buckets-1));
- if(!cache) break;
-
- cache->m_max_block_size = max_block_size;
- cache->m_num_max_blocks = num_max_blocks;
- cache->m_num_buckets = num_buckets;
- cache->m_bucket_size = bucket_size;
- cache->m_misses = 0;
- cache->m_bucket_end = &cache->m_bucket_start[num_buckets];
-
- /* allocate each bucket for the cache */
- for(ptr = cache->m_bucket_start;
- ptr < cache->m_bucket_end;
- ++ptr)
- {
- *ptr = lub_heap_static_alloc(this,
- bucket_size + offsetof(lub_heap_cache_bucket_t,m_memory_start));
- if(!*ptr) break;
- /* set up each bucket */
- lub_heap_cache_bucket_init(*ptr,
- cache,
- block_size,
- bucket_size);
- block_size <<= 1;
- }
- if(ptr != cache->m_bucket_end) break;
- /* now create a fast lookup for resolving size to bucket */
- cache->m_bucket_lookup = lub_heap_static_alloc(this,sizeof(lub_heap_cache_bucket_t*)*max_block_size);
- if(!cache->m_bucket_lookup) break;
- for(i = 0;
- i < cache->m_max_block_size;
- ++i)
- {
- cache->m_bucket_lookup[i] = _lub_heap_cache_find_bucket_from_size(cache,i+1);
- }
- status = LUB_HEAP_OK;
- } while(0);
-
- return status;
- }
- /*--------------------------------------------------------- */
- lub_heap_cache_bucket_t *
- lub_heap_cache_find_bucket_from_address(lub_heap_cache_t *this,
- const void *address)
- {
- lub_heap_cache_bucket_t **bucket = (void*)address;
-
- /* get the bucket reference */
- --bucket;
-
- if( (*bucket > this->m_bucket_start[0])
- || (*bucket < this->m_bucket_end[-1]) )
- {
- bucket = 0;
- }
- return bucket ? *bucket : 0;
- }
- /*--------------------------------------------------------- */
- lub_heap_cache_bucket_t *
- lub_heap_cache_find_bucket_from_size(lub_heap_cache_t *this,
- size_t size)
- {
- lub_heap_cache_bucket_t *bucket = 0;
-
- /* simply get the result from the fast lookup table */
- if(size > 0)
- {
- if(size <= this->m_max_block_size)
- {
- bucket = this->m_bucket_lookup[size-1];
- }
- else
- {
- ++this->m_misses;
- }
- }
- return bucket;
- }
- /*--------------------------------------------------------- */
- lub_heap_status_t
- lub_heap_cache_realloc(lub_heap_t *this,
- char **ptr,
- size_t size)
- {
- lub_heap_status_t status = LUB_HEAP_FAILED;
- lub_heap_cache_bucket_t *old_bucket = 0;
- lub_heap_cache_bucket_t *new_bucket = size ? lub_heap_cache_find_bucket_from_size(this->cache,size) : 0;
- char *new_ptr = 0;
-
- do
- {
- char *old_ptr = *ptr;
- if(old_ptr)
- {
- old_bucket = lub_heap_cache_find_bucket_from_address(this->cache,old_ptr);
- }
- else if (size == 0)
- {
- /* nothing to do */
- status = LUB_HEAP_OK;
- break;
- }
- if(old_bucket)
- {
- /********************************
- * old from CACHE, new from CACHE
- ******************************** */
- if(new_bucket)
- {
- if(old_bucket == new_bucket)
- {
- /* keep the existing cache block which is big enough */
- new_ptr = old_ptr;
- status = LUB_HEAP_OK;
- break;
- }
- /* try and get memory from the cache */
- new_ptr = lub_heap_cache_bucket_alloc(new_bucket);
- if(new_ptr)
- {
- if(old_ptr)
- {
- /* copy the old details across */
- memcpy(new_ptr,old_ptr,size);
- /* release the old cache block */
- status = lub_heap_cache_bucket_free(old_bucket,old_ptr);
- if(LUB_HEAP_OK != status)
- {
- break;
- }
- }
- /* all done */
- status = LUB_HEAP_OK;
- break;
- }
- }
- /********************************
- * old from CACHE, new from HEAP
- ******************************** */
- if(size)
- {
- /* get new memory from the dynamic heap */
- status = lub_heap_raw_realloc(this,&new_ptr,size,LUB_HEAP_ALIGN_NATIVE);
- if(LUB_HEAP_OK != status)
- {
- break;
- }
- /* copy the old details across */
- memcpy(new_ptr,old_ptr,size);
- }
- /* release the old cache block */
- status = lub_heap_cache_bucket_free(old_bucket,old_ptr);
- }
- else
- {
- /********************************
- * old from HEAP, new from CACHE
- ******************************** */
- if(size)
- {
- if(new_bucket)
- {
- /* try and get memory from the cache */
- new_ptr = lub_heap_cache_bucket_alloc(new_bucket);
- if(new_ptr)
- {
- if(old_ptr)
- {
- /* copy the old details across */
- memcpy(new_ptr,old_ptr,size);
- size = 0;
- }
- else
- {
- /* all done */
- status = LUB_HEAP_OK;
- break;
- }
- }
- }
- }
- else if(!old_ptr)
- {
- /* nothing to do */
- status = LUB_HEAP_OK;
- break;
- }
- /********************************
- * old from HEAP, new from HEAP
- ******************************** */
- /* release old memory and potentially get new memory */
- status = lub_heap_raw_realloc(this,&old_ptr,size,LUB_HEAP_ALIGN_NATIVE);
- if(LUB_HEAP_OK != status)
- {
- break;
- }
- else if(size)
- {
- new_ptr = old_ptr;
- }
- }
- } while(0);
- if(LUB_HEAP_OK == status)
- {
- /* set up the new pointer value */
- *ptr = new_ptr;
- }
- return status;
- }
- /*--------------------------------------------------------- */
- void
- lub_heap_cache_show(lub_heap_cache_t *this)
- {
- lub_heap_cache_bucket_t **ptr;
-
- printf(" size num blocks current high-tide cumulative misses\n");
- printf(" ---------- ---------- ---------- ---------- ---------- ----------\n");
- for(ptr = this->m_bucket_start;
- ptr < this->m_bucket_end;
- ++ptr)
- {
- lub_blockpool_t *blockpool = &(*ptr)->m_blockpool;
- lub_blockpool_stats_t stats;
-
- lub_blockpool__get_stats(blockpool,&stats);
- printf(" %10"SIZE_FMT" %10"SIZE_FMT" %10"SIZE_FMT" %10"SIZE_FMT" %10"SIZE_FMT" %10"SIZE_FMT"\n",
- stats.block_size,
- stats.num_blocks,
- stats.alloc_blocks,
- stats.alloc_hightide_blocks,
- stats.alloc_total_blocks,
- stats.alloc_failures);
- }
- printf(" %10u %10s %10s %10s %10s %10"SIZE_FMT"\n",
- this->m_max_block_size,
- "-",
- "-",
- "-",
- "-",
- this->m_misses);
- }
- /*--------------------------------------------------------- */
- void
- lub_heap_cache__get_stats(lub_heap_cache_t *this,
- lub_heap_stats_t *stats)
- {
- lub_heap_cache_bucket_t **ptr;
- memset(stats,0,sizeof(lub_heap_stats_t));
- stats->free_overhead = lub_heap_cache_overhead_size(this->m_max_block_size,this->m_num_max_blocks);
- for(ptr = this->m_bucket_start;
- ptr < this->m_bucket_end;
- ++ptr)
- {
- lub_blockpool_t *blockpool = &(*ptr)->m_blockpool;
- lub_blockpool_stats_t bucket_stats;
- size_t block_size;
- size_t block_overhead = sizeof(lub_heap_cache_bucket_t*); /* used for fast lookup from address */
-
- lub_blockpool__get_stats(blockpool,&bucket_stats);
- block_size = (bucket_stats.block_size - block_overhead);
- stats->free_blocks += bucket_stats.free_blocks;
- stats->free_bytes += block_size * bucket_stats.free_blocks;
- stats->free_overhead += block_overhead * bucket_stats.free_blocks;
- stats->alloc_blocks += bucket_stats.alloc_blocks;
- stats->alloc_bytes += block_size * bucket_stats.alloc_blocks;
- stats->alloc_overhead += block_overhead * bucket_stats.alloc_blocks;
- stats->alloc_total_blocks += bucket_stats.alloc_total_blocks;
- stats->alloc_total_bytes += block_size * bucket_stats.alloc_total_blocks;
- }
-
- }
- /*--------------------------------------------------------- */
|