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