Skip to content
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

HeapSelectDram for pvPortMalloc, ... #7790

Merged
67 changes: 61 additions & 6 deletions cores/esp8266/heap.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,11 @@

#include <stdlib.h>
#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 <c_types.h>
#include <sys/reent.h>
#include <user_interface.h>
Expand All @@ -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
Expand All @@ -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
Expand All @@ -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


Expand Down Expand Up @@ -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);
Expand All @@ -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);
Expand All @@ -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);
Expand All @@ -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);
Expand All @@ -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);
Expand All @@ -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);
}

};
24 changes: 24 additions & 0 deletions cores/esp8266/umm_malloc/umm_heap_select.h
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,18 @@

#include <umm_malloc/umm_malloc.h>

#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

Expand All @@ -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);
}
Expand All @@ -39,10 +55,12 @@ class HeapSelect {
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);
}
Expand All @@ -51,21 +69,27 @@ class HeapSelectIram {
size_t _heap_id;

#else
MAYBE_ALWAYS_INLINE
HeapSelectIram() {}
MAYBE_ALWAYS_INLINE
~HeapSelectIram() {}
#endif
};

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);
}
Expand Down
27 changes: 14 additions & 13 deletions cores/esp8266/umm_malloc/umm_malloc_cfg.h
Original file line number Diff line number Diff line change
Expand Up @@ -792,28 +792,29 @@ extern "C" {
// Arduino.h recall us to redefine them
#include <pgmspace.h>
// 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 <pgmspace.h>
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
Expand All @@ -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)
Expand Down