heap: added aligned calloc function plus tests

This commit is contained in:
Felipe Neves 2019-12-20 12:48:35 -03:00
parent 8e5ea171d3
commit 0d8a5ebec7
3 changed files with 98 additions and 0 deletions

View file

@ -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) {

View file

@ -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
* *

View file

@ -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
}