mirror of
https://github.com/espressif/esp-idf.git
synced 2026-08-18 06:35:35 +03:00
Merge branch 'fix/heap-minimum-free-size' into 'master'
fix(heap): Do not consider newly registered heap in minimum free size calculation Closes IDF-15682 See merge request espressif/esp-idf!48681
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2015-2025 Espressif Systems (Shanghai) CO LTD
|
||||
* SPDX-FileCopyrightText: 2015-2026 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
@@ -345,10 +345,12 @@ esp_err_t heap_caps_monitor_local_minimum_free_size_start(void)
|
||||
|
||||
heap = SLIST_FIRST(®istered_heaps);
|
||||
for (size_t counter = 0; counter < min_free_bytes_monitoring.counter; counter++) {
|
||||
size_t old_minimum = multi_heap_reset_minimum_free_bytes(heap->heap);
|
||||
if (heap->heap != NULL) {
|
||||
size_t old_minimum = multi_heap_reset_minimum_free_bytes(heap->heap);
|
||||
|
||||
if (min_free_bytes_monitoring.values[counter] > old_minimum) {
|
||||
min_free_bytes_monitoring.values[counter] = old_minimum;
|
||||
if (min_free_bytes_monitoring.values[counter] > old_minimum) {
|
||||
min_free_bytes_monitoring.values[counter] = old_minimum;
|
||||
}
|
||||
}
|
||||
|
||||
heap = SLIST_NEXT(heap, next);
|
||||
@@ -367,7 +369,9 @@ esp_err_t heap_caps_monitor_local_minimum_free_size_stop(void)
|
||||
MULTI_HEAP_LOCK(&min_free_bytes_monitoring.mux);
|
||||
heap_t *heap = SLIST_FIRST(®istered_heaps);
|
||||
for (size_t counter = 0; counter < min_free_bytes_monitoring.counter; counter++) {
|
||||
multi_heap_restore_minimum_free_bytes(heap->heap, min_free_bytes_monitoring.values[counter]);
|
||||
if (heap->heap != NULL) {
|
||||
multi_heap_restore_minimum_free_bytes(heap->heap, min_free_bytes_monitoring.values[counter]);
|
||||
}
|
||||
|
||||
heap = SLIST_NEXT(heap, next);
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2015-2025 Espressif Systems (Shanghai) CO LTD
|
||||
* SPDX-FileCopyrightText: 2015-2026 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
@@ -19,6 +19,9 @@
|
||||
|
||||
static const char *TAG = "heap_init";
|
||||
|
||||
/* Flag indicating if the system is in startup */
|
||||
static bool s_in_startup = true;
|
||||
|
||||
/* Linked-list of registered heaps */
|
||||
struct registered_heap_ll registered_heaps;
|
||||
|
||||
@@ -88,6 +91,11 @@ void heap_caps_enable_nonos_stack_heaps(void)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* heap_caps_enable_nonos_stack_heaps is called from main_task right before
|
||||
* app_main is called so setting this variable here is as close as we can get
|
||||
* within the heap component to the actual start of the application */
|
||||
s_in_startup = false;
|
||||
}
|
||||
|
||||
/* Initialize the heap allocator to use all of the memory not
|
||||
@@ -314,6 +322,15 @@ esp_err_t heap_caps_add_region_with_caps(const uint32_t caps[], intptr_t start,
|
||||
}
|
||||
multi_heap_set_lock(p_new->heap, &p_new->heap_mux);
|
||||
|
||||
if (!s_in_startup) {
|
||||
/* Set minimum_free_bytes to 0 so the newly added heap does not
|
||||
* artificially inflate minimum free size. Only perform this operation
|
||||
* for heaps created after startup. The heaps created by IDF component
|
||||
* before app_main is reached should be taken into account in the calculation
|
||||
* of the minimum free size. */
|
||||
multi_heap_restore_minimum_free_bytes(p_new->heap, 0);
|
||||
}
|
||||
|
||||
/* (This insertion is atomic to registered_heaps, so
|
||||
we don't need to worry about thread safety for readers,
|
||||
only for writers. */
|
||||
|
||||
@@ -230,6 +230,9 @@ size_t heap_caps_get_free_size( uint32_t caps );
|
||||
* tracked per-region. Individual regions' heaps may have reached their "low watermarks" at different points in time. However,
|
||||
* this result still gives a "worst case" indication for all-time minimum free heap.
|
||||
*
|
||||
* @note Heaps added at runtime using heap_caps_add_region_with_caps() (i.e., from app_main onwards) are not taken into
|
||||
* account in the minimum free size calculation.
|
||||
*
|
||||
* @param caps Bitwise OR of MALLOC_CAP_* flags indicating the type
|
||||
* of memory
|
||||
*
|
||||
|
||||
@@ -12,6 +12,8 @@
|
||||
#include "unity.h"
|
||||
#include "esp_attr.h"
|
||||
#include "esp_heap_caps.h"
|
||||
#include "esp_heap_caps_init.h"
|
||||
#include "heap_memory_layout.h"
|
||||
#include "spi_flash_mmap.h"
|
||||
#include "esp_memory_utils.h"
|
||||
#include "esp_private/spi_flash_os.h"
|
||||
@@ -206,6 +208,41 @@ TEST_CASE("heap caps minimum free bytes monitoring", "[heap]")
|
||||
TEST_ASSERT(local_minimum_free_size >= free_size);
|
||||
}
|
||||
|
||||
extern void set_leak_threshold(int threshold);
|
||||
|
||||
/* NOTE: This is not a well-formed unit test, it leaks memory */
|
||||
TEST_CASE("heap registered after startup should not affect minimum free size", "[heap]")
|
||||
{
|
||||
printf("heap registered after startup should not affect minimum free size\n");
|
||||
|
||||
const uint32_t MALLOC_CAP_INVENTED = (1 << 29); /* unused capability, must differ from (1 << 30) used in test_runtime_heap_reg.c */
|
||||
const size_t BUF_SZ = 3500;
|
||||
uint32_t caps[SOC_MEMORY_TYPE_NO_PRIOS] = { MALLOC_CAP_INVENTED };
|
||||
|
||||
// Record the minimum free size for default caps before adding a new heap
|
||||
size_t minimum_before = heap_caps_get_minimum_free_size(MALLOC_CAP_DEFAULT);
|
||||
|
||||
// Allocate a buffer and register it as a new heap region.
|
||||
// Since we are past startup (app_main has been reached), the newly
|
||||
// registered heap should NOT affect the minimum free size.
|
||||
void *buffer = malloc(BUF_SZ);
|
||||
TEST_ASSERT_NOT_NULL(buffer);
|
||||
TEST_ESP_OK(heap_caps_add_region_with_caps(caps, (intptr_t)buffer, (intptr_t)buffer + BUF_SZ));
|
||||
|
||||
// The minimum free size for the invented capability should be 0
|
||||
// because the heap was registered after startup.
|
||||
size_t minimum_invented = heap_caps_get_minimum_free_size(MALLOC_CAP_INVENTED);
|
||||
TEST_ASSERT_EQUAL(0, minimum_invented);
|
||||
|
||||
// The minimum free size for default caps should not have increased
|
||||
// (it may have decreased slightly due to the malloc above).
|
||||
size_t minimum_after = heap_caps_get_minimum_free_size(MALLOC_CAP_DEFAULT);
|
||||
TEST_ASSERT(minimum_after <= minimum_before);
|
||||
|
||||
// set the leak threshold to a bigger value as this test leaks memory
|
||||
set_leak_threshold(-4000);
|
||||
}
|
||||
|
||||
TEST_CASE("heap caps minimum free bytes fault cases", "[heap]")
|
||||
{
|
||||
printf("heap caps minimum free bytes fault cases\n");
|
||||
|
||||
Reference in New Issue
Block a user