From df5e113b88fbcf0427f1685c45aafc95446a3984 Mon Sep 17 00:00:00 2001 From: M Hightower <27247790+mhightower83@users.noreply.github.com> Date: Tue, 12 Jan 2021 15:08:41 -0800 Subject: [PATCH] HeapSelectDram for pvPortMalloc, ... (#7790) * Add inline always option to HeapSelect * Add option to force DRAM for pvPort... APIs * revert print_loc premature change * Renamed macro to be more specific, FORCE_ALWAYS_INLINE to FORCE_ALWAYS_INLINE_HEAP_SELECT --- cores/esp8266/heap.cpp | 67 ++++++++++++++++++++-- cores/esp8266/umm_malloc/umm_heap_select.h | 24 ++++++++ cores/esp8266/umm_malloc/umm_malloc_cfg.h | 27 ++++----- 3 files changed, 99 insertions(+), 19 deletions(-) diff --git a/cores/esp8266/heap.cpp b/cores/esp8266/heap.cpp index 3f549716f..4821f9b77 100644 --- a/cores/esp8266/heap.cpp +++ b/cores/esp8266/heap.cpp @@ -5,6 +5,11 @@ #include #include "umm_malloc/umm_malloc.h" + +// Need FORCE_ALWAYS_INLINE to put HeapSelect class constructor/deconstructor in IRAM +#define FORCE_ALWAYS_INLINE_HEAP_SELECT +#include "umm_malloc/umm_heap_select.h" + #include #include #include @@ -16,6 +21,7 @@ extern "C" { #define UMM_CALLOC(n,s) umm_poison_calloc(n,s) #define UMM_REALLOC_FL(p,s,f,l) umm_poison_realloc_fl(p,s,f,l) #define UMM_FREE_FL(p,f,l) umm_poison_free_fl(p,f,l) +#define STATIC_ALWAYS_INLINE #undef realloc #undef free @@ -25,6 +31,7 @@ extern "C" { #define UMM_CALLOC(n,s) umm_calloc(n,s) #define UMM_REALLOC_FL(p,s,f,l) umm_realloc(p,s) #define UMM_FREE_FL(p,f,l) umm_free(p) +#define STATIC_ALWAYS_INLINE #undef realloc #undef free @@ -34,6 +41,10 @@ extern "C" { #define UMM_CALLOC(n,s) calloc(n,s) #define UMM_REALLOC_FL(p,s,f,l) realloc(p,s) #define UMM_FREE_FL(p,f,l) free(p) + +// STATIC_ALWAYS_INLINE only applys to the non-debug build path, +// it must not be enabled on the debug build path. +#define STATIC_ALWAYS_INLINE static ALWAYS_INLINE #endif @@ -259,8 +270,8 @@ void ICACHE_RAM_ATTR free(void* p) } #endif - -void* ICACHE_RAM_ATTR pvPortMalloc(size_t size, const char* file, int line) +STATIC_ALWAYS_INLINE +void* ICACHE_RAM_ATTR heap_pvPortMalloc(size_t size, const char* file, int line) { INTEGRITY_CHECK__PANIC_FL(file, line); POISON_CHECK__PANIC_FL(file, line); @@ -270,7 +281,8 @@ void* ICACHE_RAM_ATTR pvPortMalloc(size_t size, const char* file, int line) return ret; } -void* ICACHE_RAM_ATTR pvPortCalloc(size_t count, size_t size, const char* file, int line) +STATIC_ALWAYS_INLINE +void* ICACHE_RAM_ATTR heap_pvPortCalloc(size_t count, size_t size, const char* file, int line) { INTEGRITY_CHECK__PANIC_FL(file, line); POISON_CHECK__PANIC_FL(file, line); @@ -280,7 +292,8 @@ void* ICACHE_RAM_ATTR pvPortCalloc(size_t count, size_t size, const char* file, return ret; } -void* ICACHE_RAM_ATTR pvPortRealloc(void *ptr, size_t size, const char* file, int line) +STATIC_ALWAYS_INLINE +void* ICACHE_RAM_ATTR heap_pvPortRealloc(void *ptr, size_t size, const char* file, int line) { INTEGRITY_CHECK__PANIC_FL(file, line); void* ret = UMM_REALLOC_FL(ptr, size, file, line); @@ -290,7 +303,8 @@ void* ICACHE_RAM_ATTR pvPortRealloc(void *ptr, size_t size, const char* file, in return ret; } -void* ICACHE_RAM_ATTR pvPortZalloc(size_t size, const char* file, int line) +STATIC_ALWAYS_INLINE +void* ICACHE_RAM_ATTR heap_pvPortZalloc(size_t size, const char* file, int line) { INTEGRITY_CHECK__PANIC_FL(file, line); POISON_CHECK__PANIC_FL(file, line); @@ -300,7 +314,8 @@ void* ICACHE_RAM_ATTR pvPortZalloc(size_t size, const char* file, int line) return ret; } -void ICACHE_RAM_ATTR vPortFree(void *ptr, const char* file, int line) +STATIC_ALWAYS_INLINE +void ICACHE_RAM_ATTR heap_vPortFree(void *ptr, const char* file, int line) { INTEGRITY_CHECK__PANIC_FL(file, line); UMM_FREE_FL(ptr, file, line); @@ -314,7 +329,47 @@ size_t ICACHE_RAM_ATTR xPortWantedSizeAlign(size_t size) void system_show_malloc(void) { + HeapSelectDram ephemeral; umm_info(NULL, true); } +/* + NONOS SDK and lwIP do not handle IRAM heap well. Since they also use portable + malloc calls pvPortMalloc, ... we can leverage that for this solution. + Force pvPortMalloc, ... APIs to serve DRAM only. +*/ +void* ICACHE_RAM_ATTR pvPortMalloc(size_t size, const char* file, int line) +{ + HeapSelectDram ephemeral; + return heap_pvPortMalloc(size, file, line);; +} + +void* ICACHE_RAM_ATTR pvPortCalloc(size_t count, size_t size, const char* file, int line) +{ + HeapSelectDram ephemeral; + return heap_pvPortCalloc(count, size, file, line); +} + +void* ICACHE_RAM_ATTR pvPortRealloc(void *ptr, size_t size, const char* file, int line) +{ + HeapSelectDram ephemeral; + return heap_pvPortRealloc(ptr, size, file, line); +} + +void* ICACHE_RAM_ATTR pvPortZalloc(size_t size, const char* file, int line) +{ + HeapSelectDram ephemeral; + return heap_pvPortZalloc(size, file, line); +} + +void ICACHE_RAM_ATTR vPortFree(void *ptr, const char* file, int line) +{ +#if defined(DEBUG_ESP_OOM) || defined(UMM_POISON_CHECK) || defined(UMM_POISON_CHECK_LITE) || defined(UMM_INTEGRITY_CHECK) + // This is only needed for debug checks to ensure they are performed in + // correct context. umm_malloc free internally determines the correct heap. + HeapSelectDram ephemeral; +#endif + return heap_vPortFree(ptr, file, line); +} + }; diff --git a/cores/esp8266/umm_malloc/umm_heap_select.h b/cores/esp8266/umm_malloc/umm_heap_select.h index 4c9150819..1a3728d7a 100644 --- a/cores/esp8266/umm_malloc/umm_heap_select.h +++ b/cores/esp8266/umm_malloc/umm_heap_select.h @@ -3,6 +3,18 @@ #include +#ifndef ALWAYS_INLINE +#define ALWAYS_INLINE inline __attribute__ ((always_inline)) +#endif + +// Use FORCE_ALWAYS_INLINE to ensure HeapSelect... construtor/deconstructor +// are placed in IRAM +#ifdef FORCE_ALWAYS_INLINE_HEAP_SELECT +#define MAYBE_ALWAYS_INLINE ALWAYS_INLINE +#else +#define MAYBE_ALWAYS_INLINE +#endif + /* This class is modeled after interrupts.h @@ -20,13 +32,17 @@ class HeapSelect { public: #if (UMM_NUM_HEAPS == 1) + MAYBE_ALWAYS_INLINE HeapSelect(size_t id) { (void)id; } + MAYBE_ALWAYS_INLINE ~HeapSelect() {} #else + MAYBE_ALWAYS_INLINE HeapSelect(size_t id) : _heap_id(umm_get_current_heap_id()) { umm_set_heap_by_id(id); } + MAYBE_ALWAYS_INLINE ~HeapSelect() { umm_set_heap_by_id(_heap_id); } @@ -39,10 +55,12 @@ protected: class HeapSelectIram { public: #ifdef UMM_HEAP_IRAM + MAYBE_ALWAYS_INLINE HeapSelectIram() : _heap_id(umm_get_current_heap_id()) { umm_set_heap_by_id(UMM_HEAP_IRAM); } + MAYBE_ALWAYS_INLINE ~HeapSelectIram() { umm_set_heap_by_id(_heap_id); } @@ -51,7 +69,9 @@ protected: size_t _heap_id; #else + MAYBE_ALWAYS_INLINE HeapSelectIram() {} + MAYBE_ALWAYS_INLINE ~HeapSelectIram() {} #endif }; @@ -59,13 +79,17 @@ protected: class HeapSelectDram { public: #if (UMM_NUM_HEAPS == 1) + MAYBE_ALWAYS_INLINE HeapSelectDram() {} + MAYBE_ALWAYS_INLINE ~HeapSelectDram() {} #else + MAYBE_ALWAYS_INLINE HeapSelectDram() : _heap_id(umm_get_current_heap_id()) { umm_set_heap_by_id(UMM_HEAP_DRAM); } + MAYBE_ALWAYS_INLINE ~HeapSelectDram() { umm_set_heap_by_id(_heap_id); } diff --git a/cores/esp8266/umm_malloc/umm_malloc_cfg.h b/cores/esp8266/umm_malloc/umm_malloc_cfg.h index 1e5d7f800..4fc059a49 100644 --- a/cores/esp8266/umm_malloc/umm_malloc_cfg.h +++ b/cores/esp8266/umm_malloc/umm_malloc_cfg.h @@ -792,28 +792,29 @@ extern "C" { // Arduino.h recall us to redefine them #include // Reuse pvPort* calls, since they already support passing location information. -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); +// Specificly the debug version (heap_...) that does not force DRAM heap. +void* ICACHE_RAM_ATTR heap_pvPortMalloc(size_t size, const char* file, int line); +void* ICACHE_RAM_ATTR heap_pvPortCalloc(size_t count, size_t size, const char* file, int line); +void* ICACHE_RAM_ATTR heap_pvPortRealloc(void *ptr, size_t size, const char* file, int line); +void* ICACHE_RAM_ATTR heap_pvPortZalloc(size_t size, const char* file, int line); +void ICACHE_RAM_ATTR heap_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__); }) +#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 realloc(p,s) ({ static const char mem_debug_file[] PROGMEM STORE_ATTR = __FILE__; heap_pvPortRealloc(p, s, mem_debug_file, __LINE__); }) #if defined(UMM_POISON_CHECK) || defined(UMM_POISON_CHECK_LITE) -#define dbg_heap_free(p) ({ static const char mem_debug_file[] PROGMEM STORE_ATTR = __FILE__; vPortFree(p, mem_debug_file, __LINE__); }) +#define dbg_heap_free(p) ({ static const char mem_debug_file[] PROGMEM STORE_ATTR = __FILE__; heap_vPortFree(p, mem_debug_file, __LINE__); }) #else #define dbg_heap_free(p) free(p) #endif #elif defined(UMM_POISON_CHECK) || defined(UMM_POISON_CHECK_LITE) #include -void* ICACHE_RAM_ATTR 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__; pvPortRealloc(p, s, mem_debug_file, __LINE__); }) +void* ICACHE_RAM_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__); }) -void ICACHE_RAM_ATTR vPortFree(void *ptr, const char* file, int line); +void ICACHE_RAM_ATTR heap_vPortFree(void *ptr, const char* file, int line); //C - to be discussed /* Problem, I would like to report the file and line number with the umm poison @@ -828,7 +829,7 @@ void ICACHE_RAM_ATTR vPortFree(void *ptr, const char* file, int line); Create dbg_heap_free() as an alternative for free() when you need a little more help in debugging the more challenging problems. */ -#define dbg_heap_free(p) ({ static const char mem_debug_file[] PROGMEM STORE_ATTR = __FILE__; vPortFree(p, mem_debug_file, __LINE__); }) +#define dbg_heap_free(p) ({ static const char mem_debug_file[] PROGMEM STORE_ATTR = __FILE__; heap_vPortFree(p, mem_debug_file, __LINE__); }) #else #define dbg_heap_free(p) free(p)