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