kopia lustrzana https://github.com/espressif/esp-idf
Merge branch 'bugfix/heap_tests_esp32s2beta' into 'master'
bugfix/heap test failure fixing for esp32s2 beta Closes IDF-1021 See merge request espressif/esp-idf!6659pull/4618/head
commit
cf2f732b2c
|
@ -1 +1 @@
|
||||||
Subproject commit a7bc26b69768f7fb24f0c7976fae24b157b85b13
|
Subproject commit 968b8cc46dbee47b83318d5f31a8e7907199614b
|
|
@ -107,6 +107,7 @@ IRAM_ATTR void *heap_caps_malloc( size_t size, uint32_t caps )
|
||||||
//we need to 'invert' it (lowest address in DRAM == highest address in IRAM and vice-versa) and
|
//we need to 'invert' it (lowest address in DRAM == highest address in IRAM and vice-versa) and
|
||||||
//add a pointer to the DRAM equivalent before the address we're going to return.
|
//add a pointer to the DRAM equivalent before the address we're going to return.
|
||||||
ret = multi_heap_malloc(heap->heap, size + 4); // int overflow checked above
|
ret = multi_heap_malloc(heap->heap, size + 4); // int overflow checked above
|
||||||
|
|
||||||
if (ret != NULL) {
|
if (ret != NULL) {
|
||||||
return dram_alloc_to_iram_addr(ret, size + 4); // int overflow checked above
|
return dram_alloc_to_iram_addr(ret, size + 4); // int overflow checked above
|
||||||
}
|
}
|
||||||
|
@ -274,6 +275,10 @@ IRAM_ATTR void heap_caps_free( void *ptr)
|
||||||
|
|
||||||
IRAM_ATTR void *heap_caps_realloc( void *ptr, size_t size, int caps)
|
IRAM_ATTR void *heap_caps_realloc( void *ptr, size_t size, int caps)
|
||||||
{
|
{
|
||||||
|
bool ptr_in_diram_case = false;
|
||||||
|
heap_t *heap = NULL;
|
||||||
|
void *dram_ptr = NULL;
|
||||||
|
|
||||||
if (ptr == NULL) {
|
if (ptr == NULL) {
|
||||||
return heap_caps_malloc(size, caps);
|
return heap_caps_malloc(size, caps);
|
||||||
}
|
}
|
||||||
|
@ -287,15 +292,30 @@ IRAM_ATTR void *heap_caps_realloc( void *ptr, size_t size, int caps)
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
heap_t *heap = find_containing_heap(ptr);
|
//The pointer to memory may be aliased, we need to
|
||||||
|
//recover the corresponding address before to manage a new allocation:
|
||||||
assert(heap != NULL && "realloc() pointer is outside heap areas");
|
if(esp_ptr_in_diram_iram((void *)ptr)) {
|
||||||
|
uint32_t *dram_addr = (uint32_t *)ptr;
|
||||||
|
dram_ptr = (void *)dram_addr[-1];
|
||||||
|
|
||||||
|
heap = find_containing_heap(dram_ptr);
|
||||||
|
assert(heap != NULL && "realloc() pointer is outside heap areas");
|
||||||
|
|
||||||
|
//with pointers that reside on diram space, we avoid using
|
||||||
|
//the realloc implementation due to address translation issues,
|
||||||
|
//instead force a malloc/copy/free
|
||||||
|
ptr_in_diram_case = true;
|
||||||
|
|
||||||
|
} else {
|
||||||
|
heap = find_containing_heap(ptr);
|
||||||
|
assert(heap != NULL && "realloc() pointer is outside heap areas");
|
||||||
|
}
|
||||||
|
|
||||||
// are the existing heap's capabilities compatible with the
|
// are the existing heap's capabilities compatible with the
|
||||||
// requested ones?
|
// requested ones?
|
||||||
bool compatible_caps = (caps & get_all_caps(heap)) == caps;
|
bool compatible_caps = (caps & get_all_caps(heap)) == caps;
|
||||||
|
|
||||||
if (compatible_caps) {
|
if (compatible_caps && !ptr_in_diram_case) {
|
||||||
// try to reallocate this memory within the same heap
|
// try to reallocate this memory within the same heap
|
||||||
// (which will resize the block if it can)
|
// (which will resize the block if it can)
|
||||||
void *r = multi_heap_realloc(heap->heap, ptr, size);
|
void *r = multi_heap_realloc(heap->heap, ptr, size);
|
||||||
|
@ -308,7 +328,16 @@ IRAM_ATTR void *heap_caps_realloc( void *ptr, size_t size, int caps)
|
||||||
// in a different heap with requested capabilities.
|
// in a different heap with requested capabilities.
|
||||||
void *new_p = heap_caps_malloc(size, caps);
|
void *new_p = heap_caps_malloc(size, caps);
|
||||||
if (new_p != NULL) {
|
if (new_p != NULL) {
|
||||||
size_t old_size = multi_heap_get_allocated_size(heap->heap, ptr);
|
size_t old_size = 0;
|
||||||
|
|
||||||
|
//If we're dealing with aliased ptr, information regarding its containing
|
||||||
|
//heap can only be obtained with translated address.
|
||||||
|
if(ptr_in_diram_case) {
|
||||||
|
old_size = multi_heap_get_allocated_size(heap->heap, dram_ptr);
|
||||||
|
} else {
|
||||||
|
old_size = multi_heap_get_allocated_size(heap->heap, ptr);
|
||||||
|
}
|
||||||
|
|
||||||
assert(old_size > 0);
|
assert(old_size > 0);
|
||||||
memcpy(new_p, ptr, MIN(size, old_size));
|
memcpy(new_p, ptr, MIN(size, old_size));
|
||||||
heap_caps_free(ptr);
|
heap_caps_free(ptr);
|
||||||
|
|
|
@ -268,8 +268,8 @@ void *multi_heap_realloc(multi_heap_handle_t heap, void *p, size_t size)
|
||||||
new_head = multi_heap_malloc_impl(heap, size + POISON_OVERHEAD);
|
new_head = multi_heap_malloc_impl(heap, size + POISON_OVERHEAD);
|
||||||
if (new_head != NULL) {
|
if (new_head != NULL) {
|
||||||
result = poison_allocated_region(new_head, size);
|
result = poison_allocated_region(new_head, size);
|
||||||
memcpy(result, p, MIN(size, orig_alloc_size));
|
memcpy(result, p, MIN(size, orig_alloc_size));
|
||||||
multi_heap_free(heap, p);
|
multi_heap_free(heap, p);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
|
@ -18,18 +18,18 @@ static char* check_calloc(int size)
|
||||||
|
|
||||||
TEST_CASE("Check for leaks (no leak)", "[heap]")
|
TEST_CASE("Check for leaks (no leak)", "[heap]")
|
||||||
{
|
{
|
||||||
char *arr = check_calloc(7000);
|
char *arr = check_calloc(1000);
|
||||||
free(arr);
|
free(arr);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_CASE("Check for leaks (leak)", "[heap][ignore]")
|
TEST_CASE("Check for leaks (leak)", "[heap][ignore]")
|
||||||
{
|
{
|
||||||
check_calloc(7000);
|
check_calloc(1000);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_CASE("Not check for leaks", "[heap][leaks]")
|
TEST_CASE("Not check for leaks", "[heap][leaks]")
|
||||||
{
|
{
|
||||||
check_calloc(7000);
|
check_calloc(1000);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_CASE("Set a leak level = 7016", "[heap][leaks=7016]")
|
TEST_CASE("Set a leak level = 7016", "[heap][leaks=7016]")
|
||||||
|
@ -39,7 +39,7 @@ TEST_CASE("Set a leak level = 7016", "[heap][leaks=7016]")
|
||||||
|
|
||||||
static void test_fn(void)
|
static void test_fn(void)
|
||||||
{
|
{
|
||||||
check_calloc(7000);
|
check_calloc(1000);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_CASE_MULTIPLE_STAGES("Not check for leaks in MULTIPLE_STAGES mode", "[heap][leaks]", test_fn, test_fn, test_fn);
|
TEST_CASE_MULTIPLE_STAGES("Not check for leaks in MULTIPLE_STAGES mode", "[heap][leaks]", test_fn, test_fn, test_fn);
|
||||||
|
@ -48,13 +48,13 @@ TEST_CASE_MULTIPLE_STAGES("Check for leaks in MULTIPLE_STAGES mode (leak)", "[he
|
||||||
|
|
||||||
static void test_fn2(void)
|
static void test_fn2(void)
|
||||||
{
|
{
|
||||||
check_calloc(7000);
|
check_calloc(1000);
|
||||||
esp_restart();
|
esp_restart();
|
||||||
}
|
}
|
||||||
|
|
||||||
static void test_fn3(void)
|
static void test_fn3(void)
|
||||||
{
|
{
|
||||||
check_calloc(7000);
|
check_calloc(1000);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_CASE_MULTIPLE_STAGES_ESP32("Check for leaks in MULTIPLE_STAGES mode (manual reset)", "[heap][leaks][reset=SW_CPU_RESET, SW_CPU_RESET]", test_fn2, test_fn2, test_fn3);
|
TEST_CASE_MULTIPLE_STAGES("Check for leaks in MULTIPLE_STAGES mode (manual reset)", "[heap][leaks][reset=SW_CPU_RESET, SW_CPU_RESET]", test_fn2, test_fn2, test_fn3);
|
||||||
|
|
|
@ -11,7 +11,7 @@
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <sys/param.h>
|
#include <sys/param.h>
|
||||||
|
|
||||||
TEST_CASE_ESP32("Capabilities allocator test", "[heap]")
|
TEST_CASE("Capabilities allocator test", "[heap]")
|
||||||
{
|
{
|
||||||
char *m1, *m2[10];
|
char *m1, *m2[10];
|
||||||
int x;
|
int x;
|
||||||
|
@ -24,7 +24,7 @@ TEST_CASE_ESP32("Capabilities allocator test", "[heap]")
|
||||||
free8start = heap_caps_get_free_size(MALLOC_CAP_8BIT);
|
free8start = heap_caps_get_free_size(MALLOC_CAP_8BIT);
|
||||||
free32start = heap_caps_get_free_size(MALLOC_CAP_32BIT);
|
free32start = heap_caps_get_free_size(MALLOC_CAP_32BIT);
|
||||||
printf("Free 8bit-capable memory (start): %dK, 32-bit capable memory %dK\n", free8start, free32start);
|
printf("Free 8bit-capable memory (start): %dK, 32-bit capable memory %dK\n", free8start, free32start);
|
||||||
TEST_ASSERT(free32start>free8start);
|
TEST_ASSERT(free32start >= free8start);
|
||||||
|
|
||||||
printf("Allocating 10K of 8-bit capable RAM\n");
|
printf("Allocating 10K of 8-bit capable RAM\n");
|
||||||
m1= heap_caps_malloc(10*1024, MALLOC_CAP_8BIT);
|
m1= heap_caps_malloc(10*1024, MALLOC_CAP_8BIT);
|
||||||
|
@ -44,39 +44,60 @@ TEST_CASE_ESP32("Capabilities allocator test", "[heap]")
|
||||||
size_t free_iram = heap_caps_get_free_size(MALLOC_CAP_INTERNAL) -
|
size_t free_iram = heap_caps_get_free_size(MALLOC_CAP_INTERNAL) -
|
||||||
heap_caps_get_free_size(MALLOC_CAP_8BIT | MALLOC_CAP_INTERNAL);
|
heap_caps_get_free_size(MALLOC_CAP_8BIT | MALLOC_CAP_INTERNAL);
|
||||||
size_t alloc32 = MIN(free_iram / 2, 10*1024) & (~3);
|
size_t alloc32 = MIN(free_iram / 2, 10*1024) & (~3);
|
||||||
printf("Freeing; allocating %u bytes of 32K-capable RAM\n", alloc32);
|
if(free_iram) {
|
||||||
m1 = heap_caps_malloc(alloc32, MALLOC_CAP_32BIT);
|
printf("Freeing; allocating %u bytes of 32K-capable RAM\n", alloc32);
|
||||||
printf("--> %p\n", m1);
|
m1 = heap_caps_malloc(alloc32, MALLOC_CAP_32BIT);
|
||||||
//Check that we got IRAM back
|
printf("--> %p\n", m1);
|
||||||
TEST_ASSERT((((int)m1)&0xFF000000)==0x40000000);
|
//Check that we got IRAM back
|
||||||
free8 = heap_caps_get_free_size(MALLOC_CAP_8BIT);
|
TEST_ASSERT((((int)m1)&0xFF000000)==0x40000000);
|
||||||
free32 = heap_caps_get_free_size(MALLOC_CAP_32BIT);
|
free8 = heap_caps_get_free_size(MALLOC_CAP_8BIT);
|
||||||
printf("Free 8bit-capable memory (after 32-bit): %dK, 32-bit capable memory %dK\n", free8, free32);
|
free32 = heap_caps_get_free_size(MALLOC_CAP_32BIT);
|
||||||
//Only 32-bit should have gone down by alloc32: 32-bit isn't necessarily 8bit capable
|
printf("Free 8bit-capable memory (after 32-bit): %dK, 32-bit capable memory %dK\n", free8, free32);
|
||||||
TEST_ASSERT(free32<(free32start-alloc32));
|
//Only 32-bit should have gone down by alloc32: 32-bit isn't necessarily 8bit capable
|
||||||
TEST_ASSERT(free8==free8start);
|
TEST_ASSERT(free32<(free32start-alloc32));
|
||||||
free(m1);
|
TEST_ASSERT(free8==free8start);
|
||||||
|
free(m1);
|
||||||
|
} else {
|
||||||
|
printf("This platform has no 32-bit only capable RAM, jumping to next test \n");
|
||||||
|
}
|
||||||
|
|
||||||
printf("Allocating impossible caps\n");
|
printf("Allocating impossible caps\n");
|
||||||
m1= heap_caps_malloc(10*1024, MALLOC_CAP_8BIT|MALLOC_CAP_EXEC);
|
m1= heap_caps_malloc(10*1024, MALLOC_CAP_8BIT|MALLOC_CAP_EXEC);
|
||||||
printf("--> %p\n", m1);
|
printf("--> %p\n", m1);
|
||||||
TEST_ASSERT(m1==NULL);
|
TEST_ASSERT(m1==NULL);
|
||||||
printf("Testing changeover iram -> dram");
|
|
||||||
// priorities will exhaust IRAM first, then start allocating from DRAM
|
if(free_iram) {
|
||||||
for (x=0; x<10; x++) {
|
printf("Testing changeover iram -> dram");
|
||||||
m2[x]= heap_caps_malloc(alloc32, MALLOC_CAP_32BIT);
|
// priorities will exhaust IRAM first, then start allocating from DRAM
|
||||||
printf("--> %p\n", m2[x]);
|
for (x=0; x<10; x++) {
|
||||||
|
m2[x]= heap_caps_malloc(alloc32, MALLOC_CAP_32BIT);
|
||||||
|
printf("--> %p\n", m2[x]);
|
||||||
|
}
|
||||||
|
TEST_ASSERT((((int)m2[0])&0xFF000000)==0x40000000);
|
||||||
|
TEST_ASSERT((((int)m2[9])&0xFF000000)==0x3F000000);
|
||||||
|
|
||||||
|
} else {
|
||||||
|
printf("This platform has no IRAM-only so changeover will never occur, jumping to next test\n");
|
||||||
}
|
}
|
||||||
TEST_ASSERT((((int)m2[0])&0xFF000000)==0x40000000);
|
|
||||||
TEST_ASSERT((((int)m2[9])&0xFF000000)==0x3F000000);
|
|
||||||
printf("Test if allocating executable code still gives IRAM, even with dedicated IRAM region depleted\n");
|
printf("Test if allocating executable code still gives IRAM, even with dedicated IRAM region depleted\n");
|
||||||
// (the allocation should come from D/IRAM)
|
if(free_iram) {
|
||||||
free_iram = heap_caps_get_free_size(MALLOC_CAP_EXEC);
|
// (the allocation should come from D/IRAM)
|
||||||
m1= heap_caps_malloc(MIN(free_iram / 2, 10*1024), MALLOC_CAP_EXEC);
|
free_iram = heap_caps_get_free_size(MALLOC_CAP_EXEC);
|
||||||
printf("--> %p\n", m1);
|
m1= heap_caps_malloc(MIN(free_iram / 2, 10*1024), MALLOC_CAP_EXEC);
|
||||||
TEST_ASSERT((((int)m1)&0xFF000000)==0x40000000);
|
printf("--> %p\n", m1);
|
||||||
|
TEST_ASSERT((((int)m1)&0xFF000000)==0x40000000);
|
||||||
|
for (x=0; x<10; x++) free(m2[x]);
|
||||||
|
|
||||||
|
} else {
|
||||||
|
// (the allocation should come from D/IRAM)
|
||||||
|
free_iram = heap_caps_get_free_size(MALLOC_CAP_EXEC);
|
||||||
|
m1= heap_caps_malloc(MIN(free_iram / 2, 10*1024), MALLOC_CAP_EXEC);
|
||||||
|
printf("--> %p\n", m1);
|
||||||
|
TEST_ASSERT((((int)m1)&0xFF000000)==0x40000000);
|
||||||
|
}
|
||||||
|
|
||||||
free(m1);
|
free(m1);
|
||||||
for (x=0; x<10; x++) free(m2[x]);
|
|
||||||
printf("Done.\n");
|
printf("Done.\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -7,6 +7,7 @@
|
||||||
#include "unity.h"
|
#include "unity.h"
|
||||||
#include "sdkconfig.h"
|
#include "sdkconfig.h"
|
||||||
#include "esp_heap_caps.h"
|
#include "esp_heap_caps.h"
|
||||||
|
#include "soc/soc_memory_layout.h"
|
||||||
|
|
||||||
|
|
||||||
#ifndef CONFIG_HEAP_POISONING_COMPREHENSIVE
|
#ifndef CONFIG_HEAP_POISONING_COMPREHENSIVE
|
||||||
|
@ -22,7 +23,22 @@ TEST_CASE("realloc shrink buffer in place", "[heap]")
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
TEST_CASE_ESP32("realloc move data to a new heap type", "[heap]")
|
TEST_CASE("realloc shrink buffer with EXEC CAPS", "[heap]")
|
||||||
|
{
|
||||||
|
const size_t buffer_size = 64;
|
||||||
|
|
||||||
|
void *x = heap_caps_malloc(buffer_size, MALLOC_CAP_EXEC);
|
||||||
|
TEST_ASSERT(x);
|
||||||
|
void *y = heap_caps_realloc(x, buffer_size - 16, MALLOC_CAP_EXEC);
|
||||||
|
TEST_ASSERT(y);
|
||||||
|
|
||||||
|
//y needs to fall in a compatible memory area of IRAM:
|
||||||
|
TEST_ASSERT(esp_ptr_executable(y));
|
||||||
|
|
||||||
|
free(y);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_CASE("realloc move data to a new heap type", "[heap]")
|
||||||
{
|
{
|
||||||
const char *test = "I am some test content to put in the heap";
|
const char *test = "I am some test content to put in the heap";
|
||||||
char buf[64];
|
char buf[64];
|
||||||
|
@ -31,7 +47,6 @@ TEST_CASE_ESP32("realloc move data to a new heap type", "[heap]")
|
||||||
|
|
||||||
char *a = malloc(64);
|
char *a = malloc(64);
|
||||||
memcpy(a, buf, 64);
|
memcpy(a, buf, 64);
|
||||||
|
|
||||||
// move data from 'a' to IRAM
|
// move data from 'a' to IRAM
|
||||||
char *b = heap_caps_realloc(a, 64, MALLOC_CAP_EXEC);
|
char *b = heap_caps_realloc(a, 64, MALLOC_CAP_EXEC);
|
||||||
TEST_ASSERT_NOT_NULL(b);
|
TEST_ASSERT_NOT_NULL(b);
|
||||||
|
@ -40,7 +55,7 @@ TEST_CASE_ESP32("realloc move data to a new heap type", "[heap]")
|
||||||
TEST_ASSERT_EQUAL_HEX32_ARRAY(buf, b, 64/sizeof(uint32_t));
|
TEST_ASSERT_EQUAL_HEX32_ARRAY(buf, b, 64/sizeof(uint32_t));
|
||||||
|
|
||||||
// Move data back to DRAM
|
// Move data back to DRAM
|
||||||
char *c = heap_caps_realloc(b, 48, MALLOC_CAP_8BIT);
|
char *c = heap_caps_realloc(b, 48, MALLOC_CAP_8BIT);
|
||||||
TEST_ASSERT_NOT_NULL(c);
|
TEST_ASSERT_NOT_NULL(c);
|
||||||
TEST_ASSERT_NOT_EQUAL(b, c);
|
TEST_ASSERT_NOT_EQUAL(b, c);
|
||||||
TEST_ASSERT(heap_caps_check_integrity(MALLOC_CAP_INVALID, true));
|
TEST_ASSERT(heap_caps_check_integrity(MALLOC_CAP_INVALID, true));
|
||||||
|
|
|
@ -1 +1 @@
|
||||||
Subproject commit c9e3b53c6f04052943f97210b858cec805cc98d9
|
Subproject commit 31e24ae95a59e51d74f435f48fa21091b26c1430
|
|
@ -87,6 +87,10 @@ void setUp(void)
|
||||||
|
|
||||||
static void check_leak(size_t before_free, size_t after_free, const char *type)
|
static void check_leak(size_t before_free, size_t after_free, const char *type)
|
||||||
{
|
{
|
||||||
|
printf("MALLOC_CAP_%s leak: Leak threshold is: %u \n",
|
||||||
|
type,
|
||||||
|
critical_leak_threshold);
|
||||||
|
|
||||||
if (before_free <= after_free) {
|
if (before_free <= after_free) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
Ładowanie…
Reference in New Issue