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