SingingCat 0
application
umm_info.c
1#ifdef UMM_INFO
2
3#include <stdint.h>
4#include <stddef.h>
5#include <stdbool.h>
6
7#include <math.h>
8
9/* ----------------------------------------------------------------------------
10 * One of the coolest things about this little library is that it's VERY
11 * easy to get debug information about the memory heap by simply iterating
12 * through all of the memory blocks.
13 *
14 * As you go through all the blocks, you can check to see if it's a free
15 * block by looking at the high order bit of the next block index. You can
16 * also see how big the block is by subtracting the next block index from
17 * the current block number.
18 *
19 * The umm_info function does all of that and makes the results available
20 * in the ummHeapInfo structure.
21 * ----------------------------------------------------------------------------
22 */
23
24UMM_HEAP_INFO ummHeapInfo;
25
26void compute_usage_metric(void) {
27 if (0 == ummHeapInfo.freeBlocks) {
28 ummHeapInfo.usage_metric = -1; // No free blocks!
29 } else {
30 ummHeapInfo.usage_metric = (int)((ummHeapInfo.usedBlocks * 100) / (ummHeapInfo.freeBlocks));
31 }
32}
33
34void compute_fragmentation_metric(void) {
35 if (0 == ummHeapInfo.freeBlocks) {
36 ummHeapInfo.fragmentation_metric = 0; // No free blocks ... so no fragmentation either!
37 } else {
38 ummHeapInfo.fragmentation_metric = 100 - (((uint32_t)(sqrtf(ummHeapInfo.freeBlocksSquared)) * 100) / (ummHeapInfo.freeBlocks));
39 }
40}
41
42void *umm_info(void *ptr, bool force) {
43 uint16_t blockNo = 0;
44
45 UMM_CRITICAL_DECL(id_info);
46
47 UMM_CHECK_INITIALIZED();
48
49 /* Protect the critical section... */
50 UMM_CRITICAL_ENTRY(id_info);
51
52 /*
53 * Clear out all of the entries in the ummHeapInfo structure before doing
54 * any calculations..
55 */
56 memset(&ummHeapInfo, 0, sizeof(ummHeapInfo));
57
58 DBGLOG_FORCE(force, "\n");
59 DBGLOG_FORCE(force, "+----------+-------+--------+--------+-------+--------+--------+\n");
60 DBGLOG_FORCE(force, "|0x%08x|B %5i|NB %5i|PB %5i|Z %5i|NF %5i|PF %5i|\n",
61 DBGLOG_32_BIT_PTR(&UMM_BLOCK(blockNo)),
62 blockNo,
63 UMM_NBLOCK(blockNo) & UMM_BLOCKNO_MASK,
64 UMM_PBLOCK(blockNo),
65 (UMM_NBLOCK(blockNo) & UMM_BLOCKNO_MASK) - blockNo,
66 UMM_NFREE(blockNo),
67 UMM_PFREE(blockNo));
68
69 /*
70 * Now loop through the block lists, and keep track of the number and size
71 * of used and free blocks. The terminating condition is an nb pointer with
72 * a value of zero...
73 */
74
75 blockNo = UMM_NBLOCK(blockNo) & UMM_BLOCKNO_MASK;
76
77 while (UMM_NBLOCK(blockNo) & UMM_BLOCKNO_MASK) {
78 size_t curBlocks = (UMM_NBLOCK(blockNo) & UMM_BLOCKNO_MASK) - blockNo;
79
80 ++ummHeapInfo.totalEntries;
81 ummHeapInfo.totalBlocks += curBlocks;
82
83 /* Is this a free block? */
84
85 if (UMM_NBLOCK(blockNo) & UMM_FREELIST_MASK) {
86 ++ummHeapInfo.freeEntries;
87 ummHeapInfo.freeBlocks += curBlocks;
88 ummHeapInfo.freeBlocksSquared += (curBlocks * curBlocks);
89
90 if (ummHeapInfo.maxFreeContiguousBlocks < curBlocks) {
91 ummHeapInfo.maxFreeContiguousBlocks = curBlocks;
92 }
93
94 DBGLOG_FORCE(force, "|0x%08x|B %5i|NB %5i|PB %5i|Z %5u|NF %5i|PF %5i|\n",
95 DBGLOG_32_BIT_PTR(&UMM_BLOCK(blockNo)),
96 blockNo,
97 UMM_NBLOCK(blockNo) & UMM_BLOCKNO_MASK,
98 UMM_PBLOCK(blockNo),
99 (uint16_t)curBlocks,
100 UMM_NFREE(blockNo),
101 UMM_PFREE(blockNo));
102
103 /* Does this block address match the ptr we may be trying to free? */
104
105 if (ptr == &UMM_BLOCK(blockNo)) {
106 /* Release the critical section... */
107 UMM_CRITICAL_EXIT(id_info);
108
109 return ptr;
110 }
111 } else {
112 ++ummHeapInfo.usedEntries;
113 ummHeapInfo.usedBlocks += curBlocks;
114
115 DBGLOG_FORCE(force, "|0x%08x|B %5i|NB %5i|PB %5i|Z %5u| |\n",
116 DBGLOG_32_BIT_PTR(&UMM_BLOCK(blockNo)),
117 blockNo,
118 UMM_NBLOCK(blockNo) & UMM_BLOCKNO_MASK,
119 UMM_PBLOCK(blockNo),
120 (uint16_t)curBlocks);
121 }
122
123 blockNo = UMM_NBLOCK(blockNo) & UMM_BLOCKNO_MASK;
124 }
125
126 /*
127 * The very last block is used as a placeholder to indicate that
128 * there are no more blocks in the heap, so it cannot be used
129 * for anything - at the same time, the size of this block must
130 * ALWAYS be exactly 1 !
131 */
132
133 DBGLOG_FORCE(force, "|0x%08x|B %5i|NB %5i|PB %5i|Z %5i|NF %5i|PF %5i|\n",
134 DBGLOG_32_BIT_PTR(&UMM_BLOCK(blockNo)),
135 blockNo,
136 UMM_NBLOCK(blockNo) & UMM_BLOCKNO_MASK,
137 UMM_PBLOCK(blockNo),
138 UMM_NUMBLOCKS - blockNo,
139 UMM_NFREE(blockNo),
140 UMM_PFREE(blockNo));
141
142 DBGLOG_FORCE(force, "+----------+-------+--------+--------+-------+--------+--------+\n");
143
144 DBGLOG_FORCE(force, "Total Entries %5i Used Entries %5i Free Entries %5i\n",
145 ummHeapInfo.totalEntries,
146 ummHeapInfo.usedEntries,
147 ummHeapInfo.freeEntries);
148
149 DBGLOG_FORCE(force, "Total Blocks %5i Used Blocks %5i Free Blocks %5i\n",
150 ummHeapInfo.totalBlocks,
151 ummHeapInfo.usedBlocks,
152 ummHeapInfo.freeBlocks);
153
154 DBGLOG_FORCE(force, "+--------------------------------------------------------------+\n");
155
156 compute_usage_metric();
157 DBGLOG_FORCE(force, "Usage Metric: %5i\n", ummHeapInfo.usage_metric);
158
159 compute_fragmentation_metric();
160 DBGLOG_FORCE(force, "Fragmentation Metric: %5i\n", ummHeapInfo.fragmentation_metric);
161
162 DBGLOG_FORCE(force, "+--------------------------------------------------------------+\n");
163
164 /* Release the critical section... */
165 UMM_CRITICAL_EXIT(id_info);
166
167 return NULL;
168}
169
170/* ------------------------------------------------------------------------ */
171
172size_t umm_free_heap_size(void) {
173#ifndef UMM_INLINE_METRICS
174 umm_info(NULL, false);
175#endif
176 return (size_t)ummHeapInfo.freeBlocks * UMM_BLOCKSIZE;
177}
178
179size_t umm_max_free_block_size(void) {
180 umm_info(NULL, false);
181 return ummHeapInfo.maxFreeContiguousBlocks * sizeof(umm_block);
182}
183
184int umm_usage_metric(void) {
185#ifdef UMM_INLINE_METRICS
186 compute_usage_metric();
187#else
188 umm_info(NULL, false);
189#endif
190 DBGLOG_DEBUG("usedBlocks %i totalBlocks %i\n", ummHeapInfo.usedBlocks, ummHeapInfo.totalBlocks);
191
192 return ummHeapInfo.usage_metric;
193}
194
195int umm_fragmentation_metric(void) {
196#ifdef UMM_INLINE_METRICS
197 compute_fragmentation_metric();
198#else
199 umm_info(NULL, false);
200#endif
201 DBGLOG_DEBUG("freeBlocks %i freeBlocksSquared %i\n", ummHeapInfo.freeBlocks, ummHeapInfo.freeBlocksSquared);
202
203 return ummHeapInfo.fragmentation_metric;
204}
205
206#ifdef UMM_INLINE_METRICS
207static void umm_fragmentation_metric_init(void) {
208 ummHeapInfo.freeBlocks = UMM_NUMBLOCKS - 2;
209 ummHeapInfo.freeBlocksSquared = ummHeapInfo.freeBlocks * ummHeapInfo.freeBlocks;
210}
211
212static void umm_fragmentation_metric_add(uint16_t c) {
213 uint16_t blocks = (UMM_NBLOCK(c) & UMM_BLOCKNO_MASK) - c;
214
215 DBGLOG_DEBUG("Add block %i size %i to free metric\n", c, blocks);
216 ummHeapInfo.freeBlocks += blocks;
217 ummHeapInfo.freeBlocksSquared += (blocks * blocks);
218}
219
220static void umm_fragmentation_metric_remove(uint16_t c) {
221 uint16_t blocks = (UMM_NBLOCK(c) & UMM_BLOCKNO_MASK) - c;
222
223 DBGLOG_DEBUG("Remove block %i size %i from free metric\n", c, blocks);
224 ummHeapInfo.freeBlocks -= blocks;
225 ummHeapInfo.freeBlocksSquared -= (blocks * blocks);
226}
227#endif // UMM_INLINE_METRICS
228
229/* ------------------------------------------------------------------------ */
230#endif