mirror of
https://github.com/espressif/esp-idf.git
synced 2025-11-26 20:53:11 +00:00
fix(heap): memalign respect malloc_alwaysinternal_limit
This changes `memalign` (and `posix_memalign`) so that it uses an allocation method with the same selection criteria (checking `malloc_alwaysinternal_limit` and picking one of: - always MALLOC_CAP_INTERNAL - MALLOC_CAP_INTERNAL first with fallback - MALLOC_CAP_SPIRAM first with fallback `malloc_alwaysinternal_limit` is in turn set by the options `CONFIG_SPIRAM_MALLOC_ALWAYSINTERNAL` and `CONFIG_SPRIAM_USE_CAPS_ALLOC`. This notably affects folks using esp-rs to build rust code for the esp-idf, as all allocations from rust use `memalign`. Merges https://github.com/espressif/esp-idf/pull/12375
This commit is contained in:
committed by
KonstantinKondrashov
parent
283a3d64b9
commit
9e1e245477
@@ -660,31 +660,8 @@ size_t heap_caps_get_allocated_size( void *ptr )
|
||||
return MULTI_HEAP_REMOVE_BLOCK_OWNER_SIZE(size);
|
||||
}
|
||||
|
||||
HEAP_IRAM_ATTR void *heap_caps_aligned_alloc(size_t alignment, size_t size, uint32_t caps)
|
||||
static HEAP_IRAM_ATTR void *heap_caps_aligned_alloc_base(size_t alignment, size_t size, uint32_t caps)
|
||||
{
|
||||
void *ret = NULL;
|
||||
|
||||
if(!alignment) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
//Alignment must be a power of two:
|
||||
if((alignment & (alignment - 1)) != 0) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (size == 0) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (MULTI_HEAP_ADD_BLOCK_OWNER_SIZE(size) > HEAP_SIZE_MAX) {
|
||||
// Avoids int overflow when adding small numbers to size, or
|
||||
// calculating 'end' from start+size, by limiting 'size' to the possible range
|
||||
heap_caps_alloc_failed(size, caps, __func__);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
for (int prio = 0; prio < SOC_MEMORY_TYPE_NO_PRIOS; prio++) {
|
||||
//Iterate over heaps and check capabilities at this priority
|
||||
heap_t *heap;
|
||||
@@ -697,7 +674,7 @@ HEAP_IRAM_ATTR void *heap_caps_aligned_alloc(size_t alignment, size_t size, uint
|
||||
//doesn't cover, see if they're available in other prios.
|
||||
if ((get_all_caps(heap) & caps) == caps) {
|
||||
//Just try to alloc, nothing special.
|
||||
ret = multi_heap_aligned_alloc(heap->heap, MULTI_HEAP_ADD_BLOCK_OWNER_SIZE(size), alignment);
|
||||
void *ret = multi_heap_aligned_alloc(heap->heap, MULTI_HEAP_ADD_BLOCK_OWNER_SIZE(size), alignment);
|
||||
if (ret != NULL) {
|
||||
MULTI_HEAP_SET_BLOCK_OWNER(ret);
|
||||
ret = MULTI_HEAP_ADD_BLOCK_OWNER_OFFSET(ret);
|
||||
@@ -709,12 +686,83 @@ HEAP_IRAM_ATTR void *heap_caps_aligned_alloc(size_t alignment, size_t size, uint
|
||||
}
|
||||
}
|
||||
|
||||
heap_caps_alloc_failed(size, caps, __func__);
|
||||
|
||||
//Nothing usable found.
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static HEAP_IRAM_ATTR esp_err_t heap_caps_aligned_check_args(size_t alignment, size_t size, uint32_t caps, const char *funcname)
|
||||
{
|
||||
if (!alignment) {
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
// Alignment must be a power of two:
|
||||
if ((alignment & (alignment - 1)) != 0) {
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
if (size == 0) {
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
if (MULTI_HEAP_ADD_BLOCK_OWNER_SIZE(size) > HEAP_SIZE_MAX) {
|
||||
// Avoids int overflow when adding small numbers to size, or
|
||||
// calculating 'end' from start+size, by limiting 'size' to the possible range
|
||||
heap_caps_alloc_failed(size, caps, funcname);
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
HEAP_IRAM_ATTR void *heap_caps_aligned_alloc_default(size_t alignment, size_t size)
|
||||
{
|
||||
void *ret = NULL;
|
||||
|
||||
if (malloc_alwaysinternal_limit == MALLOC_DISABLE_EXTERNAL_ALLOCS) {
|
||||
return heap_caps_aligned_alloc(alignment, size, MALLOC_CAP_DEFAULT | MALLOC_CAP_INTERNAL);
|
||||
}
|
||||
|
||||
if (heap_caps_aligned_check_args(alignment, size, MALLOC_CAP_DEFAULT, __func__) != ESP_OK) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (size <= (size_t)malloc_alwaysinternal_limit) {
|
||||
ret = heap_caps_aligned_alloc_base(alignment, size, MALLOC_CAP_DEFAULT | MALLOC_CAP_INTERNAL);
|
||||
} else {
|
||||
ret = heap_caps_aligned_alloc_base(alignment, size, MALLOC_CAP_DEFAULT | MALLOC_CAP_SPIRAM);
|
||||
}
|
||||
|
||||
if (ret != NULL) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = heap_caps_aligned_alloc_base(alignment, size, MALLOC_CAP_DEFAULT);
|
||||
|
||||
if (ret == NULL) {
|
||||
heap_caps_alloc_failed(size, MALLOC_CAP_DEFAULT, __func__);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
HEAP_IRAM_ATTR void *heap_caps_aligned_alloc(size_t alignment, size_t size, uint32_t caps)
|
||||
{
|
||||
void *ret = NULL;
|
||||
|
||||
if (heap_caps_aligned_check_args(alignment, size, caps, __func__) != ESP_OK) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ret = heap_caps_aligned_alloc_base(alignment, size, caps);
|
||||
|
||||
if (ret == NULL) {
|
||||
heap_caps_alloc_failed(size, caps, __func__);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
HEAP_IRAM_ATTR void heap_caps_aligned_free(void *ptr)
|
||||
{
|
||||
heap_caps_free(ptr);
|
||||
|
||||
Reference in New Issue
Block a user