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