2
2
3
3
#ifdef UMM_INFO
4
4
5
+ #include <stdint.h>
6
+ #include <stddef.h>
7
+ #include <stdbool.h>
8
+
9
+ #include <math.h>
10
+
5
11
/* ----------------------------------------------------------------------------
6
12
* One of the coolest things about this little library is that it's VERY
7
13
* easy to get debug information about the memory heap by simply iterating
19
25
20
26
UMM_HEAP_INFO ummHeapInfo ;
21
27
22
- void * umm_info ( void * ptr , int force ) {
28
+ void * umm_info ( void * ptr , bool force ) {
23
29
UMM_CRITICAL_DECL (id_info );
24
30
25
- unsigned short int blockNo = 0 ;
26
-
27
- if (umm_heap == NULL ) {
31
+ if (umm_heap == NULL ) {
28
32
umm_init ();
29
33
}
30
34
35
+ uint16_t blockNo = 0 ;
36
+
31
37
/* Protect the critical section... */
32
38
UMM_CRITICAL_ENTRY (id_info );
33
39
@@ -40,7 +46,7 @@ void *umm_info( void *ptr, int force ) {
40
46
DBGLOG_FORCE ( force , "\n" );
41
47
DBGLOG_FORCE ( force , "+----------+-------+--------+--------+-------+--------+--------+\n" );
42
48
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 )),
44
50
blockNo ,
45
51
UMM_NBLOCK (blockNo ) & UMM_BLOCKNO_MASK ,
46
52
UMM_PBLOCK (blockNo ),
@@ -67,21 +73,18 @@ void *umm_info( void *ptr, int force ) {
67
73
if ( UMM_NBLOCK (blockNo ) & UMM_FREELIST_MASK ) {
68
74
++ ummHeapInfo .freeEntries ;
69
75
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 );
74
77
75
78
if (ummHeapInfo .maxFreeContiguousBlocks < curBlocks ) {
76
79
ummHeapInfo .maxFreeContiguousBlocks = curBlocks ;
77
80
}
78
81
79
82
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 )),
81
84
blockNo ,
82
85
UMM_NBLOCK (blockNo ) & UMM_BLOCKNO_MASK ,
83
86
UMM_PBLOCK (blockNo ),
84
- (unsigned int )curBlocks ,
87
+ (uint16_t )curBlocks ,
85
88
UMM_NFREE (blockNo ),
86
89
UMM_PFREE (blockNo ) );
87
90
@@ -99,33 +102,25 @@ void *umm_info( void *ptr, int force ) {
99
102
ummHeapInfo .usedBlocks += curBlocks ;
100
103
101
104
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 )),
103
106
blockNo ,
104
107
UMM_NBLOCK (blockNo ) & UMM_BLOCKNO_MASK ,
105
108
UMM_PBLOCK (blockNo ),
106
- (unsigned int )curBlocks );
109
+ (uint16_t )curBlocks );
107
110
}
108
111
109
112
blockNo = UMM_NBLOCK (blockNo ) & UMM_BLOCKNO_MASK ;
110
113
}
111
114
112
115
/*
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 !
115
120
*/
116
121
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
-
127
122
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 )),
129
124
blockNo ,
130
125
UMM_NBLOCK (blockNo ) & UMM_BLOCKNO_MASK ,
131
126
UMM_PBLOCK (blockNo ),
@@ -147,7 +142,13 @@ void *umm_info( void *ptr, int force ) {
147
142
148
143
DBGLOG_FORCE ( force , "+--------------------------------------------------------------+\n" );
149
144
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
+
150
150
#if defined(UMM_STATS ) || defined(UMM_STATS_FULL )
151
+ #if !defined(UMM_INLINE_METRICS )
151
152
if (ummHeapInfo .freeBlocks == ummStats .free_blocks ) {
152
153
DBGLOG_FORCE ( force , "heap info Free blocks and heap statistics Free blocks match.\n" );
153
154
} else {
@@ -156,6 +157,7 @@ void *umm_info( void *ptr, int force ) {
156
157
ummStats .free_blocks );
157
158
}
158
159
DBGLOG_FORCE ( force , "+--------------------------------------------------------------+\n" );
160
+ #endif
159
161
160
162
print_stats (force );
161
163
#endif
@@ -169,17 +171,74 @@ void *umm_info( void *ptr, int force ) {
169
171
/* ------------------------------------------------------------------------ */
170
172
171
173
size_t umm_free_heap_size ( void ) {
172
- umm_info (NULL , 0 );
174
+ #ifndef UMM_INLINE_METRICS
175
+ umm_info (NULL , false);
176
+ #endif
173
177
return (size_t )ummHeapInfo .freeBlocks * sizeof (umm_block );
174
178
}
175
179
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 ) {
176
184
size_t umm_max_block_size ( void ) {
177
- umm_info (NULL , 0 );
185
+ umm_info (NULL , false );
178
186
return ummHeapInfo .maxFreeContiguousBlocks * sizeof (umm_block );
179
187
}
180
188
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 ));
182
201
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
+ /* ------------------------------------------------------------------------ */
183
242
#endif
184
243
185
244
#endif // defined(BUILD_UMM_MALLOC_C)
0 commit comments