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