heap: add functions to get heap runtime statistics
add functions to get the sys_heap runtime statistics, include total free bytes, total allocated bytes. Signed-off-by: Chen Peng1 <peng1.chen@intel.com>
This commit is contained in:
parent
b330e3f374
commit
a71cd8790f
5 changed files with 75 additions and 0 deletions
|
@ -61,6 +61,25 @@ struct z_heap_stress_result {
|
||||||
uint64_t accumulated_in_use_bytes;
|
uint64_t accumulated_in_use_bytes;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#ifdef CONFIG_SYS_HEAP_RUNTIME_STATS
|
||||||
|
|
||||||
|
struct sys_heap_runtime_stats {
|
||||||
|
size_t free_bytes;
|
||||||
|
size_t allocated_bytes;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Get the runtime statistics of a sys_heap
|
||||||
|
*
|
||||||
|
* @param heap Pointer to specified sys_heap
|
||||||
|
* @param stats_t Pointer to struct to copy statistics into
|
||||||
|
* @return -EINVAL if null pointers, otherwise 0
|
||||||
|
*/
|
||||||
|
int sys_heap_runtime_stats_get(struct sys_heap *heap,
|
||||||
|
struct sys_heap_runtime_stats *stats);
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
/** @brief Initialize sys_heap
|
/** @brief Initialize sys_heap
|
||||||
*
|
*
|
||||||
* Initializes a sys_heap struct to manage the specified memory.
|
* Initializes a sys_heap struct to manage the specified memory.
|
||||||
|
|
|
@ -46,6 +46,11 @@ config SYS_HEAP_ALLOC_LOOPS
|
||||||
keeps the maximum runtime at a tight bound so that the heap
|
keeps the maximum runtime at a tight bound so that the heap
|
||||||
is useful in locked or ISR contexts.
|
is useful in locked or ISR contexts.
|
||||||
|
|
||||||
|
config SYS_HEAP_RUNTIME_STATS
|
||||||
|
bool "System heap runtime statistics"
|
||||||
|
help
|
||||||
|
Gather system heap runtime statistics.
|
||||||
|
|
||||||
choice
|
choice
|
||||||
prompt "Supported heap sizes"
|
prompt "Supported heap sizes"
|
||||||
depends on !64BIT
|
depends on !64BIT
|
||||||
|
|
|
@ -386,3 +386,20 @@ void sys_heap_print_info(struct sys_heap *heap, bool dump_chunks)
|
||||||
{
|
{
|
||||||
heap_print_info(heap->heap, dump_chunks);
|
heap_print_info(heap->heap, dump_chunks);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef CONFIG_SYS_HEAP_RUNTIME_STATS
|
||||||
|
|
||||||
|
int sys_heap_runtime_stats_get(struct sys_heap *heap,
|
||||||
|
struct sys_heap_runtime_stats *stats)
|
||||||
|
{
|
||||||
|
if ((heap == NULL) || (stats == NULL)) {
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
stats->free_bytes = heap->heap->free_bytes;
|
||||||
|
stats->allocated_bytes = heap->heap->allocated_bytes;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
|
@ -38,6 +38,10 @@ static void free_list_remove_bidx(struct z_heap *h, chunkid_t c, int bidx)
|
||||||
set_next_free_chunk(h, first, second);
|
set_next_free_chunk(h, first, second);
|
||||||
set_prev_free_chunk(h, second, first);
|
set_prev_free_chunk(h, second, first);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef CONFIG_SYS_HEAP_RUNTIME_STATS
|
||||||
|
h->free_bytes -= chunksz_to_bytes(h, chunk_size(h, c));
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
static void free_list_remove(struct z_heap *h, chunkid_t c)
|
static void free_list_remove(struct z_heap *h, chunkid_t c)
|
||||||
|
@ -72,6 +76,10 @@ static void free_list_add_bidx(struct z_heap *h, chunkid_t c, int bidx)
|
||||||
set_next_free_chunk(h, first, c);
|
set_next_free_chunk(h, first, c);
|
||||||
set_prev_free_chunk(h, second, c);
|
set_prev_free_chunk(h, second, c);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef CONFIG_SYS_HEAP_RUNTIME_STATS
|
||||||
|
h->free_bytes += chunksz_to_bytes(h, chunk_size(h, c));
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
static void free_list_add(struct z_heap *h, chunkid_t c)
|
static void free_list_add(struct z_heap *h, chunkid_t c)
|
||||||
|
@ -164,6 +172,9 @@ void sys_heap_free(struct sys_heap *heap, void *mem)
|
||||||
mem);
|
mem);
|
||||||
|
|
||||||
set_chunk_used(h, c, false);
|
set_chunk_used(h, c, false);
|
||||||
|
#ifdef CONFIG_SYS_HEAP_RUNTIME_STATS
|
||||||
|
h->allocated_bytes -= chunksz_to_bytes(h, chunk_size(h, c));
|
||||||
|
#endif
|
||||||
free_chunk(h, c);
|
free_chunk(h, c);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -251,6 +262,9 @@ void *sys_heap_alloc(struct sys_heap *heap, size_t bytes)
|
||||||
}
|
}
|
||||||
|
|
||||||
set_chunk_used(h, c, true);
|
set_chunk_used(h, c, true);
|
||||||
|
#ifdef CONFIG_SYS_HEAP_RUNTIME_STATS
|
||||||
|
h->allocated_bytes += chunksz_to_bytes(h, chunk_size(h, c));
|
||||||
|
#endif
|
||||||
return chunk_mem(h, c);
|
return chunk_mem(h, c);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -318,6 +332,9 @@ void *sys_heap_aligned_alloc(struct sys_heap *heap, size_t align, size_t bytes)
|
||||||
}
|
}
|
||||||
|
|
||||||
set_chunk_used(h, c, true);
|
set_chunk_used(h, c, true);
|
||||||
|
#ifdef CONFIG_SYS_HEAP_RUNTIME_STATS
|
||||||
|
h->allocated_bytes += chunksz_to_bytes(h, chunk_size(h, c));
|
||||||
|
#endif
|
||||||
return mem;
|
return mem;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -353,6 +370,10 @@ void *sys_heap_aligned_realloc(struct sys_heap *heap, void *ptr,
|
||||||
return ptr;
|
return ptr;
|
||||||
} else if (chunk_size(h, c) > chunks_need) {
|
} else if (chunk_size(h, c) > chunks_need) {
|
||||||
/* Shrink in place, split off and free unused suffix */
|
/* Shrink in place, split off and free unused suffix */
|
||||||
|
#ifdef CONFIG_SYS_HEAP_RUNTIME_STATS
|
||||||
|
h->allocated_bytes -=
|
||||||
|
(chunk_size(h, c) - chunks_need) * CHUNK_UNIT;
|
||||||
|
#endif
|
||||||
split_chunks(h, c, c + chunks_need);
|
split_chunks(h, c, c + chunks_need);
|
||||||
set_chunk_used(h, c, true);
|
set_chunk_used(h, c, true);
|
||||||
free_chunk(h, c + chunks_need);
|
free_chunk(h, c + chunks_need);
|
||||||
|
@ -362,6 +383,10 @@ void *sys_heap_aligned_realloc(struct sys_heap *heap, void *ptr,
|
||||||
/* Expand: split the right chunk and append */
|
/* Expand: split the right chunk and append */
|
||||||
chunkid_t split_size = chunks_need - chunk_size(h, c);
|
chunkid_t split_size = chunks_need - chunk_size(h, c);
|
||||||
|
|
||||||
|
#ifdef CONFIG_SYS_HEAP_RUNTIME_STATS
|
||||||
|
h->allocated_bytes += split_size * CHUNK_UNIT;
|
||||||
|
#endif
|
||||||
|
|
||||||
free_list_remove(h, rc);
|
free_list_remove(h, rc);
|
||||||
|
|
||||||
if (split_size < chunk_size(h, rc)) {
|
if (split_size < chunk_size(h, rc)) {
|
||||||
|
@ -415,6 +440,11 @@ void sys_heap_init(struct sys_heap *heap, void *mem, size_t bytes)
|
||||||
h->end_chunk = heap_sz;
|
h->end_chunk = heap_sz;
|
||||||
h->avail_buckets = 0;
|
h->avail_buckets = 0;
|
||||||
|
|
||||||
|
#ifdef CONFIG_SYS_HEAP_RUNTIME_STATS
|
||||||
|
h->free_bytes = 0;
|
||||||
|
h->allocated_bytes = 0;
|
||||||
|
#endif
|
||||||
|
|
||||||
int nb_buckets = bucket_idx(h, heap_sz) + 1;
|
int nb_buckets = bucket_idx(h, heap_sz) + 1;
|
||||||
chunksz_t chunk0_size = chunksz(sizeof(struct z_heap) +
|
chunksz_t chunk0_size = chunksz(sizeof(struct z_heap) +
|
||||||
nb_buckets * sizeof(struct z_heap_bucket));
|
nb_buckets * sizeof(struct z_heap_bucket));
|
||||||
|
|
|
@ -69,6 +69,10 @@ struct z_heap {
|
||||||
chunkid_t chunk0_hdr[2];
|
chunkid_t chunk0_hdr[2];
|
||||||
chunkid_t end_chunk;
|
chunkid_t end_chunk;
|
||||||
uint32_t avail_buckets;
|
uint32_t avail_buckets;
|
||||||
|
#ifdef CONFIG_SYS_HEAP_RUNTIME_STATS
|
||||||
|
size_t free_bytes;
|
||||||
|
size_t allocated_bytes;
|
||||||
|
#endif
|
||||||
struct z_heap_bucket buckets[0];
|
struct z_heap_bucket buckets[0];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue