heap_caps: added special case for realloc when previous area is an diram_iram ptr, this will force a malloc/copy/free
This commit is contained in:
parent
ce9f84fba9
commit
31145f38fa
2 changed files with 31 additions and 27 deletions
|
@ -275,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);
|
||||||
}
|
}
|
||||||
|
@ -288,23 +292,32 @@ IRAM_ATTR void *heap_caps_realloc( void *ptr, size_t size, int caps)
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
//On esp32s2 the pointer to heap may be aliased, we need to
|
//The pointer to memory may be aliased, we need to
|
||||||
//recover it before to manage a new allocation:
|
//recover it before to manage a new allocation:
|
||||||
if(esp_ptr_in_diram_iram((void *)ptr)) {
|
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;
|
uint32_t *dram_addr = (uint32_t *)ptr;
|
||||||
ptr = (void *)dram_addr[-1];
|
dram_ptr = (void *)dram_addr[-1];
|
||||||
//printf("[HEAP_CAPS_MALLOC]: obtained pointer that was aliased: %p \n", (void *)ptr);
|
|
||||||
}
|
|
||||||
|
|
||||||
heap_t *heap = find_containing_heap(ptr);
|
//printf("[HEAP_CAPS_MALLOC]: obtained pointer that was aliased: %p \n", (void *)ptr);
|
||||||
|
|
||||||
|
heap = find_containing_heap(dram_ptr);
|
||||||
assert(heap != NULL && "realloc() pointer is outside heap areas");
|
assert(heap != NULL && "realloc() pointer is outside heap areas");
|
||||||
|
|
||||||
|
//with pointers that reside on diram space, we avoid to
|
||||||
|
//to use 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);
|
||||||
|
@ -317,8 +330,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 = 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);
|
||||||
|
}
|
||||||
|
|
||||||
size_t 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);
|
||||||
|
|
|
@ -21,10 +21,6 @@
|
||||||
#include <sys/param.h>
|
#include <sys/param.h>
|
||||||
#include <multi_heap.h>
|
#include <multi_heap.h>
|
||||||
#include "multi_heap_internal.h"
|
#include "multi_heap_internal.h"
|
||||||
#if CONFIG_IDF_TARGET_ESP32S2BETA
|
|
||||||
#include "heap_private.h"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
/* Note: Keep platform-specific parts in this header, this source
|
/* Note: Keep platform-specific parts in this header, this source
|
||||||
file should depend on libc only */
|
file should depend on libc only */
|
||||||
|
@ -272,20 +268,7 @@ 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);
|
||||||
|
|
||||||
#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));
|
memcpy(result, p, MIN(size, orig_alloc_size));
|
||||||
#endif
|
|
||||||
multi_heap_free(heap, p);
|
multi_heap_free(heap, p);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
Loading…
Reference in a new issue