22
33#ifdef UMM_INFO
44
5+ #include <stdint.h>
6+ #include <stddef.h>
7+ #include <stdbool.h>
8+
9+ #include <math.h>
10+
511/* ----------------------------------------------------------------------------
612 * One of the coolest things about this little library is that it's VERY
713 * easy to get debug information about the memory heap by simply iterating
1925
2026UMM_HEAP_INFO ummHeapInfo ;
2127
22- void * umm_info ( void * ptr , int force ) {
28+ void * umm_info ( void * ptr , bool force ) {
2329 UMM_CRITICAL_DECL (id_info );
2430
25- unsigned short int blockNo = 0 ;
26-
27- if (umm_heap == NULL ) {
31+ if (umm_heap == NULL ) {
2832 umm_init ();
2933 }
3034
35+ uint16_t blockNo = 0 ;
36+
3137 /* Protect the critical section... */
3238 UMM_CRITICAL_ENTRY (id_info );
3339
@@ -40,7 +46,7 @@ void *umm_info( void *ptr, int force ) {
4046 DBGLOG_FORCE ( force , "\n" );
4147 DBGLOG_FORCE ( force , "+----------+-------+--------+--------+-------+--------+--------+\n" );
4248 DBGLOG_FORCE ( force , "|0x%08lx|B %5d|NB %5d|PB %5d|Z %5d|NF %5d|PF %5d|\n" ,
43- ( unsigned long ) (& UMM_BLOCK (blockNo )),
49+ DBGLOG_32_BIT_PTR (& UMM_BLOCK (blockNo )),
4450 blockNo ,
4551 UMM_NBLOCK (blockNo ) & UMM_BLOCKNO_MASK ,
4652 UMM_PBLOCK (blockNo ),
@@ -67,21 +73,18 @@ void *umm_info( void *ptr, int force ) {
6773 if ( UMM_NBLOCK (blockNo ) & UMM_FREELIST_MASK ) {
6874 ++ ummHeapInfo .freeEntries ;
6975 ummHeapInfo .freeBlocks += curBlocks ;
70- ummHeapInfo .freeSize2 += (unsigned int )curBlocks
71- * (unsigned int )sizeof (umm_block )
72- * (unsigned int )curBlocks
73- * (unsigned int )sizeof (umm_block );
76+ ummHeapInfo .freeBlocksSquared += (curBlocks * curBlocks );
7477
7578 if (ummHeapInfo .maxFreeContiguousBlocks < curBlocks ) {
7679 ummHeapInfo .maxFreeContiguousBlocks = curBlocks ;
7780 }
7881
7982 DBGLOG_FORCE ( force , "|0x%08lx|B %5d|NB %5d|PB %5d|Z %5u|NF %5d|PF %5d|\n" ,
80- ( unsigned long ) (& UMM_BLOCK (blockNo )),
83+ DBGLOG_32_BIT_PTR (& UMM_BLOCK (blockNo )),
8184 blockNo ,
8285 UMM_NBLOCK (blockNo ) & UMM_BLOCKNO_MASK ,
8386 UMM_PBLOCK (blockNo ),
84- (unsigned int )curBlocks ,
87+ (uint16_t )curBlocks ,
8588 UMM_NFREE (blockNo ),
8689 UMM_PFREE (blockNo ) );
8790
@@ -99,33 +102,25 @@ void *umm_info( void *ptr, int force ) {
99102 ummHeapInfo .usedBlocks += curBlocks ;
100103
101104 DBGLOG_FORCE ( force , "|0x%08lx|B %5d|NB %5d|PB %5d|Z %5u|\n" ,
102- ( unsigned long ) (& UMM_BLOCK (blockNo )),
105+ DBGLOG_32_BIT_PTR (& UMM_BLOCK (blockNo )),
103106 blockNo ,
104107 UMM_NBLOCK (blockNo ) & UMM_BLOCKNO_MASK ,
105108 UMM_PBLOCK (blockNo ),
106- (unsigned int )curBlocks );
109+ (uint16_t )curBlocks );
107110 }
108111
109112 blockNo = UMM_NBLOCK (blockNo ) & UMM_BLOCKNO_MASK ;
110113 }
111114
112115 /*
113- * Update the accounting totals with information from the last block, the
114- * rest must be free!
116+ * The very last block is used as a placeholder to indicate that
117+ * there are no more blocks in the heap, so it cannot be used
118+ * for anything - at the same time, the size of this block must
119+ * ALWAYS be exactly 1 !
115120 */
116121
117- {
118- size_t curBlocks = UMM_NUMBLOCKS - blockNo ;
119- ummHeapInfo .freeBlocks += curBlocks ;
120- ummHeapInfo .totalBlocks += curBlocks ;
121-
122- if (ummHeapInfo .maxFreeContiguousBlocks < curBlocks ) {
123- ummHeapInfo .maxFreeContiguousBlocks = curBlocks ;
124- }
125- }
126-
127122 DBGLOG_FORCE ( force , "|0x%08lx|B %5d|NB %5d|PB %5d|Z %5d|NF %5d|PF %5d|\n" ,
128- ( unsigned long ) (& UMM_BLOCK (blockNo )),
123+ DBGLOG_32_BIT_PTR (& UMM_BLOCK (blockNo )),
129124 blockNo ,
130125 UMM_NBLOCK (blockNo ) & UMM_BLOCKNO_MASK ,
131126 UMM_PBLOCK (blockNo ),
@@ -147,7 +142,13 @@ void *umm_info( void *ptr, int force ) {
147142
148143 DBGLOG_FORCE ( force , "+--------------------------------------------------------------+\n" );
149144
145+ DBGLOG_FORCE ( force , "Usage Metric: %5d\n" , umm_usage_metric ());
146+ DBGLOG_FORCE ( force , "Fragmentation Metric: %5d\n" , umm_fragmentation_metric ());
147+
148+ DBGLOG_FORCE ( force , "+--------------------------------------------------------------+\n" );
149+
150150#if defined(UMM_STATS ) || defined(UMM_STATS_FULL )
151+ #if !defined(UMM_INLINE_METRICS )
151152 if (ummHeapInfo .freeBlocks == ummStats .free_blocks ) {
152153 DBGLOG_FORCE ( force , "heap info Free blocks and heap statistics Free blocks match.\n" );
153154 } else {
@@ -156,6 +157,7 @@ void *umm_info( void *ptr, int force ) {
156157 ummStats .free_blocks );
157158 }
158159 DBGLOG_FORCE ( force , "+--------------------------------------------------------------+\n" );
160+ #endif
159161
160162 print_stats (force );
161163#endif
@@ -169,17 +171,74 @@ void *umm_info( void *ptr, int force ) {
169171/* ------------------------------------------------------------------------ */
170172
171173size_t umm_free_heap_size ( void ) {
172- umm_info (NULL , 0 );
174+ #ifndef UMM_INLINE_METRICS
175+ umm_info (NULL , false);
176+ #endif
173177 return (size_t )ummHeapInfo .freeBlocks * sizeof (umm_block );
174178}
175179
180+ //C Breaking change in upstream umm_max_block_size() was changed to
181+ //C umm_max_free_block_size() keeping old function name for (dot) releases.
182+ //C TODO: update at next major release.
183+ //C size_t umm_max_free_block_size( void ) {
176184size_t umm_max_block_size ( void ) {
177- umm_info (NULL , 0 );
185+ umm_info (NULL , false );
178186 return ummHeapInfo .maxFreeContiguousBlocks * sizeof (umm_block );
179187}
180188
181- /* ------------------------------------------------------------------------ */
189+ /*
190+ Without build option UMM_INLINE_METRICS, calls to umm_usage_metric() or
191+ umm_fragmentation_metric() must to be preceeded by a call to umm_info(NULL, false)
192+ for updated results.
193+ */
194+ int umm_usage_metric ( void ) {
195+ #ifndef UMM_INLINE_METRICS
196+ umm_info (NULL , false);
197+ #endif
198+ DBGLOG_DEBUG ( "usedBlocks %d totalBlocks %d\n" , umm_metrics .usedBlocks , ummHeapInfo .totalBlocks );
199+ if (ummHeapInfo .freeBlocks )
200+ return (int )((ummHeapInfo .usedBlocks * 100 )/(ummHeapInfo .freeBlocks ));
182201
202+ return -1 ; // no freeBlocks
203+ }
204+
205+ uint32_t sqrt32 (uint32_t n );
206+
207+ int umm_fragmentation_metric ( void ) {
208+ #ifndef UMM_INLINE_METRICS
209+ umm_info (NULL , false);
210+ #endif
211+ DBGLOG_DEBUG ( "freeBlocks %d freeBlocksSquared %d\n" , umm_metrics .freeBlocks , ummHeapInfo .freeBlocksSquared );
212+ if (0 == ummHeapInfo .freeBlocks ) {
213+ return 0 ;
214+ } else {
215+ //upstream version: return (100 - (((uint32_t)(sqrtf(ummHeapInfo.freeBlocksSquared)) * 100)/(ummHeapInfo.freeBlocks)));
216+ return (100 - (((uint32_t )(sqrt32 (ummHeapInfo .freeBlocksSquared )) * 100 )/(ummHeapInfo .freeBlocks )));
217+ }
218+ }
219+
220+ #ifdef UMM_INLINE_METRICS
221+ static void umm_fragmentation_metric_init ( void ) {
222+ ummHeapInfo .freeBlocks = UMM_NUMBLOCKS - 2 ;
223+ ummHeapInfo .freeBlocksSquared = ummHeapInfo .freeBlocks * ummHeapInfo .freeBlocks ;
224+ }
225+
226+ static void umm_fragmentation_metric_add ( uint16_t c ) {
227+ uint16_t blocks = (UMM_NBLOCK (c ) & UMM_BLOCKNO_MASK ) - c ;
228+ DBGLOG_DEBUG ( "Add block %d size %d to free metric\n" , c , blocks );
229+ ummHeapInfo .freeBlocks += blocks ;
230+ ummHeapInfo .freeBlocksSquared += (blocks * blocks );
231+ }
232+
233+ static void umm_fragmentation_metric_remove ( uint16_t c ) {
234+ uint16_t blocks = (UMM_NBLOCK (c ) & UMM_BLOCKNO_MASK ) - c ;
235+ DBGLOG_DEBUG ( "Remove block %d size %d from free metric\n" , c , blocks );
236+ ummHeapInfo .freeBlocks -= blocks ;
237+ ummHeapInfo .freeBlocksSquared -= (blocks * blocks );
238+ }
239+ #endif // UMM_INLINE_METRICS
240+
241+ /* ------------------------------------------------------------------------ */
183242#endif
184243
185244#endif // defined(BUILD_UMM_MALLOC_C)
0 commit comments