Merge branch 'feat/sort-heaps-by-size' into 'master'

feat(heap): Sort list of registered heap by increasing size

Closes IDFGH-12587

See merge request espressif/esp-idf!33572
This commit is contained in:
Guillaume Souchere 2024-11-25 14:44:19 +08:00
commit ab3d179f53
3 changed files with 46 additions and 7 deletions

View File

@ -9,7 +9,7 @@
#include "esp_heap_caps.h"
// Some resources are lazy allocated in pulse_cnt driver, the threshold is left for that case
#define TEST_MEMORY_LEAK_THRESHOLD (-300)
#define TEST_MEMORY_LEAK_THRESHOLD (-400)
static size_t before_free_8bit;
static size_t before_free_32bit;

View File

@ -8,7 +8,7 @@
#include "unity_test_runner.h"
#include "esp_heap_caps.h"
#define TEST_MEMORY_LEAK_THRESHOLD (-600)
#define TEST_MEMORY_LEAK_THRESHOLD (-700)
static size_t before_free_8bit;
static size_t before_free_32bit;

View File

@ -27,6 +27,43 @@ ESP_SYSTEM_INIT_FN(init_heap, CORE, BIT(0), 100)
return ESP_OK;
}
/**
* @brief This helper function adds a new heap to list of registered
* heaps making sure to keep the heaps sorted by ascending size.
*
* @param new_heap heap to be inserted in the list of registered
* heaps
*/
static void sorted_add_to_registered_heaps(heap_t *new_heap)
{
// if list empty, insert head and return
if (SLIST_EMPTY(&registered_heaps)) {
SLIST_INSERT_HEAD(&registered_heaps, new_heap, next);
return;
}
// else, go through the registered heaps and add the new one
// so the registered heaps are sorted by increasing heap size.
heap_t *cur_heap = NULL;
heap_t *prev_heap = NULL;
const size_t new_heap_size = new_heap->end - new_heap->start;
SLIST_FOREACH(cur_heap, &registered_heaps, next) {
const size_t cur_heap_size = cur_heap->end - cur_heap->start;
if (cur_heap_size >= new_heap_size) {
if (prev_heap != NULL) {
SLIST_INSERT_AFTER(prev_heap, new_heap, next);
} else {
SLIST_INSERT_HEAD(&registered_heaps, new_heap, next);
}
return;
}
prev_heap = cur_heap;
}
// new heap size if the biggest so far, insert it at the end
SLIST_INSERT_AFTER(prev_heap, new_heap, next);
}
static void register_heap(heap_t *region)
{
size_t heap_size = region->end - region->start;
@ -154,11 +191,13 @@ void heap_caps_init(void)
if (heaps_array[i].heap != NULL) {
multi_heap_set_lock(heaps_array[i].heap, &heaps_array[i].heap_mux);
}
if (i == 0) {
SLIST_INSERT_HEAD(&registered_heaps, &heaps_array[0], next);
} else {
SLIST_INSERT_AFTER(&heaps_array[i-1], &heaps_array[i], next);
}
/* Since the registered heaps list is always traversed from head
* to tail when looking for a suitable heap when allocating memory, it is
* best to place smaller heap first. In that way, if several heaps share
* the same set of capabilities, the smallest heaps will be used first when
* processing small allocation requests, leaving the bigger heaps untouched
* until the smaller heaps are full. */
sorted_add_to_registered_heaps(&heaps_array[i]);
}
}