Skip to content

Update core with upstream umm_malloc #6438

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 40 commits into from
Oct 29, 2019
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
40 commits
Select commit Hold shift + click to select a range
88a32c8
WIP: Initial overlay of upstream version of umm_malloc over
mhightower83 Aug 20, 2019
b508642
WIP: upstream version of umm_malloc customized for Arduino ESP8266 Core
mhightower83 Aug 20, 2019
d7363e0
Resoved Travis CI - issue
mhightower83 Aug 23, 2019
57b65ab
Corrected #ifdef's for UMM_STATS/UMM_STATS_FULL
mhightower83 Aug 27, 2019
da47a79
Merge branch 'master' into WIP-upstream-umm_malloc
d-a-v Aug 29, 2019
71b10fd
Corrected UMM_REALLOC_DEFRAG option to be more like the original umm_…
mhightower83 Sep 3, 2019
4612235
Merge branch 'WIP-upstream-umm_malloc' of github.com:mhightower83/Ard…
mhightower83 Sep 3, 2019
79fe67f
Updated UMM_POISON_CHECK_LITE - Expanded the poison check on the current
mhightower83 Sep 5, 2019
5ded134
Updated printing in heap.cpp to behave the way os_printf did.
mhightower83 Sep 8, 2019
2a1923e
Merged latest, 2019-09-07, from upstream umm_malloc
mhightower83 Sep 8, 2019
f68a64f
Resolved issue where OOM selected w/ Debug port: "Disabled" caused hang.
mhightower83 Sep 8, 2019
9fcf27b
Fixed realloc OOM bug introduced due to confusing code, added comment…
mhightower83 Sep 9, 2019
ad03e16
Merge branch 'master' into WIP-upstream-umm_malloc
mhightower83 Sep 11, 2019
f438e02
Updated to track PRs for various print definitions. Cleaned up comments
mhightower83 Sep 27, 2019
919b122
Merge branch 'master' into WIP-upstream-umm_malloc
mhightower83 Sep 28, 2019
35c6868
Added missing "#ifdef __cplusplus"
mhightower83 Sep 28, 2019
47563cd
Reorganize local enhancements
mhightower83 Sep 29, 2019
2a1b722
Merge branch 'master' into WIP-upstream-umm_malloc
mhightower83 Sep 30, 2019
5560f6b
Print notice message for the need of -DUMM_INFO_PRINT
mhightower83 Sep 30, 2019
c4a46bc
Merge branch 'master' into WIP-upstream-umm_malloc
mhightower83 Sep 30, 2019
0b89ce7
This updates the heap management library, umm_malloc, to the current …
mhightower83 Sep 30, 2019
7e859c5
This updates the heap management library, umm_malloc, to the current …
mhightower83 Sep 30, 2019
2d26ccb
Updated upstream TODO
mhightower83 Oct 1, 2019
eed4b99
Merge branch 'WIP-upstream-umm_malloc' of github.com:mhightower83/Ard…
mhightower83 Oct 1, 2019
966812a
Changes on printing to comply with new understanding of SPI bus avail…
mhightower83 Oct 1, 2019
3669bf5
Removed no longer needed files.
mhightower83 Oct 1, 2019
be66ae7
OOM build option now saves file and line number for post mortem repor…
mhightower83 Oct 2, 2019
917e723
Merge branch 'master' into WIP-upstream-umm_malloc
mhightower83 Oct 2, 2019
503def2
Merge branch 'WIP-upstream-umm_malloc' of github.com:mhightower83/Ard…
mhightower83 Oct 2, 2019
3b80577
Missed change.
mhightower83 Oct 5, 2019
2507ced
Merge branch 'master' into WIP-upstream-umm_malloc
mhightower83 Oct 10, 2019
46b61fb
Consolated upstream integration comments into Notes.h. This helps
mhightower83 Oct 10, 2019
e9401c7
Comment updates.
mhightower83 Oct 10, 2019
648c028
Notes update.
mhightower83 Oct 10, 2019
3475ba2
Merge branch 'master' into WIP-upstream-umm_malloc
mhightower83 Oct 17, 2019
435b8a6
Merge branch 'master' into WIP-upstream-umm_malloc
mhightower83 Oct 23, 2019
eb5a7ca
Changes to heap.cpp -
mhightower83 Oct 24, 2019
3c77efe
Corrected Full Poison Check's placement and documented the
mhightower83 Oct 24, 2019
9da7eb8
Merge branch 'master' into WIP-upstream-umm_malloc
mhightower83 Oct 28, 2019
0eaa613
Fixed typos
mhightower83 Oct 29, 2019
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
Reorganize local enhancements
More comment cleanups
Added Status TODOs marks for upstream
  • Loading branch information
mhightower83 committed Sep 30, 2019
commit 47563cdf9165fd8c79423f600babf0783f01543a
29 changes: 2 additions & 27 deletions cores/esp8266/umm_malloc/umm_info.c
Original file line number Diff line number Diff line change
Expand Up @@ -157,18 +157,8 @@ void *umm_info( void *ptr, int force ) {
}
DBGLOG_FORCE( force, "+--------------------------------------------------------------+\n" );

DBGLOG_FORCE( force, "umm heap statistics:\n");
DBGLOG_FORCE( force, " Free Space %5u\n", ummStats.free_blocks * sizeof(umm_block));
#if defined(UMM_STATS_FULL)
DBGLOG_FORCE( force, " Low Watermark %5u\n", ummStats.free_blocks_min * sizeof(umm_block));
DBGLOG_FORCE( force, " Low Watermark ISR %5u\n", ummStats.free_blocks_isr_min * sizeof(umm_block));
DBGLOG_FORCE( force, " MAX Alloc Request %5u\n", ummStats.alloc_max_size);
DBGLOG_FORCE( force, " OOM Count %5u\n", ummStats.oom_count);
print_stats(force);
#endif
DBGLOG_FORCE( force, " Size of umm_block %5u\n", sizeof(umm_block));
DBGLOG_FORCE( force, "+--------------------------------------------------------------+\n" );
#endif


/* Release the critical section... */
UMM_CRITICAL_EXIT(id_info);
Expand All @@ -178,7 +168,7 @@ void *umm_info( void *ptr, int force ) {

/* ------------------------------------------------------------------------ */

size_t umm_free_heap_size_info( void ) {
size_t umm_free_heap_size( void ) {
umm_info(NULL, 0);
return (size_t)ummHeapInfo.freeBlocks * sizeof(umm_block);
}
Expand All @@ -189,22 +179,7 @@ size_t umm_max_block_size( void ) {
}

/* ------------------------------------------------------------------------ */
#endif

#if defined(UMM_STATS) || defined(UMM_INFO)
size_t umm_block_size( void ) {
return sizeof(umm_block);
}
#endif

#if defined(UMM_STATS) || defined(UMM_STATS_FULL)

UMM_STATISTICS ummStats;

// Complete call path in IRAM
size_t umm_free_heap_size_lw( void ) {
return (size_t)ummStats.free_blocks * sizeof(umm_block);
}
#endif

#endif // defined(BUILD_UMM_MALLOC_C)
45 changes: 42 additions & 3 deletions cores/esp8266/umm_malloc/umm_local.c
Original file line number Diff line number Diff line change
Expand Up @@ -149,12 +149,51 @@ void umm_poison_free_fl(void *ptr, const char* file, int line) {
}
#endif

/* ------------------------------------------------------------------------ */

#if defined(UMM_STATS) || defined(UMM_STATS_FULL) || defined(UMM_INFO)
size_t umm_block_size( void ) {
return sizeof(umm_block);
}
#endif

#if defined(UMM_STATS) || defined(UMM_STATS_FULL)
UMM_STATISTICS ummStats;

// Keep complete call path in IRAM
size_t umm_free_heap_size_lw( void ) {
return (size_t)ummStats.free_blocks * sizeof(umm_block);
}
#endif

/*
I assume xPortGetFreeHeapSize needs to be in IRAM. Since
system_get_free_heap_size is in IRAM. Which would mean, umm_free_heap_size()
in flash, was not a safe alternative for returning the same information.
*/
#if defined(UMM_STATS) || defined(UMM_STATS_FULL)
size_t umm_free_heap_size( void ) __attribute__ ((alias("umm_free_heap_size_lw")));
size_t xPortGetFreeHeapSize(void) __attribute__ ((alias("umm_free_heap_size_lw")));
#elif defined(UMM_INFO)
size_t umm_free_heap_size( void ) __attribute__ ((alias("umm_free_heap_size_info")));
size_t xPortGetFreeHeapSize(void) __attribute__ ((alias("umm_free_heap_size_info")));
#warning "No ISR safe function available to implement xPortGetFreeHeapSize()"
size_t xPortGetFreeHeapSize(void) __attribute__ ((alias("umm_free_heap_size")));
#endif

#if defined(UMM_STATS) || defined(UMM_STATS_FULL)
void print_stats(int force) {
DBGLOG_FORCE( force, "umm heap statistics:\n");
DBGLOG_FORCE( force, " Free Space %5u\n", ummStats.free_blocks * sizeof(umm_block));
DBGLOG_FORCE( force, " OOM Count %5u\n", ummStats.oom_count);
#if defined(UMM_STATS_FULL)
DBGLOG_FORCE( force, " Low Watermark %5u\n", ummStats.free_blocks_min * sizeof(umm_block));
DBGLOG_FORCE( force, " Low Watermark ISR %5u\n", ummStats.free_blocks_isr_min * sizeof(umm_block));
DBGLOG_FORCE( force, " MAX Alloc Request %5u\n", ummStats.alloc_max_size);
#endif
DBGLOG_FORCE( force, " Size of umm_block %5u\n", sizeof(umm_block));
DBGLOG_FORCE( force, "+--------------------------------------------------------------+\n" );
}
#endif


#endif // BUILD_UMM_MALLOC_C


4 changes: 4 additions & 0 deletions cores/esp8266/umm_malloc/umm_local.h
Original file line number Diff line number Diff line change
Expand Up @@ -34,4 +34,8 @@
static int check_poison_neighbors( unsigned short cur );
#endif

#if defined(UMM_STATS) || defined(UMM_STATS_FULL)
void ICACHE_FLASH_ATTR print_stats(int force);
#endif

#endif
17 changes: 7 additions & 10 deletions cores/esp8266/umm_malloc/umm_malloc.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -41,15 +41,10 @@
* In umm_malloc.c
* Renamed to umm_malloc.cpp
*
* Added `extern "C" { ...b};` around code.
* Added `extern "C" { ... };` around code.
*
* Surround DBGLOG_LEVEL with #ifndef... Now defined value in umm_malloc_cfg.h
*
* umm_free() - moved critical section to start after safe calculations.
*
* umm_malloc() - moved critical section to start after umm_blocks()
* computations are based on constants that don't change, calling
* argument excepted.
* Surround DBGLOG_LEVEL with #ifndef... Define value of DBGLOG_LEVEL
* from umm_malloc_cfg.h
*
* umm_realloc() - Added UMM_CRITICAL_SUSPEND()/UMM_CRITICAL_RESUME() for
* when lightweight locks are available. eg. sti/cli. Single threaded
Expand Down Expand Up @@ -119,7 +114,7 @@
* add to list to report.
*/
/*
* Current Deltas from the old umm_malloc
* New upstream umm_malloc feature delta's from the old umm_malloc we were using:
*
* umm_posion check for a given *alloc - failure - no longer panics.
*
Expand All @@ -132,8 +127,10 @@
* Defragmenting effect of realloc is gone. It now minimizes copy. This
* may have been an accident during code cleanup.
*
* In one form or another these features have been restored in the
* reintegration of the upstream umm_malloc into the Arduino ESP8266 Core.
*/
/* This block will be used for the PR description:
/* This block will be used for the non-WIP PR description:

This updates the heap management library, umm_malloc, to the current upstream
version at https://github.com/rhempel/umm_malloc. Some reorganizing and new code
Expand Down
90 changes: 46 additions & 44 deletions cores/esp8266/umm_malloc/umm_malloc_cfg.h
Original file line number Diff line number Diff line change
Expand Up @@ -108,10 +108,8 @@ extern char _heap_start[];
extern UMM_HEAP_INFO ummHeapInfo;

void ICACHE_FLASH_ATTR *umm_info( void *ptr, int force );
size_t ICACHE_FLASH_ATTR umm_free_heap_size_info( void );
size_t ICACHE_FLASH_ATTR umm_free_heap_size( void );
size_t ICACHE_FLASH_ATTR umm_max_block_size( void );
size_t ICACHE_FLASH_ATTR umm_block_size( void );

#else
#endif

Expand All @@ -127,13 +125,16 @@ extern char _heap_start[];
*
* UMM_INFO_PRINT is enabled as part of selecting `Debug port: "Serial" or
* "Serial1"`. To make available all the time use '-D UMM_INFO_PRINT`.
*
* Status: Local Enhancement - addresses platform specific issue.
*/
#if defined(DEBUG_ESP_PORT) && !defined(UMM_INFO_PRINT)
#if defined(DEBUG_ESP_PORT) && !defined(UMM_INFO_PRINT) && defined(UMM_INFO)
#define UMM_INFO_PRINT
#endif

/*
* -D UMM_STATS :
* -D UMM_STATS_FULL
*
* This option provides a lightweight alternative to using `umm_info` just for
* getting `umm_free_heap_size`. With this option, a "free blocks" value is
Expand All @@ -144,18 +145,31 @@ extern char _heap_start[];
* example is when an app closely monitors free heap to detect memory leaks. In
* this case a single-core CPUs interrupt processing would have suffered the
* most.
*
* UMM_STATS_FULL provides additional heap statistics. It can be used to gain
* additional insight into heap usage. This option would add an additional 132
* bytes of IRAM.
*
* Status: TODO: Needs to be proposed for upstream.
*/
/*
#define UMM_STATS
#define UMM_STATS_FULL
*/

#if defined(DEBUG_ESP_PORT) && !defined(UMM_STATS) && !defined(UMM_STATS_FULL)
#define UMM_STATS_FULL
#elif !defined(UMM_STATS) && !defined(UMM_STATS_FULL)
/*
* For the ESP8266 we want at lest UMM_STATS built, so we have an ISR safe
* function to call for implementing xPortGetFreeHeapSize(), because umm_info()
* is in flash.
*/
#if !defined(UMM_STATS) && !defined(UMM_STATS_FULL)
#define UMM_STATS
#endif

#if defined(UMM_STATS) && defined(UMM_STATS_FULL)
#undef UMM_STATS
#endif

#if defined(UMM_STATS) || defined(UMM_STATS_FULL)

typedef struct UMM_STATISTICS_t {
Expand Down Expand Up @@ -191,6 +205,10 @@ static inline size_t ICACHE_FLASH_ATTR umm_get_oom_count( void ) {
#define STATS__OOM_UPDATE() (void)0
#endif

#if defined(UMM_STATS) || defined(UMM_STATS_FULL) || defined(UMM_INFO)
size_t ICACHE_FLASH_ATTR umm_block_size( void );
#endif

#ifdef UMM_STATS_FULL
#define STATS__FREE_BLOCKS_MIN() \
do { \
Expand Down Expand Up @@ -285,10 +303,6 @@ static inline size_t ICACHE_FLASH_ATTR umm_get_free_null_count( void ) {
#define STATS__FREE_REQUEST(tag) (void)0
#endif

#if defined(UMM_STATS) || defined(UMM_STATS_FULL) || defined(UMM_INFO)
size_t umm_free_heap_size( void );
#endif

/*
Per Devyte, the core currently doesn't support masking a specific interrupt
level. That doesn't mean it can't be implemented, only that at this time
Expand All @@ -306,11 +320,12 @@ size_t umm_free_heap_size( void );
*
* Build option to collect timing usage data on critical section usage in
* functions: info, malloc, realloc. Collects MIN, MAX, and number of time IRQs
* were disabled at request time. Note, for realloc MAX disabled time will not
* include the time from calling malloc and/or free when UMM_LIGHTWEIGHT_CPU is
* defined. Examine code for specifics on what info is available and how to
* access.
*/
* were disabled at request time. Note, for realloc MAX disabled time will
* include the time spent in calling malloc and/or free. Examine code for
* specifics on what info is available and how to access.
*
* Status: TODO: Needs to be proposed for upstream.
*/
/*
#define UMM_CRITICAL_METRICS
*/
Expand Down Expand Up @@ -402,11 +417,12 @@ static inline void _critical_exit(UMM_TIME_STAT *p, uint32_t *saved_ps) {
* UMM_CRITICAL_SUSPEND and UMM_CRITICAL_RESUME to the values of
* UMM_CRITICAL_EXIT and UMM_CRITICAL_ENTRY. These additional exit/entries
* allow time to service interrupts during the reentrant sections of the code.
* Also, using these macros will relieve the nesting requirement.
*
* These macros should probably not be used on multicore CPUs. Hardware locking
* methods sometimes carry higher overhead and may not be suitable for frequent
* calling.
* Performance may be impacked if used with multicore CPUs. The higher frquency
* of locking and unlocking may be an issue with locking methods that have a
* high overhead.
*
* Status: TODO: Needs to be proposed for upstream.
*/
/*
*/
Expand All @@ -428,6 +444,10 @@ static inline void _critical_exit(UMM_TIME_STAT *p, uint32_t *saved_ps) {
* shrinks an allocation, avoiding copy when possible. UMM_REALLOC_DEFRAG gives
* priority with growing the revised allocation toward an adjacent hole in the
* direction of the beginning of the heap when possible.
*
* Status: TODO: These are new options introduced to optionally restore the
* previous defrag propery of realloc. The issue has been raised in the upstream
* repo. No response at this time. Based on response, may propose for upstream.
*/
/*
#define UMM_REALLOC_MINIMIZE_COPY
Expand Down Expand Up @@ -503,6 +523,11 @@ static inline void _critical_exit(UMM_TIME_STAT *p, uint32_t *saved_ps) {
* include its nearest allocated neighbors in the heap.
* umm_malloc() will also checks the neighbors of the selected allocation
* before use.
*
* Status: TODO?: UMM_POISON_CHECK_LITE is a new option. We could propose for
* upstream; however, the upstream version has much of the framework for calling
* poison check on each alloc call refactored out. Not sure how this will be
* received.
*/

/*
Expand Down Expand Up @@ -571,6 +596,7 @@ static inline void _critical_exit(UMM_TIME_STAT *p, uint32_t *saved_ps) {
// PROGMEM. Only the 1st parameter, fmt, is supported in PROGMEM.
#define DBGLOG_FUNCTION(fmt, ...) ISR_PRINTF(fmt, ##__VA_ARGS__)
#define DBGLOG_FUNCTION_P(fmt, ...) ISR_PRINTF_P(fmt, ##__VA_ARGS__)

#else
#define DBGLOG_FUNCTION(fmt, ...) do { (void)fmt; } while(false)
#define DBGLOG_FUNCTION_P(fmt, ...) do { (void)fmt; } while(false)
Expand Down Expand Up @@ -646,38 +672,14 @@ void* ICACHE_RAM_ATTR pvPortMalloc(size_t size, const char* file, int line);
void* ICACHE_RAM_ATTR pvPortCalloc(size_t count, size_t size, const char* file, int line);
void* ICACHE_RAM_ATTR pvPortRealloc(void *ptr, size_t size, const char* file, int line);
void* ICACHE_RAM_ATTR pvPortZalloc(size_t size, const char* file, int line);
void ICACHE_RAM_ATTR vPortFree(void *ptr, const char* file, int line);
#define malloc(s) ({ static const char mem_debug_file[] PROGMEM STORE_ATTR = __FILE__; pvPortMalloc(s, mem_debug_file, __LINE__); })
#define calloc(n,s) ({ static const char mem_debug_file[] PROGMEM STORE_ATTR = __FILE__; pvPortCalloc(n, s, mem_debug_file, __LINE__); })
#define realloc(p,s) ({ static const char mem_debug_file[] PROGMEM STORE_ATTR = __FILE__; pvPortRealloc(p, s, mem_debug_file, __LINE__); })
#if defined(UMM_POISON_CHECK) || defined(UMM_POISON_CHECK_LITE)
#if 0
#define free(p) ({ static const char mem_debug_file[] PROGMEM STORE_ATTR = __FILE__; vPortFree(p, mem_debug_file, __LINE__); })
#endif
#endif

#elif defined(UMM_POISON_CHECK) || defined(UMM_POISON_CHECK_LITE)
#include <pgmspace.h>

void* ICACHE_RAM_ATTR pvPortRealloc(void *ptr, size_t size, const char* file, int line);
void ICACHE_RAM_ATTR vPortFree(void *ptr, const char* file, int line);

#define realloc(p,s) ({ static const char mem_debug_file[] PROGMEM STORE_ATTR = __FILE__; pvPortRealloc(p, s, mem_debug_file, __LINE__); })
#if 0
//C
/*
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,
calloc, and realloc those names are not as generic as "free". A #define free
captures too much. Classes with methods called free are included :(
Inline functions would report the address of the inline function in the .h
not where they are called.

Anybody know a trick to make this work?
*/
#define free(p) ({ static const char mem_debug_file[] PROGMEM STORE_ATTR = __FILE__; vPortFree(p, mem_debug_file, __LINE__); })
#endif

#endif /* DEBUG_ESP_OOM */

#ifdef __cplusplus
Expand Down