123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402 |
- #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;
- }
- }
- /*--------------------------------------------------------- */
|