heap/heap_caps: added special case for esp32s2 when handling memory allocated (and aliased) from IRAM

This commit is contained in:
Felipe Neves 2019-11-12 14:01:27 +08:00
parent ecc4955c68
commit 4a392932f1
3 changed files with 28 additions and 3 deletions

View file

@ -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
//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
if (ret != NULL) {
return dram_alloc_to_iram_addr(ret, size + 4); // int overflow checked above
}
@ -287,8 +288,18 @@ IRAM_ATTR void *heap_caps_realloc( void *ptr, size_t size, int caps)
return NULL;
}
heap_t *heap = find_containing_heap(ptr);
#if CONFIG_IDF_TARGET_ESP32S2BETA
//On esp32s2 the pointer to heap may be aliased, we need to
//recover it before to manage a new allocation:
if(esp_ptr_in_diram_iram((void *)ptr)) {
//pointer must be already aliased, otherwise just ignore this part:
uint32_t *dram_addr = (uint32_t *)ptr;
ptr = (void *)dram_addr[-1];
//printf("[HEAP_CAPS_MALLOC]: obtained pointer that was aliased: %p \n", (void *)ptr);
}
#endif
heap_t *heap = find_containing_heap(ptr);
assert(heap != NULL && "realloc() pointer is outside heap areas");
// are the existing heap's capabilities compatible with the
@ -308,6 +319,7 @@ IRAM_ATTR void *heap_caps_realloc( void *ptr, size_t size, int caps)
// in a different heap with requested capabilities.
void *new_p = heap_caps_malloc(size, caps);
if (new_p != NULL) {
size_t old_size = multi_heap_get_allocated_size(heap->heap, ptr);
assert(old_size > 0);
memcpy(new_p, ptr, MIN(size, old_size));

View file

@ -21,6 +21,7 @@
#include <sys/param.h>
#include <multi_heap.h>
#include "multi_heap_internal.h"
#include "heap_private.h"
/* Note: Keep platform-specific parts in this header, this source
file should depend on libc only */
@ -268,7 +269,20 @@ void *multi_heap_realloc(multi_heap_handle_t heap, void *p, size_t size)
new_head = multi_heap_malloc_impl(heap, size + POISON_OVERHEAD);
if (new_head != NULL) {
result = poison_allocated_region(new_head, size);
#if CONFIG_IDF_TARGET_ESP32S2BETA
//We may need to deal with aliased heap pointers. here too,
//mainly because the heap canary is located before the
//the slot reserved to preserve original DRAM address
//so the original user data is actually p + 4 ahead :
if(esp_ptr_in_diram_dram((void *)p)) {
memcpy(result, p + sizeof(intptr_t), MIN(size, orig_alloc_size));
} else {
memcpy(result, p , MIN(size, orig_alloc_size));
}
#else
memcpy(result, p, MIN(size, orig_alloc_size));
#endif
multi_heap_free(heap, p);
}
#endif

View file

@ -31,7 +31,6 @@ TEST_CASE("realloc move data to a new heap type", "[heap]")
char *a = malloc(64);
memcpy(a, buf, 64);
// move data from 'a' to IRAM
char *b = heap_caps_realloc(a, 64, MALLOC_CAP_EXEC);
TEST_ASSERT_NOT_NULL(b);
@ -40,7 +39,7 @@ TEST_CASE("realloc move data to a new heap type", "[heap]")
TEST_ASSERT_EQUAL_HEX32_ARRAY(buf, b, 64/sizeof(uint32_t));
// 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_EQUAL(b, c);
TEST_ASSERT(heap_caps_check_integrity(MALLOC_CAP_INVALID, true));