8000 Ensure xPortGetFreeHeapSize reports DRAM by mhightower83 · Pull Request #8680 · esp8266/Arduino · GitHub
[go: up one dir, main page]

Skip to content

Ensure xPortGetFreeHeapSize reports DRAM #8680

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 7 commits into from
Oct 11, 2022
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
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
Updated function names and alias usage.
While touching and regression testing of build macros for umm_info...
and umm_stats..., improved/fixed macros for better support of
build options specified through Sketch.ino.globals.h.
  • Loading branch information
mhightower83 committed Sep 29, 2022
commit 7af81082ccdcb02d7c6fb2586d07e2a02cd7d65e
2 changes: 1 addition & 1 deletion cores/esp8266/Esp.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -219,7 +219,7 @@ uint16_t EspClass::getVcc(void)

uint32_t EspClass::getFreeHeap(void)
{
return umm_free_heap_size();
return umm_free_heap_size_lw();
}

uint32_t EspClass::getMaxFreeBlockSize(void)
Expand Down
20 changes: 9 additions & 11 deletions cores/esp8266/umm_malloc/Notes.h
Original file line number Diff line number Diff line change
Expand Up @@ -319,28 +319,26 @@ Enhancement ideas:
upstream umm_malloc's `umm_free_heap_size()` and require the build option
UMM_INLINE_METRICS. Otherwise, fail the build.

Use function name `umm_free_heap_size()` to support external request for
current heap size.
Use function name `umm_free_heap_size_lw()` to support external request for
current heap size. When build options result in fallback using umm_info.c,
ensure UMM_INLINE_METRICS enabled and alias to `umm_free_heap_size()`.

For the multiple Heap case `xPortGetFreeHeapSize()` becomes a unique function
For the multiple Heap case, `xPortGetFreeHeapSize()` becomes a unique function
and reports only DRAM free heap size. Now `system_get_free_heap_size()` will
always report DRAM free Heap size. This might be a breaking change.

Specifics:

* rename `umm_free_heap_size_lw()` to `umm_free_heap_size()` for builds that
include option UMM_STATS(default) or UMM_STATS_FULL.
* rename upstream umm_malloc's `umm_free_heap_size()` to
`umm_free_heap_size_info()`.
* Support `umm_free_heap_size_lw()` as an `extern`.

* When the build options UMM_STATS/UMM_STATS_FULL are not used, fallback to
the upstream umm_malloc's original `umm_free_heap_size()` function in
umm_info.c
the upstream umm_malloc's `umm_free_heap_size()` function in umm_info.c
* require the UMM_INLINE_METRICS build option.
* assign `umm_free_heap_size_lw()` as an alias to `umm_free_heap_size()`

* `xPortGetFreeHeapSize()`
* For single heap builds, alias to `umm_free_heap_size()`
* For multi-heap builds, add a dedicated function that always reports
* For single heap builds, alias to `umm_free_heap_size_lw()`
* For multiple Heaps builds, add a dedicated function that always reports
DRAM results.

*/
Expand Down
37 changes: 7 additions & 30 deletions cores/esp8266/umm_malloc/umm_info.c
Original file line number Diff line number Diff line change
Expand Up @@ -175,37 +175,14 @@ size_t umm_free_heap_size_core(umm_heap_context_t *_context) {
}

/*
Need to expose a function for getting the current free heap size
Using umm_free_heap_size for this purpose.

For an expanded discussion see Notes.h, entry dated "Sep 26, 2022"
*/
#if defined(UMM_STATS) || defined(UMM_STATS_FULL)
/*
For this build option, see umm_free_heap_size in umm_local.c
*/

/*
Make upstream logic available under a new name.
May be useful for sanity checks between methods.
Only takes .bin space if used.
When used as the fallback option for supporting exported function
`umm_free_heap_size_lw()`, the build option UMM_INLINE_METRICS is required.
Otherwise, umm_info() would be used to complete the operation, which uses a
time-consuming method for getting free Heap and runs with interrupts off,
which can negatively impact WiFi operations. Also, it cannot support calls
from ISRs, `umm_info()` runs from flash.
*/
size_t umm_free_heap_size_info(void)

#else
/*
Not our default build path. For this path to function well with WiFi enabled,
you must use the build option UMM_INLINE_METRICS. Otherwise, umm_info() is
used to complete the operation, which uses a time-consuming method for getting
free Heap and runs with interrupts off. Also, it cannot support calls from
ISRs, `umm_info()` runs from flash.

Current build test in umm_local.c fails the build option that uses the
umm_info() method.
*/
size_t umm_free_heap_size(void)
#endif
{
size_t umm_free_heap_size(void) {
#ifndef UMM_INLINE_METRICS
umm_info(NULL, false);
#endif
Expand Down
61 changes: 45 additions & 16 deletions cores/esp8266/umm_malloc/umm_local.c
Original file line number Diff line number Diff line change
Expand Up @@ -161,16 +161,29 @@ void umm_poison_free_fl(void *ptr, const char *file, int line) {
/* ------------------------------------------------------------------------ */

#if defined(UMM_STATS) || defined(UMM_STATS_FULL) || defined(UMM_INFO)
/*
For internal, mainly used by UMM_STATS_FULL; exported so external components
can perform Heap related calculations.
*/
size_t umm_block_size(void) {
return sizeof(umm_block);
}
#endif

/*
Need to expose a function to support getting the current free heap size.
Export `size_t umm_free_heap_size_lw(void)` for this purpose.
Used by ESP.getFreeHeap().

For an expanded discussion see Notes.h, entry dated "Sep 26, 2022"
*/
#if defined(UMM_STATS) || defined(UMM_STATS_FULL)
// Support a consistant external name across build options. Used by
// ESP.getFreeHeap(). Keep complete call path in IRAM.
size_t umm_free_heap_size(void) {
/*
Default build option to support export.

Keep complete call path in IRAM.
*/
size_t umm_free_heap_size_lw(void) {
UMM_CHECK_INITIALIZED();

umm_heap_context_t *_context = umm_get_current_heap();
Expand All @@ -179,41 +192,57 @@ size_t umm_free_heap_size(void) {

#elif defined(UMM_INLINE_METRICS)
/*
Use `size_t umm_free_heap_size(void)` (in umm_info.c) from upstream
umm_malloc. It must have the UMM_INLINE_METRICS Build option enabled to
support free heap size reporting without the use of `umm_info()`
For the fallback option using `size_t umm_free_heap_size(void)`, we must have
the UMM_INLINE_METRICS build option enabled to support free heap size
reporting without the use of `umm_info()`.
*/
size_t umm_free_heap_size_lw(void) __attribute__ ((alias("umm_free_heap_size")));

#else
// We require a resources to track and report free heap with low overhead.
// See umm_free_heap_size in umm_info.c for more details
/*
We require a resource to track and report free Heap size with low overhead.
For an expanded discussion see Notes.h, entry dated "Sep 26, 2022"
*/
#error UMM_INLINE_METRICS, UMM_STATS, or UMM_STATS_FULL needs to be defined.
#endif

#if defined(UMM_STATS) || defined(UMM_STATS_FULL)
size_t umm_free_heap_size_core_lw(umm_heap_context_t *_context) {
return (size_t)_context->UMM_FREE_BLOCKS * sizeof(umm_block);
}

#elif defined(UMM_INFO)
// Backfill support for umm_free_heap_size_core_lw()
size_t umm_free_heap_size_core_lw(umm_heap_context_t *_context) __attribute__ ((alias("umm_free_heap_size_core")));
#endif

/*
This API is called by `system_get_free_heap_size()` which is in IRAM. Use IRAM
to ensure the call chain is in IRAM. Which implies it may be called from an
ISR.
This API is called by `system_get_free_heap_size()` which is in IRAM. Driving
the assumption the callee may be in an ISR or Cache_Read_Disable state. Use
IRAM to ensure that the complete call chain is in IRAM.

To satisfy this requirement, we need UMM_STATS... or UMM_INLINE_METRICS
defined. These support an always available without intense computation
free-Heap value.

Like the other vPort... APIs used by the SDK, this must always report on the
DRAM Heap not current Heap.
DRAM Heap not the current Heap.
*/
#if (UMM_NUM_HEAPS == 1)
// Reduce IRAM usage for the single Heap case
#if defined(UMM_STATS) || defined(UMM_STATS_FULL)
size_t xPortGetFreeHeapSize(void) __attribute__ ((alias("umm_free_heap_size_lw")));
#else
size_t xPortGetFreeHeapSize(void) __attribute__ ((alias("umm_free_heap_size")));
#endif

#else
size_t xPortGetFreeHeapSize(void) {
#if defined(UMM_STATS) || defined(UMM_STATS_FULL) || defined(UMM_INLINE_METRICS)
UMM_CHECK_INITIALIZED();
umm_heap_context_t *_context = umm_get_heap_by_id(UMM_HEAP_DRAM);

#if defined(UMM_STATS) || defined(UMM_STATS_FULL)
return (size_t)_context->UMM_FREE_BLOCKS * sizeof(umm_block);
#elif defined(UMM_INLINE_METRICS)
return umm_free_heap_size_core(_context);
return umm_free_heap_size_core_lw(_context);
#else
// At this time, this build path is not reachable. In case things change,
// keep build check.
Expand Down
58 changes: 21 additions & 37 deletions cores/esp8266/umm_malloc/umm_malloc_cfg.h
Original file line number Diff line number Diff line change
Expand Up @@ -106,31 +106,6 @@ extern "C" {
#include "umm_malloc_cfgport.h"
#endif

#define UMM_BEST_FIT
#define UMM_INFO
// #define UMM_INLINE_METRICS
#define UMM_STATS

/*
* To support API call, system_show_malloc(), -DUMM_INFO is required.
*
* For the ESP8266 we need an ISR safe function to call for implementing
* xPortGetFreeHeapSize(). We can get this with one of these options:
* 1) -DUMM_STATS or -DUMM_STATS_FULL
* 2) -DUMM_INLINE_METRICS (and implicitly includes -DUMM_INFO)
*
* If frequent calls are made to ESP.getHeapFragmentation(),
* -DUMM_INLINE_METRICS would reduce long periods of interrupts disabled caused
* by frequent calls to `umm_info()`. Instead, the computations get distributed
* across each malloc, realloc, and free. This appears to require an additional
* 116 bytes of IRAM vs using `UMM_STATS` with `UMM_INFO`.
*
* When both UMM_STATS and UMM_INLINE_METRICS are defined, macros and structures
* have been optimized to reduce duplications.
*
*/


/* A couple of macros to make packing structures less compiler dependent */

#define UMM_H_ATTPACKPRE
Expand Down Expand Up @@ -177,12 +152,22 @@ extern "C" {
#define UMM_FRAGMENTATION_METRIC_REMOVE(c)
#endif // UMM_INLINE_METRICS

struct UMM_HEAP_CONTEXT;
typedef struct UMM_HEAP_CONTEXT umm_heap_context_t;

/*
Must always be defined. Core support for getting free Heap size.
When possible, access via ESP.getFreeHeap();
*/
extern size_t umm_free_heap_size_lw(void);
extern size_t umm_free_heap_size_core_lw(umm_heap_context_t *_context);

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

/*
* -D UMM_INFO :
*
* Enables a dup of the heap contents and a function to return the total
* Enables a dump of the heap contents and a function to return the total
* heap size that is unallocated - note this is not the same as the largest
* unallocated block on the heap!
*/
Expand All @@ -209,20 +194,20 @@ typedef struct UMM_HEAP_INFO_t {
UMM_HEAP_INFO;

// extern UMM_HEAP_INFO ummHeapInfo;
struct UMM_HEAP_CONTEXT;
typedef struct UMM_HEAP_CONTEXT umm_heap_context_t;

extern ICACHE_FLASH_ATTR void *umm_info(void *ptr, bool force);
#if (defined(UMM_STATS) || defined(UMM_STATS_FULL)) && defined(UMM_INFO)
extern ICACHE_FLASH_ATTR size_t umm_free_heap_size_info(void);
#endif
#if defined(UMM_STATS) || defined(UMM_STATS_FULL)
extern ICACHE_FLASH_ATTR size_t umm_free_heap_size(void);
extern ICACHE_FLASH_ATTR size_t umm_free_heap_size_core(umm_heap_context_t *_context);
#else
extern size_t umm_free_heap_size(void);
extern size_t umm_free_heap_size_core(umm_heap_context_t *_context);
#endif


// 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 int umm_usage_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_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_fragmentation_metric_core(umm_heap_context_t *_context);
Expand All @@ -232,9 +217,9 @@ extern ICACHE_FLASH_ATTR int umm_fragmentation_metric_core(umm_heap_context_t *_
#define umm_max_block_size() (0)
#define umm_fragmentation_metric() (0)
#define umm_usage_metric() (0)
#define umm_free_heap_size_core() (0)
#define umm_max_block_size_core() (0)
#define umm_fragmentation_metric_core() (0)
#define umm_free_heap_size_core(c) (0)
#define umm_max_block_size_core(c) (0)
#define umm_fragmentation_metric_core(c) (0)
#endif

/*
Expand Down Expand Up @@ -305,7 +290,6 @@ UMM_STATISTICS;

#define STATS__OOM_UPDATE() _context->UMM_OOM_COUNT += 1

extern size_t umm_free_heap_size_lw(void);
extern size_t umm_get_oom_count(void);

#else // not UMM_STATS or UMM_STATS_FULL
Expand Down
Loading
0