1a9de470cSBruce Richardson /* SPDX-License-Identifier: BSD-3-Clause 2a7cece2eSTomasz Jozwiak * Copyright(c) 2010-2019 Intel Corporation 3a9de470cSBruce Richardson */ 4a9de470cSBruce Richardson 53c60274cSJie Zhou #include "test.h" 63c60274cSJie Zhou 7a9de470cSBruce Richardson #include <stdio.h> 8a9de470cSBruce Richardson #include <stdint.h> 9a9de470cSBruce Richardson #include <string.h> 10a9de470cSBruce Richardson #include <stdarg.h> 11a9de470cSBruce Richardson #include <errno.h> 12a9de470cSBruce Richardson #include <stdlib.h> 133c60274cSJie Zhou #ifndef RTE_EXEC_ENV_WINDOWS 14dd467777SAnatoly Burakov #include <sys/mman.h> 153c60274cSJie Zhou #endif 16a9de470cSBruce Richardson #include <sys/queue.h> 17dd467777SAnatoly Burakov #include <unistd.h> 18a9de470cSBruce Richardson 19a9de470cSBruce Richardson #include <rte_common.h> 20a9de470cSBruce Richardson #include <rte_memory.h> 21a9de470cSBruce Richardson #include <rte_per_lcore.h> 22a9de470cSBruce Richardson #include <rte_launch.h> 23a9de470cSBruce Richardson #include <rte_eal.h> 24a9de470cSBruce Richardson #include <rte_lcore.h> 25a9de470cSBruce Richardson #include <rte_malloc.h> 26a9de470cSBruce Richardson #include <rte_cycles.h> 27a9de470cSBruce Richardson #include <rte_random.h> 28a9de470cSBruce Richardson #include <rte_string_fns.h> 29a9de470cSBruce Richardson 30a9de470cSBruce Richardson #define N 10000 31a9de470cSBruce Richardson 32a7cece2eSTomasz Jozwiak static int 33a7cece2eSTomasz Jozwiak is_mem_on_socket(int32_t socket); 34a7cece2eSTomasz Jozwiak 35a7cece2eSTomasz Jozwiak static int32_t 36a7cece2eSTomasz Jozwiak addr_to_socket(void *addr); 37a7cece2eSTomasz Jozwiak 38a9de470cSBruce Richardson /* 39a9de470cSBruce Richardson * Malloc 40a9de470cSBruce Richardson * ====== 41a9de470cSBruce Richardson * 42a9de470cSBruce Richardson * Allocate some dynamic memory from heap (3 areas). Check that areas 43a9de470cSBruce Richardson * don't overlap and that alignment constraints match. This test is 44a9de470cSBruce Richardson * done many times on different lcores simultaneously. 45a9de470cSBruce Richardson */ 46a9de470cSBruce Richardson 47a9de470cSBruce Richardson /* Test if memory overlaps: return 1 if true, or 0 if false. */ 48a9de470cSBruce Richardson static int 49a9de470cSBruce Richardson is_memory_overlap(void *p1, size_t len1, void *p2, size_t len2) 50a9de470cSBruce Richardson { 513c60274cSJie Zhou uintptr_t ptr1 = (uintptr_t)p1; 523c60274cSJie Zhou uintptr_t ptr2 = (uintptr_t)p2; 53a9de470cSBruce Richardson 54a9de470cSBruce Richardson if (ptr2 >= ptr1 && (ptr2 - ptr1) < len1) 55a9de470cSBruce Richardson return 1; 56a9de470cSBruce Richardson else if (ptr2 < ptr1 && (ptr1 - ptr2) < len2) 57a9de470cSBruce Richardson return 1; 58a9de470cSBruce Richardson return 0; 59a9de470cSBruce Richardson } 60a9de470cSBruce Richardson 61a9de470cSBruce Richardson static int 62a9de470cSBruce Richardson is_aligned(void *p, int align) 63a9de470cSBruce Richardson { 643c60274cSJie Zhou uintptr_t addr = (uintptr_t)p; 65a9de470cSBruce Richardson unsigned mask = align - 1; 66a9de470cSBruce Richardson 67a9de470cSBruce Richardson if (addr & mask) 68a9de470cSBruce Richardson return 0; 69a9de470cSBruce Richardson return 1; 70a9de470cSBruce Richardson } 71a9de470cSBruce Richardson 72a9de470cSBruce Richardson static int 73f2fc83b4SThomas Monjalon test_align_overlap_per_lcore(__rte_unused void *arg) 74a9de470cSBruce Richardson { 75a9de470cSBruce Richardson const unsigned align1 = 8, 76a9de470cSBruce Richardson align2 = 64, 77a9de470cSBruce Richardson align3 = 2048; 78a9de470cSBruce Richardson unsigned i,j; 79a9de470cSBruce Richardson void *p1 = NULL, *p2 = NULL, *p3 = NULL; 80a9de470cSBruce Richardson int ret = 0; 81a9de470cSBruce Richardson 82a9de470cSBruce Richardson for (i = 0; i < N; i++) { 83a9de470cSBruce Richardson p1 = rte_zmalloc("dummy", 1000, align1); 84a9de470cSBruce Richardson if (!p1){ 85a9de470cSBruce Richardson printf("rte_zmalloc returned NULL (i=%u)\n", i); 86a9de470cSBruce Richardson ret = -1; 87a9de470cSBruce Richardson break; 88a9de470cSBruce Richardson } 89a9de470cSBruce Richardson for(j = 0; j < 1000 ; j++) { 90a9de470cSBruce Richardson if( *(char *)p1 != 0) { 91a9de470cSBruce Richardson printf("rte_zmalloc didn't zero the allocated memory\n"); 92a9de470cSBruce Richardson ret = -1; 93a9de470cSBruce Richardson } 94a9de470cSBruce Richardson } 95a9de470cSBruce Richardson p2 = rte_malloc("dummy", 1000, align2); 96a9de470cSBruce Richardson if (!p2){ 97a9de470cSBruce Richardson printf("rte_malloc returned NULL (i=%u)\n", i); 98a9de470cSBruce Richardson ret = -1; 99a9de470cSBruce Richardson rte_free(p1); 100a9de470cSBruce Richardson break; 101a9de470cSBruce Richardson } 102a9de470cSBruce Richardson p3 = rte_malloc("dummy", 1000, align3); 103a9de470cSBruce Richardson if (!p3){ 104a9de470cSBruce Richardson printf("rte_malloc returned NULL (i=%u)\n", i); 105a9de470cSBruce Richardson ret = -1; 106a9de470cSBruce Richardson rte_free(p1); 107a9de470cSBruce Richardson rte_free(p2); 108a9de470cSBruce Richardson break; 109a9de470cSBruce Richardson } 110a9de470cSBruce Richardson if (is_memory_overlap(p1, 1000, p2, 1000)) { 111a9de470cSBruce Richardson printf("p1 and p2 overlaps\n"); 112a9de470cSBruce Richardson ret = -1; 113a9de470cSBruce Richardson } 114a9de470cSBruce Richardson if (is_memory_overlap(p2, 1000, p3, 1000)) { 115a9de470cSBruce Richardson printf("p2 and p3 overlaps\n"); 116a9de470cSBruce Richardson ret = -1; 117a9de470cSBruce Richardson } 118a9de470cSBruce Richardson if (is_memory_overlap(p1, 1000, p3, 1000)) { 119a9de470cSBruce Richardson printf("p1 and p3 overlaps\n"); 120a9de470cSBruce Richardson ret = -1; 121a9de470cSBruce Richardson } 122a9de470cSBruce Richardson if (!is_aligned(p1, align1)) { 123a9de470cSBruce Richardson printf("p1 is not aligned\n"); 124a9de470cSBruce Richardson ret = -1; 125a9de470cSBruce Richardson } 126a9de470cSBruce Richardson if (!is_aligned(p2, align2)) { 127a9de470cSBruce Richardson printf("p2 is not aligned\n"); 128a9de470cSBruce Richardson ret = -1; 129a9de470cSBruce Richardson } 130a9de470cSBruce Richardson if (!is_aligned(p3, align3)) { 131a9de470cSBruce Richardson printf("p3 is not aligned\n"); 132a9de470cSBruce Richardson ret = -1; 133a9de470cSBruce Richardson } 134a9de470cSBruce Richardson rte_free(p1); 135a9de470cSBruce Richardson rte_free(p2); 136a9de470cSBruce Richardson rte_free(p3); 137a9de470cSBruce Richardson } 138a9de470cSBruce Richardson rte_malloc_dump_stats(stdout, "dummy"); 139a9de470cSBruce Richardson 140a9de470cSBruce Richardson return ret; 141a9de470cSBruce Richardson } 142a9de470cSBruce Richardson 143a9de470cSBruce Richardson static int 144f2fc83b4SThomas Monjalon test_reordered_free_per_lcore(__rte_unused void *arg) 145a9de470cSBruce Richardson { 146a9de470cSBruce Richardson const unsigned align1 = 8, 147a9de470cSBruce Richardson align2 = 64, 148a9de470cSBruce Richardson align3 = 2048; 149a9de470cSBruce Richardson unsigned i,j; 150a9de470cSBruce Richardson void *p1, *p2, *p3; 151a9de470cSBruce Richardson int ret = 0; 152a9de470cSBruce Richardson 153a9de470cSBruce Richardson for (i = 0; i < 30; i++) { 154a9de470cSBruce Richardson p1 = rte_zmalloc("dummy", 1000, align1); 155a9de470cSBruce Richardson if (!p1){ 156a9de470cSBruce Richardson printf("rte_zmalloc returned NULL (i=%u)\n", i); 157a9de470cSBruce Richardson ret = -1; 158a9de470cSBruce Richardson break; 159a9de470cSBruce Richardson } 160a9de470cSBruce Richardson for(j = 0; j < 1000 ; j++) { 161a9de470cSBruce Richardson if( *(char *)p1 != 0) { 162a9de470cSBruce Richardson printf("rte_zmalloc didn't zero the allocated memory\n"); 163a9de470cSBruce Richardson ret = -1; 164a9de470cSBruce Richardson } 165a9de470cSBruce Richardson } 166a9de470cSBruce Richardson /* use calloc to allocate 1000 16-byte items this time */ 167a9de470cSBruce Richardson p2 = rte_calloc("dummy", 1000, 16, align2); 168a9de470cSBruce Richardson /* for third request use regular malloc again */ 169a9de470cSBruce Richardson p3 = rte_malloc("dummy", 1000, align3); 170a9de470cSBruce Richardson if (!p2 || !p3){ 171a9de470cSBruce Richardson printf("rte_malloc returned NULL (i=%u)\n", i); 172a9de470cSBruce Richardson ret = -1; 173a9de470cSBruce Richardson break; 174a9de470cSBruce Richardson } 175a9de470cSBruce Richardson if (is_memory_overlap(p1, 1000, p2, 1000)) { 176a9de470cSBruce Richardson printf("p1 and p2 overlaps\n"); 177a9de470cSBruce Richardson ret = -1; 178a9de470cSBruce Richardson } 179a9de470cSBruce Richardson if (is_memory_overlap(p2, 1000, p3, 1000)) { 180a9de470cSBruce Richardson printf("p2 and p3 overlaps\n"); 181a9de470cSBruce Richardson ret = -1; 182a9de470cSBruce Richardson } 183a9de470cSBruce Richardson if (is_memory_overlap(p1, 1000, p3, 1000)) { 184a9de470cSBruce Richardson printf("p1 and p3 overlaps\n"); 185a9de470cSBruce Richardson ret = -1; 186a9de470cSBruce Richardson } 187a9de470cSBruce Richardson if (!is_aligned(p1, align1)) { 188a9de470cSBruce Richardson printf("p1 is not aligned\n"); 189a9de470cSBruce Richardson ret = -1; 190a9de470cSBruce Richardson } 191a9de470cSBruce Richardson if (!is_aligned(p2, align2)) { 192a9de470cSBruce Richardson printf("p2 is not aligned\n"); 193a9de470cSBruce Richardson ret = -1; 194a9de470cSBruce Richardson } 195a9de470cSBruce Richardson if (!is_aligned(p3, align3)) { 196a9de470cSBruce Richardson printf("p3 is not aligned\n"); 197a9de470cSBruce Richardson ret = -1; 198a9de470cSBruce Richardson } 199a9de470cSBruce Richardson /* try freeing in every possible order */ 200a9de470cSBruce Richardson switch (i%6){ 201a9de470cSBruce Richardson case 0: 202a9de470cSBruce Richardson rte_free(p1); 203a9de470cSBruce Richardson rte_free(p2); 204a9de470cSBruce Richardson rte_free(p3); 205a9de470cSBruce Richardson break; 206a9de470cSBruce Richardson case 1: 207a9de470cSBruce Richardson rte_free(p1); 208a9de470cSBruce Richardson rte_free(p3); 209a9de470cSBruce Richardson rte_free(p2); 210a9de470cSBruce Richardson break; 211a9de470cSBruce Richardson case 2: 212a9de470cSBruce Richardson rte_free(p2); 213a9de470cSBruce Richardson rte_free(p1); 214a9de470cSBruce Richardson rte_free(p3); 215a9de470cSBruce Richardson break; 216a9de470cSBruce Richardson case 3: 217a9de470cSBruce Richardson rte_free(p2); 218a9de470cSBruce Richardson rte_free(p3); 219a9de470cSBruce Richardson rte_free(p1); 220a9de470cSBruce Richardson break; 221a9de470cSBruce Richardson case 4: 222a9de470cSBruce Richardson rte_free(p3); 223a9de470cSBruce Richardson rte_free(p1); 224a9de470cSBruce Richardson rte_free(p2); 225a9de470cSBruce Richardson break; 226a9de470cSBruce Richardson case 5: 227a9de470cSBruce Richardson rte_free(p3); 228a9de470cSBruce Richardson rte_free(p2); 229a9de470cSBruce Richardson rte_free(p1); 230a9de470cSBruce Richardson break; 231a9de470cSBruce Richardson } 232a9de470cSBruce Richardson } 233a9de470cSBruce Richardson rte_malloc_dump_stats(stdout, "dummy"); 234a9de470cSBruce Richardson 235a9de470cSBruce Richardson return ret; 236a9de470cSBruce Richardson } 237a9de470cSBruce Richardson 238a9de470cSBruce Richardson /* test function inside the malloc lib*/ 239a9de470cSBruce Richardson static int 240a9de470cSBruce Richardson test_str_to_size(void) 241a9de470cSBruce Richardson { 242a9de470cSBruce Richardson struct { 243a9de470cSBruce Richardson const char *str; 244a9de470cSBruce Richardson uint64_t value; 245a9de470cSBruce Richardson } test_values[] = 246a9de470cSBruce Richardson {{ "5G", (uint64_t)5 * 1024 * 1024 *1024 }, 247a9de470cSBruce Richardson {"0x20g", (uint64_t)0x20 * 1024 * 1024 *1024}, 248a9de470cSBruce Richardson {"10M", 10 * 1024 * 1024}, 249a9de470cSBruce Richardson {"050m", 050 * 1024 * 1024}, 250a9de470cSBruce Richardson {"8K", 8 * 1024}, 251a9de470cSBruce Richardson {"15k", 15 * 1024}, 252a9de470cSBruce Richardson {"0200", 0200}, 253a9de470cSBruce Richardson {"0x103", 0x103}, 254a9de470cSBruce Richardson {"432", 432}, 255a9de470cSBruce Richardson {"-1", 0}, /* negative values return 0 */ 256a9de470cSBruce Richardson {" -2", 0}, 257a9de470cSBruce Richardson {" -3MB", 0}, 258a9de470cSBruce Richardson {"18446744073709551616", 0} /* ULLONG_MAX + 1 == out of range*/ 259a9de470cSBruce Richardson }; 260a9de470cSBruce Richardson unsigned i; 26171bdd8a1SPavan Nikhilesh for (i = 0; i < RTE_DIM(test_values); i++) 262a9de470cSBruce Richardson if (rte_str_to_size(test_values[i].str) != test_values[i].value) 263a9de470cSBruce Richardson return -1; 264a9de470cSBruce Richardson return 0; 265a9de470cSBruce Richardson } 266a9de470cSBruce Richardson 267a9de470cSBruce Richardson static int 268a9de470cSBruce Richardson test_multi_alloc_statistics(void) 269a9de470cSBruce Richardson { 270a9de470cSBruce Richardson int socket = 0; 271a9de470cSBruce Richardson struct rte_malloc_socket_stats pre_stats, post_stats ,first_stats, second_stats; 272a9de470cSBruce Richardson size_t size = 2048; 273a9de470cSBruce Richardson int align = 1024; 274a9de470cSBruce Richardson int overhead = 0; 275a9de470cSBruce Richardson 276a9de470cSBruce Richardson /* Dynamically calculate the overhead by allocating one cacheline and 277a9de470cSBruce Richardson * then comparing what was allocated from the heap. 278a9de470cSBruce Richardson */ 279a9de470cSBruce Richardson rte_malloc_get_socket_stats(socket, &pre_stats); 280a9de470cSBruce Richardson 281a9de470cSBruce Richardson void *dummy = rte_malloc_socket(NULL, RTE_CACHE_LINE_SIZE, 0, socket); 282a9de470cSBruce Richardson if (dummy == NULL) 283a9de470cSBruce Richardson return -1; 284a9de470cSBruce Richardson 285a9de470cSBruce Richardson rte_malloc_get_socket_stats(socket, &post_stats); 286a9de470cSBruce Richardson 287a9de470cSBruce Richardson /* after subtracting cache line, remainder is overhead */ 288a9de470cSBruce Richardson overhead = post_stats.heap_allocsz_bytes - pre_stats.heap_allocsz_bytes; 289a9de470cSBruce Richardson overhead -= RTE_CACHE_LINE_SIZE; 290a9de470cSBruce Richardson 291a9de470cSBruce Richardson rte_free(dummy); 292a9de470cSBruce Richardson 293a9de470cSBruce Richardson /* Now start the real tests */ 294a9de470cSBruce Richardson rte_malloc_get_socket_stats(socket, &pre_stats); 295a9de470cSBruce Richardson 296a9de470cSBruce Richardson void *p1 = rte_malloc_socket("stats", size , align, socket); 297a9de470cSBruce Richardson if (!p1) 298a9de470cSBruce Richardson return -1; 299a9de470cSBruce Richardson rte_free(p1); 300a9de470cSBruce Richardson rte_malloc_dump_stats(stdout, "stats"); 301a9de470cSBruce Richardson 302a9de470cSBruce Richardson rte_malloc_get_socket_stats(socket,&post_stats); 303a9de470cSBruce Richardson /* Check statistics reported are correct */ 304a9de470cSBruce Richardson /* All post stats should be equal to pre stats after alloc freed */ 30519606f83SRuifeng Wang if ((post_stats.heap_totalsz_bytes != pre_stats.heap_totalsz_bytes) || 30619606f83SRuifeng Wang (post_stats.heap_freesz_bytes != pre_stats.heap_freesz_bytes) || 30719606f83SRuifeng Wang (post_stats.heap_allocsz_bytes != pre_stats.heap_allocsz_bytes) || 30819606f83SRuifeng Wang (post_stats.alloc_count != pre_stats.alloc_count) || 309a9de470cSBruce Richardson (post_stats.free_count != pre_stats.free_count)) { 310a9de470cSBruce Richardson printf("Malloc statistics are incorrect - freed alloc\n"); 311a9de470cSBruce Richardson return -1; 312a9de470cSBruce Richardson } 313a9de470cSBruce Richardson /* Check two consecutive allocations */ 314a9de470cSBruce Richardson size = 1024; 315a9de470cSBruce Richardson align = 0; 316a9de470cSBruce Richardson rte_malloc_get_socket_stats(socket,&pre_stats); 317a9de470cSBruce Richardson void *p2 = rte_malloc_socket("add", size ,align, socket); 318a9de470cSBruce Richardson if (!p2) 319a9de470cSBruce Richardson return -1; 320a9de470cSBruce Richardson rte_malloc_get_socket_stats(socket,&first_stats); 321a9de470cSBruce Richardson 322a9de470cSBruce Richardson void *p3 = rte_malloc_socket("add2", size,align, socket); 323a9de470cSBruce Richardson if (!p3) 324a9de470cSBruce Richardson return -1; 325a9de470cSBruce Richardson 326a9de470cSBruce Richardson rte_malloc_get_socket_stats(socket,&second_stats); 327a9de470cSBruce Richardson 328a9de470cSBruce Richardson rte_free(p2); 329a9de470cSBruce Richardson rte_free(p3); 330a9de470cSBruce Richardson 331a9de470cSBruce Richardson /* After freeing both allocations check stats return to original */ 332a9de470cSBruce Richardson rte_malloc_get_socket_stats(socket, &post_stats); 333a9de470cSBruce Richardson 334a9de470cSBruce Richardson if(second_stats.heap_totalsz_bytes != first_stats.heap_totalsz_bytes) { 335a9de470cSBruce Richardson printf("Incorrect heap statistics: Total size \n"); 336a9de470cSBruce Richardson return -1; 337a9de470cSBruce Richardson } 338a9de470cSBruce Richardson /* Check allocated size is equal to two additions plus overhead */ 339a9de470cSBruce Richardson if(second_stats.heap_allocsz_bytes != 340a9de470cSBruce Richardson size + overhead + first_stats.heap_allocsz_bytes) { 341a9de470cSBruce Richardson printf("Incorrect heap statistics: Allocated size \n"); 342a9de470cSBruce Richardson return -1; 343a9de470cSBruce Richardson } 344a9de470cSBruce Richardson /* Check that allocation count increments correctly i.e. +1 */ 345a9de470cSBruce Richardson if (second_stats.alloc_count != first_stats.alloc_count + 1) { 346a9de470cSBruce Richardson printf("Incorrect heap statistics: Allocated count \n"); 347a9de470cSBruce Richardson return -1; 348a9de470cSBruce Richardson } 349a9de470cSBruce Richardson 350a9de470cSBruce Richardson if (second_stats.free_count != first_stats.free_count){ 351a9de470cSBruce Richardson printf("Incorrect heap statistics: Free count \n"); 352a9de470cSBruce Richardson return -1; 353a9de470cSBruce Richardson } 354a9de470cSBruce Richardson 355a9de470cSBruce Richardson /* Make sure that we didn't touch our greatest chunk: 2 * 11M) */ 356a9de470cSBruce Richardson if (post_stats.greatest_free_size != pre_stats.greatest_free_size) { 357a9de470cSBruce Richardson printf("Incorrect heap statistics: Greatest free size \n"); 358a9de470cSBruce Richardson return -1; 359a9de470cSBruce Richardson } 360a9de470cSBruce Richardson /* Free size must equal the original free size minus the new allocation*/ 361a9de470cSBruce Richardson if (first_stats.heap_freesz_bytes <= second_stats.heap_freesz_bytes) { 362a9de470cSBruce Richardson printf("Incorrect heap statistics: Free size \n"); 363a9de470cSBruce Richardson return -1; 364a9de470cSBruce Richardson } 365a9de470cSBruce Richardson 36619606f83SRuifeng Wang if ((post_stats.heap_totalsz_bytes != pre_stats.heap_totalsz_bytes) || 36719606f83SRuifeng Wang (post_stats.heap_freesz_bytes != pre_stats.heap_freesz_bytes) || 36819606f83SRuifeng Wang (post_stats.heap_allocsz_bytes != pre_stats.heap_allocsz_bytes) || 36919606f83SRuifeng Wang (post_stats.alloc_count != pre_stats.alloc_count) || 370a9de470cSBruce Richardson (post_stats.free_count != pre_stats.free_count)) { 371a9de470cSBruce Richardson printf("Malloc statistics are incorrect - freed alloc\n"); 372a9de470cSBruce Richardson return -1; 373a9de470cSBruce Richardson } 374a9de470cSBruce Richardson return 0; 375a9de470cSBruce Richardson } 376a9de470cSBruce Richardson 3773c60274cSJie Zhou #ifdef RTE_EXEC_ENV_WINDOWS 3783c60274cSJie Zhou static int 3793c60274cSJie Zhou test_realloc(void) 3803c60274cSJie Zhou { 3813c60274cSJie Zhou return TEST_SKIPPED; 3823c60274cSJie Zhou } 3833c60274cSJie Zhou #else 3843c60274cSJie Zhou 385a9de470cSBruce Richardson static int 386dd467777SAnatoly Burakov test_realloc_socket(int socket) 387a9de470cSBruce Richardson { 388a9de470cSBruce Richardson const char hello_str[] = "Hello, world!"; 389a9de470cSBruce Richardson const unsigned size1 = 1024; 390a9de470cSBruce Richardson const unsigned size2 = size1 + 1024; 391a9de470cSBruce Richardson const unsigned size3 = size2; 392a9de470cSBruce Richardson const unsigned size4 = size3 + 1024; 393a9de470cSBruce Richardson 394a9de470cSBruce Richardson /* test data is the same even if element is moved*/ 395dd467777SAnatoly Burakov char *ptr1 = rte_zmalloc_socket( 396dd467777SAnatoly Burakov NULL, size1, RTE_CACHE_LINE_SIZE, socket); 397a9de470cSBruce Richardson if (!ptr1){ 398a9de470cSBruce Richardson printf("NULL pointer returned from rte_zmalloc\n"); 399a9de470cSBruce Richardson return -1; 400a9de470cSBruce Richardson } 401a9de470cSBruce Richardson strlcpy(ptr1, hello_str, size1); 402dd467777SAnatoly Burakov char *ptr2 = rte_realloc_socket( 403dd467777SAnatoly Burakov ptr1, size2, RTE_CACHE_LINE_SIZE, socket); 404a9de470cSBruce Richardson if (!ptr2){ 405a9de470cSBruce Richardson rte_free(ptr1); 406a9de470cSBruce Richardson printf("NULL pointer returned from rte_realloc\n"); 407a9de470cSBruce Richardson return -1; 408a9de470cSBruce Richardson } 409a9de470cSBruce Richardson if (ptr1 == ptr2){ 410a9de470cSBruce Richardson printf("unexpected - ptr1 == ptr2\n"); 411a9de470cSBruce Richardson } 412a9de470cSBruce Richardson if (strcmp(ptr2, hello_str) != 0){ 413a9de470cSBruce Richardson printf("Error - lost data from pointed area\n"); 414a9de470cSBruce Richardson rte_free(ptr2); 415a9de470cSBruce Richardson return -1; 416a9de470cSBruce Richardson } 417a9de470cSBruce Richardson unsigned i; 418a9de470cSBruce Richardson for (i = strnlen(hello_str, sizeof(hello_str)); i < size1; i++) 419a9de470cSBruce Richardson if (ptr2[i] != 0){ 420a9de470cSBruce Richardson printf("Bad data in realloc\n"); 421a9de470cSBruce Richardson rte_free(ptr2); 422a9de470cSBruce Richardson return -1; 423a9de470cSBruce Richardson } 424a9de470cSBruce Richardson /* now allocate third element, free the second 425a9de470cSBruce Richardson * and resize third. It should not move. (ptr1 is now invalid) 426a9de470cSBruce Richardson */ 427dd467777SAnatoly Burakov char *ptr3 = rte_zmalloc_socket( 428dd467777SAnatoly Burakov NULL, size3, RTE_CACHE_LINE_SIZE, socket); 429a9de470cSBruce Richardson if (!ptr3){ 430a9de470cSBruce Richardson printf("NULL pointer returned from rte_zmalloc\n"); 431a9de470cSBruce Richardson rte_free(ptr2); 432a9de470cSBruce Richardson return -1; 433a9de470cSBruce Richardson } 434a9de470cSBruce Richardson for (i = 0; i < size3; i++) 435a9de470cSBruce Richardson if (ptr3[i] != 0){ 436a9de470cSBruce Richardson printf("Bad data in zmalloc\n"); 437a9de470cSBruce Richardson rte_free(ptr3); 438a9de470cSBruce Richardson rte_free(ptr2); 439a9de470cSBruce Richardson return -1; 440a9de470cSBruce Richardson } 441a9de470cSBruce Richardson rte_free(ptr2); 442a9de470cSBruce Richardson /* first resize to half the size of the freed block */ 443dd467777SAnatoly Burakov char *ptr4 = rte_realloc_socket( 444dd467777SAnatoly Burakov ptr3, size4, RTE_CACHE_LINE_SIZE, socket); 445a9de470cSBruce Richardson if (!ptr4){ 446a9de470cSBruce Richardson printf("NULL pointer returned from rte_realloc\n"); 447a9de470cSBruce Richardson rte_free(ptr3); 448a9de470cSBruce Richardson return -1; 449a9de470cSBruce Richardson } 450a9de470cSBruce Richardson if (ptr3 != ptr4){ 451a9de470cSBruce Richardson printf("Unexpected - ptr4 != ptr3\n"); 452a9de470cSBruce Richardson rte_free(ptr4); 453a9de470cSBruce Richardson return -1; 454a9de470cSBruce Richardson } 455a9de470cSBruce Richardson /* now resize again to the full size of the freed block */ 456dd467777SAnatoly Burakov ptr4 = rte_realloc_socket(ptr3, size3 + size2 + size1, 457dd467777SAnatoly Burakov RTE_CACHE_LINE_SIZE, socket); 458a9de470cSBruce Richardson if (ptr3 != ptr4){ 459a9de470cSBruce Richardson printf("Unexpected - ptr4 != ptr3 on second resize\n"); 460a9de470cSBruce Richardson rte_free(ptr4); 461a9de470cSBruce Richardson return -1; 462a9de470cSBruce Richardson } 463a9de470cSBruce Richardson rte_free(ptr4); 464a9de470cSBruce Richardson 465a9de470cSBruce Richardson /* now try a resize to a smaller size, see if it works */ 466a9de470cSBruce Richardson const unsigned size5 = 1024; 467a9de470cSBruce Richardson const unsigned size6 = size5 / 2; 468dd467777SAnatoly Burakov char *ptr5 = rte_malloc_socket( 469dd467777SAnatoly Burakov NULL, size5, RTE_CACHE_LINE_SIZE, socket); 470a9de470cSBruce Richardson if (!ptr5){ 471a9de470cSBruce Richardson printf("NULL pointer returned from rte_malloc\n"); 472a9de470cSBruce Richardson return -1; 473a9de470cSBruce Richardson } 474dd467777SAnatoly Burakov char *ptr6 = rte_realloc_socket( 475dd467777SAnatoly Burakov ptr5, size6, RTE_CACHE_LINE_SIZE, socket); 476a9de470cSBruce Richardson if (!ptr6){ 477a9de470cSBruce Richardson printf("NULL pointer returned from rte_realloc\n"); 478a9de470cSBruce Richardson rte_free(ptr5); 479a9de470cSBruce Richardson return -1; 480a9de470cSBruce Richardson } 481a9de470cSBruce Richardson if (ptr5 != ptr6){ 482a9de470cSBruce Richardson printf("Error, resizing to a smaller size moved data\n"); 483a9de470cSBruce Richardson rte_free(ptr6); 484a9de470cSBruce Richardson return -1; 485a9de470cSBruce Richardson } 486a9de470cSBruce Richardson rte_free(ptr6); 487a9de470cSBruce Richardson 488a9de470cSBruce Richardson /* check for behaviour changing alignment */ 489a9de470cSBruce Richardson const unsigned size7 = 1024; 490a9de470cSBruce Richardson const unsigned orig_align = RTE_CACHE_LINE_SIZE; 491a9de470cSBruce Richardson unsigned new_align = RTE_CACHE_LINE_SIZE * 2; 492dd467777SAnatoly Burakov char *ptr7 = rte_malloc_socket(NULL, size7, orig_align, socket); 493a9de470cSBruce Richardson if (!ptr7){ 494a9de470cSBruce Richardson printf("NULL pointer returned from rte_malloc\n"); 495a9de470cSBruce Richardson return -1; 496a9de470cSBruce Richardson } 497a9de470cSBruce Richardson /* calc an alignment we don't already have */ 498a9de470cSBruce Richardson while(RTE_PTR_ALIGN(ptr7, new_align) == ptr7) 499a9de470cSBruce Richardson new_align *= 2; 500dd467777SAnatoly Burakov char *ptr8 = rte_realloc_socket(ptr7, size7, new_align, socket); 501a9de470cSBruce Richardson if (!ptr8){ 502a9de470cSBruce Richardson printf("NULL pointer returned from rte_realloc\n"); 503a9de470cSBruce Richardson rte_free(ptr7); 504a9de470cSBruce Richardson return -1; 505a9de470cSBruce Richardson } 506a9de470cSBruce Richardson if (RTE_PTR_ALIGN(ptr8, new_align) != ptr8){ 507a9de470cSBruce Richardson printf("Failure to re-align data\n"); 508a9de470cSBruce Richardson rte_free(ptr8); 509a9de470cSBruce Richardson return -1; 510a9de470cSBruce Richardson } 511a9de470cSBruce Richardson rte_free(ptr8); 512a9de470cSBruce Richardson 513a9de470cSBruce Richardson /* test behaviour when there is a free block after current one, 514a9de470cSBruce Richardson * but its not big enough 515a9de470cSBruce Richardson */ 516a9de470cSBruce Richardson unsigned size9 = 1024, size10 = 1024; 517a9de470cSBruce Richardson unsigned size11 = size9 + size10 + 256; 518dd467777SAnatoly Burakov char *ptr9 = rte_malloc_socket( 519dd467777SAnatoly Burakov NULL, size9, RTE_CACHE_LINE_SIZE, socket); 520a9de470cSBruce Richardson if (!ptr9){ 521a9de470cSBruce Richardson printf("NULL pointer returned from rte_malloc\n"); 522a9de470cSBruce Richardson return -1; 523a9de470cSBruce Richardson } 524dd467777SAnatoly Burakov char *ptr10 = rte_malloc_socket( 525dd467777SAnatoly Burakov NULL, size10, RTE_CACHE_LINE_SIZE, socket); 526a9de470cSBruce Richardson if (!ptr10){ 527a9de470cSBruce Richardson printf("NULL pointer returned from rte_malloc\n"); 528a9de470cSBruce Richardson return -1; 529a9de470cSBruce Richardson } 530a9de470cSBruce Richardson rte_free(ptr9); 531dd467777SAnatoly Burakov char *ptr11 = rte_realloc_socket( 532dd467777SAnatoly Burakov ptr10, size11, RTE_CACHE_LINE_SIZE, socket); 533a9de470cSBruce Richardson if (!ptr11){ 534a9de470cSBruce Richardson printf("NULL pointer returned from rte_realloc\n"); 535a9de470cSBruce Richardson rte_free(ptr10); 536a9de470cSBruce Richardson return -1; 537a9de470cSBruce Richardson } 538a9de470cSBruce Richardson if (ptr11 == ptr10){ 539a9de470cSBruce Richardson printf("Error, unexpected that realloc has not created new buffer\n"); 540a9de470cSBruce Richardson rte_free(ptr11); 541a9de470cSBruce Richardson return -1; 542a9de470cSBruce Richardson } 543a9de470cSBruce Richardson rte_free(ptr11); 544a9de470cSBruce Richardson 545a9de470cSBruce Richardson /* check we don't crash if we pass null to realloc 546a9de470cSBruce Richardson * We should get a malloc of the size requested*/ 547a9de470cSBruce Richardson const size_t size12 = 1024; 548a9de470cSBruce Richardson size_t size12_check; 549dd467777SAnatoly Burakov char *ptr12 = rte_realloc_socket( 550dd467777SAnatoly Burakov NULL, size12, RTE_CACHE_LINE_SIZE, socket); 551a9de470cSBruce Richardson if (!ptr12){ 552a9de470cSBruce Richardson printf("NULL pointer returned from rte_realloc\n"); 553a9de470cSBruce Richardson return -1; 554a9de470cSBruce Richardson } 555a9de470cSBruce Richardson if (rte_malloc_validate(ptr12, &size12_check) < 0 || 556a9de470cSBruce Richardson size12_check != size12){ 557a9de470cSBruce Richardson rte_free(ptr12); 558a9de470cSBruce Richardson return -1; 559a9de470cSBruce Richardson } 560a9de470cSBruce Richardson rte_free(ptr12); 561a7cece2eSTomasz Jozwiak 562dd467777SAnatoly Burakov /* do the same, but for regular memory */ 563dd467777SAnatoly Burakov ptr12 = rte_realloc(NULL, size12, RTE_CACHE_LINE_SIZE); 564dd467777SAnatoly Burakov if (!ptr12) { 565dd467777SAnatoly Burakov printf("NULL pointer returned from rte_realloc\n"); 566dd467777SAnatoly Burakov return -1; 567dd467777SAnatoly Burakov } 568dd467777SAnatoly Burakov if (rte_malloc_validate(ptr12, &size12_check) < 0 || 569dd467777SAnatoly Burakov size12_check != size12) { 570dd467777SAnatoly Burakov rte_free(ptr12); 571dd467777SAnatoly Burakov return -1; 572dd467777SAnatoly Burakov } 573dd467777SAnatoly Burakov rte_free(ptr12); 574dd467777SAnatoly Burakov 575dd467777SAnatoly Burakov return 0; 576dd467777SAnatoly Burakov } 577dd467777SAnatoly Burakov 578dd467777SAnatoly Burakov static int 579dd467777SAnatoly Burakov test_realloc_numa(void) 580dd467777SAnatoly Burakov { 581a7cece2eSTomasz Jozwiak /* check realloc_socket part */ 582a7cece2eSTomasz Jozwiak int32_t socket_count = 0, socket_allocated, socket; 583dd467777SAnatoly Burakov void *ptr1, *ptr2; 584a7cece2eSTomasz Jozwiak int ret = -1; 585a7cece2eSTomasz Jozwiak size_t size = 1024; 586a7cece2eSTomasz Jozwiak 587a7cece2eSTomasz Jozwiak ptr1 = NULL; 588a7cece2eSTomasz Jozwiak for (socket = 0; socket < RTE_MAX_NUMA_NODES; socket++) { 589a7cece2eSTomasz Jozwiak if (is_mem_on_socket(socket)) { 590a7cece2eSTomasz Jozwiak int j = 2; 591a7cece2eSTomasz Jozwiak 592a7cece2eSTomasz Jozwiak socket_count++; 593a7cece2eSTomasz Jozwiak while (j--) { 594a7cece2eSTomasz Jozwiak /* j == 1 -> resizing */ 595a7cece2eSTomasz Jozwiak ptr2 = rte_realloc_socket(ptr1, size, 596a7cece2eSTomasz Jozwiak RTE_CACHE_LINE_SIZE, 597a7cece2eSTomasz Jozwiak socket); 598a7cece2eSTomasz Jozwiak if (ptr2 == NULL) { 599a7cece2eSTomasz Jozwiak printf("NULL pointer returned from rte_realloc_socket\n"); 600a7cece2eSTomasz Jozwiak goto end; 601a7cece2eSTomasz Jozwiak } 602a7cece2eSTomasz Jozwiak 603a7cece2eSTomasz Jozwiak ptr1 = ptr2; 604a7cece2eSTomasz Jozwiak socket_allocated = addr_to_socket(ptr2); 605a7cece2eSTomasz Jozwiak if (socket_allocated != socket) { 606a7cece2eSTomasz Jozwiak printf("Requested socket (%d) doesn't mach allocated one (%d)\n", 607a7cece2eSTomasz Jozwiak socket, socket_allocated); 608a7cece2eSTomasz Jozwiak goto end; 609a7cece2eSTomasz Jozwiak } 610a7cece2eSTomasz Jozwiak size += RTE_CACHE_LINE_SIZE; 611a7cece2eSTomasz Jozwiak } 612a7cece2eSTomasz Jozwiak } 613a7cece2eSTomasz Jozwiak } 614a7cece2eSTomasz Jozwiak 6154a6672c2SStephen Hemminger /* Print warning if only a single socket, but don't fail the test */ 616a7cece2eSTomasz Jozwiak if (socket_count < 2) 617a7cece2eSTomasz Jozwiak printf("WARNING: realloc_socket test needs memory on multiple sockets!\n"); 618a7cece2eSTomasz Jozwiak 619a7cece2eSTomasz Jozwiak ret = 0; 620a7cece2eSTomasz Jozwiak end: 621a7cece2eSTomasz Jozwiak rte_free(ptr1); 622dd467777SAnatoly Burakov return ret; 623dd467777SAnatoly Burakov } 624a7cece2eSTomasz Jozwiak 625dd467777SAnatoly Burakov static int 626dd467777SAnatoly Burakov test_realloc(void) 627dd467777SAnatoly Burakov { 628dd467777SAnatoly Burakov const char *heap_name = "realloc_heap"; 629dd467777SAnatoly Burakov int realloc_heap_socket; 630dd467777SAnatoly Burakov unsigned int mem_sz = 1U << 13; /* 8K */ 631dd467777SAnatoly Burakov unsigned int page_sz = sysconf(_SC_PAGESIZE); 632dd467777SAnatoly Burakov void *mem; 633dd467777SAnatoly Burakov int ret; 634dd467777SAnatoly Burakov 635dd467777SAnatoly Burakov /* page size may be bigger than total mem size, so adjust */ 636dd467777SAnatoly Burakov mem_sz = RTE_MAX(mem_sz, page_sz); 637dd467777SAnatoly Burakov 638dd467777SAnatoly Burakov /* 639dd467777SAnatoly Burakov * the realloc tests depend on specific layout of underlying memory, so 640dd467777SAnatoly Burakov * to prevent accidental failures to do fragmented main heap, we will 641dd467777SAnatoly Burakov * do all of our tests on an artificially created memory. 642dd467777SAnatoly Burakov */ 643dd467777SAnatoly Burakov if (rte_malloc_heap_create(heap_name) != 0) { 644dd467777SAnatoly Burakov printf("Failed to create external heap\n"); 645dd467777SAnatoly Burakov ret = -1; 646dd467777SAnatoly Burakov goto end; 647dd467777SAnatoly Burakov } 648dd467777SAnatoly Burakov realloc_heap_socket = rte_malloc_heap_get_socket(heap_name); 649dd467777SAnatoly Burakov 650dd467777SAnatoly Burakov mem = mmap(NULL, mem_sz, PROT_READ | PROT_WRITE, 651dd467777SAnatoly Burakov MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); 652dd467777SAnatoly Burakov if (mem == MAP_FAILED) { 653dd467777SAnatoly Burakov printf("Failed to allocate memory for external heap\n"); 654dd467777SAnatoly Burakov ret = -1; 655dd467777SAnatoly Burakov goto heap_destroy; 656dd467777SAnatoly Burakov } 657dd467777SAnatoly Burakov 658dd467777SAnatoly Burakov if (rte_malloc_heap_memory_add( 659dd467777SAnatoly Burakov heap_name, mem, mem_sz, NULL, 0, page_sz) != 0) { 660dd467777SAnatoly Burakov printf("Failed to add memory to external heap\n"); 661dd467777SAnatoly Burakov ret = -1; 662dd467777SAnatoly Burakov goto mem_free; 663dd467777SAnatoly Burakov } 664dd467777SAnatoly Burakov 665dd467777SAnatoly Burakov /* run the socket-bound tests */ 666dd467777SAnatoly Burakov ret = test_realloc_socket(realloc_heap_socket); 667dd467777SAnatoly Burakov if (ret != 0) 668dd467777SAnatoly Burakov goto mem_remove; 669dd467777SAnatoly Burakov 670dd467777SAnatoly Burakov /* now, run the NUMA node tests */ 671dd467777SAnatoly Burakov ret = test_realloc_numa(); 672dd467777SAnatoly Burakov 673dd467777SAnatoly Burakov mem_remove: 674dd467777SAnatoly Burakov rte_malloc_heap_memory_remove(heap_name, mem, mem_sz); 675dd467777SAnatoly Burakov mem_free: 676dd467777SAnatoly Burakov munmap(mem, mem_sz); 677dd467777SAnatoly Burakov heap_destroy: 678dd467777SAnatoly Burakov rte_malloc_heap_destroy(heap_name); 679dd467777SAnatoly Burakov end: 680a7cece2eSTomasz Jozwiak return ret; 681a9de470cSBruce Richardson } 682a9de470cSBruce Richardson 6833c60274cSJie Zhou #endif /* !RTE_EXEC_ENV_WINDOWS */ 6843c60274cSJie Zhou 685a9de470cSBruce Richardson static int 686f2fc83b4SThomas Monjalon test_random_alloc_free(void *_ __rte_unused) 687a9de470cSBruce Richardson { 688a9de470cSBruce Richardson struct mem_list { 689a9de470cSBruce Richardson struct mem_list *next; 690a9de470cSBruce Richardson char data[0]; 691a9de470cSBruce Richardson } *list_head = NULL; 692a9de470cSBruce Richardson unsigned i; 693a9de470cSBruce Richardson unsigned count = 0; 694a9de470cSBruce Richardson 695a9de470cSBruce Richardson rte_srand((unsigned)rte_rdtsc()); 696a9de470cSBruce Richardson 697a9de470cSBruce Richardson for (i = 0; i < N; i++){ 698a9de470cSBruce Richardson unsigned free_mem = 0; 699a9de470cSBruce Richardson size_t allocated_size; 700a9de470cSBruce Richardson while (!free_mem){ 701a9de470cSBruce Richardson const unsigned mem_size = sizeof(struct mem_list) + \ 702a9de470cSBruce Richardson rte_rand() % (64 * 1024); 703a9de470cSBruce Richardson const unsigned align = 1 << (rte_rand() % 12); /* up to 4k alignment */ 704a9de470cSBruce Richardson struct mem_list *entry = rte_malloc(NULL, 705a9de470cSBruce Richardson mem_size, align); 706a9de470cSBruce Richardson if (entry == NULL) 707a9de470cSBruce Richardson return -1; 708a9de470cSBruce Richardson if (RTE_PTR_ALIGN(entry, align)!= entry) 709a9de470cSBruce Richardson return -1; 710a9de470cSBruce Richardson if (rte_malloc_validate(entry, &allocated_size) == -1 711a9de470cSBruce Richardson || allocated_size < mem_size) 712a9de470cSBruce Richardson return -1; 713a9de470cSBruce Richardson memset(entry->data, rte_lcore_id(), 714a9de470cSBruce Richardson mem_size - sizeof(*entry)); 715a9de470cSBruce Richardson entry->next = list_head; 716a9de470cSBruce Richardson if (rte_malloc_validate(entry, NULL) == -1) 717a9de470cSBruce Richardson return -1; 718a9de470cSBruce Richardson list_head = entry; 719a9de470cSBruce Richardson 720a9de470cSBruce Richardson count++; 721a9de470cSBruce Richardson /* switch to freeing the memory with a 20% probability */ 722a9de470cSBruce Richardson free_mem = ((rte_rand() % 10) >= 8); 723a9de470cSBruce Richardson } 724a9de470cSBruce Richardson while (list_head){ 725a9de470cSBruce Richardson struct mem_list *entry = list_head; 726a9de470cSBruce Richardson list_head = list_head->next; 727a9de470cSBruce Richardson rte_free(entry); 728a9de470cSBruce Richardson } 729a9de470cSBruce Richardson } 730a9de470cSBruce Richardson printf("Lcore %u allocated/freed %u blocks\n", rte_lcore_id(), count); 731a9de470cSBruce Richardson return 0; 732a9de470cSBruce Richardson } 733a9de470cSBruce Richardson 734a9de470cSBruce Richardson #define err_return() do { \ 735a9de470cSBruce Richardson printf("%s: %d - Error\n", __func__, __LINE__); \ 736a9de470cSBruce Richardson goto err_return; \ 737a9de470cSBruce Richardson } while (0) 738a9de470cSBruce Richardson 739a9de470cSBruce Richardson static int 740a9de470cSBruce Richardson test_rte_malloc_validate(void) 741a9de470cSBruce Richardson { 742a9de470cSBruce Richardson const size_t request_size = 1024; 743a9de470cSBruce Richardson size_t allocated_size; 744a9de470cSBruce Richardson char *data_ptr = rte_malloc(NULL, request_size, RTE_CACHE_LINE_SIZE); 745a9de470cSBruce Richardson #ifdef RTE_MALLOC_DEBUG 746a9de470cSBruce Richardson int retval; 747a9de470cSBruce Richardson char *over_write_vals = NULL; 748a9de470cSBruce Richardson #endif 749a9de470cSBruce Richardson 750a9de470cSBruce Richardson if (data_ptr == NULL) { 751a9de470cSBruce Richardson printf("%s: %d - Allocation error\n", __func__, __LINE__); 752a9de470cSBruce Richardson return -1; 753a9de470cSBruce Richardson } 754a9de470cSBruce Richardson 755a9de470cSBruce Richardson /* check that a null input returns -1 */ 756a9de470cSBruce Richardson if (rte_malloc_validate(NULL, NULL) != -1) 757a9de470cSBruce Richardson err_return(); 758a9de470cSBruce Richardson 759a9de470cSBruce Richardson /* check that we get ok on a valid pointer */ 760a9de470cSBruce Richardson if (rte_malloc_validate(data_ptr, &allocated_size) < 0) 761a9de470cSBruce Richardson err_return(); 762a9de470cSBruce Richardson 763a9de470cSBruce Richardson /* check that the returned size is ok */ 764a9de470cSBruce Richardson if (allocated_size < request_size) 765a9de470cSBruce Richardson err_return(); 766a9de470cSBruce Richardson 767a9de470cSBruce Richardson #ifdef RTE_MALLOC_DEBUG 768a9de470cSBruce Richardson 769a9de470cSBruce Richardson /****** change the header to be bad */ 770a9de470cSBruce Richardson char save_buf[64]; 771a9de470cSBruce Richardson over_write_vals = (char *)((uintptr_t)data_ptr - sizeof(save_buf)); 772a9de470cSBruce Richardson /* first save the data as a backup before overwriting it */ 773a9de470cSBruce Richardson memcpy(save_buf, over_write_vals, sizeof(save_buf)); 774a9de470cSBruce Richardson memset(over_write_vals, 1, sizeof(save_buf)); 775a9de470cSBruce Richardson /* then run validate */ 776a9de470cSBruce Richardson retval = rte_malloc_validate(data_ptr, NULL); 777a9de470cSBruce Richardson /* finally restore the data again */ 778a9de470cSBruce Richardson memcpy(over_write_vals, save_buf, sizeof(save_buf)); 779a9de470cSBruce Richardson /* check we previously had an error */ 780a9de470cSBruce Richardson if (retval != -1) 781a9de470cSBruce Richardson err_return(); 782a9de470cSBruce Richardson 783a9de470cSBruce Richardson /* check all ok again */ 784a9de470cSBruce Richardson if (rte_malloc_validate(data_ptr, &allocated_size) < 0) 785a9de470cSBruce Richardson err_return(); 786a9de470cSBruce Richardson 787a9de470cSBruce Richardson /**** change the trailer to be bad */ 788a9de470cSBruce Richardson over_write_vals = (char *)((uintptr_t)data_ptr + allocated_size); 789a9de470cSBruce Richardson /* first save the data as a backup before overwriting it */ 790a9de470cSBruce Richardson memcpy(save_buf, over_write_vals, sizeof(save_buf)); 791a9de470cSBruce Richardson memset(over_write_vals, 1, sizeof(save_buf)); 792a9de470cSBruce Richardson /* then run validate */ 793a9de470cSBruce Richardson retval = rte_malloc_validate(data_ptr, NULL); 794a9de470cSBruce Richardson /* finally restore the data again */ 795a9de470cSBruce Richardson memcpy(over_write_vals, save_buf, sizeof(save_buf)); 796a9de470cSBruce Richardson if (retval != -1) 797a9de470cSBruce Richardson err_return(); 798a9de470cSBruce Richardson 799a9de470cSBruce Richardson /* check all ok again */ 800a9de470cSBruce Richardson if (rte_malloc_validate(data_ptr, &allocated_size) < 0) 801a9de470cSBruce Richardson err_return(); 802a9de470cSBruce Richardson #endif 803a9de470cSBruce Richardson 804a9de470cSBruce Richardson rte_free(data_ptr); 805a9de470cSBruce Richardson return 0; 806a9de470cSBruce Richardson 807a9de470cSBruce Richardson err_return: 808a9de470cSBruce Richardson /*clean up */ 809a9de470cSBruce Richardson rte_free(data_ptr); 810a9de470cSBruce Richardson return -1; 811a9de470cSBruce Richardson } 812a9de470cSBruce Richardson 813a9de470cSBruce Richardson static int 814a9de470cSBruce Richardson test_zero_aligned_alloc(void) 815a9de470cSBruce Richardson { 816a9de470cSBruce Richardson char *p1 = rte_malloc(NULL,1024, 0); 817a9de470cSBruce Richardson if (!p1) 818a9de470cSBruce Richardson goto err_return; 819a9de470cSBruce Richardson if (!rte_is_aligned(p1, RTE_CACHE_LINE_SIZE)) 820a9de470cSBruce Richardson goto err_return; 821a9de470cSBruce Richardson rte_free(p1); 822a9de470cSBruce Richardson return 0; 823a9de470cSBruce Richardson 824a9de470cSBruce Richardson err_return: 825a9de470cSBruce Richardson /*clean up */ 82606c047b6SStephen Hemminger rte_free(p1); 827a9de470cSBruce Richardson return -1; 828a9de470cSBruce Richardson } 829a9de470cSBruce Richardson 830a9de470cSBruce Richardson static int 831a9de470cSBruce Richardson test_malloc_bad_params(void) 832a9de470cSBruce Richardson { 833a9de470cSBruce Richardson const char *type = NULL; 834a9de470cSBruce Richardson size_t size = 0; 835a9de470cSBruce Richardson unsigned align = RTE_CACHE_LINE_SIZE; 836a9de470cSBruce Richardson 837a9de470cSBruce Richardson /* rte_malloc expected to return null with inappropriate size */ 838a9de470cSBruce Richardson char *bad_ptr = rte_malloc(type, size, align); 839a9de470cSBruce Richardson if (bad_ptr != NULL) 840a9de470cSBruce Richardson goto err_return; 841a9de470cSBruce Richardson 8424a5a8678SAnatoly Burakov /* rte_realloc expected to return null with inappropriate size */ 8434a5a8678SAnatoly Burakov bad_ptr = rte_realloc(NULL, size, align); 8444a5a8678SAnatoly Burakov if (bad_ptr != NULL) 8454a5a8678SAnatoly Burakov goto err_return; 8464a5a8678SAnatoly Burakov 847a9de470cSBruce Richardson /* rte_malloc expected to return null with inappropriate alignment */ 848a9de470cSBruce Richardson align = 17; 849a9de470cSBruce Richardson size = 1024; 850a9de470cSBruce Richardson 851a9de470cSBruce Richardson bad_ptr = rte_malloc(type, size, align); 852a9de470cSBruce Richardson if (bad_ptr != NULL) 853a9de470cSBruce Richardson goto err_return; 854a9de470cSBruce Richardson 8554a5a8678SAnatoly Burakov /* rte_realloc expected to return null with inappropriate alignment */ 8564a5a8678SAnatoly Burakov bad_ptr = rte_realloc(NULL, size, align); 8574a5a8678SAnatoly Burakov if (bad_ptr != NULL) 8584a5a8678SAnatoly Burakov goto err_return; 8594a5a8678SAnatoly Burakov 86017b347daSStephen Hemminger #if defined(RTE_CC_GCC) || defined(RTE_CC_CLANG) 86117b347daSStephen Hemminger /* this test can not be built, will get trapped at compile time! */ 86217b347daSStephen Hemminger #else 863b341a09cSBing Zhao /* rte_malloc expected to return null with size will cause overflow */ 864b341a09cSBing Zhao align = RTE_CACHE_LINE_SIZE; 865b341a09cSBing Zhao size = (size_t)-8; 866b341a09cSBing Zhao 867b341a09cSBing Zhao bad_ptr = rte_malloc(type, size, align); 868b341a09cSBing Zhao if (bad_ptr != NULL) 869b341a09cSBing Zhao goto err_return; 870b341a09cSBing Zhao 871b341a09cSBing Zhao bad_ptr = rte_realloc(NULL, size, align); 872b341a09cSBing Zhao if (bad_ptr != NULL) 873b341a09cSBing Zhao goto err_return; 87417b347daSStephen Hemminger #endif 875a9de470cSBruce Richardson return 0; 876a9de470cSBruce Richardson 877a9de470cSBruce Richardson err_return: 878a9de470cSBruce Richardson /* clean up pointer */ 879a9de470cSBruce Richardson rte_free(bad_ptr); 880a9de470cSBruce Richardson return -1; 881a9de470cSBruce Richardson } 882a9de470cSBruce Richardson 883a9de470cSBruce Richardson static int 884a9de470cSBruce Richardson check_socket_mem(const struct rte_memseg_list *msl, void *arg) 885a9de470cSBruce Richardson { 886a9de470cSBruce Richardson int32_t *socket = arg; 887a9de470cSBruce Richardson 888a9de470cSBruce Richardson if (msl->external) 889a9de470cSBruce Richardson return 0; 890a9de470cSBruce Richardson 891a9de470cSBruce Richardson return *socket == msl->socket_id; 892a9de470cSBruce Richardson } 893a9de470cSBruce Richardson 894a9de470cSBruce Richardson /* Check if memory is available on a specific socket */ 895a9de470cSBruce Richardson static int 896a9de470cSBruce Richardson is_mem_on_socket(int32_t socket) 897a9de470cSBruce Richardson { 898a9de470cSBruce Richardson return rte_memseg_list_walk(check_socket_mem, &socket); 899a9de470cSBruce Richardson } 900a9de470cSBruce Richardson 901a9de470cSBruce Richardson 902a9de470cSBruce Richardson /* 903a9de470cSBruce Richardson * Find what socket a memory address is on. Only works for addresses within 904a9de470cSBruce Richardson * memsegs, not heap or stack... 905a9de470cSBruce Richardson */ 906a9de470cSBruce Richardson static int32_t 907a9de470cSBruce Richardson addr_to_socket(void * addr) 908a9de470cSBruce Richardson { 909a9de470cSBruce Richardson const struct rte_memseg *ms = rte_mem_virt2memseg(addr, NULL); 910a9de470cSBruce Richardson return ms == NULL ? -1 : ms->socket_id; 911a9de470cSBruce Richardson 912a9de470cSBruce Richardson } 913a9de470cSBruce Richardson 914a9de470cSBruce Richardson /* Test using rte_[c|m|zm]alloc_socket() on a specific socket */ 915a9de470cSBruce Richardson static int 916a9de470cSBruce Richardson test_alloc_single_socket(int32_t socket) 917a9de470cSBruce Richardson { 918a9de470cSBruce Richardson const char *type = NULL; 919a9de470cSBruce Richardson const size_t size = 10; 920a9de470cSBruce Richardson const unsigned align = 0; 921a9de470cSBruce Richardson char *mem = NULL; 922a9de470cSBruce Richardson int32_t desired_socket = (socket == SOCKET_ID_ANY) ? 923a9de470cSBruce Richardson (int32_t)rte_socket_id() : socket; 924a9de470cSBruce Richardson 925a9de470cSBruce Richardson /* Test rte_calloc_socket() */ 926a9de470cSBruce Richardson mem = rte_calloc_socket(type, size, sizeof(char), align, socket); 927a9de470cSBruce Richardson if (mem == NULL) 928a9de470cSBruce Richardson return -1; 929a9de470cSBruce Richardson if (addr_to_socket(mem) != desired_socket) { 930a9de470cSBruce Richardson rte_free(mem); 931a9de470cSBruce Richardson return -1; 932a9de470cSBruce Richardson } 933a9de470cSBruce Richardson rte_free(mem); 934a9de470cSBruce Richardson 935a9de470cSBruce Richardson /* Test rte_malloc_socket() */ 936a9de470cSBruce Richardson mem = rte_malloc_socket(type, size, align, socket); 937a9de470cSBruce Richardson if (mem == NULL) 938a9de470cSBruce Richardson return -1; 939a9de470cSBruce Richardson if (addr_to_socket(mem) != desired_socket) { 940ec8ef136SRuifeng Wang rte_free(mem); 941a9de470cSBruce Richardson return -1; 942a9de470cSBruce Richardson } 943a9de470cSBruce Richardson rte_free(mem); 944a9de470cSBruce Richardson 945a9de470cSBruce Richardson /* Test rte_zmalloc_socket() */ 946a9de470cSBruce Richardson mem = rte_zmalloc_socket(type, size, align, socket); 947a9de470cSBruce Richardson if (mem == NULL) 948a9de470cSBruce Richardson return -1; 949a9de470cSBruce Richardson if (addr_to_socket(mem) != desired_socket) { 950a9de470cSBruce Richardson rte_free(mem); 951a9de470cSBruce Richardson return -1; 952a9de470cSBruce Richardson } 953a9de470cSBruce Richardson rte_free(mem); 954a9de470cSBruce Richardson 955a9de470cSBruce Richardson return 0; 956a9de470cSBruce Richardson } 957a9de470cSBruce Richardson 958a9de470cSBruce Richardson static int 959a9de470cSBruce Richardson test_alloc_socket(void) 960a9de470cSBruce Richardson { 961a9de470cSBruce Richardson unsigned socket_count = 0; 962a9de470cSBruce Richardson unsigned i; 963a9de470cSBruce Richardson 964a9de470cSBruce Richardson if (test_alloc_single_socket(SOCKET_ID_ANY) < 0) 965a9de470cSBruce Richardson return -1; 966a9de470cSBruce Richardson 967a9de470cSBruce Richardson for (i = 0; i < RTE_MAX_NUMA_NODES; i++) { 968a9de470cSBruce Richardson if (is_mem_on_socket(i)) { 969a9de470cSBruce Richardson socket_count++; 970a9de470cSBruce Richardson if (test_alloc_single_socket(i) < 0) { 971a9de470cSBruce Richardson printf("Fail: rte_malloc_socket(..., %u) did not succeed\n", 972a9de470cSBruce Richardson i); 973a9de470cSBruce Richardson return -1; 974a9de470cSBruce Richardson } 975a9de470cSBruce Richardson } 976a9de470cSBruce Richardson else { 977a9de470cSBruce Richardson if (test_alloc_single_socket(i) == 0) { 978a9de470cSBruce Richardson printf("Fail: rte_malloc_socket(..., %u) succeeded\n", 979a9de470cSBruce Richardson i); 980a9de470cSBruce Richardson return -1; 981a9de470cSBruce Richardson } 982a9de470cSBruce Richardson } 983a9de470cSBruce Richardson } 984a9de470cSBruce Richardson 9854a6672c2SStephen Hemminger /* Print warning if only a single socket, but don't fail the test */ 986a9de470cSBruce Richardson if (socket_count < 2) { 987a9de470cSBruce Richardson printf("WARNING: alloc_socket test needs memory on multiple sockets!\n"); 988a9de470cSBruce Richardson } 989a9de470cSBruce Richardson 990a9de470cSBruce Richardson return 0; 991a9de470cSBruce Richardson } 992a9de470cSBruce Richardson 993a9de470cSBruce Richardson static int 994a9de470cSBruce Richardson test_malloc(void) 995a9de470cSBruce Richardson { 996a9de470cSBruce Richardson unsigned lcore_id; 997a9de470cSBruce Richardson int ret = 0; 998a9de470cSBruce Richardson 999a9de470cSBruce Richardson if (test_str_to_size() < 0){ 1000a9de470cSBruce Richardson printf("test_str_to_size() failed\n"); 1001a9de470cSBruce Richardson return -1; 1002a9de470cSBruce Richardson } 1003a9de470cSBruce Richardson else printf("test_str_to_size() passed\n"); 1004a9de470cSBruce Richardson 1005a9de470cSBruce Richardson if (test_zero_aligned_alloc() < 0){ 1006a9de470cSBruce Richardson printf("test_zero_aligned_alloc() failed\n"); 1007a9de470cSBruce Richardson return -1; 1008a9de470cSBruce Richardson } 1009a9de470cSBruce Richardson else printf("test_zero_aligned_alloc() passed\n"); 1010a9de470cSBruce Richardson 1011a9de470cSBruce Richardson if (test_malloc_bad_params() < 0){ 1012a9de470cSBruce Richardson printf("test_malloc_bad_params() failed\n"); 1013a9de470cSBruce Richardson return -1; 1014a9de470cSBruce Richardson } 1015a9de470cSBruce Richardson else printf("test_malloc_bad_params() passed\n"); 1016a9de470cSBruce Richardson 1017a9de470cSBruce Richardson if (test_realloc() < 0){ 1018a9de470cSBruce Richardson printf("test_realloc() failed\n"); 1019a9de470cSBruce Richardson return -1; 1020a9de470cSBruce Richardson } 1021a9de470cSBruce Richardson else printf("test_realloc() passed\n"); 1022a9de470cSBruce Richardson 1023a9de470cSBruce Richardson /*----------------------------*/ 1024cb056611SStephen Hemminger RTE_LCORE_FOREACH_WORKER(lcore_id) { 1025a9de470cSBruce Richardson rte_eal_remote_launch(test_align_overlap_per_lcore, NULL, lcore_id); 1026a9de470cSBruce Richardson } 1027a9de470cSBruce Richardson 1028cb056611SStephen Hemminger RTE_LCORE_FOREACH_WORKER(lcore_id) { 1029a9de470cSBruce Richardson if (rte_eal_wait_lcore(lcore_id) < 0) 1030a9de470cSBruce Richardson ret = -1; 1031a9de470cSBruce Richardson } 1032a9de470cSBruce Richardson if (ret < 0){ 1033a9de470cSBruce Richardson printf("test_align_overlap_per_lcore() failed\n"); 1034a9de470cSBruce Richardson return ret; 1035a9de470cSBruce Richardson } 1036a9de470cSBruce Richardson else printf("test_align_overlap_per_lcore() passed\n"); 1037a9de470cSBruce Richardson 1038a9de470cSBruce Richardson /*----------------------------*/ 1039cb056611SStephen Hemminger RTE_LCORE_FOREACH_WORKER(lcore_id) { 1040a9de470cSBruce Richardson rte_eal_remote_launch(test_reordered_free_per_lcore, NULL, lcore_id); 1041a9de470cSBruce Richardson } 1042a9de470cSBruce Richardson 1043cb056611SStephen Hemminger RTE_LCORE_FOREACH_WORKER(lcore_id) { 1044a9de470cSBruce Richardson if (rte_eal_wait_lcore(lcore_id) < 0) 1045a9de470cSBruce Richardson ret = -1; 1046a9de470cSBruce Richardson } 1047a9de470cSBruce Richardson if (ret < 0){ 1048a9de470cSBruce Richardson printf("test_reordered_free_per_lcore() failed\n"); 1049a9de470cSBruce Richardson return ret; 1050a9de470cSBruce Richardson } 1051a9de470cSBruce Richardson else printf("test_reordered_free_per_lcore() passed\n"); 1052a9de470cSBruce Richardson 1053a9de470cSBruce Richardson /*----------------------------*/ 1054cb056611SStephen Hemminger RTE_LCORE_FOREACH_WORKER(lcore_id) { 1055a9de470cSBruce Richardson rte_eal_remote_launch(test_random_alloc_free, NULL, lcore_id); 1056a9de470cSBruce Richardson } 1057a9de470cSBruce Richardson 1058cb056611SStephen Hemminger RTE_LCORE_FOREACH_WORKER(lcore_id) { 1059a9de470cSBruce Richardson if (rte_eal_wait_lcore(lcore_id) < 0) 1060a9de470cSBruce Richardson ret = -1; 1061a9de470cSBruce Richardson } 1062a9de470cSBruce Richardson if (ret < 0){ 1063a9de470cSBruce Richardson printf("test_random_alloc_free() failed\n"); 1064a9de470cSBruce Richardson return ret; 1065a9de470cSBruce Richardson } 1066a9de470cSBruce Richardson else printf("test_random_alloc_free() passed\n"); 1067a9de470cSBruce Richardson 1068a9de470cSBruce Richardson /*----------------------------*/ 1069a9de470cSBruce Richardson ret = test_rte_malloc_validate(); 1070a9de470cSBruce Richardson if (ret < 0){ 1071a9de470cSBruce Richardson printf("test_rte_malloc_validate() failed\n"); 1072a9de470cSBruce Richardson return ret; 1073a9de470cSBruce Richardson } 1074a9de470cSBruce Richardson else printf("test_rte_malloc_validate() passed\n"); 1075a9de470cSBruce Richardson 1076a9de470cSBruce Richardson ret = test_alloc_socket(); 1077a9de470cSBruce Richardson if (ret < 0){ 1078a9de470cSBruce Richardson printf("test_alloc_socket() failed\n"); 1079a9de470cSBruce Richardson return ret; 1080a9de470cSBruce Richardson } 1081a9de470cSBruce Richardson else printf("test_alloc_socket() passed\n"); 1082a9de470cSBruce Richardson 1083a9de470cSBruce Richardson ret = test_multi_alloc_statistics(); 1084a9de470cSBruce Richardson if (ret < 0) { 1085a9de470cSBruce Richardson printf("test_multi_alloc_statistics() failed\n"); 1086a9de470cSBruce Richardson return ret; 1087a9de470cSBruce Richardson } 1088a9de470cSBruce Richardson else 1089a9de470cSBruce Richardson printf("test_multi_alloc_statistics() passed\n"); 1090a9de470cSBruce Richardson 1091a9de470cSBruce Richardson return 0; 1092a9de470cSBruce Richardson } 1093a9de470cSBruce Richardson 1094*e0a8442cSBruce Richardson REGISTER_FAST_TEST(malloc_autotest, false, true, test_malloc); 1095