#ifdef UMM_INFO
#include <stdint.h>
#include <stddef.h>
#include <stdbool.h>
#include <math.h>
UMM_HEAP_INFO ummHeapInfo;
void compute_usage_metric(void)
{
if (0 == ummHeapInfo.freeBlocks) {
ummHeapInfo.usage_metric = -1; } else {
ummHeapInfo.usage_metric = (int)((ummHeapInfo.usedBlocks * 100) / (ummHeapInfo.freeBlocks));
}
}
void compute_fragmentation_metric(void)
{
if (0 == ummHeapInfo.freeBlocks) {
ummHeapInfo.fragmentation_metric = 0; } else {
ummHeapInfo.fragmentation_metric = 100 - (((uint32_t)(sqrtf(ummHeapInfo.freeBlocksSquared)) * 100) / (ummHeapInfo.freeBlocks));
}
}
void *umm_info(void *ptr, bool force) {
uint16_t blockNo = 0;
UMM_CRITICAL_DECL(id_info);
UMM_CHECK_INITIALIZED();
UMM_CRITICAL_ENTRY(id_info);
memset(&ummHeapInfo, 0, sizeof(ummHeapInfo));
DBGLOG_FORCE(force, "\n");
DBGLOG_FORCE(force, "+----------+-------+--------+--------+-------+--------+--------+\n");
DBGLOG_FORCE(force, "|0x%08x|B %5i|NB %5i|PB %5i|Z %5i|NF %5i|PF %5i|\n",
DBGLOG_32_BIT_PTR(&UMM_BLOCK(blockNo)),
blockNo,
UMM_NBLOCK(blockNo) & UMM_BLOCKNO_MASK,
UMM_PBLOCK(blockNo),
(UMM_NBLOCK(blockNo) & UMM_BLOCKNO_MASK) - blockNo,
UMM_NFREE(blockNo),
UMM_PFREE(blockNo));
blockNo = UMM_NBLOCK(blockNo) & UMM_BLOCKNO_MASK;
while (UMM_NBLOCK(blockNo) & UMM_BLOCKNO_MASK) {
size_t curBlocks = (UMM_NBLOCK(blockNo) & UMM_BLOCKNO_MASK) - blockNo;
++ummHeapInfo.totalEntries;
ummHeapInfo.totalBlocks += curBlocks;
if (UMM_NBLOCK(blockNo) & UMM_FREELIST_MASK) {
++ummHeapInfo.freeEntries;
ummHeapInfo.freeBlocks += curBlocks;
ummHeapInfo.freeBlocksSquared += (curBlocks * curBlocks);
if (ummHeapInfo.maxFreeContiguousBlocks < curBlocks) {
ummHeapInfo.maxFreeContiguousBlocks = curBlocks;
}
DBGLOG_FORCE(force, "|0x%08x|B %5i|NB %5i|PB %5i|Z %5u|NF %5i|PF %5i|\n",
DBGLOG_32_BIT_PTR(&UMM_BLOCK(blockNo)),
blockNo,
UMM_NBLOCK(blockNo) & UMM_BLOCKNO_MASK,
UMM_PBLOCK(blockNo),
(uint16_t)curBlocks,
UMM_NFREE(blockNo),
UMM_PFREE(blockNo));
if (ptr == &UMM_BLOCK(blockNo)) {
UMM_CRITICAL_EXIT(id_info);
return ptr;
}
} else {
++ummHeapInfo.usedEntries;
ummHeapInfo.usedBlocks += curBlocks;
DBGLOG_FORCE(force, "|0x%08x|B %5i|NB %5i|PB %5i|Z %5u| |\n",
DBGLOG_32_BIT_PTR(&UMM_BLOCK(blockNo)),
blockNo,
UMM_NBLOCK(blockNo) & UMM_BLOCKNO_MASK,
UMM_PBLOCK(blockNo),
(uint16_t)curBlocks);
}
blockNo = UMM_NBLOCK(blockNo) & UMM_BLOCKNO_MASK;
}
DBGLOG_FORCE(force, "|0x%08x|B %5i|NB %5i|PB %5i|Z %5i|NF %5i|PF %5i|\n",
DBGLOG_32_BIT_PTR(&UMM_BLOCK(blockNo)),
blockNo,
UMM_NBLOCK(blockNo) & UMM_BLOCKNO_MASK,
UMM_PBLOCK(blockNo),
UMM_NUMBLOCKS - blockNo,
UMM_NFREE(blockNo),
UMM_PFREE(blockNo));
DBGLOG_FORCE(force, "+----------+-------+--------+--------+-------+--------+--------+\n");
DBGLOG_FORCE(force, "Total Entries %5i Used Entries %5i Free Entries %5i\n",
ummHeapInfo.totalEntries,
ummHeapInfo.usedEntries,
ummHeapInfo.freeEntries);
DBGLOG_FORCE(force, "Total Blocks %5i Used Blocks %5i Free Blocks %5i\n",
ummHeapInfo.totalBlocks,
ummHeapInfo.usedBlocks,
ummHeapInfo.freeBlocks);
DBGLOG_FORCE(force, "+--------------------------------------------------------------+\n");
compute_usage_metric();
DBGLOG_FORCE(force, "Usage Metric: %5i\n", ummHeapInfo.usage_metric);
compute_fragmentation_metric();
DBGLOG_FORCE(force, "Fragmentation Metric: %5i\n", ummHeapInfo.fragmentation_metric);
DBGLOG_FORCE(force, "+--------------------------------------------------------------+\n");
UMM_CRITICAL_EXIT(id_info);
return NULL;
}
size_t umm_free_heap_size(void) {
#ifndef UMM_INLINE_METRICS
umm_info(NULL, false);
#endif
return (size_t)ummHeapInfo.freeBlocks * UMM_BLOCKSIZE;
}
size_t umm_max_free_block_size(void) {
umm_info(NULL, false);
return ummHeapInfo.maxFreeContiguousBlocks * sizeof(umm_block);
}
int umm_usage_metric(void) {
#ifdef UMM_INLINE_METRICS
compute_usage_metric();
#else
umm_info(NULL, false);
#endif
DBGLOG_DEBUG("usedBlocks %i totalBlocks %i\n", ummHeapInfo.usedBlocks, ummHeapInfo.totalBlocks);
return ummHeapInfo.usage_metric;
}
int umm_fragmentation_metric(void) {
#ifdef UMM_INLINE_METRICS
compute_fragmentation_metric();
#else
umm_info(NULL, false);
#endif
DBGLOG_DEBUG("freeBlocks %i freeBlocksSquared %i\n", ummHeapInfo.freeBlocks, ummHeapInfo.freeBlocksSquared);
return ummHeapInfo.fragmentation_metric;
}
#ifdef UMM_INLINE_METRICS
static void umm_fragmentation_metric_init(void) {
ummHeapInfo.freeBlocks = UMM_NUMBLOCKS - 2;
ummHeapInfo.freeBlocksSquared = ummHeapInfo.freeBlocks * ummHeapInfo.freeBlocks;
}
static void umm_fragmentation_metric_add(uint16_t c) {
uint16_t blocks = (UMM_NBLOCK(c) & UMM_BLOCKNO_MASK) - c;
DBGLOG_DEBUG("Add block %i size %i to free metric\n", c, blocks);
ummHeapInfo.freeBlocks += blocks;
ummHeapInfo.freeBlocksSquared += (blocks * blocks);
}
static void umm_fragmentation_metric_remove(uint16_t c) {
uint16_t blocks = (UMM_NBLOCK(c) & UMM_BLOCKNO_MASK) - c;
DBGLOG_DEBUG("Remove block %i size %i from free metric\n", c, blocks);
ummHeapInfo.freeBlocks -= blocks;
ummHeapInfo.freeBlocksSquared -= (blocks * blocks);
}
#endif
#endif