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 /* rte_malloc expected to return null with size will cause overflow */ 750 align = RTE_CACHE_LINE_SIZE; 751 size = (size_t)-8; 752 753 bad_ptr = rte_malloc(type, size, align); 754 if (bad_ptr != NULL) 755 goto err_return; 756 757 bad_ptr = rte_realloc(NULL, size, align); 758 if (bad_ptr != NULL) 759 goto err_return; 760 761 return 0; 762 763 err_return: 764 /* clean up pointer */ 765 if (bad_ptr) 766 rte_free(bad_ptr); 767 return -1; 768 } 769 770 static int 771 check_socket_mem(const struct rte_memseg_list *msl, void *arg) 772 { 773 int32_t *socket = arg; 774 775 if (msl->external) 776 return 0; 777 778 return *socket == msl->socket_id; 779 } 780 781 /* Check if memory is available on a specific socket */ 782 static int 783 is_mem_on_socket(int32_t socket) 784 { 785 return rte_memseg_list_walk(check_socket_mem, &socket); 786 } 787 788 789 /* 790 * Find what socket a memory address is on. Only works for addresses within 791 * memsegs, not heap or stack... 792 */ 793 static int32_t 794 addr_to_socket(void * addr) 795 { 796 const struct rte_memseg *ms = rte_mem_virt2memseg(addr, NULL); 797 return ms == NULL ? -1 : ms->socket_id; 798 799 } 800 801 /* Test using rte_[c|m|zm]alloc_socket() on a specific socket */ 802 static int 803 test_alloc_single_socket(int32_t socket) 804 { 805 const char *type = NULL; 806 const size_t size = 10; 807 const unsigned align = 0; 808 char *mem = NULL; 809 int32_t desired_socket = (socket == SOCKET_ID_ANY) ? 810 (int32_t)rte_socket_id() : socket; 811 812 /* Test rte_calloc_socket() */ 813 mem = rte_calloc_socket(type, size, sizeof(char), align, socket); 814 if (mem == NULL) 815 return -1; 816 if (addr_to_socket(mem) != desired_socket) { 817 rte_free(mem); 818 return -1; 819 } 820 rte_free(mem); 821 822 /* Test rte_malloc_socket() */ 823 mem = rte_malloc_socket(type, size, align, socket); 824 if (mem == NULL) 825 return -1; 826 if (addr_to_socket(mem) != desired_socket) { 827 return -1; 828 } 829 rte_free(mem); 830 831 /* Test rte_zmalloc_socket() */ 832 mem = rte_zmalloc_socket(type, size, align, socket); 833 if (mem == NULL) 834 return -1; 835 if (addr_to_socket(mem) != desired_socket) { 836 rte_free(mem); 837 return -1; 838 } 839 rte_free(mem); 840 841 return 0; 842 } 843 844 static int 845 test_alloc_socket(void) 846 { 847 unsigned socket_count = 0; 848 unsigned i; 849 850 if (test_alloc_single_socket(SOCKET_ID_ANY) < 0) 851 return -1; 852 853 for (i = 0; i < RTE_MAX_NUMA_NODES; i++) { 854 if (is_mem_on_socket(i)) { 855 socket_count++; 856 if (test_alloc_single_socket(i) < 0) { 857 printf("Fail: rte_malloc_socket(..., %u) did not succeed\n", 858 i); 859 return -1; 860 } 861 } 862 else { 863 if (test_alloc_single_socket(i) == 0) { 864 printf("Fail: rte_malloc_socket(..., %u) succeeded\n", 865 i); 866 return -1; 867 } 868 } 869 } 870 871 /* Print warnign if only a single socket, but don't fail the test */ 872 if (socket_count < 2) { 873 printf("WARNING: alloc_socket test needs memory on multiple sockets!\n"); 874 } 875 876 return 0; 877 } 878 879 static int 880 test_malloc(void) 881 { 882 unsigned lcore_id; 883 int ret = 0; 884 885 if (test_str_to_size() < 0){ 886 printf("test_str_to_size() failed\n"); 887 return -1; 888 } 889 else printf("test_str_to_size() passed\n"); 890 891 if (test_zero_aligned_alloc() < 0){ 892 printf("test_zero_aligned_alloc() failed\n"); 893 return -1; 894 } 895 else printf("test_zero_aligned_alloc() passed\n"); 896 897 if (test_malloc_bad_params() < 0){ 898 printf("test_malloc_bad_params() failed\n"); 899 return -1; 900 } 901 else printf("test_malloc_bad_params() passed\n"); 902 903 if (test_realloc() < 0){ 904 printf("test_realloc() failed\n"); 905 return -1; 906 } 907 else printf("test_realloc() passed\n"); 908 909 /*----------------------------*/ 910 RTE_LCORE_FOREACH_SLAVE(lcore_id) { 911 rte_eal_remote_launch(test_align_overlap_per_lcore, NULL, lcore_id); 912 } 913 914 RTE_LCORE_FOREACH_SLAVE(lcore_id) { 915 if (rte_eal_wait_lcore(lcore_id) < 0) 916 ret = -1; 917 } 918 if (ret < 0){ 919 printf("test_align_overlap_per_lcore() failed\n"); 920 return ret; 921 } 922 else printf("test_align_overlap_per_lcore() passed\n"); 923 924 /*----------------------------*/ 925 RTE_LCORE_FOREACH_SLAVE(lcore_id) { 926 rte_eal_remote_launch(test_reordered_free_per_lcore, NULL, lcore_id); 927 } 928 929 RTE_LCORE_FOREACH_SLAVE(lcore_id) { 930 if (rte_eal_wait_lcore(lcore_id) < 0) 931 ret = -1; 932 } 933 if (ret < 0){ 934 printf("test_reordered_free_per_lcore() failed\n"); 935 return ret; 936 } 937 else printf("test_reordered_free_per_lcore() passed\n"); 938 939 /*----------------------------*/ 940 RTE_LCORE_FOREACH_SLAVE(lcore_id) { 941 rte_eal_remote_launch(test_random_alloc_free, NULL, lcore_id); 942 } 943 944 RTE_LCORE_FOREACH_SLAVE(lcore_id) { 945 if (rte_eal_wait_lcore(lcore_id) < 0) 946 ret = -1; 947 } 948 if (ret < 0){ 949 printf("test_random_alloc_free() failed\n"); 950 return ret; 951 } 952 else printf("test_random_alloc_free() passed\n"); 953 954 /*----------------------------*/ 955 ret = test_rte_malloc_validate(); 956 if (ret < 0){ 957 printf("test_rte_malloc_validate() failed\n"); 958 return ret; 959 } 960 else printf("test_rte_malloc_validate() passed\n"); 961 962 ret = test_alloc_socket(); 963 if (ret < 0){ 964 printf("test_alloc_socket() failed\n"); 965 return ret; 966 } 967 else printf("test_alloc_socket() passed\n"); 968 969 ret = test_multi_alloc_statistics(); 970 if (ret < 0) { 971 printf("test_multi_alloc_statistics() failed\n"); 972 return ret; 973 } 974 else 975 printf("test_multi_alloc_statistics() passed\n"); 976 977 return 0; 978 } 979 980 REGISTER_TEST_COMMAND(malloc_autotest, test_malloc); 981