1 #include "freertos/FreeRTOS.h"
2 #include <esp_types.h>
3 #include <stdio.h>
4 #include "unity.h"
5 #include "esp_attr.h"
6 #include "esp_heap_caps.h"
7 #include <stdlib.h>
8 #include <sys/param.h>
9 #include <string.h>
10 #include <test_utils.h>
11 
12 //This test only makes sense with poisoning disabled (light or comprehensive)
13 #if !defined(CONFIG_HEAP_POISONING_COMPREHENSIVE) && !defined(CONFIG_HEAP_POISONING_LIGHT)
14 
15 #define NUM_POINTERS 128
16 #define ITERATIONS 10000
17 
18 TEST_CASE("Heap many random allocations timings", "[heap]")
19 {
20     void *p[NUM_POINTERS] = { 0 };
21     size_t s[NUM_POINTERS] = { 0 };
22 
23     uint32_t cycles_before;
24     uint64_t alloc_time_average = 0;
25     uint64_t free_time_average = 0;
26     uint64_t realloc_time_average = 0;
27 
28     for (int i = 0; i < ITERATIONS; i++) {
29         uint8_t n = esp_random() % NUM_POINTERS;
30 
31         if (esp_random() % 4 == 0) {
32             /* 1 in 4 iterations, try to realloc the buffer instead
33                of using malloc/free
34             */
35             size_t new_size = esp_random() % 1024;
36 
37             cycles_before = portGET_RUN_TIME_COUNTER_VALUE();
38             void *new_p = heap_caps_realloc(p[n], new_size, MALLOC_CAP_DEFAULT);
39             realloc_time_average = portGET_RUN_TIME_COUNTER_VALUE() - cycles_before;
40 
41             printf("realloc %p -> %p (%zu -> %zu) time spent cycles: %lld \n", p[n], new_p, s[n], new_size, realloc_time_average);
42             heap_caps_check_integrity(MALLOC_CAP_DEFAULT, true);
43             if (new_size == 0 || new_p != NULL) {
44                 p[n] = new_p;
45                 s[n] = new_size;
46                 if (new_size > 0) {
47                     memset(p[n], n, new_size);
48                 }
49             }
50             continue;
51         }
52 
53         if (p[n] != NULL) {
54             if (s[n] > 0) {
55                 /* Verify pre-existing contents of p[n] */
56                 uint8_t compare[s[n]];
57                 memset(compare, n, s[n]);
58                 TEST_ASSERT(( memcmp(compare, p[n], s[n]) == 0 ));
59             }
60             TEST_ASSERT(heap_caps_check_integrity(MALLOC_CAP_DEFAULT, true));
61 
62             cycles_before = portGET_RUN_TIME_COUNTER_VALUE();
63             heap_caps_free(p[n]);
64             free_time_average = portGET_RUN_TIME_COUNTER_VALUE() - cycles_before;
65 
66             printf("freed %p (%zu) time spent cycles: %lld\n", p[n], s[n], free_time_average);
67 
68             if (!heap_caps_check_integrity(MALLOC_CAP_DEFAULT, true)) {
69                 printf("FAILED iteration %d after freeing %p\n", i, p[n]);
70                 heap_caps_dump(MALLOC_CAP_DEFAULT);
71                 TEST_ASSERT(0);
72             }
73         }
74 
75         s[n] = rand() % 1024;
76         heap_caps_check_integrity(MALLOC_CAP_DEFAULT, true);
77         cycles_before = portGET_RUN_TIME_COUNTER_VALUE();
78         p[n] = heap_caps_malloc(s[n], MALLOC_CAP_DEFAULT);
79         alloc_time_average = portGET_RUN_TIME_COUNTER_VALUE() - cycles_before;
80 
81         printf("malloc %p (%zu) time spent cycles: %lld \n", p[n], s[n], alloc_time_average);
82 
83         if (!heap_caps_check_integrity(MALLOC_CAP_DEFAULT, true)) {
84             printf("FAILED iteration %d after mallocing %p (%zu bytes)\n", i, p[n], s[n]);
85             heap_caps_dump(MALLOC_CAP_DEFAULT);
86             TEST_ASSERT(0);
87         }
88 
89         if (p[n] != NULL) {
90             memset(p[n], n, s[n]);
91         }
92     }
93 
94     for (int i = 0; i < NUM_POINTERS; i++) {
95         cycles_before = portGET_RUN_TIME_COUNTER_VALUE();
96         heap_caps_free( p[i]);
97         free_time_average = portGET_RUN_TIME_COUNTER_VALUE() - cycles_before;
98 
99         if (!heap_caps_check_integrity(MALLOC_CAP_DEFAULT, true)) {
100             printf("FAILED during cleanup after freeing %p\n", p[i]);
101             heap_caps_dump(MALLOC_CAP_DEFAULT);
102             TEST_ASSERT(0);
103         }
104     }
105 
106     TEST_ASSERT(heap_caps_check_integrity(MALLOC_CAP_DEFAULT, true));
107 }
108 #endif
109