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