浏览代码

heap: added aligned calloc function plus tests

Felipe Neves 6 年之前
父节点
当前提交
0d8a5ebec7
共有 3 个文件被更改,包括 98 次插入0 次删除
  1. 15 0
      components/heap/heap_caps.c
  2. 14 0
      components/heap/include/esp_heap_caps.h
  3. 69 0
      components/heap/test/test_aligned_alloc_caps.c

+ 15 - 0
components/heap/heap_caps.c

@@ -555,6 +555,21 @@ IRAM_ATTR void *heap_caps_aligned_alloc(size_t alignment, size_t size, int caps)
     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)
 {
     if (ptr == NULL) {

+ 14 - 0
components/heap/include/esp_heap_caps.h

@@ -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);
 
+/**
+ * @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
  * 

+ 69 - 0
components/heap/test/test_aligned_alloc_caps.c

@@ -67,4 +67,73 @@ TEST_CASE("Capabilities aligned allocator test", "[heap]")
     } 
 #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
+
 }