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:
parent
f401f08aba
commit
f26201e6a9
@ -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
|
||||||
|
@ -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.
|
||||||
|
@ -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__);}}
|
||||||
|
@ -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
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -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);
|
||||||
}
|
}
|
||||||
|
@ -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
|
||||||
|
@ -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
|
||||||
|
|
||||||
|
@ -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
@ -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
|
||||||
}
|
}
|
||||||
|
@ -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,
|
||||||
|
@ -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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ------------------------------------------------------------------------ */
|
/* ------------------------------------------------------------------------ */
|
||||||
|
Loading…
x
Reference in New Issue
Block a user