heap: added aligned calloc function plus tests
This commit is contained in:
parent
8e5ea171d3
commit
0d8a5ebec7
3 changed files with 98 additions and 0 deletions
|
@ -555,6 +555,21 @@ IRAM_ATTR void *heap_caps_aligned_alloc(size_t alignment, size_t size, int caps)
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void *heap_caps_aligned_calloc(size_t alignment, size_t n, size_t size, uint32_t caps)
|
||||||
|
{
|
||||||
|
size_t size_bytes;
|
||||||
|
if (__builtin_mul_overflow(n, size, &size_bytes)) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
void *ptr = heap_caps_aligned_alloc(alignment,size_bytes, caps);
|
||||||
|
if(ptr != NULL) {
|
||||||
|
memset(ptr, 0, size_bytes);
|
||||||
|
}
|
||||||
|
|
||||||
|
return ptr;
|
||||||
|
}
|
||||||
|
|
||||||
IRAM_ATTR void heap_caps_aligned_free(void *ptr)
|
IRAM_ATTR void heap_caps_aligned_free(void *ptr)
|
||||||
{
|
{
|
||||||
if (ptr == NULL) {
|
if (ptr == NULL) {
|
||||||
|
|
|
@ -99,6 +99,20 @@ void *heap_caps_realloc( void *ptr, size_t size, int caps);
|
||||||
*/
|
*/
|
||||||
void *heap_caps_aligned_alloc(size_t alignment, size_t size, int caps);
|
void *heap_caps_aligned_alloc(size_t alignment, size_t size, int caps);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Allocate a aligned chunk of memory which has the given capabilities. The initialized value in the memory is set to zero.
|
||||||
|
*
|
||||||
|
* @param alignment How the pointer received needs to be aligned
|
||||||
|
* must be a power of two
|
||||||
|
* @param n Number of continuing chunks of memory to allocate
|
||||||
|
* @param size Size, in bytes, of a chunk of memory to allocate
|
||||||
|
* @param caps Bitwise OR of MALLOC_CAP_* flags indicating the type
|
||||||
|
* of memory to be returned
|
||||||
|
*
|
||||||
|
* @return A pointer to the memory allocated on success, NULL on failure
|
||||||
|
*/
|
||||||
|
void *heap_caps_aligned_calloc(size_t alignment, size_t n, size_t size, uint32_t caps);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Used to deallocate memory previously allocated with heap_caps_aligned_alloc
|
* @brief Used to deallocate memory previously allocated with heap_caps_aligned_alloc
|
||||||
*
|
*
|
||||||
|
|
|
@ -68,3 +68,72 @@ TEST_CASE("Capabilities aligned allocator test", "[heap]")
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST_CASE("Capabilities aligned calloc test", "[heap]")
|
||||||
|
{
|
||||||
|
uint32_t alignments = 0;
|
||||||
|
|
||||||
|
printf("[ALIGNED_ALLOC] Allocating from default CAP: \n");
|
||||||
|
|
||||||
|
for(;alignments <= 1024; alignments++) {
|
||||||
|
uint8_t *buf = (uint8_t *)heap_caps_aligned_calloc(alignments, 1, (alignments + 137), MALLOC_CAP_DEFAULT);
|
||||||
|
if(((alignments & (alignments - 1)) != 0) || (!alignments)) {
|
||||||
|
TEST_ASSERT( buf == NULL );
|
||||||
|
//printf("[ALIGNED_ALLOC] alignment: %u is not a power of two, don't allow allocation \n", aligments);
|
||||||
|
} else {
|
||||||
|
TEST_ASSERT( buf != NULL );
|
||||||
|
printf("[ALIGNED_ALLOC] alignment required: %u \n", alignments);
|
||||||
|
printf("[ALIGNED_ALLOC] address of allocated memory: %p \n\n", (void *)buf);
|
||||||
|
//Address of obtained block must be aligned with selected value
|
||||||
|
TEST_ASSERT(((intptr_t)buf & (alignments - 1)) == 0);
|
||||||
|
|
||||||
|
//Write some data, if it corrupts memory probably the heap
|
||||||
|
//canary verification will fail:
|
||||||
|
memset(buf, 0xA5, (alignments + 137));
|
||||||
|
|
||||||
|
heap_caps_aligned_free(buf);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//Check if memory is initialized with zero:
|
||||||
|
uint8_t byte_array[1024];
|
||||||
|
memset(&byte_array, 0, sizeof(byte_array));
|
||||||
|
uint8_t *buf = (uint8_t *)heap_caps_aligned_calloc(1024, 1, 1024, MALLOC_CAP_DEFAULT);
|
||||||
|
TEST_ASSERT(memcmp(byte_array, buf, sizeof(byte_array)) == 0);
|
||||||
|
heap_caps_aligned_free(buf);
|
||||||
|
|
||||||
|
//Same size, but different chunk:
|
||||||
|
buf = (uint8_t *)heap_caps_aligned_calloc(1024, 1024, 1, MALLOC_CAP_DEFAULT);
|
||||||
|
TEST_ASSERT(memcmp(byte_array, buf, sizeof(byte_array)) == 0);
|
||||||
|
heap_caps_aligned_free(buf);
|
||||||
|
|
||||||
|
//Alloc from a non permitted area:
|
||||||
|
uint32_t *not_permitted_buf = (uint32_t *)heap_caps_aligned_calloc(alignments, 1, (alignments + 137), MALLOC_CAP_32BIT);
|
||||||
|
TEST_ASSERT( not_permitted_buf == NULL );
|
||||||
|
|
||||||
|
#if CONFIG_ESP32_SPIRAM_SUPPORT || CONFIG_ESP32S2_SPIRAM_SUPPORT
|
||||||
|
alignments = 0;
|
||||||
|
printf("[ALIGNED_ALLOC] Allocating from external memory: \n");
|
||||||
|
|
||||||
|
for(;alignments <= 1024 * 1024; alignments++) {
|
||||||
|
//Now try to take aligned memory from IRAM:
|
||||||
|
uint8_t *buf = (uint8_t *)(uint8_t *)heap_caps_aligned_calloc(alignments, 1, 10*1024, MALLOC_CAP_SPIRAM);;
|
||||||
|
if(((alignments & (alignments - 1)) != 0) || (!alignments)) {
|
||||||
|
TEST_ASSERT( buf == NULL );
|
||||||
|
//printf("[ALIGNED_ALLOC] alignment: %u is not a power of two, don't allow allocation \n", aligments);
|
||||||
|
} else {
|
||||||
|
TEST_ASSERT( buf != NULL );
|
||||||
|
printf("[ALIGNED_ALLOC] alignment required: %u \n", alignments);
|
||||||
|
printf("[ALIGNED_ALLOC] address of allocated memory: %p \n\n", (void *)buf);
|
||||||
|
//Address of obtained block must be aligned with selected value
|
||||||
|
TEST_ASSERT(((intptr_t)buf & (alignments - 1)) == 0);
|
||||||
|
|
||||||
|
//Write some data, if it corrupts memory probably the heap
|
||||||
|
//canary verification will fail:
|
||||||
|
memset(buf, 0xA5, (10*1024));
|
||||||
|
heap_caps_aligned_free(buf);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
}
|
Loading…
Reference in a new issue