1
0
mirror of https://github.com/esp8266/Arduino.git synced 2025-04-19 23:22:16 +03:00

Sync umm_malloc style with upstream (#8426)

Upstream umm_malloc at git hash id 4dac43c3be7a7470dd669323021ba238081da18e
processed all project files with the style program uncrustify.

This PR updates our ported version of umm_malloc processed with "uncrustify".
This should make subsequent merges of upstream into this port easier.

This also makes the style more consistant through umm_malloc.
This commit is contained in:
M Hightower 2022-01-03 13:36:03 -08:00 committed by GitHub
parent f401f08aba
commit f26201e6a9
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
12 changed files with 1449 additions and 1403 deletions

View File

@ -248,4 +248,32 @@ Enhancement ideas:
save on the execution time spent with interrupts disabled. save on the execution time spent with interrupts disabled.
*/ */
/*
Dec 29, 2021
Upstream umm_malloc at git hash id 4dac43c3be7a7470dd669323021ba238081da18e
processed all project files with the style program uncrustify.
This PR updates our ported version of umm_malloc processed with "uncrustify".
This should make subsequent merges of upstream into this port easier.
This also makes the style more consistant through umm_malloc.
Some edits to source files was needed to get uncrustify to work.
1) macros with "if"s need to be of the form "if ( blah ) { } " curley braces
are needed for it to parse correctly
2) These "#ifdef __cplusplus" also had to be commented out while running to
avoid parser confusion.
```
#ifdef __cplusplus
extern "C" {
#endif
```
and
```
#ifdef __cplusplus
}
#endif
```
*/
#endif #endif

View File

@ -1 +1,2 @@
Downloaded from: https://github.com/rhempel/c-helper-macros/tree/develop Downloaded from: https://github.com/rhempel/c-helper-macros/tree/develop
Applied uncrustify to be consistent with the rest of the umm_malloc files.

View File

@ -50,11 +50,11 @@
#undef DBGLOG_FORCE #undef DBGLOG_FORCE
#ifndef DBGLOG_LEVEL #ifndef DBGLOG_LEVEL
# define DBGLOG_LEVEL 0 #define DBGLOG_LEVEL 0
#endif #endif
#ifndef DBGLOG_FUNCTION #ifndef DBGLOG_FUNCTION
# define DBGLOG_FUNCTION printf #define DBGLOG_FUNCTION printf
#endif #endif
#define DBGLOG_32_BIT_PTR(x) ((uint32_t)(((uintptr_t)(x)) & 0xffffffff)) #define DBGLOG_32_BIT_PTR(x) ((uint32_t)(((uintptr_t)(x)) & 0xffffffff))
@ -62,39 +62,39 @@
/* ------------------------------------------------------------------------- */ /* ------------------------------------------------------------------------- */
#if DBGLOG_LEVEL >= 6 #if DBGLOG_LEVEL >= 6
# define DBGLOG_TRACE(format, ...) DBGLOG_FUNCTION(format, ## __VA_ARGS__) #define DBGLOG_TRACE(format, ...) DBGLOG_FUNCTION(format,##__VA_ARGS__)
#else #else
# define DBGLOG_TRACE(format, ...) #define DBGLOG_TRACE(format, ...)
#endif #endif
#if DBGLOG_LEVEL >= 5 #if DBGLOG_LEVEL >= 5
# define DBGLOG_DEBUG(format, ...) DBGLOG_FUNCTION(format, ## __VA_ARGS__) #define DBGLOG_DEBUG(format, ...) DBGLOG_FUNCTION(format,##__VA_ARGS__)
#else #else
# define DBGLOG_DEBUG(format, ...) #define DBGLOG_DEBUG(format, ...)
#endif #endif
#if DBGLOG_LEVEL >= 4 #if DBGLOG_LEVEL >= 4
# define DBGLOG_CRITICAL(format, ...) DBGLOG_FUNCTION(format, ## __VA_ARGS__) #define DBGLOG_CRITICAL(format, ...) DBGLOG_FUNCTION(format,##__VA_ARGS__)
#else #else
# define DBGLOG_CRITICAL(format, ...) #define DBGLOG_CRITICAL(format, ...)
#endif #endif
#if DBGLOG_LEVEL >= 3 #if DBGLOG_LEVEL >= 3
# define DBGLOG_ERROR(format, ...) DBGLOG_FUNCTION(format, ## __VA_ARGS__) #define DBGLOG_ERROR(format, ...) DBGLOG_FUNCTION(format,##__VA_ARGS__)
#else #else
# define DBGLOG_ERROR(format, ...) #define DBGLOG_ERROR(format, ...)
#endif #endif
#if DBGLOG_LEVEL >= 2 #if DBGLOG_LEVEL >= 2
# define DBGLOG_WARNING(format, ...) DBGLOG_FUNCTION(format, ## __VA_ARGS__) #define DBGLOG_WARNING(format, ...) DBGLOG_FUNCTION(format,##__VA_ARGS__)
#else #else
# define DBGLOG_WARNING(format, ...) #define DBGLOG_WARNING(format, ...)
#endif #endif
#if DBGLOG_LEVEL >= 1 #if DBGLOG_LEVEL >= 1
# define DBGLOG_INFO(format, ...) DBGLOG_FUNCTION(format, ## __VA_ARGS__) #define DBGLOG_INFO(format, ...) DBGLOG_FUNCTION(format,##__VA_ARGS__)
#else #else
# define DBGLOG_INFO(format, ...) #define DBGLOG_INFO(format, ...)
#endif #endif
#define DBGLOG_FORCE(force, format, ...) {if(force) {DBGLOG_FUNCTION(format, ## __VA_ARGS__);}} #define DBGLOG_FORCE(force, format, ...) {if (force) {DBGLOG_FUNCTION(format,##__VA_ARGS__);}}

View File

@ -32,70 +32,77 @@
class HeapSelect { class HeapSelect {
public: public:
#if (UMM_NUM_HEAPS == 1) #if (UMM_NUM_HEAPS == 1)
MAYBE_ALWAYS_INLINE MAYBE_ALWAYS_INLINE
HeapSelect(size_t id) { (void)id; } HeapSelect(size_t id) {
MAYBE_ALWAYS_INLINE (void)id;
~HeapSelect() {} }
MAYBE_ALWAYS_INLINE
~HeapSelect() {
}
#else #else
MAYBE_ALWAYS_INLINE MAYBE_ALWAYS_INLINE
HeapSelect(size_t id) : _heap_id(umm_get_current_heap_id()) { HeapSelect(size_t id) : _heap_id(umm_get_current_heap_id()) {
umm_set_heap_by_id(id); umm_set_heap_by_id(id);
} }
MAYBE_ALWAYS_INLINE MAYBE_ALWAYS_INLINE
~HeapSelect() { ~HeapSelect() {
umm_set_heap_by_id(_heap_id); umm_set_heap_by_id(_heap_id);
} }
protected: protected:
size_t _heap_id; size_t _heap_id;
#endif #endif
}; };
class HeapSelectIram { class HeapSelectIram {
public: public:
#ifdef UMM_HEAP_IRAM #ifdef UMM_HEAP_IRAM
MAYBE_ALWAYS_INLINE MAYBE_ALWAYS_INLINE
HeapSelectIram() : _heap_id(umm_get_current_heap_id()) { HeapSelectIram() : _heap_id(umm_get_current_heap_id()) {
umm_set_heap_by_id(UMM_HEAP_IRAM); umm_set_heap_by_id(UMM_HEAP_IRAM);
} }
MAYBE_ALWAYS_INLINE MAYBE_ALWAYS_INLINE
~HeapSelectIram() { ~HeapSelectIram() {
umm_set_heap_by_id(_heap_id); umm_set_heap_by_id(_heap_id);
} }
protected: protected:
size_t _heap_id; size_t _heap_id;
#else #else
MAYBE_ALWAYS_INLINE MAYBE_ALWAYS_INLINE
HeapSelectIram() {} HeapSelectIram() {
MAYBE_ALWAYS_INLINE }
~HeapSelectIram() {} MAYBE_ALWAYS_INLINE
~HeapSelectIram() {
}
#endif #endif
}; };
class HeapSelectDram { class HeapSelectDram {
public: public:
#if (UMM_NUM_HEAPS == 1) #if (UMM_NUM_HEAPS == 1)
MAYBE_ALWAYS_INLINE MAYBE_ALWAYS_INLINE
HeapSelectDram() {} HeapSelectDram() {
MAYBE_ALWAYS_INLINE }
~HeapSelectDram() {} MAYBE_ALWAYS_INLINE
~HeapSelectDram() {
}
#else #else
MAYBE_ALWAYS_INLINE MAYBE_ALWAYS_INLINE
HeapSelectDram() : _heap_id(umm_get_current_heap_id()) { HeapSelectDram() : _heap_id(umm_get_current_heap_id()) {
umm_set_heap_by_id(UMM_HEAP_DRAM); umm_set_heap_by_id(UMM_HEAP_DRAM);
} }
MAYBE_ALWAYS_INLINE MAYBE_ALWAYS_INLINE
~HeapSelectDram() { ~HeapSelectDram() {
umm_set_heap_by_id(_heap_id); umm_set_heap_by_id(_heap_id);
} }
protected: protected:
size_t _heap_id; size_t _heap_id;
#endif #endif
}; };

View File

@ -25,174 +25,174 @@
// UMM_HEAP_INFO ummHeapInfo; // UMM_HEAP_INFO ummHeapInfo;
void *umm_info( void *ptr, bool force ) { void *umm_info(void *ptr, bool force) {
UMM_CRITICAL_DECL(id_info); UMM_CRITICAL_DECL(id_info);
UMM_INIT_HEAP; UMM_INIT_HEAP;
uint16_t blockNo = 0; uint16_t blockNo = 0;
/* Protect the critical section... */ /* Protect the critical section... */
UMM_CRITICAL_ENTRY(id_info); UMM_CRITICAL_ENTRY(id_info);
umm_heap_context_t *_context = umm_get_current_heap(); umm_heap_context_t *_context = umm_get_current_heap();
/* /*
* Clear out all of the entries in the ummHeapInfo structure before doing * Clear out all of the entries in the ummHeapInfo structure before doing
* any calculations.. * any calculations..
*/ */
memset( &_context->info, 0, sizeof( _context->info ) ); memset(&_context->info, 0, sizeof(_context->info));
DBGLOG_FORCE( force, "\n" ); DBGLOG_FORCE(force, "\n");
DBGLOG_FORCE( force, "+----------+-------+--------+--------+-------+--------+--------+\n" ); DBGLOG_FORCE(force, "+----------+-------+--------+--------+-------+--------+--------+\n");
DBGLOG_FORCE( force, "|0x%08lx|B %5d|NB %5d|PB %5d|Z %5d|NF %5d|PF %5d|\n", DBGLOG_FORCE(force, "|0x%08lx|B %5d|NB %5d|PB %5d|Z %5d|NF %5d|PF %5d|\n",
DBGLOG_32_BIT_PTR(&UMM_BLOCK(blockNo)), DBGLOG_32_BIT_PTR(&UMM_BLOCK(blockNo)),
blockNo, blockNo,
UMM_NBLOCK(blockNo) & UMM_BLOCKNO_MASK, UMM_NBLOCK(blockNo) & UMM_BLOCKNO_MASK,
UMM_PBLOCK(blockNo), UMM_PBLOCK(blockNo),
(UMM_NBLOCK(blockNo) & UMM_BLOCKNO_MASK )-blockNo, (UMM_NBLOCK(blockNo) & UMM_BLOCKNO_MASK) - blockNo,
UMM_NFREE(blockNo), UMM_NFREE(blockNo),
UMM_PFREE(blockNo) ); UMM_PFREE(blockNo));
/* /*
* Now loop through the block lists, and keep track of the number and size * Now loop through the block lists, and keep track of the number and size
* of used and free blocks. The terminating condition is an nb pointer with * of used and free blocks. The terminating condition is an nb pointer with
* a value of zero... * a value of zero...
*/ */
blockNo = UMM_NBLOCK(blockNo) & UMM_BLOCKNO_MASK;
while( UMM_NBLOCK(blockNo) & UMM_BLOCKNO_MASK ) {
size_t curBlocks = (UMM_NBLOCK(blockNo) & UMM_BLOCKNO_MASK )-blockNo;
++_context->info.totalEntries;
_context->info.totalBlocks += curBlocks;
/* Is this a free block? */
if( UMM_NBLOCK(blockNo) & UMM_FREELIST_MASK ) {
++_context->info.freeEntries;
_context->info.freeBlocks += curBlocks;
_context->info.freeBlocksSquared += (curBlocks * curBlocks);
if (_context->info.maxFreeContiguousBlocks < curBlocks) {
_context->info.maxFreeContiguousBlocks = curBlocks;
}
DBGLOG_FORCE( force, "|0x%08lx|B %5d|NB %5d|PB %5d|Z %5u|NF %5d|PF %5d|\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) );
/* Does this block address match the ptr we may be trying to free? */
if( ptr == &UMM_BLOCK(blockNo) ) {
/* Release the critical section... */
UMM_CRITICAL_EXIT(id_info);
return( ptr );
}
} else {
++_context->info.usedEntries;
_context->info.usedBlocks += curBlocks;
DBGLOG_FORCE( force, "|0x%08lx|B %5d|NB %5d|PB %5d|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; blockNo = UMM_NBLOCK(blockNo) & UMM_BLOCKNO_MASK;
}
/* while (UMM_NBLOCK(blockNo) & UMM_BLOCKNO_MASK) {
* The very last block is used as a placeholder to indicate that size_t curBlocks = (UMM_NBLOCK(blockNo) & UMM_BLOCKNO_MASK) - blockNo;
* there are no more blocks in the heap, so it cannot be used
* for anything - at the same time, the size of this block must
* ALWAYS be exactly 1 !
*/
DBGLOG_FORCE( force, "|0x%08lx|B %5d|NB %5d|PB %5d|Z %5d|NF %5d|PF %5d|\n", ++_context->info.totalEntries;
DBGLOG_32_BIT_PTR(&UMM_BLOCK(blockNo)), _context->info.totalBlocks += curBlocks;
blockNo,
UMM_NBLOCK(blockNo) & UMM_BLOCKNO_MASK,
UMM_PBLOCK(blockNo),
UMM_NUMBLOCKS-blockNo,
UMM_NFREE(blockNo),
UMM_PFREE(blockNo) );
DBGLOG_FORCE( force, "+----------+-------+--------+--------+-------+--------+--------+\n" ); /* Is this a free block? */
DBGLOG_FORCE( force, "Total Entries %5d Used Entries %5d Free Entries %5d\n", if (UMM_NBLOCK(blockNo) & UMM_FREELIST_MASK) {
_context->info.totalEntries, ++_context->info.freeEntries;
_context->info.usedEntries, _context->info.freeBlocks += curBlocks;
_context->info.freeEntries ); _context->info.freeBlocksSquared += (curBlocks * curBlocks);
DBGLOG_FORCE( force, "Total Blocks %5d Used Blocks %5d Free Blocks %5d\n", if (_context->info.maxFreeContiguousBlocks < curBlocks) {
_context->info.totalBlocks, _context->info.maxFreeContiguousBlocks = curBlocks;
_context->info.usedBlocks, }
_context->info.freeBlocks );
DBGLOG_FORCE( force, "+--------------------------------------------------------------+\n" ); DBGLOG_FORCE(force, "|0x%08lx|B %5d|NB %5d|PB %5d|Z %5u|NF %5d|PF %5d|\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));
DBGLOG_FORCE( force, "Usage Metric: %5d\n", umm_usage_metric_core(_context)); /* Does this block address match the ptr we may be trying to free? */
DBGLOG_FORCE( force, "Fragmentation Metric: %5d\n", umm_fragmentation_metric_core(_context));
DBGLOG_FORCE( force, "+--------------------------------------------------------------+\n" ); if (ptr == &UMM_BLOCK(blockNo)) {
#if defined(UMM_STATS) || defined(UMM_STATS_FULL) /* Release the critical section... */
#if !defined(UMM_INLINE_METRICS) UMM_CRITICAL_EXIT(id_info);
if (_context->info.freeBlocks == _context->stats.free_blocks) {
DBGLOG_FORCE( force, "heap info Free blocks and heap statistics Free blocks match.\n");
} else {
DBGLOG_FORCE( force, "\nheap info Free blocks %5d != heap statistics Free Blocks %5d\n\n",
_context->info.freeBlocks,
_context->stats.free_blocks );
}
DBGLOG_FORCE( force, "+--------------------------------------------------------------+\n" );
#endif
umm_print_stats(force); return ptr;
#endif }
} else {
++_context->info.usedEntries;
_context->info.usedBlocks += curBlocks;
/* Release the critical section... */ DBGLOG_FORCE(force, "|0x%08lx|B %5d|NB %5d|PB %5d|Z %5u|\n",
UMM_CRITICAL_EXIT(id_info); DBGLOG_32_BIT_PTR(&UMM_BLOCK(blockNo)),
blockNo,
UMM_NBLOCK(blockNo) & UMM_BLOCKNO_MASK,
UMM_PBLOCK(blockNo),
(uint16_t)curBlocks);
}
return( NULL ); blockNo = UMM_NBLOCK(blockNo) & UMM_BLOCKNO_MASK;
}
/*
* The very last block is used as a placeholder to indicate that
* there are no more blocks in the heap, so it cannot be used
* for anything - at the same time, the size of this block must
* ALWAYS be exactly 1 !
*/
DBGLOG_FORCE(force, "|0x%08lx|B %5d|NB %5d|PB %5d|Z %5d|NF %5d|PF %5d|\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 %5d Used Entries %5d Free Entries %5d\n",
_context->info.totalEntries,
_context->info.usedEntries,
_context->info.freeEntries);
DBGLOG_FORCE(force, "Total Blocks %5d Used Blocks %5d Free Blocks %5d\n",
_context->info.totalBlocks,
_context->info.usedBlocks,
_context->info.freeBlocks);
DBGLOG_FORCE(force, "+--------------------------------------------------------------+\n");
DBGLOG_FORCE(force, "Usage Metric: %5d\n", umm_usage_metric_core(_context));
DBGLOG_FORCE(force, "Fragmentation Metric: %5d\n", umm_fragmentation_metric_core(_context));
DBGLOG_FORCE(force, "+--------------------------------------------------------------+\n");
#if defined(UMM_STATS) || defined(UMM_STATS_FULL)
#if !defined(UMM_INLINE_METRICS)
if (_context->info.freeBlocks == _context->stats.free_blocks) {
DBGLOG_FORCE(force, "heap info Free blocks and heap statistics Free blocks match.\n");
} else {
DBGLOG_FORCE(force, "\nheap info Free blocks %5d != heap statistics Free Blocks %5d\n\n",
_context->info.freeBlocks,
_context->stats.free_blocks);
}
DBGLOG_FORCE(force, "+--------------------------------------------------------------+\n");
#endif
umm_print_stats(force);
#endif
/* Release the critical section... */
UMM_CRITICAL_EXIT(id_info);
return NULL;
} }
/* ------------------------------------------------------------------------ */ /* ------------------------------------------------------------------------ */
size_t umm_free_heap_size_core( umm_heap_context_t *_context ) { size_t umm_free_heap_size_core(umm_heap_context_t *_context) {
return (size_t)_context->info.freeBlocks * sizeof(umm_block); return (size_t)_context->info.freeBlocks * sizeof(umm_block);
} }
size_t umm_free_heap_size( void ) { size_t umm_free_heap_size(void) {
#ifndef UMM_INLINE_METRICS #ifndef UMM_INLINE_METRICS
umm_info(NULL, false); umm_info(NULL, false);
#endif #endif
return umm_free_heap_size_core(umm_get_current_heap()); return umm_free_heap_size_core(umm_get_current_heap());
} }
//C Breaking change in upstream umm_max_block_size() was changed to // C Breaking change in upstream umm_max_block_size() was changed to
//C umm_max_free_block_size() keeping old function name for (dot) releases. // C umm_max_free_block_size() keeping old function name for (dot) releases.
//C TODO: update at next major release. // C TODO: update at next major release.
//C size_t umm_max_free_block_size( void ) { // C size_t umm_max_free_block_size( void ) {
size_t umm_max_block_size_core( umm_heap_context_t *_context ) { size_t umm_max_block_size_core(umm_heap_context_t *_context) {
return _context->info.maxFreeContiguousBlocks * sizeof(umm_block); return _context->info.maxFreeContiguousBlocks * sizeof(umm_block);
} }
size_t umm_max_block_size( void ) { size_t umm_max_block_size(void) {
umm_info(NULL, false); umm_info(NULL, false);
return umm_max_block_size_core(umm_get_current_heap()); return umm_max_block_size_core(umm_get_current_heap());
} }
/* /*
@ -200,60 +200,61 @@ size_t umm_max_block_size( void ) {
umm_fragmentation_metric() must to be preceded by a call to umm_info(NULL, false) umm_fragmentation_metric() must to be preceded by a call to umm_info(NULL, false)
for updated results. for updated results.
*/ */
int umm_usage_metric_core( umm_heap_context_t *_context ) { int umm_usage_metric_core(umm_heap_context_t *_context) {
//C Note, umm_metrics also appears in the upstrean w/o definition. I suspect it is suppose to be ummHeapInfo. // C Note, umm_metrics also appears in the upstrean w/o definition. I suspect it is suppose to be ummHeapInfo.
// DBGLOG_DEBUG( "usedBlocks %d totalBlocks %d\n", umm_metrics.usedBlocks, ummHeapInfo.totalBlocks); // DBGLOG_DEBUG( "usedBlocks %d totalBlocks %d\n", umm_metrics.usedBlocks, ummHeapInfo.totalBlocks);
DBGLOG_DEBUG( "usedBlocks %d totalBlocks %d\n", _context->info.usedBlocks, _context->info.totalBlocks); DBGLOG_DEBUG("usedBlocks %d totalBlocks %d\n", _context->info.usedBlocks, _context->info.totalBlocks);
if (_context->info.freeBlocks) if (_context->info.freeBlocks) {
return (int)((_context->info.usedBlocks * 100)/(_context->info.freeBlocks)); return (int)((_context->info.usedBlocks * 100) / (_context->info.freeBlocks));
}
return -1; // no freeBlocks return -1; // no freeBlocks
} }
int umm_usage_metric( void ) { int umm_usage_metric(void) {
#ifndef UMM_INLINE_METRICS #ifndef UMM_INLINE_METRICS
umm_info(NULL, false); umm_info(NULL, false);
#endif #endif
return umm_usage_metric_core(umm_get_current_heap()); return umm_usage_metric_core(umm_get_current_heap());
} }
uint32_t sqrt32 (uint32_t n); uint32_t sqrt32(uint32_t n);
int umm_fragmentation_metric_core( umm_heap_context_t *_context ) { int umm_fragmentation_metric_core(umm_heap_context_t *_context) {
// DBGLOG_DEBUG( "freeBlocks %d freeBlocksSquared %d\n", umm_metrics.freeBlocks, ummHeapInfo.freeBlocksSquared); // DBGLOG_DEBUG( "freeBlocks %d freeBlocksSquared %d\n", umm_metrics.freeBlocks, ummHeapInfo.freeBlocksSquared);
DBGLOG_DEBUG( "freeBlocks %d freeBlocksSquared %d\n", _context->info.freeBlocks, _context->info.freeBlocksSquared); DBGLOG_DEBUG("freeBlocks %d freeBlocksSquared %d\n", _context->info.freeBlocks, _context->info.freeBlocksSquared);
if (0 == _context->info.freeBlocks) { if (0 == _context->info.freeBlocks) {
return 0; return 0;
} else { } else {
//upstream version: return (100 - (((uint32_t)(sqrtf(ummHeapInfo.freeBlocksSquared)) * 100)/(ummHeapInfo.freeBlocks))); // upstream version: return (100 - (((uint32_t)(sqrtf(ummHeapInfo.freeBlocksSquared)) * 100)/(ummHeapInfo.freeBlocks)));
return (100 - (((uint32_t)(sqrt32(_context->info.freeBlocksSquared)) * 100)/(_context->info.freeBlocks))); return 100 - (((uint32_t)(sqrt32(_context->info.freeBlocksSquared)) * 100) / (_context->info.freeBlocks));
} }
} }
int umm_fragmentation_metric( void ) { int umm_fragmentation_metric(void) {
#ifndef UMM_INLINE_METRICS #ifndef UMM_INLINE_METRICS
umm_info(NULL, false); umm_info(NULL, false);
#endif #endif
return umm_fragmentation_metric_core(umm_get_current_heap()); return umm_fragmentation_metric_core(umm_get_current_heap());
} }
#ifdef UMM_INLINE_METRICS #ifdef UMM_INLINE_METRICS
static void umm_fragmentation_metric_init( umm_heap_context_t *_context ) { static void umm_fragmentation_metric_init(umm_heap_context_t *_context) {
_context->info.freeBlocks = UMM_NUMBLOCKS - 2; _context->info.freeBlocks = UMM_NUMBLOCKS - 2;
_context->info.freeBlocksSquared = _context->info.freeBlocks * _context->info.freeBlocks; _context->info.freeBlocksSquared = _context->info.freeBlocks * _context->info.freeBlocks;
} }
static void umm_fragmentation_metric_add( umm_heap_context_t *_context, uint16_t c ) { static void umm_fragmentation_metric_add(umm_heap_context_t *_context, uint16_t c) {
uint16_t blocks = (UMM_NBLOCK(c) & UMM_BLOCKNO_MASK) - c; uint16_t blocks = (UMM_NBLOCK(c) & UMM_BLOCKNO_MASK) - c;
DBGLOG_DEBUG( "Add block %d size %d to free metric\n", c, blocks); DBGLOG_DEBUG("Add block %d size %d to free metric\n", c, blocks);
_context->info.freeBlocks += blocks; _context->info.freeBlocks += blocks;
_context->info.freeBlocksSquared += (blocks * blocks); _context->info.freeBlocksSquared += (blocks * blocks);
} }
static void umm_fragmentation_metric_remove( umm_heap_context_t *_context, uint16_t c ) { static void umm_fragmentation_metric_remove(umm_heap_context_t *_context, uint16_t c) {
uint16_t blocks = (UMM_NBLOCK(c) & UMM_BLOCKNO_MASK) - c; uint16_t blocks = (UMM_NBLOCK(c) & UMM_BLOCKNO_MASK) - c;
DBGLOG_DEBUG( "Remove block %d size %d from free metric\n", c, blocks); DBGLOG_DEBUG("Remove block %d size %d from free metric\n", c, blocks);
_context->info.freeBlocks -= blocks; _context->info.freeBlocks -= blocks;
_context->info.freeBlocksSquared -= (blocks * blocks); _context->info.freeBlocksSquared -= (blocks * blocks);
} }

View File

@ -28,109 +28,108 @@
* chain. * chain.
*/ */
bool umm_integrity_check(void) { bool umm_integrity_check(void) {
UMM_CRITICAL_DECL(id_integrity); UMM_CRITICAL_DECL(id_integrity);
bool ok = true; bool ok = true;
uint16_t prev; uint16_t prev;
uint16_t cur; uint16_t cur;
UMM_INIT_HEAP; UMM_INIT_HEAP;
/* Iterate through all free blocks */ /* Iterate through all free blocks */
prev = 0; prev = 0;
UMM_CRITICAL_ENTRY(id_integrity); UMM_CRITICAL_ENTRY(id_integrity);
umm_heap_context_t *_context = umm_get_current_heap(); umm_heap_context_t *_context = umm_get_current_heap();
while(1) { while (1) {
cur = UMM_NFREE(prev); cur = UMM_NFREE(prev);
/* Check that next free block number is valid */ /* Check that next free block number is valid */
if (cur >= UMM_NUMBLOCKS) { if (cur >= UMM_NUMBLOCKS) {
DBGLOG_FUNCTION("heap integrity broken: too large next free num: %d " DBGLOG_FUNCTION("heap integrity broken: too large next free num: %d "
"(in block %d, addr 0x%08x)\n", cur, prev, "(in block %d, addr 0x%08x)\n", cur, prev,
DBGLOG_32_BIT_PTR(&UMM_NBLOCK(prev))); DBGLOG_32_BIT_PTR(&UMM_NBLOCK(prev)));
ok = false; ok = false;
goto clean; goto clean;
} }
if (cur == 0) { if (cur == 0) {
/* No more free blocks */ /* No more free blocks */
break; break;
}
/* Check if prev free block number matches */
if (UMM_PFREE(cur) != prev) {
DBGLOG_FUNCTION("heap integrity broken: free links don't match: "
"%d -> %d, but %d -> %d\n",
prev, cur, cur, UMM_PFREE(cur));
ok = false;
goto clean;
}
UMM_PBLOCK(cur) |= UMM_FREELIST_MASK;
prev = cur;
} }
/* Check if prev free block number matches */ /* Iterate through all blocks */
if (UMM_PFREE(cur) != prev) { prev = 0;
DBGLOG_FUNCTION("heap integrity broken: free links don't match: " while (1) {
"%d -> %d, but %d -> %d\n", cur = UMM_NBLOCK(prev) & UMM_BLOCKNO_MASK;
prev, cur, cur, UMM_PFREE(cur));
ok = false;
goto clean;
}
UMM_PBLOCK(cur) |= UMM_FREELIST_MASK; /* Check that next block number is valid */
if (cur >= UMM_NUMBLOCKS) {
DBGLOG_FUNCTION("heap integrity broken: too large next block num: %d "
"(in block %d, addr 0x%08x)\n", cur, prev,
DBGLOG_32_BIT_PTR(&UMM_NBLOCK(prev)));
ok = false;
goto clean;
}
if (cur == 0) {
/* No more blocks */
break;
}
prev = cur; /* make sure the free mark is appropriate, and unmark it */
} if ((UMM_NBLOCK(cur) & UMM_FREELIST_MASK)
!= (UMM_PBLOCK(cur) & UMM_FREELIST_MASK)) {
DBGLOG_FUNCTION("heap integrity broken: mask wrong at addr 0x%08x: n=0x%x, p=0x%x\n",
DBGLOG_32_BIT_PTR(&UMM_NBLOCK(cur)),
(UMM_NBLOCK(cur) & UMM_FREELIST_MASK),
(UMM_PBLOCK(cur) & UMM_FREELIST_MASK));
ok = false;
goto clean;
}
/* Iterate through all blocks */ /* make sure the block list is sequential */
prev = 0; if (cur <= prev) {
while(1) { DBGLOG_FUNCTION("heap integrity broken: next block %d is before prev this one "
cur = UMM_NBLOCK(prev) & UMM_BLOCKNO_MASK; "(in block %d, addr 0x%08x)\n", cur, prev,
DBGLOG_32_BIT_PTR(&UMM_NBLOCK(prev)));
/* Check that next block number is valid */ ok = false;
if (cur >= UMM_NUMBLOCKS) { goto clean;
DBGLOG_FUNCTION("heap integrity broken: too large next block num: %d " }
"(in block %d, addr 0x%08x)\n", cur, prev,
DBGLOG_32_BIT_PTR(&UMM_NBLOCK(prev)));
ok = false;
goto clean;
}
if (cur == 0) {
/* No more blocks */
break;
}
/* make sure the free mark is appropriate, and unmark it */
if ((UMM_NBLOCK(cur) & UMM_FREELIST_MASK)
!= (UMM_PBLOCK(cur) & UMM_FREELIST_MASK))
{
DBGLOG_FUNCTION("heap integrity broken: mask wrong at addr 0x%08x: n=0x%x, p=0x%x\n",
DBGLOG_32_BIT_PTR(&UMM_NBLOCK(cur)),
(UMM_NBLOCK(cur) & UMM_FREELIST_MASK),
(UMM_PBLOCK(cur) & UMM_FREELIST_MASK));
ok = false;
goto clean;
}
/* make sure the block list is sequential */
if (cur <= prev ) {
DBGLOG_FUNCTION("heap integrity broken: next block %d is before prev this one "
"(in block %d, addr 0x%08x)\n", cur, prev,
DBGLOG_32_BIT_PTR(&UMM_NBLOCK(prev)));
ok = false;
goto clean;
}
/* unmark */ /* unmark */
UMM_PBLOCK(cur) &= UMM_BLOCKNO_MASK; UMM_PBLOCK(cur) &= UMM_BLOCKNO_MASK;
/* Check if prev block number matches */ /* Check if prev block number matches */
if (UMM_PBLOCK(cur) != prev) { if (UMM_PBLOCK(cur) != prev) {
DBGLOG_FUNCTION("heap integrity broken: block links don't match: " DBGLOG_FUNCTION("heap integrity broken: block links don't match: "
"%d -> %d, but %d -> %d\n", "%d -> %d, but %d -> %d\n",
prev, cur, cur, UMM_PBLOCK(cur)); prev, cur, cur, UMM_PBLOCK(cur));
ok = false; ok = false;
goto clean; goto clean;
}
prev = cur;
} }
prev = cur;
}
clean: clean:
UMM_CRITICAL_EXIT(id_integrity); UMM_CRITICAL_EXIT(id_integrity);
if (!ok){ if (!ok) {
UMM_HEAP_CORRUPTION_CB(); UMM_HEAP_CORRUPTION_CB();
} }
return ok; return ok;
} }
#endif #endif

View File

@ -12,22 +12,21 @@ UMM_TIME_STATS time_stats = {
{0xFFFFFFFF, 0U, 0U, 0U}, {0xFFFFFFFF, 0U, 0U, 0U},
{0xFFFFFFFF, 0U, 0U, 0U}, {0xFFFFFFFF, 0U, 0U, 0U},
{0xFFFFFFFF, 0U, 0U, 0U}, {0xFFFFFFFF, 0U, 0U, 0U},
#ifdef UMM_INFO #ifdef UMM_INFO
{0xFFFFFFFF, 0U, 0U, 0U}, {0xFFFFFFFF, 0U, 0U, 0U},
#endif #endif
#if defined(UMM_POISON_CHECK) || defined(UMM_POISON_CHECK_LITE) #if defined(UMM_POISON_CHECK) || defined(UMM_POISON_CHECK_LITE)
{0xFFFFFFFF, 0U, 0U, 0U}, {0xFFFFFFFF, 0U, 0U, 0U},
#endif #endif
#ifdef UMM_INTEGRITY_CHECK #ifdef UMM_INTEGRITY_CHECK
{0xFFFFFFFF, 0U, 0U, 0U}, {0xFFFFFFFF, 0U, 0U, 0U},
#endif #endif
{0xFFFFFFFF, 0U, 0U, 0U} }; {0xFFFFFFFF, 0U, 0U, 0U}
};
bool ICACHE_FLASH_ATTR get_umm_get_perf_data(UMM_TIME_STATS *p, size_t size) bool ICACHE_FLASH_ATTR get_umm_get_perf_data(UMM_TIME_STATS *p, size_t size) {
{
UMM_CRITICAL_DECL(id_no_tag); UMM_CRITICAL_DECL(id_no_tag);
if (p && sizeof(time_stats) == size) if (p && sizeof(time_stats) == size) {
{
UMM_CRITICAL_ENTRY(id_no_tag); UMM_CRITICAL_ENTRY(id_no_tag);
memcpy(p, &time_stats, size); memcpy(p, &time_stats, size);
UMM_CRITICAL_EXIT(id_no_tag); UMM_CRITICAL_EXIT(id_no_tag);
@ -42,42 +41,45 @@ bool ICACHE_FLASH_ATTR get_umm_get_perf_data(UMM_TIME_STATS *p, size_t size)
#if defined(UMM_POISON_CHECK_LITE) #if defined(UMM_POISON_CHECK_LITE)
// We skip this when doing the full poison check. // We skip this when doing the full poison check.
static bool check_poison_neighbors( umm_heap_context_t *_context, uint16_t cur ) { static bool check_poison_neighbors(umm_heap_context_t *_context, uint16_t cur) {
uint16_t c; uint16_t c;
if (0 == cur) {
return true;
}
c = UMM_PBLOCK(cur) & UMM_BLOCKNO_MASK;
while (c && (UMM_NBLOCK(c) & UMM_BLOCKNO_MASK)) {
/*
There can be up to 1 free block neighbor in either direction.
This loop should self limit to 2 passes, due to heap design.
i.e. Adjacent free space is always consolidated.
*/
if (!(UMM_NBLOCK(c) & UMM_FREELIST_MASK)) {
if (!check_poison_block(&UMM_BLOCK(c))) {
return false;
}
break;
}
c = UMM_PBLOCK(c) & UMM_BLOCKNO_MASK;
}
c = UMM_NBLOCK(cur) & UMM_BLOCKNO_MASK;
while ((UMM_NBLOCK(c) & UMM_BLOCKNO_MASK)) {
if (!(UMM_NBLOCK(c) & UMM_FREELIST_MASK)) {
if (!check_poison_block(&UMM_BLOCK(c))) {
return false;
}
break;
}
c = UMM_NBLOCK(c) & UMM_BLOCKNO_MASK;
}
if ( 0 == cur )
return true; return true;
c = UMM_PBLOCK(cur) & UMM_BLOCKNO_MASK;
while( c && (UMM_NBLOCK(c) & UMM_BLOCKNO_MASK) ) {
/*
There can be up to 1 free block neighbor in either direction.
This loop should self limit to 2 passes, due to heap design.
i.e. Adjacent free space is always consolidated.
*/
if ( !(UMM_NBLOCK(c) & UMM_FREELIST_MASK) ) {
if ( !check_poison_block(&UMM_BLOCK(c)) )
return false;
break;
}
c = UMM_PBLOCK(c) & UMM_BLOCKNO_MASK;
}
c = UMM_NBLOCK(cur) & UMM_BLOCKNO_MASK;
while( (UMM_NBLOCK(c) & UMM_BLOCKNO_MASK) ) {
if ( !(UMM_NBLOCK(c) & UMM_FREELIST_MASK) ) {
if ( !check_poison_block(&UMM_BLOCK(c)) )
return false;
break;
}
c = UMM_NBLOCK(c) & UMM_BLOCKNO_MASK;
}
return true;
} }
#endif #endif
@ -85,52 +87,52 @@ static bool check_poison_neighbors( umm_heap_context_t *_context, uint16_t cur )
/* ------------------------------------------------------------------------ */ /* ------------------------------------------------------------------------ */
static void *get_unpoisoned_check_neighbors( void *vptr, const char* file, int line ) { static void *get_unpoisoned_check_neighbors(void *vptr, const char *file, int line) {
uintptr_t ptr = (uintptr_t)vptr; uintptr_t ptr = (uintptr_t)vptr;
if (ptr != 0) { if (ptr != 0) {
ptr -= (sizeof(UMM_POISONED_BLOCK_LEN_TYPE) + UMM_POISON_SIZE_BEFORE); ptr -= (sizeof(UMM_POISONED_BLOCK_LEN_TYPE) + UMM_POISON_SIZE_BEFORE);
#if defined(UMM_POISON_CHECK_LITE) #if defined(UMM_POISON_CHECK_LITE)
UMM_CRITICAL_DECL(id_poison); UMM_CRITICAL_DECL(id_poison);
uint16_t c; uint16_t c;
bool poison = false; bool poison = false;
umm_heap_context_t *_context = umm_get_ptr_context( vptr ); umm_heap_context_t *_context = umm_get_ptr_context(vptr);
if (NULL == _context) { if (NULL == _context) {
panic(); panic();
return NULL; return NULL;
}
/* Figure out which block we're in. Note the use of truncated division... */
c = (ptr - (uintptr_t)(&(_context->heap[0]))) / sizeof(umm_block);
UMM_CRITICAL_ENTRY(id_poison);
poison = check_poison_block(&UMM_BLOCK(c)) && check_poison_neighbors(_context, c);
UMM_CRITICAL_EXIT(id_poison);
if (!poison) {
if (file) {
__panic_func(file, line, "");
} else {
abort();
}
}
#else
/*
* No need to check poison here. POISON_CHECK() has already done a
* full heap check.
*/
(void)file;
(void)line;
#endif
} }
/* Figure out which block we're in. Note the use of truncated division... */
c = (ptr - (uintptr_t)(&(_context->heap[0])))/sizeof(umm_block);
UMM_CRITICAL_ENTRY(id_poison); return (void *)ptr;
poison = check_poison_block(&UMM_BLOCK(c)) && check_poison_neighbors(_context, c);
UMM_CRITICAL_EXIT(id_poison);
if (!poison) {
if (file) {
__panic_func(file, line, "");
} else {
abort();
}
}
#else
/*
* No need to check poison here. POISON_CHECK() has already done a
* full heap check.
*/
(void)file;
(void)line;
#endif
}
return (void *)ptr;
} }
/* ------------------------------------------------------------------------ */ /* ------------------------------------------------------------------------ */
void *umm_poison_realloc_fl(void *ptr, size_t size, const char* file, int line) { void *umm_poison_realloc_fl(void *ptr, size_t size, const char *file, int line) {
void *ret; void *ret;
ptr = get_unpoisoned_check_neighbors(ptr, file, line); ptr = get_unpoisoned_check_neighbors(ptr, file, line);
@ -145,7 +147,7 @@ void *umm_poison_realloc_fl(void *ptr, size_t size, const char* file, int line)
/* ------------------------------------------------------------------------ */ /* ------------------------------------------------------------------------ */
void umm_poison_free_fl(void *ptr, const char* file, int line) { void umm_poison_free_fl(void *ptr, const char *file, int line) {
ptr = get_unpoisoned_check_neighbors(ptr, file, line); ptr = get_unpoisoned_check_neighbors(ptr, file, line);
@ -156,18 +158,18 @@ void umm_poison_free_fl(void *ptr, const char* file, int line) {
/* ------------------------------------------------------------------------ */ /* ------------------------------------------------------------------------ */
#if defined(UMM_STATS) || defined(UMM_STATS_FULL) || defined(UMM_INFO) #if defined(UMM_STATS) || defined(UMM_STATS_FULL) || defined(UMM_INFO)
size_t umm_block_size( void ) { size_t umm_block_size(void) {
return sizeof(umm_block); return sizeof(umm_block);
} }
#endif #endif
#if defined(UMM_STATS) || defined(UMM_STATS_FULL) #if defined(UMM_STATS) || defined(UMM_STATS_FULL)
// Keep complete call path in IRAM // Keep complete call path in IRAM
size_t umm_free_heap_size_lw( void ) { size_t umm_free_heap_size_lw(void) {
UMM_INIT_HEAP; UMM_INIT_HEAP;
umm_heap_context_t *_context = umm_get_current_heap(); umm_heap_context_t *_context = umm_get_current_heap();
return (size_t)_context->UMM_FREE_BLOCKS * sizeof(umm_block); return (size_t)_context->UMM_FREE_BLOCKS * sizeof(umm_block);
} }
#endif #endif
@ -187,19 +189,19 @@ size_t xPortGetFreeHeapSize(void) __attribute__ ((alias("umm_free_heap_size")));
#if defined(UMM_STATS) || defined(UMM_STATS_FULL) #if defined(UMM_STATS) || defined(UMM_STATS_FULL)
void umm_print_stats(int force) { void umm_print_stats(int force) {
umm_heap_context_t *_context = umm_get_current_heap(); umm_heap_context_t *_context = umm_get_current_heap();
DBGLOG_FORCE( force, "umm heap statistics:\n"); DBGLOG_FORCE(force, "umm heap statistics:\n");
DBGLOG_FORCE( force, " Heap ID %5u\n", _context->id); DBGLOG_FORCE(force, " Heap ID %5u\n", _context->id);
DBGLOG_FORCE( force, " Free Space %5u\n", _context->UMM_FREE_BLOCKS * sizeof(umm_block)); DBGLOG_FORCE(force, " Free Space %5u\n", _context->UMM_FREE_BLOCKS * sizeof(umm_block));
DBGLOG_FORCE( force, " OOM Count %5u\n", _context->UMM_OOM_COUNT); DBGLOG_FORCE(force, " OOM Count %5u\n", _context->UMM_OOM_COUNT);
#if defined(UMM_STATS_FULL) #if defined(UMM_STATS_FULL)
DBGLOG_FORCE( force, " Low Watermark %5u\n", _context->stats.free_blocks_min * sizeof(umm_block)); DBGLOG_FORCE(force, " Low Watermark %5u\n", _context->stats.free_blocks_min * sizeof(umm_block));
DBGLOG_FORCE( force, " Low Watermark ISR %5u\n", _context->stats.free_blocks_isr_min * sizeof(umm_block)); DBGLOG_FORCE(force, " Low Watermark ISR %5u\n", _context->stats.free_blocks_isr_min * sizeof(umm_block));
DBGLOG_FORCE( force, " MAX Alloc Request %5u\n", _context->stats.alloc_max_size); DBGLOG_FORCE(force, " MAX Alloc Request %5u\n", _context->stats.alloc_max_size);
#endif #endif
DBGLOG_FORCE( force, " Size of umm_block %5u\n", sizeof(umm_block)); DBGLOG_FORCE(force, " Size of umm_block %5u\n", sizeof(umm_block));
DBGLOG_FORCE( force, "+--------------------------------------------------------------+\n" ); DBGLOG_FORCE(force, "+--------------------------------------------------------------+\n");
} }
#endif #endif
@ -214,9 +216,9 @@ int ICACHE_FLASH_ATTR umm_info_safe_printf_P(const char *fmt, ...) {
} }
#if defined(UMM_STATS) || defined(UMM_STATS_FULL) #if defined(UMM_STATS) || defined(UMM_STATS_FULL)
size_t ICACHE_FLASH_ATTR umm_get_oom_count( void ) { size_t ICACHE_FLASH_ATTR umm_get_oom_count(void) {
umm_heap_context_t *_context = umm_get_current_heap(); umm_heap_context_t *_context = umm_get_current_heap();
return _context->UMM_OOM_COUNT; return _context->UMM_OOM_COUNT;
} }
#endif #endif
@ -228,69 +230,69 @@ size_t ICACHE_FLASH_ATTR umm_get_oom_count( void ) {
// //
// If this is correct use alias. // If this is correct use alias.
// //
size_t ICACHE_FLASH_ATTR umm_free_heap_size_lw_min( void ) { size_t ICACHE_FLASH_ATTR umm_free_heap_size_lw_min(void) {
umm_heap_context_t *_context = umm_get_current_heap(); umm_heap_context_t *_context = umm_get_current_heap();
return _context->stats.free_blocks_min * umm_block_size(); return _context->stats.free_blocks_min * umm_block_size();
} }
size_t ICACHE_FLASH_ATTR umm_free_heap_size_min_reset( void ) { size_t ICACHE_FLASH_ATTR umm_free_heap_size_min_reset(void) {
umm_heap_context_t *_context = umm_get_current_heap(); umm_heap_context_t *_context = umm_get_current_heap();
_context->stats.free_blocks_min = _context->UMM_FREE_BLOCKS; _context->stats.free_blocks_min = _context->UMM_FREE_BLOCKS;
return _context->stats.free_blocks_min * umm_block_size(); return _context->stats.free_blocks_min * umm_block_size();
} }
#if 0 // TODO - Don't understand this why do both umm_free_heap_size_(lw_)min exist #if 0 // TODO - Don't understand this why do both umm_free_heap_size_(lw_)min exist
size_t umm_free_heap_size_min(void) __attribute__ ((alias("umm_free_heap_size_lw_min"))); size_t umm_free_heap_size_min(void) __attribute__ ((alias("umm_free_heap_size_lw_min")));
#else #else
size_t ICACHE_FLASH_ATTR umm_free_heap_size_min( void ) { size_t ICACHE_FLASH_ATTR umm_free_heap_size_min(void) {
umm_heap_context_t *_context = umm_get_current_heap(); umm_heap_context_t *_context = umm_get_current_heap();
return _context->stats.free_blocks_min * umm_block_size(); return _context->stats.free_blocks_min * umm_block_size();
} }
#endif #endif
size_t ICACHE_FLASH_ATTR umm_free_heap_size_isr_min( void ) { size_t ICACHE_FLASH_ATTR umm_free_heap_size_isr_min(void) {
umm_heap_context_t *_context = umm_get_current_heap(); umm_heap_context_t *_context = umm_get_current_heap();
return _context->stats.free_blocks_isr_min * umm_block_size(); return _context->stats.free_blocks_isr_min * umm_block_size();
} }
size_t ICACHE_FLASH_ATTR umm_get_max_alloc_size( void ) { size_t ICACHE_FLASH_ATTR umm_get_max_alloc_size(void) {
umm_heap_context_t *_context = umm_get_current_heap(); umm_heap_context_t *_context = umm_get_current_heap();
return _context->stats.alloc_max_size; return _context->stats.alloc_max_size;
} }
size_t ICACHE_FLASH_ATTR umm_get_last_alloc_size( void ) { size_t ICACHE_FLASH_ATTR umm_get_last_alloc_size(void) {
umm_heap_context_t *_context = umm_get_current_heap(); umm_heap_context_t *_context = umm_get_current_heap();
return _context->stats.last_alloc_size; return _context->stats.last_alloc_size;
} }
size_t ICACHE_FLASH_ATTR umm_get_malloc_count( void ) { size_t ICACHE_FLASH_ATTR umm_get_malloc_count(void) {
umm_heap_context_t *_context = umm_get_current_heap(); umm_heap_context_t *_context = umm_get_current_heap();
return _context->stats.id_malloc_count; return _context->stats.id_malloc_count;
} }
size_t ICACHE_FLASH_ATTR umm_get_malloc_zero_count( void ) { size_t ICACHE_FLASH_ATTR umm_get_malloc_zero_count(void) {
umm_heap_context_t *_context = umm_get_current_heap(); umm_heap_context_t *_context = umm_get_current_heap();
return _context->stats.id_malloc_zero_count; return _context->stats.id_malloc_zero_count;
} }
size_t ICACHE_FLASH_ATTR umm_get_realloc_count( void ) { size_t ICACHE_FLASH_ATTR umm_get_realloc_count(void) {
umm_heap_context_t *_context = umm_get_current_heap(); umm_heap_context_t *_context = umm_get_current_heap();
return _context->stats.id_realloc_count; return _context->stats.id_realloc_count;
} }
size_t ICACHE_FLASH_ATTR umm_get_realloc_zero_count( void ) { size_t ICACHE_FLASH_ATTR umm_get_realloc_zero_count(void) {
umm_heap_context_t *_context = umm_get_current_heap(); umm_heap_context_t *_context = umm_get_current_heap();
return _context->stats.id_realloc_zero_count; return _context->stats.id_realloc_zero_count;
} }
size_t ICACHE_FLASH_ATTR umm_get_free_count( void ) { size_t ICACHE_FLASH_ATTR umm_get_free_count(void) {
umm_heap_context_t *_context = umm_get_current_heap(); umm_heap_context_t *_context = umm_get_current_heap();
return _context->stats.id_free_count; return _context->stats.id_free_count;
} }
size_t ICACHE_FLASH_ATTR umm_get_free_null_count( void ) { size_t ICACHE_FLASH_ATTR umm_get_free_null_count(void) {
umm_heap_context_t *_context = umm_get_current_heap(); umm_heap_context_t *_context = umm_get_current_heap();
return _context->stats.id_free_null_count; return _context->stats.id_free_null_count;
} }
#endif // UMM_STATS_FULL #endif // UMM_STATS_FULL

View File

@ -22,7 +22,7 @@
* string while INTLEVEL is non-zero. * string while INTLEVEL is non-zero.
*/ */
#undef DBGLOG_FORCE #undef DBGLOG_FORCE
#define DBGLOG_FORCE(force, format, ...) {if(force) {UMM_INFO_PRINTF(format, ## __VA_ARGS__);}} #define DBGLOG_FORCE(force, format, ...) {if (force) {UMM_INFO_PRINTF(format,##__VA_ARGS__);}}
// #define DBGLOG_FORCE(force, format, ...) {if(force) {::printf(PSTR(format), ## __VA_ARGS__);}} // #define DBGLOG_FORCE(force, format, ...) {if(force) {::printf(PSTR(format), ## __VA_ARGS__);}}
@ -37,7 +37,7 @@
#if defined(UMM_POISON_CHECK_LITE) #if defined(UMM_POISON_CHECK_LITE)
static bool check_poison_neighbors( umm_heap_context_t *_context, uint16_t cur ); static bool check_poison_neighbors(umm_heap_context_t *_context, uint16_t cur);
#endif #endif
@ -48,22 +48,22 @@ void ICACHE_FLASH_ATTR umm_print_stats(int force);
int ICACHE_FLASH_ATTR umm_info_safe_printf_P(const char *fmt, ...) __attribute__((format(printf, 1, 2))); int ICACHE_FLASH_ATTR umm_info_safe_printf_P(const char *fmt, ...) __attribute__((format(printf, 1, 2)));
#define UMM_INFO_PRINTF(fmt, ...) umm_info_safe_printf_P(PSTR(fmt), ##__VA_ARGS__) #define UMM_INFO_PRINTF(fmt, ...) umm_info_safe_printf_P(PSTR(fmt),##__VA_ARGS__)
typedef struct umm_block_t umm_block; typedef struct umm_block_t umm_block;
struct UMM_HEAP_CONTEXT { struct UMM_HEAP_CONTEXT {
umm_block *heap; umm_block *heap;
void *heap_end; void *heap_end;
#if (!defined(UMM_INLINE_METRICS) && defined(UMM_STATS)) || defined(UMM_STATS_FULL) #if (!defined(UMM_INLINE_METRICS) && defined(UMM_STATS)) || defined(UMM_STATS_FULL)
UMM_STATISTICS stats; UMM_STATISTICS stats;
#endif #endif
#ifdef UMM_INFO #ifdef UMM_INFO
UMM_HEAP_INFO info; UMM_HEAP_INFO info;
#endif #endif
unsigned short int numblocks; unsigned short int numblocks;
unsigned char id; unsigned char id;
}; };

File diff suppressed because it is too large Load Diff

View File

@ -10,7 +10,7 @@
#include <stdint.h> #include <stdint.h>
//C This include is not in upstream // C This include is not in upstream
#include "umm_malloc_cfg.h" /* user-dependent */ #include "umm_malloc_cfg.h" /* user-dependent */
#ifdef __cplusplus #ifdef __cplusplus
@ -19,28 +19,28 @@ extern "C" {
#ifdef UMM_HEAP_EXTERNAL #ifdef UMM_HEAP_EXTERNAL
extern void umm_init_vm( void *vmaddr, unsigned int vmsize ); extern void umm_init_vm(void *vmaddr, unsigned int vmsize);
#endif #endif
#ifdef UMM_HEAP_IRAM #ifdef UMM_HEAP_IRAM
extern void umm_init_iram(void); extern void umm_init_iram(void);
extern void umm_init_iram_ex( void *addr, unsigned int size, bool zero ); extern void umm_init_iram_ex(void *addr, unsigned int size, bool zero);
#endif #endif
/* ------------------------------------------------------------------------ */ /* ------------------------------------------------------------------------ */
extern void umm_init( void ); extern void umm_init(void);
extern void *umm_malloc( size_t size ); extern void *umm_malloc(size_t size);
extern void *umm_calloc( size_t num, size_t size ); extern void *umm_calloc(size_t num, size_t size);
extern void *umm_realloc( void *ptr, size_t size ); extern void *umm_realloc(void *ptr, size_t size);
extern void umm_free( void *ptr ); extern void umm_free(void *ptr);
/* ------------------------------------------------------------------------ */ /* ------------------------------------------------------------------------ */
extern umm_heap_context_t *umm_push_heap( size_t heap_number ); extern umm_heap_context_t *umm_push_heap(size_t heap_number);
extern umm_heap_context_t *umm_pop_heap( void ); extern umm_heap_context_t *umm_pop_heap(void);
extern int umm_get_heap_stack_index( void ); extern int umm_get_heap_stack_index(void);
extern umm_heap_context_t *umm_set_heap_by_id( size_t which ); extern umm_heap_context_t *umm_set_heap_by_id(size_t which);
extern size_t umm_get_current_heap_id( void ); extern size_t umm_get_current_heap_id(void);
extern umm_heap_context_t *umm_get_current_heap( void ); extern umm_heap_context_t *umm_get_current_heap(void);
#ifdef __cplusplus #ifdef __cplusplus
} }

View File

@ -192,13 +192,13 @@ extern char _heap_start[];
/* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */
#ifdef UMM_BEST_FIT #ifdef UMM_BEST_FIT
#ifdef UMM_FIRST_FIT #ifdef UMM_FIRST_FIT
#error Both UMM_BEST_FIT and UMM_FIRST_FIT are defined - pick one! #error Both UMM_BEST_FIT and UMM_FIRST_FIT are defined - pick one!
#endif #endif
#else /* UMM_BEST_FIT is not defined */ #else /* UMM_BEST_FIT is not defined */
#ifndef UMM_FIRST_FIT #ifndef UMM_FIRST_FIT
#define UMM_BEST_FIT #define UMM_BEST_FIT
#endif #endif
#endif #endif
/* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */
@ -207,9 +207,9 @@ extern char _heap_start[];
#define UMM_FRAGMENTATION_METRIC_INIT() umm_fragmentation_metric_init(_context) #define UMM_FRAGMENTATION_METRIC_INIT() umm_fragmentation_metric_init(_context)
#define UMM_FRAGMENTATION_METRIC_ADD(c) umm_fragmentation_metric_add(_context, c) #define UMM_FRAGMENTATION_METRIC_ADD(c) umm_fragmentation_metric_add(_context, c)
#define UMM_FRAGMENTATION_METRIC_REMOVE(c) umm_fragmentation_metric_remove(_context, c) #define UMM_FRAGMENTATION_METRIC_REMOVE(c) umm_fragmentation_metric_remove(_context, c)
#ifndef UMM_INFO #ifndef UMM_INFO
#define UMM_INFO #define UMM_INFO
#endif #endif
#else #else
#define UMM_FRAGMENTATION_METRIC_INIT() #define UMM_FRAGMENTATION_METRIC_INIT()
#define UMM_FRAGMENTATION_METRIC_ADD(c) #define UMM_FRAGMENTATION_METRIC_ADD(c)
@ -229,7 +229,7 @@ extern char _heap_start[];
// #define UMM_INFO // #define UMM_INFO
#ifdef UMM_INFO #ifdef UMM_INFO
typedef struct UMM_HEAP_INFO_t { typedef struct UMM_HEAP_INFO_t {
unsigned int totalEntries; unsigned int totalEntries;
unsigned int usedEntries; unsigned int usedEntries;
unsigned int freeEntries; unsigned int freeEntries;
@ -238,33 +238,33 @@ extern char _heap_start[];
unsigned int usedBlocks; unsigned int usedBlocks;
unsigned int freeBlocks; unsigned int freeBlocks;
unsigned int freeBlocksSquared; unsigned int freeBlocksSquared;
#ifdef UMM_INLINE_METRICS #ifdef UMM_INLINE_METRICS
size_t oom_count; size_t oom_count;
#define UMM_OOM_COUNT info.oom_count #define UMM_OOM_COUNT info.oom_count
#define UMM_FREE_BLOCKS info.freeBlocks #define UMM_FREE_BLOCKS info.freeBlocks
#endif #endif
unsigned int maxFreeContiguousBlocks; unsigned int maxFreeContiguousBlocks;
} }
UMM_HEAP_INFO; UMM_HEAP_INFO;
// extern UMM_HEAP_INFO ummHeapInfo; // extern UMM_HEAP_INFO ummHeapInfo;
struct UMM_HEAP_CONTEXT; struct UMM_HEAP_CONTEXT;
typedef struct UMM_HEAP_CONTEXT umm_heap_context_t; typedef struct UMM_HEAP_CONTEXT umm_heap_context_t;
extern ICACHE_FLASH_ATTR void *umm_info( void *ptr, bool force ); extern ICACHE_FLASH_ATTR void *umm_info(void *ptr, bool force);
#ifdef UMM_INLINE_METRICS #ifdef UMM_INLINE_METRICS
extern size_t umm_free_heap_size( void ); extern size_t umm_free_heap_size(void);
#else #else
extern ICACHE_FLASH_ATTR size_t umm_free_heap_size( void ); extern ICACHE_FLASH_ATTR size_t umm_free_heap_size(void);
#endif #endif
// umm_max_block_size changed to umm_max_free_block_size in upstream. // umm_max_block_size changed to umm_max_free_block_size in upstream.
extern ICACHE_FLASH_ATTR size_t umm_max_block_size( void ); extern ICACHE_FLASH_ATTR size_t umm_max_block_size(void);
extern ICACHE_FLASH_ATTR int umm_usage_metric( void ); extern ICACHE_FLASH_ATTR int umm_usage_metric(void);
extern ICACHE_FLASH_ATTR int umm_fragmentation_metric( void ); extern ICACHE_FLASH_ATTR int umm_fragmentation_metric(void);
extern ICACHE_FLASH_ATTR size_t umm_free_heap_size_core( umm_heap_context_t *_context ); extern ICACHE_FLASH_ATTR size_t umm_free_heap_size_core(umm_heap_context_t *_context);
extern ICACHE_FLASH_ATTR size_t umm_max_block_size_core( umm_heap_context_t *_context ); extern ICACHE_FLASH_ATTR size_t umm_max_block_size_core(umm_heap_context_t *_context);
extern ICACHE_FLASH_ATTR int umm_usage_metric_core( umm_heap_context_t *_context ); extern ICACHE_FLASH_ATTR int umm_usage_metric_core(umm_heap_context_t *_context);
extern ICACHE_FLASH_ATTR int umm_fragmentation_metric_core( umm_heap_context_t *_context ); extern ICACHE_FLASH_ATTR int umm_fragmentation_metric_core(umm_heap_context_t *_context);
#else #else
#define umm_info(p,b) #define umm_info(p,b)
#define umm_free_heap_size() (0) #define umm_free_heap_size() (0)
@ -312,27 +312,27 @@ typedef struct UMM_HEAP_CONTEXT umm_heap_context_t;
#if defined(UMM_STATS) || defined(UMM_STATS_FULL) #if defined(UMM_STATS) || defined(UMM_STATS_FULL)
typedef struct UMM_STATISTICS_t { typedef struct UMM_STATISTICS_t {
#ifndef UMM_INLINE_METRICS #ifndef UMM_INLINE_METRICS
// If we are doing UMM_INLINE_METRICS, we can move oom_count and free_blocks to // If we are doing UMM_INLINE_METRICS, we can move oom_count and free_blocks to
// umm_info's structure and save a little DRAM and IRAM. // umm_info's structure and save a little DRAM and IRAM.
// Otherwise it is defined here. // Otherwise it is defined here.
size_t free_blocks; size_t free_blocks;
size_t oom_count; size_t oom_count;
#define UMM_OOM_COUNT stats.oom_count #define UMM_OOM_COUNT stats.oom_count
#define UMM_FREE_BLOCKS stats.free_blocks #define UMM_FREE_BLOCKS stats.free_blocks
#endif #endif
#ifdef UMM_STATS_FULL #ifdef UMM_STATS_FULL
size_t free_blocks_min; size_t free_blocks_min;
size_t free_blocks_isr_min; size_t free_blocks_isr_min;
size_t alloc_max_size; size_t alloc_max_size;
size_t last_alloc_size; size_t last_alloc_size;
size_t id_malloc_count; size_t id_malloc_count;
size_t id_malloc_zero_count; size_t id_malloc_zero_count;
size_t id_realloc_count; size_t id_realloc_count;
size_t id_realloc_zero_count; size_t id_realloc_zero_count;
size_t id_free_count; size_t id_free_count;
size_t id_free_null_count; size_t id_free_null_count;
#endif #endif
} }
UMM_STATISTICS; UMM_STATISTICS;
@ -344,8 +344,8 @@ UMM_STATISTICS;
#define STATS__OOM_UPDATE() _context->UMM_OOM_COUNT += 1 #define STATS__OOM_UPDATE() _context->UMM_OOM_COUNT += 1
extern size_t umm_free_heap_size_lw( void ); extern size_t umm_free_heap_size_lw(void);
extern size_t umm_get_oom_count( void ); extern size_t umm_get_oom_count(void);
#else // not UMM_STATS or UMM_STATS_FULL #else // not UMM_STATS or UMM_STATS_FULL
#define STATS__FREE_BLOCKS_UPDATE(s) (void)(s) #define STATS__FREE_BLOCKS_UPDATE(s) (void)(s)
@ -353,59 +353,62 @@ extern size_t umm_get_oom_count( void );
#endif #endif
#if defined(UMM_STATS) || defined(UMM_STATS_FULL) || defined(UMM_INFO) #if defined(UMM_STATS) || defined(UMM_STATS_FULL) || defined(UMM_INFO)
size_t ICACHE_FLASH_ATTR umm_block_size( void ); size_t ICACHE_FLASH_ATTR umm_block_size(void);
#endif #endif
#ifdef UMM_STATS_FULL #ifdef UMM_STATS_FULL
#define STATS__FREE_BLOCKS_MIN() \ #define STATS__FREE_BLOCKS_MIN() \
do { \ do { \
if (_context->UMM_FREE_BLOCKS < _context->stats.free_blocks_min) \ if (_context->UMM_FREE_BLOCKS < _context->stats.free_blocks_min) { \
_context->stats.free_blocks_min = _context->UMM_FREE_BLOCKS; \ _context->stats.free_blocks_min = _context->UMM_FREE_BLOCKS; \
} while(false) } \
} while (false)
#define STATS__FREE_BLOCKS_ISR_MIN() \ #define STATS__FREE_BLOCKS_ISR_MIN() \
do { \ do { \
if (_context->UMM_FREE_BLOCKS < _context->stats.free_blocks_isr_min) \ if (_context->UMM_FREE_BLOCKS < _context->stats.free_blocks_isr_min) { \
_context->stats.free_blocks_isr_min = _context->UMM_FREE_BLOCKS; \ _context->stats.free_blocks_isr_min = _context->UMM_FREE_BLOCKS; \
} while(false) } \
} while (false)
#define STATS__ALLOC_REQUEST(tag, s) \ #define STATS__ALLOC_REQUEST(tag, s) \
do { \ do { \
_context->stats.tag##_count += 1; \ _context->stats.tag##_count += 1; \
_context->stats.last_alloc_size = s; \ _context->stats.last_alloc_size = s; \
if (_context->stats.alloc_max_size < s) \ if (_context->stats.alloc_max_size < s) { \
_context->stats.alloc_max_size = s; \ _context->stats.alloc_max_size = s; \
} while(false) } \
} while (false)
#define STATS__ZERO_ALLOC_REQUEST(tag, s) \ #define STATS__ZERO_ALLOC_REQUEST(tag, s) \
do { \ do { \
_context->stats.tag##_zero_count += 1; \ _context->stats.tag##_zero_count += 1; \
} while(false) } while (false)
#define STATS__NULL_FREE_REQUEST(tag) \ #define STATS__NULL_FREE_REQUEST(tag) \
do { \ do { \
umm_heap_context_t *_context = umm_get_current_heap(); \ umm_heap_context_t *_context = umm_get_current_heap(); \
_context->stats.tag##_null_count += 1; \ _context->stats.tag##_null_count += 1; \
} while(false) } while (false)
#define STATS__FREE_REQUEST(tag) \ #define STATS__FREE_REQUEST(tag) \
do { \ do { \
_context->stats.tag##_count += 1; \ _context->stats.tag##_count += 1; \
} while(false) } while (false)
size_t umm_free_heap_size_lw_min( void ); size_t umm_free_heap_size_lw_min(void);
size_t umm_free_heap_size_min_reset( void ); size_t umm_free_heap_size_min_reset(void);
size_t umm_free_heap_size_min( void ); size_t umm_free_heap_size_min(void);
size_t umm_free_heap_size_isr_min( void ); size_t umm_free_heap_size_isr_min(void);
size_t umm_get_max_alloc_size( void ); size_t umm_get_max_alloc_size(void);
size_t umm_get_last_alloc_size( void ); size_t umm_get_last_alloc_size(void);
size_t umm_get_malloc_count( void ); size_t umm_get_malloc_count(void);
size_t umm_get_malloc_zero_count( void ); size_t umm_get_malloc_zero_count(void);
size_t umm_get_realloc_count( void ); size_t umm_get_realloc_count(void);
size_t umm_get_realloc_zero_count( void ); size_t umm_get_realloc_zero_count(void);
size_t umm_get_free_count( void ); size_t umm_get_free_count(void);
size_t umm_get_free_null_count( void ); size_t umm_get_free_null_count(void);
#else // Not UMM_STATS_FULL #else // Not UMM_STATS_FULL
#define STATS__FREE_BLOCKS_MIN() (void)0 #define STATS__FREE_BLOCKS_MIN() (void)0
@ -448,10 +451,10 @@ size_t umm_get_free_null_count( void );
// This option adds support for gathering time locked data // This option adds support for gathering time locked data
typedef struct UMM_TIME_STAT_t { typedef struct UMM_TIME_STAT_t {
uint32_t min; uint32_t min;
uint32_t max; uint32_t max;
uint32_t start; uint32_t start;
uint32_t intlevel; uint32_t intlevel;
} }
UMM_TIME_STAT; UMM_TIME_STAT;
@ -462,23 +465,25 @@ extern UMM_TIME_STATS time_stats;
bool get_umm_get_perf_data(UMM_TIME_STATS *p, size_t size); bool get_umm_get_perf_data(UMM_TIME_STATS *p, size_t size);
static inline void _critical_entry(UMM_TIME_STAT *p, uint32_t *saved_ps) { static inline void _critical_entry(UMM_TIME_STAT *p, uint32_t *saved_ps) {
*saved_ps = xt_rsil(DEFAULT_CRITICAL_SECTION_INTLEVEL); *saved_ps = xt_rsil(DEFAULT_CRITICAL_SECTION_INTLEVEL);
if (0U != (*saved_ps & 0x0FU)) { if (0U != (*saved_ps & 0x0FU)) {
p->intlevel += 1U; p->intlevel += 1U;
} }
p->start = esp_get_cycle_count(); p->start = esp_get_cycle_count();
} }
static inline void _critical_exit(UMM_TIME_STAT *p, uint32_t *saved_ps) { static inline void _critical_exit(UMM_TIME_STAT *p, uint32_t *saved_ps) {
uint32_t elapse = esp_get_cycle_count() - p->start; uint32_t elapse = esp_get_cycle_count() - p->start;
if (elapse < p->min) if (elapse < p->min) {
p->min = elapse; p->min = elapse;
}
if (elapse > p->max) if (elapse > p->max) {
p->max = elapse; p->max = elapse;
}
xt_wsr_ps(*saved_ps); xt_wsr_ps(*saved_ps);
} }
#endif #endif
////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////
@ -495,33 +500,33 @@ static inline void _critical_exit(UMM_TIME_STAT *p, uint32_t *saved_ps) {
*/ */
#ifdef UMM_TEST_BUILD #ifdef UMM_TEST_BUILD
extern int umm_critical_depth; extern int umm_critical_depth;
extern int umm_max_critical_depth; extern int umm_max_critical_depth;
#define UMM_CRITICAL_ENTRY() {\ #define UMM_CRITICAL_ENTRY() { \
++umm_critical_depth; \ ++umm_critical_depth; \
if (umm_critical_depth > umm_max_critical_depth) { \ if (umm_critical_depth > umm_max_critical_depth) { \
umm_max_critical_depth = umm_critical_depth; \ umm_max_critical_depth = umm_critical_depth; \
} \ } \
} }
#define UMM_CRITICAL_EXIT() (umm_critical_depth--) #define UMM_CRITICAL_EXIT() (umm_critical_depth--)
#else #else
#if defined(UMM_CRITICAL_METRICS) #if defined(UMM_CRITICAL_METRICS)
#define UMM_CRITICAL_DECL(tag) uint32_t _saved_ps_##tag #define UMM_CRITICAL_DECL(tag) uint32_t _saved_ps_##tag
#define UMM_CRITICAL_ENTRY(tag)_critical_entry(&time_stats.tag, &_saved_ps_##tag) #define UMM_CRITICAL_ENTRY(tag)_critical_entry(&time_stats.tag, &_saved_ps_##tag)
#define UMM_CRITICAL_EXIT(tag) _critical_exit(&time_stats.tag, &_saved_ps_##tag) #define UMM_CRITICAL_EXIT(tag) _critical_exit(&time_stats.tag, &_saved_ps_##tag)
#define UMM_CRITICAL_WITHINISR(tag) (0 != (_saved_ps_##tag & 0x0F)) #define UMM_CRITICAL_WITHINISR(tag) (0 != (_saved_ps_##tag & 0x0F))
#else // ! UMM_CRITICAL_METRICS #else // ! UMM_CRITICAL_METRICS
// This method preserves the intlevel on entry and restores the // This method preserves the intlevel on entry and restores the
// original intlevel at exit. // original intlevel at exit.
#define UMM_CRITICAL_DECL(tag) uint32_t _saved_ps_##tag #define UMM_CRITICAL_DECL(tag) uint32_t _saved_ps_##tag
#define UMM_CRITICAL_ENTRY(tag) _saved_ps_##tag = xt_rsil(DEFAULT_CRITICAL_SECTION_INTLEVEL) #define UMM_CRITICAL_ENTRY(tag) _saved_ps_##tag = xt_rsil(DEFAULT_CRITICAL_SECTION_INTLEVEL)
#define UMM_CRITICAL_EXIT(tag) xt_wsr_ps(_saved_ps_##tag) #define UMM_CRITICAL_EXIT(tag) xt_wsr_ps(_saved_ps_##tag)
#define UMM_CRITICAL_WITHINISR(tag) (0 != (_saved_ps_##tag & 0x0F)) #define UMM_CRITICAL_WITHINISR(tag) (0 != (_saved_ps_##tag & 0x0F))
#endif #endif
#endif #endif
/* /*
* -D UMM_LIGHTWEIGHT_CPU * -D UMM_LIGHTWEIGHT_CPU
* *
* The use of this macro is hardware/application specific. * The use of this macro is hardware/application specific.
@ -550,8 +555,8 @@ static inline void _critical_exit(UMM_TIME_STAT *p, uint32_t *saved_ps) {
#define UMM_CRITICAL_SUSPEND(tag) UMM_CRITICAL_EXIT(tag) #define UMM_CRITICAL_SUSPEND(tag) UMM_CRITICAL_EXIT(tag)
#define UMM_CRITICAL_RESUME(tag) UMM_CRITICAL_ENTRY(tag) #define UMM_CRITICAL_RESUME(tag) UMM_CRITICAL_ENTRY(tag)
#else #else
#define UMM_CRITICAL_SUSPEND(tag) do {} while(0) #define UMM_CRITICAL_SUSPEND(tag) do {} while (0)
#define UMM_CRITICAL_RESUME(tag) do {} while(0) #define UMM_CRITICAL_RESUME(tag) do {} while (0)
#endif #endif
/* /*
@ -594,12 +599,12 @@ static inline void _critical_exit(UMM_TIME_STAT *p, uint32_t *saved_ps) {
*/ */
#ifdef UMM_INTEGRITY_CHECK #ifdef UMM_INTEGRITY_CHECK
extern bool umm_integrity_check( void ); extern bool umm_integrity_check(void);
# define INTEGRITY_CHECK() umm_integrity_check() #define INTEGRITY_CHECK() umm_integrity_check()
extern void umm_corruption(void); extern void umm_corruption(void);
# define UMM_HEAP_CORRUPTION_CB() DBGLOG_FUNCTION( "Heap Corruption!" ) #define UMM_HEAP_CORRUPTION_CB() DBGLOG_FUNCTION("Heap Corruption!")
#else #else
# define INTEGRITY_CHECK() (1) #define INTEGRITY_CHECK() (1)
#endif #endif
///////////////////////////////////////////////// /////////////////////////////////////////////////
@ -669,33 +674,33 @@ static inline void _critical_exit(UMM_TIME_STAT *p, uint32_t *saved_ps) {
#define UMM_POISONED_BLOCK_LEN_TYPE uint32_t #define UMM_POISONED_BLOCK_LEN_TYPE uint32_t
#if defined(UMM_POISON_CHECK) || defined(UMM_POISON_CHECK_LITE) #if defined(UMM_POISON_CHECK) || defined(UMM_POISON_CHECK_LITE)
extern void *umm_poison_malloc( size_t size ); extern void *umm_poison_malloc(size_t size);
extern void *umm_poison_calloc( size_t num, size_t size ); extern void *umm_poison_calloc(size_t num, size_t size);
extern void *umm_poison_realloc( void *ptr, size_t size ); extern void *umm_poison_realloc(void *ptr, size_t size);
extern void umm_poison_free( void *ptr ); extern void umm_poison_free(void *ptr);
extern bool umm_poison_check( void ); extern bool umm_poison_check(void);
// Local Additions to better report location in code of the caller. // Local Additions to better report location in code of the caller.
void *umm_poison_realloc_fl( void *ptr, size_t size, const char* file, int line ); void *umm_poison_realloc_fl(void *ptr, size_t size, const char *file, int line);
void umm_poison_free_fl( void *ptr, const char* file, int line ); void umm_poison_free_fl(void *ptr, const char *file, int line);
#if defined(UMM_POISON_CHECK_LITE) #if defined(UMM_POISON_CHECK_LITE)
/* /*
* We can safely do individual poison checks at free and realloc and stay * We can safely do individual poison checks at free and realloc and stay
* under 10us or close. * under 10us or close.
*/ */
# define POISON_CHECK() 1 #define POISON_CHECK() 1
# define POISON_CHECK_NEIGHBORS(c) \ #define POISON_CHECK_NEIGHBORS(c) \
do {\ do { \
if(!check_poison_neighbors(_context, c)) \ if (!check_poison_neighbors(_context, c)) \
panic();\ panic(); \
} while(false) } while (false)
#else
/* Not normally enabled. A full heap poison check may exceed 10us. */
# define POISON_CHECK() umm_poison_check()
# define POISON_CHECK_NEIGHBORS(c) do{}while(false)
#endif
#else #else
# define POISON_CHECK() 1 /* Not normally enabled. A full heap poison check may exceed 10us. */
# define POISON_CHECK_NEIGHBORS(c) do{}while(false) #define POISON_CHECK() umm_poison_check()
#define POISON_CHECK_NEIGHBORS(c) do {} while (false)
#endif
#else
#define POISON_CHECK() 1
#define POISON_CHECK_NEIGHBORS(c) do {} while (false)
#endif #endif
@ -705,13 +710,13 @@ static inline void _critical_exit(UMM_TIME_STAT *p, uint32_t *saved_ps) {
* that can actually be allocated. * that can actually be allocated.
*/ */
#define UMM_OVERHEAD_ADJUST ( \ #define UMM_OVERHEAD_ADJUST ( \
umm_block_size()/2 + \ umm_block_size() / 2 + \
UMM_POISON_SIZE_BEFORE + \ UMM_POISON_SIZE_BEFORE + \
UMM_POISON_SIZE_AFTER + \ UMM_POISON_SIZE_AFTER + \
sizeof(UMM_POISONED_BLOCK_LEN_TYPE)) sizeof(UMM_POISONED_BLOCK_LEN_TYPE))
#else #else
#define UMM_OVERHEAD_ADJUST (umm_block_size()/2) #define UMM_OVERHEAD_ADJUST (umm_block_size() / 2)
#endif #endif
@ -722,9 +727,9 @@ static inline void _critical_exit(UMM_TIME_STAT *p, uint32_t *saved_ps) {
#if defined(DEBUG_ESP_PORT) || defined(DEBUG_ESP_OOM) || \ #if defined(DEBUG_ESP_PORT) || defined(DEBUG_ESP_OOM) || \
defined(UMM_POISON_CHECK) || defined(UMM_POISON_CHECK_LITE) || \ defined(UMM_POISON_CHECK) || defined(UMM_POISON_CHECK_LITE) || \
defined(UMM_INTEGRITY_CHECK) defined(UMM_INTEGRITY_CHECK)
#define DBGLOG_FUNCTION(fmt, ...) ets_uart_printf(fmt, ##__VA_ARGS__) #define DBGLOG_FUNCTION(fmt, ...) ets_uart_printf(fmt,##__VA_ARGS__)
#else #else
#define DBGLOG_FUNCTION(fmt, ...) do { (void)fmt; } while(false) #define DBGLOG_FUNCTION(fmt, ...) do { (void)fmt; } while (false)
#endif #endif
///////////////////////////////////////////////// /////////////////////////////////////////////////
@ -739,19 +744,19 @@ static inline void _critical_exit(UMM_TIME_STAT *p, uint32_t *saved_ps) {
#if defined(UMM_CRITICAL_METRICS) #if defined(UMM_CRITICAL_METRICS)
struct UMM_TIME_STATS_t { struct UMM_TIME_STATS_t {
UMM_TIME_STAT id_malloc; UMM_TIME_STAT id_malloc;
UMM_TIME_STAT id_realloc; UMM_TIME_STAT id_realloc;
UMM_TIME_STAT id_free; UMM_TIME_STAT id_free;
#ifdef UMM_INFO #ifdef UMM_INFO
UMM_TIME_STAT id_info; UMM_TIME_STAT id_info;
#endif #endif
#if defined(UMM_POISON_CHECK) || defined(UMM_POISON_CHECK_LITE) #if defined(UMM_POISON_CHECK) || defined(UMM_POISON_CHECK_LITE)
UMM_TIME_STAT id_poison; UMM_TIME_STAT id_poison;
#endif #endif
#ifdef UMM_INTEGRITY_CHECK #ifdef UMM_INTEGRITY_CHECK
UMM_TIME_STAT id_integrity; UMM_TIME_STAT id_integrity;
#endif #endif
UMM_TIME_STAT id_no_tag; UMM_TIME_STAT id_no_tag;
}; };
#endif #endif
///////////////////////////////////////////////// /////////////////////////////////////////////////
@ -764,17 +769,17 @@ struct UMM_TIME_STATS_t {
#define umm_zalloc(s) umm_calloc(1,s) #define umm_zalloc(s) umm_calloc(1,s)
void* malloc_loc (size_t s, const char* file, int line); void *malloc_loc(size_t s, const char *file, int line);
void* calloc_loc (size_t n, size_t s, const char* file, int line); void *calloc_loc(size_t n, size_t s, const char *file, int line);
void* realloc_loc (void* p, size_t s, const char* file, int line); void *realloc_loc(void *p, size_t s, const char *file, int line);
// *alloc are macro calling *alloc_loc calling+checking umm_*alloc() // *alloc are macro calling *alloc_loc calling+checking umm_*alloc()
// they are defined at the bottom of this file // they are defined at the bottom of this file
///////////////////////////////////////////////// /////////////////////////////////////////////////
#elif defined(UMM_POISON_CHECK) #elif defined(UMM_POISON_CHECK)
void* realloc_loc (void* p, size_t s, const char* file, int line); void *realloc_loc(void *p, size_t s, const char *file, int line);
void free_loc (void* p, const char* file, int line); void free_loc(void *p, const char *file, int line);
#else // !defined(ESP_DEBUG_OOM) #else // !defined(ESP_DEBUG_OOM)
#endif #endif
@ -797,11 +802,11 @@ extern "C" {
#include <pgmspace.h> #include <pgmspace.h>
// Reuse pvPort* calls, since they already support passing location information. // Reuse pvPort* calls, since they already support passing location information.
// Specifically the debug version (heap_...) that does not force DRAM heap. // Specifically the debug version (heap_...) that does not force DRAM heap.
void* IRAM_ATTR heap_pvPortMalloc(size_t size, const char* file, int line); void *IRAM_ATTR heap_pvPortMalloc(size_t size, const char *file, int line);
void* IRAM_ATTR heap_pvPortCalloc(size_t count, size_t size, const char* file, int line); void *IRAM_ATTR heap_pvPortCalloc(size_t count, size_t size, const char *file, int line);
void* IRAM_ATTR heap_pvPortRealloc(void *ptr, size_t size, const char* file, int line); void *IRAM_ATTR heap_pvPortRealloc(void *ptr, size_t size, const char *file, int line);
void* IRAM_ATTR heap_pvPortZalloc(size_t size, const char* file, int line); void *IRAM_ATTR heap_pvPortZalloc(size_t size, const char *file, int line);
void IRAM_ATTR heap_vPortFree(void *ptr, const char* file, int line); void IRAM_ATTR heap_vPortFree(void *ptr, const char *file, int line);
#define malloc(s) ({ static const char mem_debug_file[] PROGMEM STORE_ATTR = __FILE__; heap_pvPortMalloc(s, mem_debug_file, __LINE__); }) #define malloc(s) ({ static const char mem_debug_file[] PROGMEM STORE_ATTR = __FILE__; heap_pvPortMalloc(s, mem_debug_file, __LINE__); })
#define calloc(n,s) ({ static const char mem_debug_file[] PROGMEM STORE_ATTR = __FILE__; heap_pvPortCalloc(n, s, mem_debug_file, __LINE__); }) #define calloc(n,s) ({ static const char mem_debug_file[] PROGMEM STORE_ATTR = __FILE__; heap_pvPortCalloc(n, s, mem_debug_file, __LINE__); })
@ -815,11 +820,11 @@ void IRAM_ATTR heap_vPortFree(void *ptr, const char* file, int line);
#elif defined(UMM_POISON_CHECK) || defined(UMM_POISON_CHECK_LITE) #elif defined(UMM_POISON_CHECK) || defined(UMM_POISON_CHECK_LITE)
#include <pgmspace.h> #include <pgmspace.h>
void* IRAM_ATTR heap_pvPortRealloc(void *ptr, size_t size, const char* file, int line); void *IRAM_ATTR heap_pvPortRealloc(void *ptr, size_t size, const char *file, int line);
#define realloc(p,s) ({ static const char mem_debug_file[] PROGMEM STORE_ATTR = __FILE__; heap_pvPortRealloc(p, s, mem_debug_file, __LINE__); }) #define realloc(p,s) ({ static const char mem_debug_file[] PROGMEM STORE_ATTR = __FILE__; heap_pvPortRealloc(p, s, mem_debug_file, __LINE__); })
void IRAM_ATTR heap_vPortFree(void *ptr, const char* file, int line); void IRAM_ATTR heap_vPortFree(void *ptr, const char *file, int line);
//C - to be discussed // C - to be discussed
/* /*
Problem, I would like to report the file and line number with the umm poison Problem, I would like to report the file and line number with the umm poison
event as close as possible to the event. The #define method works for malloc, event as close as possible to the event. The #define method works for malloc,

View File

@ -13,27 +13,27 @@
* If `s` is 0, returns 0. * If `s` is 0, returns 0.
*/ */
static size_t poison_size(size_t s) { static size_t poison_size(size_t s) {
return(s ? (UMM_POISON_SIZE_BEFORE + return s ? (UMM_POISON_SIZE_BEFORE +
sizeof(UMM_POISONED_BLOCK_LEN_TYPE) + sizeof(UMM_POISONED_BLOCK_LEN_TYPE) +
UMM_POISON_SIZE_AFTER) UMM_POISON_SIZE_AFTER)
: 0); : 0;
} }
/* /*
* Print memory contents starting from given `ptr` * Print memory contents starting from given `ptr`
*/ */
static void dump_mem ( const void *vptr, size_t len ) { static void dump_mem(const void *vptr, size_t len) {
const uint8_t *ptr = (const uint8_t *)vptr; const uint8_t *ptr = (const uint8_t *)vptr;
while (len--) { while (len--) {
DBGLOG_ERROR(" 0x%.2x", (unsigned int)(*ptr++)); DBGLOG_ERROR(" 0x%.2x", (unsigned int)(*ptr++));
} }
} }
/* /*
* Put poison data at given `ptr` and `poison_size` * Put poison data at given `ptr` and `poison_size`
*/ */
static void put_poison( void *ptr, size_t poison_size ) { static void put_poison(void *ptr, size_t poison_size) {
memset(ptr, POISON_BYTE, poison_size); memset(ptr, POISON_BYTE, poison_size);
} }
/* /*
@ -43,56 +43,56 @@ static void put_poison( void *ptr, size_t poison_size ) {
* If poison is there, returns 1. * If poison is there, returns 1.
* Otherwise, prints the appropriate message, and returns 0. * Otherwise, prints the appropriate message, and returns 0.
*/ */
static bool check_poison( const void *ptr, size_t poison_size, static bool check_poison(const void *ptr, size_t poison_size,
const char *where) { const char *where) {
size_t i; size_t i;
bool ok = true; bool ok = true;
for (i = 0; i < poison_size; i++) { for (i = 0; i < poison_size; i++) {
if (((const uint8_t *)ptr)[i] != POISON_BYTE) { if (((const uint8_t *)ptr)[i] != POISON_BYTE) {
ok = false; ok = false;
break; break;
}
} }
}
if (!ok) { if (!ok) {
DBGLOG_ERROR( "No poison %s block at: 0x%lx, actual data:", where, (unsigned long)ptr); DBGLOG_ERROR("No poison %s block at: 0x%lx, actual data:", where, (unsigned long)ptr);
dump_mem(ptr, poison_size); dump_mem(ptr, poison_size);
DBGLOG_ERROR( "\n" ); DBGLOG_ERROR("\n");
} }
return ok; return ok;
} }
/* /*
* Check if a block is properly poisoned. Must be called only for non-free * Check if a block is properly poisoned. Must be called only for non-free
* blocks. * blocks.
*/ */
static bool check_poison_block( umm_block *pblock ) { static bool check_poison_block(umm_block *pblock) {
bool ok = true; bool ok = true;
if (pblock->header.used.next & UMM_FREELIST_MASK) { if (pblock->header.used.next & UMM_FREELIST_MASK) {
DBGLOG_ERROR( "check_poison_block is called for free block 0x%lx\n", (unsigned long)pblock); DBGLOG_ERROR("check_poison_block is called for free block 0x%lx\n", (unsigned long)pblock);
} else { } else {
/* the block is used; let's check poison */ /* the block is used; let's check poison */
unsigned char *pc = (unsigned char *)pblock->body.data; unsigned char *pc = (unsigned char *)pblock->body.data;
unsigned char *pc_cur; unsigned char *pc_cur;
pc_cur = pc + sizeof(UMM_POISONED_BLOCK_LEN_TYPE); pc_cur = pc + sizeof(UMM_POISONED_BLOCK_LEN_TYPE);
if (!check_poison(pc_cur, UMM_POISON_SIZE_BEFORE, "before")) { if (!check_poison(pc_cur, UMM_POISON_SIZE_BEFORE, "before")) {
ok = false; ok = false;
goto clean; goto clean;
}
pc_cur = pc + *((UMM_POISONED_BLOCK_LEN_TYPE *)pc) - UMM_POISON_SIZE_AFTER;
if (!check_poison(pc_cur, UMM_POISON_SIZE_AFTER, "after")) {
ok = false;
goto clean;
}
} }
pc_cur = pc + *((UMM_POISONED_BLOCK_LEN_TYPE *)pc) - UMM_POISON_SIZE_AFTER;
if (!check_poison(pc_cur, UMM_POISON_SIZE_AFTER, "after")) {
ok = false;
goto clean;
}
}
clean: clean:
return ok; return ok;
} }
/* /*
@ -102,25 +102,25 @@ clean:
* *
* `size_w_poison` is a size of the whole block, including a poison. * `size_w_poison` is a size of the whole block, including a poison.
*/ */
static void *get_poisoned( void *vptr, size_t size_w_poison ) { static void *get_poisoned(void *vptr, size_t size_w_poison) {
unsigned char *ptr = (unsigned char *)vptr; unsigned char *ptr = (unsigned char *)vptr;
if (size_w_poison != 0 && ptr != NULL) { if (size_w_poison != 0 && ptr != NULL) {
/* Poison beginning and the end of the allocated chunk */ /* Poison beginning and the end of the allocated chunk */
put_poison(ptr + sizeof(UMM_POISONED_BLOCK_LEN_TYPE), put_poison(ptr + sizeof(UMM_POISONED_BLOCK_LEN_TYPE),
UMM_POISON_SIZE_BEFORE); UMM_POISON_SIZE_BEFORE);
put_poison(ptr + size_w_poison - UMM_POISON_SIZE_AFTER, put_poison(ptr + size_w_poison - UMM_POISON_SIZE_AFTER,
UMM_POISON_SIZE_AFTER); UMM_POISON_SIZE_AFTER);
/* Put exact length of the user's chunk of memory */ /* Put exact length of the user's chunk of memory */
*(UMM_POISONED_BLOCK_LEN_TYPE *)ptr = (UMM_POISONED_BLOCK_LEN_TYPE)size_w_poison; *(UMM_POISONED_BLOCK_LEN_TYPE *)ptr = (UMM_POISONED_BLOCK_LEN_TYPE)size_w_poison;
/* Return pointer at the first non-poisoned byte */ /* Return pointer at the first non-poisoned byte */
ptr += sizeof(UMM_POISONED_BLOCK_LEN_TYPE) + UMM_POISON_SIZE_BEFORE; ptr += sizeof(UMM_POISONED_BLOCK_LEN_TYPE) + UMM_POISON_SIZE_BEFORE;
} }
return (void *)ptr; return (void *)ptr;
} }
/* /*
@ -129,84 +129,85 @@ static void *get_poisoned( void *vptr, size_t size_w_poison ) {
* *
* Returns unpoisoned pointer, i.e. actual pointer to the allocated memory. * Returns unpoisoned pointer, i.e. actual pointer to the allocated memory.
*/ */
static void *get_unpoisoned( void *vptr ) { static void *get_unpoisoned(void *vptr) {
uintptr_t ptr = (uintptr_t)vptr; uintptr_t ptr = (uintptr_t)vptr;
if (ptr != 0) { if (ptr != 0) {
uint16_t c; uint16_t c;
ptr -= (sizeof(UMM_POISONED_BLOCK_LEN_TYPE) + UMM_POISON_SIZE_BEFORE); ptr -= (sizeof(UMM_POISONED_BLOCK_LEN_TYPE) + UMM_POISON_SIZE_BEFORE);
umm_heap_context_t *_context = umm_get_ptr_context( vptr ); umm_heap_context_t *_context = umm_get_ptr_context(vptr);
if (NULL == _context) { if (NULL == _context) {
panic(); panic();
return NULL; return NULL;
}
/* Figure out which block we're in. Note the use of truncated division... */
c = (ptr - (uintptr_t)(&(_context->heap[0]))) / sizeof(umm_block);
check_poison_block(&UMM_BLOCK(c));
} }
/* Figure out which block we're in. Note the use of truncated division... */
c = (ptr - (uintptr_t)(&(_context->heap[0])))/sizeof(umm_block);
check_poison_block(&UMM_BLOCK(c)); return (void *)ptr;
}
return (void *)ptr;
} }
/* }}} */ /* }}} */
/* ------------------------------------------------------------------------ */ /* ------------------------------------------------------------------------ */
void *umm_poison_malloc( size_t size ) { void *umm_poison_malloc(size_t size) {
void *ret; void *ret;
size += poison_size(size); size += poison_size(size);
ret = umm_malloc( size ); ret = umm_malloc(size);
ret = get_poisoned(ret, size); ret = get_poisoned(ret, size);
return ret; return ret;
} }
/* ------------------------------------------------------------------------ */ /* ------------------------------------------------------------------------ */
void *umm_poison_calloc( size_t num, size_t item_size ) { void *umm_poison_calloc(size_t num, size_t item_size) {
void *ret; void *ret;
size_t size = item_size * num; size_t size = item_size * num;
size += poison_size(size); size += poison_size(size);
ret = umm_malloc(size); ret = umm_malloc(size);
if (NULL != ret) if (NULL != ret) {
memset(ret, 0x00, size); memset(ret, 0x00, size);
}
ret = get_poisoned(ret, size); ret = get_poisoned(ret, size);
return ret; return ret;
} }
/* ------------------------------------------------------------------------ */ /* ------------------------------------------------------------------------ */
void *umm_poison_realloc( void *ptr, size_t size ) { void *umm_poison_realloc(void *ptr, size_t size) {
void *ret; void *ret;
ptr = get_unpoisoned(ptr); ptr = get_unpoisoned(ptr);
size += poison_size(size); size += poison_size(size);
ret = umm_realloc( ptr, size ); ret = umm_realloc(ptr, size);
ret = get_poisoned(ret, size); ret = get_poisoned(ret, size);
return ret; return ret;
} }
/* ------------------------------------------------------------------------ */ /* ------------------------------------------------------------------------ */
void umm_poison_free( void *ptr ) { void umm_poison_free(void *ptr) {
ptr = get_unpoisoned(ptr); ptr = get_unpoisoned(ptr);
umm_free( ptr ); umm_free(ptr);
} }
/* /*
@ -215,32 +216,32 @@ void umm_poison_free( void *ptr ) {
*/ */
bool umm_poison_check(void) { bool umm_poison_check(void) {
UMM_CRITICAL_DECL(id_poison); UMM_CRITICAL_DECL(id_poison);
bool ok = true; bool ok = true;
uint16_t cur; uint16_t cur;
UMM_INIT_HEAP; UMM_INIT_HEAP;
UMM_CRITICAL_ENTRY(id_poison); UMM_CRITICAL_ENTRY(id_poison);
umm_heap_context_t *_context = umm_get_current_heap(); umm_heap_context_t *_context = umm_get_current_heap();
/* Now iterate through the blocks list */ /* Now iterate through the blocks list */
cur = UMM_NBLOCK(0) & UMM_BLOCKNO_MASK; cur = UMM_NBLOCK(0) & UMM_BLOCKNO_MASK;
while( UMM_NBLOCK(cur) & UMM_BLOCKNO_MASK ) { while (UMM_NBLOCK(cur) & UMM_BLOCKNO_MASK) {
if ( !(UMM_NBLOCK(cur) & UMM_FREELIST_MASK) ) { if (!(UMM_NBLOCK(cur) & UMM_FREELIST_MASK)) {
/* This is a used block (not free), so, check its poison */ /* This is a used block (not free), so, check its poison */
ok = check_poison_block(&UMM_BLOCK(cur)); ok = check_poison_block(&UMM_BLOCK(cur));
if (!ok){ if (!ok) {
break; break;
} }
}
cur = UMM_NBLOCK(cur) & UMM_BLOCKNO_MASK;
} }
UMM_CRITICAL_EXIT(id_poison);
cur = UMM_NBLOCK(cur) & UMM_BLOCKNO_MASK; return ok;
}
UMM_CRITICAL_EXIT(id_poison);
return ok;
} }
/* ------------------------------------------------------------------------ */ /* ------------------------------------------------------------------------ */