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 and 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 may increase, or may 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_totalsz_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 post_stats.free_count != pre_stats.free_count - 1) { 341 printf("Malloc statistics are incorrect - free_count\n"); 342 return -1; 343 } 344 345 rte_free(p1); 346 return 0; 347 } 348 349 static int 350 test_multi_alloc_statistics(void) 351 { 352 int socket = 0; 353 struct rte_malloc_socket_stats pre_stats, post_stats ,first_stats, second_stats; 354 size_t size = 2048; 355 int align = 1024; 356 #ifndef RTE_LIBRTE_MALLOC_DEBUG 357 int trailer_size = 0; 358 #else 359 int trailer_size = 64; 360 #endif 361 int overhead = 64 + trailer_size; 362 363 rte_malloc_get_socket_stats(socket, &pre_stats); 364 365 void *p1 = rte_malloc_socket("stats", size , align, socket); 366 if (!p1) 367 return -1; 368 rte_free(p1); 369 rte_malloc_dump_stats(stdout, "stats"); 370 371 rte_malloc_get_socket_stats(socket,&post_stats); 372 /* Check statistics reported are correct */ 373 /* All post stats should be equal to pre stats after alloc freed */ 374 if ((post_stats.heap_totalsz_bytes != pre_stats.heap_totalsz_bytes) && 375 (post_stats.heap_freesz_bytes!=pre_stats.heap_freesz_bytes) && 376 (post_stats.heap_allocsz_bytes!=pre_stats.heap_allocsz_bytes)&& 377 (post_stats.alloc_count!=pre_stats.alloc_count)&& 378 (post_stats.free_count!=pre_stats.free_count)) { 379 printf("Malloc statistics are incorrect - freed alloc\n"); 380 return -1; 381 } 382 /* Check two consecutive allocations */ 383 size = 1024; 384 align = 0; 385 rte_malloc_get_socket_stats(socket,&pre_stats); 386 void *p2 = rte_malloc_socket("add", size ,align, socket); 387 if (!p2) 388 return -1; 389 rte_malloc_get_socket_stats(socket,&first_stats); 390 391 void *p3 = rte_malloc_socket("add2", size,align, socket); 392 if (!p3) 393 return -1; 394 395 rte_malloc_get_socket_stats(socket,&second_stats); 396 397 rte_free(p2); 398 rte_free(p3); 399 400 /* After freeing both allocations check stats return to original */ 401 rte_malloc_get_socket_stats(socket, &post_stats); 402 403 /* 404 * Check that no new blocks added after small allocations 405 * i.e. < RTE_MALLOC_MEMZONE_SIZE 406 */ 407 if(second_stats.heap_totalsz_bytes != first_stats.heap_totalsz_bytes) { 408 printf("Incorrect heap statistics: Total size \n"); 409 return -1; 410 } 411 /* Check allocated size is equal to two additions plus overhead */ 412 if(second_stats.heap_allocsz_bytes != 413 size + overhead + first_stats.heap_allocsz_bytes) { 414 printf("Incorrect heap statistics: Allocated size \n"); 415 return -1; 416 } 417 /* Check that allocation count increments correctly i.e. +1 */ 418 if (second_stats.alloc_count != first_stats.alloc_count + 1) { 419 printf("Incorrect heap statistics: Allocated count \n"); 420 return -1; 421 } 422 423 if (second_stats.free_count != first_stats.free_count){ 424 printf("Incorrect heap statistics: Free count \n"); 425 return -1; 426 } 427 428 /* Make sure that we didn't touch our greatest chunk: 2 * 11M) */ 429 if (post_stats.greatest_free_size != pre_stats.greatest_free_size) { 430 printf("Incorrect heap statistics: Greatest free size \n"); 431 return -1; 432 } 433 /* Free size must equal the original free size minus the new allocation*/ 434 if (first_stats.heap_freesz_bytes <= second_stats.heap_freesz_bytes) { 435 printf("Incorrect heap statistics: Free size \n"); 436 return -1; 437 } 438 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", (size_t)(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(stdout, 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 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 static 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_multi_alloc_statistics() failed\n"); 1041 return ret; 1042 } 1043 else 1044 printf("test_multi_alloc_statistics() passed\n"); 1045 1046 return 0; 1047 } 1048 1049 static struct test_command malloc_cmd = { 1050 .command = "malloc_autotest", 1051 .callback = test_malloc, 1052 }; 1053 REGISTER_TEST_COMMAND(malloc_cmd); 1054