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