xref: /f-stack/dpdk/app/test/test_malloc.c (revision 2d9fd380)
14418919fSjohnjiang /* SPDX-License-Identifier: BSD-3-Clause
24418919fSjohnjiang  * Copyright(c) 2010-2019 Intel Corporation
34418919fSjohnjiang  */
44418919fSjohnjiang 
54418919fSjohnjiang #include <stdio.h>
64418919fSjohnjiang #include <stdint.h>
74418919fSjohnjiang #include <string.h>
84418919fSjohnjiang #include <stdarg.h>
94418919fSjohnjiang #include <errno.h>
104418919fSjohnjiang #include <stdlib.h>
11*2d9fd380Sjfb8856606 #include <sys/mman.h>
124418919fSjohnjiang #include <sys/queue.h>
13*2d9fd380Sjfb8856606 #include <unistd.h>
144418919fSjohnjiang 
154418919fSjohnjiang #include <rte_common.h>
164418919fSjohnjiang #include <rte_memory.h>
174418919fSjohnjiang #include <rte_per_lcore.h>
184418919fSjohnjiang #include <rte_launch.h>
194418919fSjohnjiang #include <rte_eal.h>
204418919fSjohnjiang #include <rte_lcore.h>
214418919fSjohnjiang #include <rte_malloc.h>
224418919fSjohnjiang #include <rte_cycles.h>
234418919fSjohnjiang #include <rte_random.h>
244418919fSjohnjiang #include <rte_string_fns.h>
254418919fSjohnjiang 
264418919fSjohnjiang #include "test.h"
274418919fSjohnjiang 
284418919fSjohnjiang #define N 10000
294418919fSjohnjiang 
304418919fSjohnjiang 
314418919fSjohnjiang static int
324418919fSjohnjiang is_mem_on_socket(int32_t socket);
334418919fSjohnjiang 
344418919fSjohnjiang static int32_t
354418919fSjohnjiang addr_to_socket(void *addr);
364418919fSjohnjiang 
374418919fSjohnjiang /*
384418919fSjohnjiang  * Malloc
394418919fSjohnjiang  * ======
404418919fSjohnjiang  *
414418919fSjohnjiang  * Allocate some dynamic memory from heap (3 areas). Check that areas
424418919fSjohnjiang  * don't overlap and that alignment constraints match. This test is
434418919fSjohnjiang  * done many times on different lcores simultaneously.
444418919fSjohnjiang  */
454418919fSjohnjiang 
464418919fSjohnjiang /* Test if memory overlaps: return 1 if true, or 0 if false. */
474418919fSjohnjiang static int
is_memory_overlap(void * p1,size_t len1,void * p2,size_t len2)484418919fSjohnjiang is_memory_overlap(void *p1, size_t len1, void *p2, size_t len2)
494418919fSjohnjiang {
504418919fSjohnjiang 	unsigned long ptr1 = (unsigned long)p1;
514418919fSjohnjiang 	unsigned long ptr2 = (unsigned long)p2;
524418919fSjohnjiang 
534418919fSjohnjiang 	if (ptr2 >= ptr1 && (ptr2 - ptr1) < len1)
544418919fSjohnjiang 		return 1;
554418919fSjohnjiang 	else if (ptr2 < ptr1 && (ptr1 - ptr2) < len2)
564418919fSjohnjiang 		return 1;
574418919fSjohnjiang 	return 0;
584418919fSjohnjiang }
594418919fSjohnjiang 
604418919fSjohnjiang static int
is_aligned(void * p,int align)614418919fSjohnjiang is_aligned(void *p, int align)
624418919fSjohnjiang {
634418919fSjohnjiang 	unsigned long addr = (unsigned long)p;
644418919fSjohnjiang 	unsigned mask = align - 1;
654418919fSjohnjiang 
664418919fSjohnjiang 	if (addr & mask)
674418919fSjohnjiang 		return 0;
684418919fSjohnjiang 	return 1;
694418919fSjohnjiang }
704418919fSjohnjiang 
714418919fSjohnjiang static int
test_align_overlap_per_lcore(__rte_unused void * arg)72*2d9fd380Sjfb8856606 test_align_overlap_per_lcore(__rte_unused void *arg)
734418919fSjohnjiang {
744418919fSjohnjiang 	const unsigned align1 = 8,
754418919fSjohnjiang 			align2 = 64,
764418919fSjohnjiang 			align3 = 2048;
774418919fSjohnjiang 	unsigned i,j;
784418919fSjohnjiang 	void *p1 = NULL, *p2 = NULL, *p3 = NULL;
794418919fSjohnjiang 	int ret = 0;
804418919fSjohnjiang 
814418919fSjohnjiang 	for (i = 0; i < N; i++) {
824418919fSjohnjiang 		p1 = rte_zmalloc("dummy", 1000, align1);
834418919fSjohnjiang 		if (!p1){
844418919fSjohnjiang 			printf("rte_zmalloc returned NULL (i=%u)\n", i);
854418919fSjohnjiang 			ret = -1;
864418919fSjohnjiang 			break;
874418919fSjohnjiang 		}
884418919fSjohnjiang 		for(j = 0; j < 1000 ; j++) {
894418919fSjohnjiang 			if( *(char *)p1 != 0) {
904418919fSjohnjiang 				printf("rte_zmalloc didn't zero the allocated memory\n");
914418919fSjohnjiang 				ret = -1;
924418919fSjohnjiang 			}
934418919fSjohnjiang 		}
944418919fSjohnjiang 		p2 = rte_malloc("dummy", 1000, align2);
954418919fSjohnjiang 		if (!p2){
964418919fSjohnjiang 			printf("rte_malloc returned NULL (i=%u)\n", i);
974418919fSjohnjiang 			ret = -1;
984418919fSjohnjiang 			rte_free(p1);
994418919fSjohnjiang 			break;
1004418919fSjohnjiang 		}
1014418919fSjohnjiang 		p3 = rte_malloc("dummy", 1000, align3);
1024418919fSjohnjiang 		if (!p3){
1034418919fSjohnjiang 			printf("rte_malloc returned NULL (i=%u)\n", i);
1044418919fSjohnjiang 			ret = -1;
1054418919fSjohnjiang 			rte_free(p1);
1064418919fSjohnjiang 			rte_free(p2);
1074418919fSjohnjiang 			break;
1084418919fSjohnjiang 		}
1094418919fSjohnjiang 		if (is_memory_overlap(p1, 1000, p2, 1000)) {
1104418919fSjohnjiang 			printf("p1 and p2 overlaps\n");
1114418919fSjohnjiang 			ret = -1;
1124418919fSjohnjiang 		}
1134418919fSjohnjiang 		if (is_memory_overlap(p2, 1000, p3, 1000)) {
1144418919fSjohnjiang 			printf("p2 and p3 overlaps\n");
1154418919fSjohnjiang 			ret = -1;
1164418919fSjohnjiang 		}
1174418919fSjohnjiang 		if (is_memory_overlap(p1, 1000, p3, 1000)) {
1184418919fSjohnjiang 			printf("p1 and p3 overlaps\n");
1194418919fSjohnjiang 			ret = -1;
1204418919fSjohnjiang 		}
1214418919fSjohnjiang 		if (!is_aligned(p1, align1)) {
1224418919fSjohnjiang 			printf("p1 is not aligned\n");
1234418919fSjohnjiang 			ret = -1;
1244418919fSjohnjiang 		}
1254418919fSjohnjiang 		if (!is_aligned(p2, align2)) {
1264418919fSjohnjiang 			printf("p2 is not aligned\n");
1274418919fSjohnjiang 			ret = -1;
1284418919fSjohnjiang 		}
1294418919fSjohnjiang 		if (!is_aligned(p3, align3)) {
1304418919fSjohnjiang 			printf("p3 is not aligned\n");
1314418919fSjohnjiang 			ret = -1;
1324418919fSjohnjiang 		}
1334418919fSjohnjiang 		rte_free(p1);
1344418919fSjohnjiang 		rte_free(p2);
1354418919fSjohnjiang 		rte_free(p3);
1364418919fSjohnjiang 	}
1374418919fSjohnjiang 	rte_malloc_dump_stats(stdout, "dummy");
1384418919fSjohnjiang 
1394418919fSjohnjiang 	return ret;
1404418919fSjohnjiang }
1414418919fSjohnjiang 
1424418919fSjohnjiang static int
test_reordered_free_per_lcore(__rte_unused void * arg)143*2d9fd380Sjfb8856606 test_reordered_free_per_lcore(__rte_unused void *arg)
1444418919fSjohnjiang {
1454418919fSjohnjiang 	const unsigned align1 = 8,
1464418919fSjohnjiang 			align2 = 64,
1474418919fSjohnjiang 			align3 = 2048;
1484418919fSjohnjiang 	unsigned i,j;
1494418919fSjohnjiang 	void *p1, *p2, *p3;
1504418919fSjohnjiang 	int ret = 0;
1514418919fSjohnjiang 
1524418919fSjohnjiang 	for (i = 0; i < 30; i++) {
1534418919fSjohnjiang 		p1 = rte_zmalloc("dummy", 1000, align1);
1544418919fSjohnjiang 		if (!p1){
1554418919fSjohnjiang 			printf("rte_zmalloc returned NULL (i=%u)\n", i);
1564418919fSjohnjiang 			ret = -1;
1574418919fSjohnjiang 			break;
1584418919fSjohnjiang 		}
1594418919fSjohnjiang 		for(j = 0; j < 1000 ; j++) {
1604418919fSjohnjiang 			if( *(char *)p1 != 0) {
1614418919fSjohnjiang 				printf("rte_zmalloc didn't zero the allocated memory\n");
1624418919fSjohnjiang 				ret = -1;
1634418919fSjohnjiang 			}
1644418919fSjohnjiang 		}
1654418919fSjohnjiang 		/* use calloc to allocate 1000 16-byte items this time */
1664418919fSjohnjiang 		p2 = rte_calloc("dummy", 1000, 16, align2);
1674418919fSjohnjiang 		/* for third request use regular malloc again */
1684418919fSjohnjiang 		p3 = rte_malloc("dummy", 1000, align3);
1694418919fSjohnjiang 		if (!p2 || !p3){
1704418919fSjohnjiang 			printf("rte_malloc returned NULL (i=%u)\n", i);
1714418919fSjohnjiang 			ret = -1;
1724418919fSjohnjiang 			break;
1734418919fSjohnjiang 		}
1744418919fSjohnjiang 		if (is_memory_overlap(p1, 1000, p2, 1000)) {
1754418919fSjohnjiang 			printf("p1 and p2 overlaps\n");
1764418919fSjohnjiang 			ret = -1;
1774418919fSjohnjiang 		}
1784418919fSjohnjiang 		if (is_memory_overlap(p2, 1000, p3, 1000)) {
1794418919fSjohnjiang 			printf("p2 and p3 overlaps\n");
1804418919fSjohnjiang 			ret = -1;
1814418919fSjohnjiang 		}
1824418919fSjohnjiang 		if (is_memory_overlap(p1, 1000, p3, 1000)) {
1834418919fSjohnjiang 			printf("p1 and p3 overlaps\n");
1844418919fSjohnjiang 			ret = -1;
1854418919fSjohnjiang 		}
1864418919fSjohnjiang 		if (!is_aligned(p1, align1)) {
1874418919fSjohnjiang 			printf("p1 is not aligned\n");
1884418919fSjohnjiang 			ret = -1;
1894418919fSjohnjiang 		}
1904418919fSjohnjiang 		if (!is_aligned(p2, align2)) {
1914418919fSjohnjiang 			printf("p2 is not aligned\n");
1924418919fSjohnjiang 			ret = -1;
1934418919fSjohnjiang 		}
1944418919fSjohnjiang 		if (!is_aligned(p3, align3)) {
1954418919fSjohnjiang 			printf("p3 is not aligned\n");
1964418919fSjohnjiang 			ret = -1;
1974418919fSjohnjiang 		}
1984418919fSjohnjiang 		/* try freeing in every possible order */
1994418919fSjohnjiang 		switch (i%6){
2004418919fSjohnjiang 		case 0:
2014418919fSjohnjiang 			rte_free(p1);
2024418919fSjohnjiang 			rte_free(p2);
2034418919fSjohnjiang 			rte_free(p3);
2044418919fSjohnjiang 			break;
2054418919fSjohnjiang 		case 1:
2064418919fSjohnjiang 			rte_free(p1);
2074418919fSjohnjiang 			rte_free(p3);
2084418919fSjohnjiang 			rte_free(p2);
2094418919fSjohnjiang 			break;
2104418919fSjohnjiang 		case 2:
2114418919fSjohnjiang 			rte_free(p2);
2124418919fSjohnjiang 			rte_free(p1);
2134418919fSjohnjiang 			rte_free(p3);
2144418919fSjohnjiang 			break;
2154418919fSjohnjiang 		case 3:
2164418919fSjohnjiang 			rte_free(p2);
2174418919fSjohnjiang 			rte_free(p3);
2184418919fSjohnjiang 			rte_free(p1);
2194418919fSjohnjiang 			break;
2204418919fSjohnjiang 		case 4:
2214418919fSjohnjiang 			rte_free(p3);
2224418919fSjohnjiang 			rte_free(p1);
2234418919fSjohnjiang 			rte_free(p2);
2244418919fSjohnjiang 			break;
2254418919fSjohnjiang 		case 5:
2264418919fSjohnjiang 			rte_free(p3);
2274418919fSjohnjiang 			rte_free(p2);
2284418919fSjohnjiang 			rte_free(p1);
2294418919fSjohnjiang 			break;
2304418919fSjohnjiang 		}
2314418919fSjohnjiang 	}
2324418919fSjohnjiang 	rte_malloc_dump_stats(stdout, "dummy");
2334418919fSjohnjiang 
2344418919fSjohnjiang 	return ret;
2354418919fSjohnjiang }
2364418919fSjohnjiang 
2374418919fSjohnjiang /* test function inside the malloc lib*/
2384418919fSjohnjiang static int
test_str_to_size(void)2394418919fSjohnjiang test_str_to_size(void)
2404418919fSjohnjiang {
2414418919fSjohnjiang 	struct {
2424418919fSjohnjiang 		const char *str;
2434418919fSjohnjiang 		uint64_t value;
2444418919fSjohnjiang 	} test_values[] =
2454418919fSjohnjiang 	{{ "5G", (uint64_t)5 * 1024 * 1024 *1024 },
2464418919fSjohnjiang 			{"0x20g", (uint64_t)0x20 * 1024 * 1024 *1024},
2474418919fSjohnjiang 			{"10M", 10 * 1024 * 1024},
2484418919fSjohnjiang 			{"050m", 050 * 1024 * 1024},
2494418919fSjohnjiang 			{"8K", 8 * 1024},
2504418919fSjohnjiang 			{"15k", 15 * 1024},
2514418919fSjohnjiang 			{"0200", 0200},
2524418919fSjohnjiang 			{"0x103", 0x103},
2534418919fSjohnjiang 			{"432", 432},
2544418919fSjohnjiang 			{"-1", 0}, /* negative values return 0 */
2554418919fSjohnjiang 			{"  -2", 0},
2564418919fSjohnjiang 			{"  -3MB", 0},
2574418919fSjohnjiang 			{"18446744073709551616", 0} /* ULLONG_MAX + 1 == out of range*/
2584418919fSjohnjiang 	};
2594418919fSjohnjiang 	unsigned i;
260*2d9fd380Sjfb8856606 	for (i = 0; i < RTE_DIM(test_values); i++)
2614418919fSjohnjiang 		if (rte_str_to_size(test_values[i].str) != test_values[i].value)
2624418919fSjohnjiang 			return -1;
2634418919fSjohnjiang 	return 0;
2644418919fSjohnjiang }
2654418919fSjohnjiang 
2664418919fSjohnjiang static int
test_multi_alloc_statistics(void)2674418919fSjohnjiang test_multi_alloc_statistics(void)
2684418919fSjohnjiang {
2694418919fSjohnjiang 	int socket = 0;
2704418919fSjohnjiang 	struct rte_malloc_socket_stats pre_stats, post_stats ,first_stats, second_stats;
2714418919fSjohnjiang 	size_t size = 2048;
2724418919fSjohnjiang 	int align = 1024;
2734418919fSjohnjiang 	int overhead = 0;
2744418919fSjohnjiang 
2754418919fSjohnjiang 	/* Dynamically calculate the overhead by allocating one cacheline and
2764418919fSjohnjiang 	 * then comparing what was allocated from the heap.
2774418919fSjohnjiang 	 */
2784418919fSjohnjiang 	rte_malloc_get_socket_stats(socket, &pre_stats);
2794418919fSjohnjiang 
2804418919fSjohnjiang 	void *dummy = rte_malloc_socket(NULL, RTE_CACHE_LINE_SIZE, 0, socket);
2814418919fSjohnjiang 	if (dummy == NULL)
2824418919fSjohnjiang 		return -1;
2834418919fSjohnjiang 
2844418919fSjohnjiang 	rte_malloc_get_socket_stats(socket, &post_stats);
2854418919fSjohnjiang 
2864418919fSjohnjiang 	/* after subtracting cache line, remainder is overhead */
2874418919fSjohnjiang 	overhead = post_stats.heap_allocsz_bytes - pre_stats.heap_allocsz_bytes;
2884418919fSjohnjiang 	overhead -= RTE_CACHE_LINE_SIZE;
2894418919fSjohnjiang 
2904418919fSjohnjiang 	rte_free(dummy);
2914418919fSjohnjiang 
2924418919fSjohnjiang 	/* Now start the real tests */
2934418919fSjohnjiang 	rte_malloc_get_socket_stats(socket, &pre_stats);
2944418919fSjohnjiang 
2954418919fSjohnjiang 	void *p1 = rte_malloc_socket("stats", size , align, socket);
2964418919fSjohnjiang 	if (!p1)
2974418919fSjohnjiang 		return -1;
2984418919fSjohnjiang 	rte_free(p1);
2994418919fSjohnjiang 	rte_malloc_dump_stats(stdout, "stats");
3004418919fSjohnjiang 
3014418919fSjohnjiang 	rte_malloc_get_socket_stats(socket,&post_stats);
3024418919fSjohnjiang 	/* Check statistics reported are correct */
3034418919fSjohnjiang 	/* All post stats should be equal to pre stats after alloc freed */
3044418919fSjohnjiang 	if ((post_stats.heap_totalsz_bytes != pre_stats.heap_totalsz_bytes) &&
3054418919fSjohnjiang 			(post_stats.heap_freesz_bytes!=pre_stats.heap_freesz_bytes) &&
3064418919fSjohnjiang 			(post_stats.heap_allocsz_bytes!=pre_stats.heap_allocsz_bytes)&&
3074418919fSjohnjiang 			(post_stats.alloc_count!=pre_stats.alloc_count)&&
3084418919fSjohnjiang 			(post_stats.free_count!=pre_stats.free_count)) {
3094418919fSjohnjiang 		printf("Malloc statistics are incorrect - freed alloc\n");
3104418919fSjohnjiang 		return -1;
3114418919fSjohnjiang 	}
3124418919fSjohnjiang 	/* Check two consecutive allocations */
3134418919fSjohnjiang 	size = 1024;
3144418919fSjohnjiang 	align = 0;
3154418919fSjohnjiang 	rte_malloc_get_socket_stats(socket,&pre_stats);
3164418919fSjohnjiang 	void *p2 = rte_malloc_socket("add", size ,align, socket);
3174418919fSjohnjiang 	if (!p2)
3184418919fSjohnjiang 		return -1;
3194418919fSjohnjiang 	rte_malloc_get_socket_stats(socket,&first_stats);
3204418919fSjohnjiang 
3214418919fSjohnjiang 	void *p3 = rte_malloc_socket("add2", size,align, socket);
3224418919fSjohnjiang 	if (!p3)
3234418919fSjohnjiang 		return -1;
3244418919fSjohnjiang 
3254418919fSjohnjiang 	rte_malloc_get_socket_stats(socket,&second_stats);
3264418919fSjohnjiang 
3274418919fSjohnjiang 	rte_free(p2);
3284418919fSjohnjiang 	rte_free(p3);
3294418919fSjohnjiang 
3304418919fSjohnjiang 	/* After freeing both allocations check stats return to original */
3314418919fSjohnjiang 	rte_malloc_get_socket_stats(socket, &post_stats);
3324418919fSjohnjiang 
3334418919fSjohnjiang 	if(second_stats.heap_totalsz_bytes != first_stats.heap_totalsz_bytes) {
3344418919fSjohnjiang 		printf("Incorrect heap statistics: Total size \n");
3354418919fSjohnjiang 		return -1;
3364418919fSjohnjiang 	}
3374418919fSjohnjiang 	/* Check allocated size is equal to two additions plus overhead */
3384418919fSjohnjiang 	if(second_stats.heap_allocsz_bytes !=
3394418919fSjohnjiang 			size + overhead + first_stats.heap_allocsz_bytes) {
3404418919fSjohnjiang 		printf("Incorrect heap statistics: Allocated size \n");
3414418919fSjohnjiang 		return -1;
3424418919fSjohnjiang 	}
3434418919fSjohnjiang 	/* Check that allocation count increments correctly i.e. +1 */
3444418919fSjohnjiang 	if (second_stats.alloc_count != first_stats.alloc_count + 1) {
3454418919fSjohnjiang 		printf("Incorrect heap statistics: Allocated count \n");
3464418919fSjohnjiang 		return -1;
3474418919fSjohnjiang 	}
3484418919fSjohnjiang 
3494418919fSjohnjiang 	if (second_stats.free_count != first_stats.free_count){
3504418919fSjohnjiang 		printf("Incorrect heap statistics: Free count \n");
3514418919fSjohnjiang 		return -1;
3524418919fSjohnjiang 	}
3534418919fSjohnjiang 
3544418919fSjohnjiang 	/* Make sure that we didn't touch our greatest chunk: 2 * 11M)  */
3554418919fSjohnjiang 	if (post_stats.greatest_free_size != pre_stats.greatest_free_size) {
3564418919fSjohnjiang 		printf("Incorrect heap statistics: Greatest free size \n");
3574418919fSjohnjiang 		return -1;
3584418919fSjohnjiang 	}
3594418919fSjohnjiang 	/* Free size must equal the original free size minus the new allocation*/
3604418919fSjohnjiang 	if (first_stats.heap_freesz_bytes <= second_stats.heap_freesz_bytes) {
3614418919fSjohnjiang 		printf("Incorrect heap statistics: Free size \n");
3624418919fSjohnjiang 		return -1;
3634418919fSjohnjiang 	}
3644418919fSjohnjiang 
3654418919fSjohnjiang 	if ((post_stats.heap_totalsz_bytes != pre_stats.heap_totalsz_bytes) &&
3664418919fSjohnjiang 			(post_stats.heap_freesz_bytes!=pre_stats.heap_freesz_bytes) &&
3674418919fSjohnjiang 			(post_stats.heap_allocsz_bytes!=pre_stats.heap_allocsz_bytes)&&
3684418919fSjohnjiang 			(post_stats.alloc_count!=pre_stats.alloc_count)&&
3694418919fSjohnjiang 			(post_stats.free_count!=pre_stats.free_count)) {
3704418919fSjohnjiang 		printf("Malloc statistics are incorrect - freed alloc\n");
3714418919fSjohnjiang 		return -1;
3724418919fSjohnjiang 	}
3734418919fSjohnjiang 	return 0;
3744418919fSjohnjiang }
3754418919fSjohnjiang 
3764418919fSjohnjiang static int
test_realloc_socket(int socket)377*2d9fd380Sjfb8856606 test_realloc_socket(int socket)
3784418919fSjohnjiang {
3794418919fSjohnjiang 	const char hello_str[] = "Hello, world!";
3804418919fSjohnjiang 	const unsigned size1 = 1024;
3814418919fSjohnjiang 	const unsigned size2 = size1 + 1024;
3824418919fSjohnjiang 	const unsigned size3 = size2;
3834418919fSjohnjiang 	const unsigned size4 = size3 + 1024;
3844418919fSjohnjiang 
3854418919fSjohnjiang 	/* test data is the same even if element is moved*/
386*2d9fd380Sjfb8856606 	char *ptr1 = rte_zmalloc_socket(
387*2d9fd380Sjfb8856606 			NULL, size1, RTE_CACHE_LINE_SIZE, socket);
3884418919fSjohnjiang 	if (!ptr1){
3894418919fSjohnjiang 		printf("NULL pointer returned from rte_zmalloc\n");
3904418919fSjohnjiang 		return -1;
3914418919fSjohnjiang 	}
3924418919fSjohnjiang 	strlcpy(ptr1, hello_str, size1);
393*2d9fd380Sjfb8856606 	char *ptr2 = rte_realloc_socket(
394*2d9fd380Sjfb8856606 			ptr1, size2, RTE_CACHE_LINE_SIZE, socket);
3954418919fSjohnjiang 	if (!ptr2){
3964418919fSjohnjiang 		rte_free(ptr1);
3974418919fSjohnjiang 		printf("NULL pointer returned from rte_realloc\n");
3984418919fSjohnjiang 		return -1;
3994418919fSjohnjiang 	}
4004418919fSjohnjiang 	if (ptr1 == ptr2){
4014418919fSjohnjiang 		printf("unexpected - ptr1 == ptr2\n");
4024418919fSjohnjiang 	}
4034418919fSjohnjiang 	if (strcmp(ptr2, hello_str) != 0){
4044418919fSjohnjiang 		printf("Error - lost data from pointed area\n");
4054418919fSjohnjiang 		rte_free(ptr2);
4064418919fSjohnjiang 		return -1;
4074418919fSjohnjiang 	}
4084418919fSjohnjiang 	unsigned i;
4094418919fSjohnjiang 	for (i = strnlen(hello_str, sizeof(hello_str)); i < size1; i++)
4104418919fSjohnjiang 		if (ptr2[i] != 0){
4114418919fSjohnjiang 			printf("Bad data in realloc\n");
4124418919fSjohnjiang 			rte_free(ptr2);
4134418919fSjohnjiang 			return -1;
4144418919fSjohnjiang 		}
4154418919fSjohnjiang 	/* now allocate third element, free the second
4164418919fSjohnjiang 	 * and resize third. It should not move. (ptr1 is now invalid)
4174418919fSjohnjiang 	 */
418*2d9fd380Sjfb8856606 	char *ptr3 = rte_zmalloc_socket(
419*2d9fd380Sjfb8856606 			NULL, size3, RTE_CACHE_LINE_SIZE, socket);
4204418919fSjohnjiang 	if (!ptr3){
4214418919fSjohnjiang 		printf("NULL pointer returned from rte_zmalloc\n");
4224418919fSjohnjiang 		rte_free(ptr2);
4234418919fSjohnjiang 		return -1;
4244418919fSjohnjiang 	}
4254418919fSjohnjiang 	for (i = 0; i < size3; i++)
4264418919fSjohnjiang 		if (ptr3[i] != 0){
4274418919fSjohnjiang 			printf("Bad data in zmalloc\n");
4284418919fSjohnjiang 			rte_free(ptr3);
4294418919fSjohnjiang 			rte_free(ptr2);
4304418919fSjohnjiang 			return -1;
4314418919fSjohnjiang 		}
4324418919fSjohnjiang 	rte_free(ptr2);
4334418919fSjohnjiang 	/* first resize to half the size of the freed block */
434*2d9fd380Sjfb8856606 	char *ptr4 = rte_realloc_socket(
435*2d9fd380Sjfb8856606 			ptr3, size4, RTE_CACHE_LINE_SIZE, socket);
4364418919fSjohnjiang 	if (!ptr4){
4374418919fSjohnjiang 		printf("NULL pointer returned from rte_realloc\n");
4384418919fSjohnjiang 		rte_free(ptr3);
4394418919fSjohnjiang 		return -1;
4404418919fSjohnjiang 	}
4414418919fSjohnjiang 	if (ptr3 != ptr4){
4424418919fSjohnjiang 		printf("Unexpected - ptr4 != ptr3\n");
4434418919fSjohnjiang 		rte_free(ptr4);
4444418919fSjohnjiang 		return -1;
4454418919fSjohnjiang 	}
4464418919fSjohnjiang 	/* now resize again to the full size of the freed block */
447*2d9fd380Sjfb8856606 	ptr4 = rte_realloc_socket(ptr3, size3 + size2 + size1,
448*2d9fd380Sjfb8856606 			RTE_CACHE_LINE_SIZE, socket);
4494418919fSjohnjiang 	if (ptr3 != ptr4){
4504418919fSjohnjiang 		printf("Unexpected - ptr4 != ptr3 on second resize\n");
4514418919fSjohnjiang 		rte_free(ptr4);
4524418919fSjohnjiang 		return -1;
4534418919fSjohnjiang 	}
4544418919fSjohnjiang 	rte_free(ptr4);
4554418919fSjohnjiang 
4564418919fSjohnjiang 	/* now try a resize to a smaller size, see if it works */
4574418919fSjohnjiang 	const unsigned size5 = 1024;
4584418919fSjohnjiang 	const unsigned size6 = size5 / 2;
459*2d9fd380Sjfb8856606 	char *ptr5 = rte_malloc_socket(
460*2d9fd380Sjfb8856606 			NULL, size5, RTE_CACHE_LINE_SIZE, socket);
4614418919fSjohnjiang 	if (!ptr5){
4624418919fSjohnjiang 		printf("NULL pointer returned from rte_malloc\n");
4634418919fSjohnjiang 		return -1;
4644418919fSjohnjiang 	}
465*2d9fd380Sjfb8856606 	char *ptr6 = rte_realloc_socket(
466*2d9fd380Sjfb8856606 			ptr5, size6, RTE_CACHE_LINE_SIZE, socket);
4674418919fSjohnjiang 	if (!ptr6){
4684418919fSjohnjiang 		printf("NULL pointer returned from rte_realloc\n");
4694418919fSjohnjiang 		rte_free(ptr5);
4704418919fSjohnjiang 		return -1;
4714418919fSjohnjiang 	}
4724418919fSjohnjiang 	if (ptr5 != ptr6){
4734418919fSjohnjiang 		printf("Error, resizing to a smaller size moved data\n");
4744418919fSjohnjiang 		rte_free(ptr6);
4754418919fSjohnjiang 		return -1;
4764418919fSjohnjiang 	}
4774418919fSjohnjiang 	rte_free(ptr6);
4784418919fSjohnjiang 
4794418919fSjohnjiang 	/* check for behaviour changing alignment */
4804418919fSjohnjiang 	const unsigned size7 = 1024;
4814418919fSjohnjiang 	const unsigned orig_align = RTE_CACHE_LINE_SIZE;
4824418919fSjohnjiang 	unsigned new_align = RTE_CACHE_LINE_SIZE * 2;
483*2d9fd380Sjfb8856606 	char *ptr7 = rte_malloc_socket(NULL, size7, orig_align, socket);
4844418919fSjohnjiang 	if (!ptr7){
4854418919fSjohnjiang 		printf("NULL pointer returned from rte_malloc\n");
4864418919fSjohnjiang 		return -1;
4874418919fSjohnjiang 	}
4884418919fSjohnjiang 	/* calc an alignment we don't already have */
4894418919fSjohnjiang 	while(RTE_PTR_ALIGN(ptr7, new_align) == ptr7)
4904418919fSjohnjiang 		new_align *= 2;
491*2d9fd380Sjfb8856606 	char *ptr8 = rte_realloc_socket(ptr7, size7, new_align, socket);
4924418919fSjohnjiang 	if (!ptr8){
4934418919fSjohnjiang 		printf("NULL pointer returned from rte_realloc\n");
4944418919fSjohnjiang 		rte_free(ptr7);
4954418919fSjohnjiang 		return -1;
4964418919fSjohnjiang 	}
4974418919fSjohnjiang 	if (RTE_PTR_ALIGN(ptr8, new_align) != ptr8){
4984418919fSjohnjiang 		printf("Failure to re-align data\n");
4994418919fSjohnjiang 		rte_free(ptr8);
5004418919fSjohnjiang 		return -1;
5014418919fSjohnjiang 	}
5024418919fSjohnjiang 	rte_free(ptr8);
5034418919fSjohnjiang 
5044418919fSjohnjiang 	/* test behaviour when there is a free block after current one,
5054418919fSjohnjiang 	 * but its not big enough
5064418919fSjohnjiang 	 */
5074418919fSjohnjiang 	unsigned size9 = 1024, size10 = 1024;
5084418919fSjohnjiang 	unsigned size11 = size9 + size10 + 256;
509*2d9fd380Sjfb8856606 	char *ptr9 = rte_malloc_socket(
510*2d9fd380Sjfb8856606 			NULL, size9, RTE_CACHE_LINE_SIZE, socket);
5114418919fSjohnjiang 	if (!ptr9){
5124418919fSjohnjiang 		printf("NULL pointer returned from rte_malloc\n");
5134418919fSjohnjiang 		return -1;
5144418919fSjohnjiang 	}
515*2d9fd380Sjfb8856606 	char *ptr10 = rte_malloc_socket(
516*2d9fd380Sjfb8856606 			NULL, size10, RTE_CACHE_LINE_SIZE, socket);
5174418919fSjohnjiang 	if (!ptr10){
5184418919fSjohnjiang 		printf("NULL pointer returned from rte_malloc\n");
5194418919fSjohnjiang 		return -1;
5204418919fSjohnjiang 	}
5214418919fSjohnjiang 	rte_free(ptr9);
522*2d9fd380Sjfb8856606 	char *ptr11 = rte_realloc_socket(
523*2d9fd380Sjfb8856606 			ptr10, size11, RTE_CACHE_LINE_SIZE, socket);
5244418919fSjohnjiang 	if (!ptr11){
5254418919fSjohnjiang 		printf("NULL pointer returned from rte_realloc\n");
5264418919fSjohnjiang 		rte_free(ptr10);
5274418919fSjohnjiang 		return -1;
5284418919fSjohnjiang 	}
5294418919fSjohnjiang 	if (ptr11 == ptr10){
5304418919fSjohnjiang 		printf("Error, unexpected that realloc has not created new buffer\n");
5314418919fSjohnjiang 		rte_free(ptr11);
5324418919fSjohnjiang 		return -1;
5334418919fSjohnjiang 	}
5344418919fSjohnjiang 	rte_free(ptr11);
5354418919fSjohnjiang 
5364418919fSjohnjiang 	/* check we don't crash if we pass null to realloc
5374418919fSjohnjiang 	 * We should get a malloc of the size requested*/
5384418919fSjohnjiang 	const size_t size12 = 1024;
5394418919fSjohnjiang 	size_t size12_check;
540*2d9fd380Sjfb8856606 	char *ptr12 = rte_realloc_socket(
541*2d9fd380Sjfb8856606 			NULL, size12, RTE_CACHE_LINE_SIZE, socket);
5424418919fSjohnjiang 	if (!ptr12){
5434418919fSjohnjiang 		printf("NULL pointer returned from rte_realloc\n");
5444418919fSjohnjiang 		return -1;
5454418919fSjohnjiang 	}
5464418919fSjohnjiang 	if (rte_malloc_validate(ptr12, &size12_check) < 0 ||
5474418919fSjohnjiang 			size12_check != size12){
5484418919fSjohnjiang 		rte_free(ptr12);
5494418919fSjohnjiang 		return -1;
5504418919fSjohnjiang 	}
5514418919fSjohnjiang 	rte_free(ptr12);
5524418919fSjohnjiang 
553*2d9fd380Sjfb8856606 	/* do the same, but for regular memory */
554*2d9fd380Sjfb8856606 	ptr12 = rte_realloc(NULL, size12, RTE_CACHE_LINE_SIZE);
555*2d9fd380Sjfb8856606 	if (!ptr12) {
556*2d9fd380Sjfb8856606 		printf("NULL pointer returned from rte_realloc\n");
557*2d9fd380Sjfb8856606 		return -1;
558*2d9fd380Sjfb8856606 	}
559*2d9fd380Sjfb8856606 	if (rte_malloc_validate(ptr12, &size12_check) < 0 ||
560*2d9fd380Sjfb8856606 			size12_check != size12) {
561*2d9fd380Sjfb8856606 		rte_free(ptr12);
562*2d9fd380Sjfb8856606 		return -1;
563*2d9fd380Sjfb8856606 	}
564*2d9fd380Sjfb8856606 	rte_free(ptr12);
565*2d9fd380Sjfb8856606 
566*2d9fd380Sjfb8856606 	return 0;
567*2d9fd380Sjfb8856606 }
568*2d9fd380Sjfb8856606 
569*2d9fd380Sjfb8856606 static int
test_realloc_numa(void)570*2d9fd380Sjfb8856606 test_realloc_numa(void)
571*2d9fd380Sjfb8856606 {
5724418919fSjohnjiang 	/* check realloc_socket part */
5734418919fSjohnjiang 	int32_t socket_count = 0, socket_allocated, socket;
574*2d9fd380Sjfb8856606 	void *ptr1, *ptr2;
5754418919fSjohnjiang 	int ret = -1;
5764418919fSjohnjiang 	size_t size = 1024;
5774418919fSjohnjiang 
5784418919fSjohnjiang 	ptr1 = NULL;
5794418919fSjohnjiang 	for (socket = 0; socket < RTE_MAX_NUMA_NODES; socket++) {
5804418919fSjohnjiang 		if (is_mem_on_socket(socket)) {
5814418919fSjohnjiang 			int j = 2;
5824418919fSjohnjiang 
5834418919fSjohnjiang 			socket_count++;
5844418919fSjohnjiang 			while (j--) {
5854418919fSjohnjiang 				/* j == 1 -> resizing */
5864418919fSjohnjiang 				ptr2 = rte_realloc_socket(ptr1, size,
5874418919fSjohnjiang 							  RTE_CACHE_LINE_SIZE,
5884418919fSjohnjiang 							  socket);
5894418919fSjohnjiang 				if (ptr2 == NULL) {
5904418919fSjohnjiang 					printf("NULL pointer returned from rte_realloc_socket\n");
5914418919fSjohnjiang 					goto end;
5924418919fSjohnjiang 				}
5934418919fSjohnjiang 
5944418919fSjohnjiang 				ptr1 = ptr2;
5954418919fSjohnjiang 				socket_allocated = addr_to_socket(ptr2);
5964418919fSjohnjiang 				if (socket_allocated != socket) {
5974418919fSjohnjiang 					printf("Requested socket (%d) doesn't mach allocated one (%d)\n",
5984418919fSjohnjiang 					       socket, socket_allocated);
5994418919fSjohnjiang 					goto end;
6004418919fSjohnjiang 				}
6014418919fSjohnjiang 				size += RTE_CACHE_LINE_SIZE;
6024418919fSjohnjiang 			}
6034418919fSjohnjiang 		}
6044418919fSjohnjiang 	}
6054418919fSjohnjiang 
6064418919fSjohnjiang 	/* Print warnign if only a single socket, but don't fail the test */
6074418919fSjohnjiang 	if (socket_count < 2)
6084418919fSjohnjiang 		printf("WARNING: realloc_socket test needs memory on multiple sockets!\n");
6094418919fSjohnjiang 
6104418919fSjohnjiang 	ret = 0;
6114418919fSjohnjiang end:
6124418919fSjohnjiang 	rte_free(ptr1);
6134418919fSjohnjiang 	return ret;
6144418919fSjohnjiang }
6154418919fSjohnjiang 
6164418919fSjohnjiang static int
test_realloc(void)617*2d9fd380Sjfb8856606 test_realloc(void)
618*2d9fd380Sjfb8856606 {
619*2d9fd380Sjfb8856606 	const char *heap_name = "realloc_heap";
620*2d9fd380Sjfb8856606 	int realloc_heap_socket;
621*2d9fd380Sjfb8856606 	unsigned int mem_sz = 1U << 13; /* 8K */
622*2d9fd380Sjfb8856606 	unsigned int page_sz = sysconf(_SC_PAGESIZE);
623*2d9fd380Sjfb8856606 	void *mem;
624*2d9fd380Sjfb8856606 	int ret;
625*2d9fd380Sjfb8856606 
626*2d9fd380Sjfb8856606 	/* page size may be bigger than total mem size, so adjust */
627*2d9fd380Sjfb8856606 	mem_sz = RTE_MAX(mem_sz, page_sz);
628*2d9fd380Sjfb8856606 
629*2d9fd380Sjfb8856606 	/*
630*2d9fd380Sjfb8856606 	 * the realloc tests depend on specific layout of underlying memory, so
631*2d9fd380Sjfb8856606 	 * to prevent accidental failures to do fragmented main heap, we will
632*2d9fd380Sjfb8856606 	 * do all of our tests on an artificially created memory.
633*2d9fd380Sjfb8856606 	 */
634*2d9fd380Sjfb8856606 	if (rte_malloc_heap_create(heap_name) != 0) {
635*2d9fd380Sjfb8856606 		printf("Failed to create external heap\n");
636*2d9fd380Sjfb8856606 		ret = -1;
637*2d9fd380Sjfb8856606 		goto end;
638*2d9fd380Sjfb8856606 	}
639*2d9fd380Sjfb8856606 	realloc_heap_socket = rte_malloc_heap_get_socket(heap_name);
640*2d9fd380Sjfb8856606 
641*2d9fd380Sjfb8856606 	mem = mmap(NULL, mem_sz, PROT_READ | PROT_WRITE,
642*2d9fd380Sjfb8856606 			MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
643*2d9fd380Sjfb8856606 	if (mem == MAP_FAILED) {
644*2d9fd380Sjfb8856606 		printf("Failed to allocate memory for external heap\n");
645*2d9fd380Sjfb8856606 		ret = -1;
646*2d9fd380Sjfb8856606 		goto heap_destroy;
647*2d9fd380Sjfb8856606 	}
648*2d9fd380Sjfb8856606 
649*2d9fd380Sjfb8856606 	if (rte_malloc_heap_memory_add(
650*2d9fd380Sjfb8856606 			heap_name, mem, mem_sz, NULL, 0, page_sz) != 0) {
651*2d9fd380Sjfb8856606 		printf("Failed to add memory to external heap\n");
652*2d9fd380Sjfb8856606 		ret = -1;
653*2d9fd380Sjfb8856606 		goto mem_free;
654*2d9fd380Sjfb8856606 	}
655*2d9fd380Sjfb8856606 
656*2d9fd380Sjfb8856606 	/* run the socket-bound tests */
657*2d9fd380Sjfb8856606 	ret = test_realloc_socket(realloc_heap_socket);
658*2d9fd380Sjfb8856606 	if (ret != 0)
659*2d9fd380Sjfb8856606 		goto mem_remove;
660*2d9fd380Sjfb8856606 
661*2d9fd380Sjfb8856606 	/* now, run the NUMA node tests */
662*2d9fd380Sjfb8856606 	ret = test_realloc_numa();
663*2d9fd380Sjfb8856606 
664*2d9fd380Sjfb8856606 mem_remove:
665*2d9fd380Sjfb8856606 	rte_malloc_heap_memory_remove(heap_name, mem, mem_sz);
666*2d9fd380Sjfb8856606 mem_free:
667*2d9fd380Sjfb8856606 	munmap(mem, mem_sz);
668*2d9fd380Sjfb8856606 heap_destroy:
669*2d9fd380Sjfb8856606 	rte_malloc_heap_destroy(heap_name);
670*2d9fd380Sjfb8856606 end:
671*2d9fd380Sjfb8856606 	return ret;
672*2d9fd380Sjfb8856606 }
673*2d9fd380Sjfb8856606 
674*2d9fd380Sjfb8856606 static int
test_random_alloc_free(void * _ __rte_unused)675*2d9fd380Sjfb8856606 test_random_alloc_free(void *_ __rte_unused)
6764418919fSjohnjiang {
6774418919fSjohnjiang 	struct mem_list {
6784418919fSjohnjiang 		struct mem_list *next;
6794418919fSjohnjiang 		char data[0];
6804418919fSjohnjiang 	} *list_head = NULL;
6814418919fSjohnjiang 	unsigned i;
6824418919fSjohnjiang 	unsigned count = 0;
6834418919fSjohnjiang 
6844418919fSjohnjiang 	rte_srand((unsigned)rte_rdtsc());
6854418919fSjohnjiang 
6864418919fSjohnjiang 	for (i = 0; i < N; i++){
6874418919fSjohnjiang 		unsigned free_mem = 0;
6884418919fSjohnjiang 		size_t allocated_size;
6894418919fSjohnjiang 		while (!free_mem){
6904418919fSjohnjiang 			const unsigned mem_size = sizeof(struct mem_list) + \
6914418919fSjohnjiang 					rte_rand() % (64 * 1024);
6924418919fSjohnjiang 			const unsigned align = 1 << (rte_rand() % 12); /* up to 4k alignment */
6934418919fSjohnjiang 			struct mem_list *entry = rte_malloc(NULL,
6944418919fSjohnjiang 					mem_size, align);
6954418919fSjohnjiang 			if (entry == NULL)
6964418919fSjohnjiang 				return -1;
6974418919fSjohnjiang 			if (RTE_PTR_ALIGN(entry, align)!= entry)
6984418919fSjohnjiang 				return -1;
6994418919fSjohnjiang 			if (rte_malloc_validate(entry, &allocated_size) == -1
7004418919fSjohnjiang 					|| allocated_size < mem_size)
7014418919fSjohnjiang 				return -1;
7024418919fSjohnjiang 			memset(entry->data, rte_lcore_id(),
7034418919fSjohnjiang 					mem_size - sizeof(*entry));
7044418919fSjohnjiang 			entry->next = list_head;
7054418919fSjohnjiang 			if (rte_malloc_validate(entry, NULL) == -1)
7064418919fSjohnjiang 				return -1;
7074418919fSjohnjiang 			list_head = entry;
7084418919fSjohnjiang 
7094418919fSjohnjiang 			count++;
7104418919fSjohnjiang 			/* switch to freeing the memory with a 20% probability */
7114418919fSjohnjiang 			free_mem = ((rte_rand() % 10) >= 8);
7124418919fSjohnjiang 		}
7134418919fSjohnjiang 		while (list_head){
7144418919fSjohnjiang 			struct mem_list *entry = list_head;
7154418919fSjohnjiang 			list_head = list_head->next;
7164418919fSjohnjiang 			rte_free(entry);
7174418919fSjohnjiang 		}
7184418919fSjohnjiang 	}
7194418919fSjohnjiang 	printf("Lcore %u allocated/freed %u blocks\n", rte_lcore_id(), count);
7204418919fSjohnjiang 	return 0;
7214418919fSjohnjiang }
7224418919fSjohnjiang 
7234418919fSjohnjiang #define err_return() do { \
7244418919fSjohnjiang 	printf("%s: %d - Error\n", __func__, __LINE__); \
7254418919fSjohnjiang 	goto err_return; \
7264418919fSjohnjiang } while (0)
7274418919fSjohnjiang 
7284418919fSjohnjiang static int
test_rte_malloc_validate(void)7294418919fSjohnjiang test_rte_malloc_validate(void)
7304418919fSjohnjiang {
7314418919fSjohnjiang 	const size_t request_size = 1024;
7324418919fSjohnjiang 	size_t allocated_size;
7334418919fSjohnjiang 	char *data_ptr = rte_malloc(NULL, request_size, RTE_CACHE_LINE_SIZE);
7344418919fSjohnjiang #ifdef RTE_MALLOC_DEBUG
7354418919fSjohnjiang 	int retval;
7364418919fSjohnjiang 	char *over_write_vals = NULL;
7374418919fSjohnjiang #endif
7384418919fSjohnjiang 
7394418919fSjohnjiang 	if (data_ptr == NULL) {
7404418919fSjohnjiang 		printf("%s: %d - Allocation error\n", __func__, __LINE__);
7414418919fSjohnjiang 		return -1;
7424418919fSjohnjiang 	}
7434418919fSjohnjiang 
7444418919fSjohnjiang 	/* check that a null input returns -1 */
7454418919fSjohnjiang 	if (rte_malloc_validate(NULL, NULL) != -1)
7464418919fSjohnjiang 		err_return();
7474418919fSjohnjiang 
7484418919fSjohnjiang 	/* check that we get ok on a valid pointer */
7494418919fSjohnjiang 	if (rte_malloc_validate(data_ptr, &allocated_size) < 0)
7504418919fSjohnjiang 		err_return();
7514418919fSjohnjiang 
7524418919fSjohnjiang 	/* check that the returned size is ok */
7534418919fSjohnjiang 	if (allocated_size < request_size)
7544418919fSjohnjiang 		err_return();
7554418919fSjohnjiang 
7564418919fSjohnjiang #ifdef RTE_MALLOC_DEBUG
7574418919fSjohnjiang 
7584418919fSjohnjiang 	/****** change the header to be bad */
7594418919fSjohnjiang 	char save_buf[64];
7604418919fSjohnjiang 	over_write_vals = (char *)((uintptr_t)data_ptr - sizeof(save_buf));
7614418919fSjohnjiang 	/* first save the data as a backup before overwriting it */
7624418919fSjohnjiang 	memcpy(save_buf, over_write_vals, sizeof(save_buf));
7634418919fSjohnjiang 	memset(over_write_vals, 1, sizeof(save_buf));
7644418919fSjohnjiang 	/* then run validate */
7654418919fSjohnjiang 	retval = rte_malloc_validate(data_ptr, NULL);
7664418919fSjohnjiang 	/* finally restore the data again */
7674418919fSjohnjiang 	memcpy(over_write_vals, save_buf, sizeof(save_buf));
7684418919fSjohnjiang 	/* check we previously had an error */
7694418919fSjohnjiang 	if (retval != -1)
7704418919fSjohnjiang 		err_return();
7714418919fSjohnjiang 
7724418919fSjohnjiang 	/* check all ok again */
7734418919fSjohnjiang 	if (rte_malloc_validate(data_ptr, &allocated_size) < 0)
7744418919fSjohnjiang 		err_return();
7754418919fSjohnjiang 
7764418919fSjohnjiang 	/**** change the trailer to be bad */
7774418919fSjohnjiang 	over_write_vals = (char *)((uintptr_t)data_ptr + allocated_size);
7784418919fSjohnjiang 	/* first save the data as a backup before overwriting it */
7794418919fSjohnjiang 	memcpy(save_buf, over_write_vals, sizeof(save_buf));
7804418919fSjohnjiang 	memset(over_write_vals, 1, sizeof(save_buf));
7814418919fSjohnjiang 	/* then run validate */
7824418919fSjohnjiang 	retval = rte_malloc_validate(data_ptr, NULL);
7834418919fSjohnjiang 	/* finally restore the data again */
7844418919fSjohnjiang 	memcpy(over_write_vals, save_buf, sizeof(save_buf));
7854418919fSjohnjiang 	if (retval != -1)
7864418919fSjohnjiang 		err_return();
7874418919fSjohnjiang 
7884418919fSjohnjiang 	/* check all ok again */
7894418919fSjohnjiang 	if (rte_malloc_validate(data_ptr, &allocated_size) < 0)
7904418919fSjohnjiang 		err_return();
7914418919fSjohnjiang #endif
7924418919fSjohnjiang 
7934418919fSjohnjiang 	rte_free(data_ptr);
7944418919fSjohnjiang 	return 0;
7954418919fSjohnjiang 
7964418919fSjohnjiang err_return:
7974418919fSjohnjiang 	/*clean up */
7984418919fSjohnjiang 	rte_free(data_ptr);
7994418919fSjohnjiang 	return -1;
8004418919fSjohnjiang }
8014418919fSjohnjiang 
8024418919fSjohnjiang static int
test_zero_aligned_alloc(void)8034418919fSjohnjiang test_zero_aligned_alloc(void)
8044418919fSjohnjiang {
8054418919fSjohnjiang 	char *p1 = rte_malloc(NULL,1024, 0);
8064418919fSjohnjiang 	if (!p1)
8074418919fSjohnjiang 		goto err_return;
8084418919fSjohnjiang 	if (!rte_is_aligned(p1, RTE_CACHE_LINE_SIZE))
8094418919fSjohnjiang 		goto err_return;
8104418919fSjohnjiang 	rte_free(p1);
8114418919fSjohnjiang 	return 0;
8124418919fSjohnjiang 
8134418919fSjohnjiang err_return:
8144418919fSjohnjiang 	/*clean up */
8154418919fSjohnjiang 	if (p1) rte_free(p1);
8164418919fSjohnjiang 	return -1;
8174418919fSjohnjiang }
8184418919fSjohnjiang 
8194418919fSjohnjiang static int
test_malloc_bad_params(void)8204418919fSjohnjiang test_malloc_bad_params(void)
8214418919fSjohnjiang {
8224418919fSjohnjiang 	const char *type = NULL;
8234418919fSjohnjiang 	size_t size = 0;
8244418919fSjohnjiang 	unsigned align = RTE_CACHE_LINE_SIZE;
8254418919fSjohnjiang 
8264418919fSjohnjiang 	/* rte_malloc expected to return null with inappropriate size */
8274418919fSjohnjiang 	char *bad_ptr = rte_malloc(type, size, align);
8284418919fSjohnjiang 	if (bad_ptr != NULL)
8294418919fSjohnjiang 		goto err_return;
8304418919fSjohnjiang 
831*2d9fd380Sjfb8856606 	/* rte_realloc expected to return null with inappropriate size */
832*2d9fd380Sjfb8856606 	bad_ptr = rte_realloc(NULL, size, align);
833*2d9fd380Sjfb8856606 	if (bad_ptr != NULL)
834*2d9fd380Sjfb8856606 		goto err_return;
835*2d9fd380Sjfb8856606 
8364418919fSjohnjiang 	/* rte_malloc expected to return null with inappropriate alignment */
8374418919fSjohnjiang 	align = 17;
8384418919fSjohnjiang 	size = 1024;
8394418919fSjohnjiang 
8404418919fSjohnjiang 	bad_ptr = rte_malloc(type, size, align);
8414418919fSjohnjiang 	if (bad_ptr != NULL)
8424418919fSjohnjiang 		goto err_return;
8434418919fSjohnjiang 
844*2d9fd380Sjfb8856606 	/* rte_realloc expected to return null with inappropriate alignment */
845*2d9fd380Sjfb8856606 	bad_ptr = rte_realloc(NULL, size, align);
846*2d9fd380Sjfb8856606 	if (bad_ptr != NULL)
847*2d9fd380Sjfb8856606 		goto err_return;
848*2d9fd380Sjfb8856606 
849*2d9fd380Sjfb8856606 #if defined(RTE_CC_GCC) || defined(RTE_CC_CLANG)
850*2d9fd380Sjfb8856606 	/* this test can not be built, will get trapped at compile time! */
851*2d9fd380Sjfb8856606 #else
8520c6bd470Sfengbojiang 	/* rte_malloc expected to return null with size will cause overflow */
8530c6bd470Sfengbojiang 	align = RTE_CACHE_LINE_SIZE;
8540c6bd470Sfengbojiang 	size = (size_t)-8;
8550c6bd470Sfengbojiang 
8560c6bd470Sfengbojiang 	bad_ptr = rte_malloc(type, size, align);
8570c6bd470Sfengbojiang 	if (bad_ptr != NULL)
8580c6bd470Sfengbojiang 		goto err_return;
8590c6bd470Sfengbojiang 
8600c6bd470Sfengbojiang 	bad_ptr = rte_realloc(NULL, size, align);
8610c6bd470Sfengbojiang 	if (bad_ptr != NULL)
8620c6bd470Sfengbojiang 		goto err_return;
863*2d9fd380Sjfb8856606 #endif
8644418919fSjohnjiang 	return 0;
8654418919fSjohnjiang 
8664418919fSjohnjiang err_return:
8674418919fSjohnjiang 	/* clean up pointer */
8684418919fSjohnjiang 	if (bad_ptr)
8694418919fSjohnjiang 		rte_free(bad_ptr);
8704418919fSjohnjiang 	return -1;
8714418919fSjohnjiang }
8724418919fSjohnjiang 
8734418919fSjohnjiang static int
check_socket_mem(const struct rte_memseg_list * msl,void * arg)8744418919fSjohnjiang check_socket_mem(const struct rte_memseg_list *msl, void *arg)
8754418919fSjohnjiang {
8764418919fSjohnjiang 	int32_t *socket = arg;
8774418919fSjohnjiang 
8784418919fSjohnjiang 	if (msl->external)
8794418919fSjohnjiang 		return 0;
8804418919fSjohnjiang 
8814418919fSjohnjiang 	return *socket == msl->socket_id;
8824418919fSjohnjiang }
8834418919fSjohnjiang 
8844418919fSjohnjiang /* Check if memory is available on a specific socket */
8854418919fSjohnjiang static int
is_mem_on_socket(int32_t socket)8864418919fSjohnjiang is_mem_on_socket(int32_t socket)
8874418919fSjohnjiang {
8884418919fSjohnjiang 	return rte_memseg_list_walk(check_socket_mem, &socket);
8894418919fSjohnjiang }
8904418919fSjohnjiang 
8914418919fSjohnjiang 
8924418919fSjohnjiang /*
8934418919fSjohnjiang  * Find what socket a memory address is on. Only works for addresses within
8944418919fSjohnjiang  * memsegs, not heap or stack...
8954418919fSjohnjiang  */
8964418919fSjohnjiang static int32_t
addr_to_socket(void * addr)8974418919fSjohnjiang addr_to_socket(void * addr)
8984418919fSjohnjiang {
8994418919fSjohnjiang 	const struct rte_memseg *ms = rte_mem_virt2memseg(addr, NULL);
9004418919fSjohnjiang 	return ms == NULL ? -1 : ms->socket_id;
9014418919fSjohnjiang 
9024418919fSjohnjiang }
9034418919fSjohnjiang 
9044418919fSjohnjiang /* Test using rte_[c|m|zm]alloc_socket() on a specific socket */
9054418919fSjohnjiang static int
test_alloc_single_socket(int32_t socket)9064418919fSjohnjiang test_alloc_single_socket(int32_t socket)
9074418919fSjohnjiang {
9084418919fSjohnjiang 	const char *type = NULL;
9094418919fSjohnjiang 	const size_t size = 10;
9104418919fSjohnjiang 	const unsigned align = 0;
9114418919fSjohnjiang 	char *mem = NULL;
9124418919fSjohnjiang 	int32_t desired_socket = (socket == SOCKET_ID_ANY) ?
9134418919fSjohnjiang 			(int32_t)rte_socket_id() : socket;
9144418919fSjohnjiang 
9154418919fSjohnjiang 	/* Test rte_calloc_socket() */
9164418919fSjohnjiang 	mem = rte_calloc_socket(type, size, sizeof(char), align, socket);
9174418919fSjohnjiang 	if (mem == NULL)
9184418919fSjohnjiang 		return -1;
9194418919fSjohnjiang 	if (addr_to_socket(mem) != desired_socket) {
9204418919fSjohnjiang 		rte_free(mem);
9214418919fSjohnjiang 		return -1;
9224418919fSjohnjiang 	}
9234418919fSjohnjiang 	rte_free(mem);
9244418919fSjohnjiang 
9254418919fSjohnjiang 	/* Test rte_malloc_socket() */
9264418919fSjohnjiang 	mem = rte_malloc_socket(type, size, align, socket);
9274418919fSjohnjiang 	if (mem == NULL)
9284418919fSjohnjiang 		return -1;
9294418919fSjohnjiang 	if (addr_to_socket(mem) != desired_socket) {
9304418919fSjohnjiang 		return -1;
9314418919fSjohnjiang 	}
9324418919fSjohnjiang 	rte_free(mem);
9334418919fSjohnjiang 
9344418919fSjohnjiang 	/* Test rte_zmalloc_socket() */
9354418919fSjohnjiang 	mem = rte_zmalloc_socket(type, size, align, socket);
9364418919fSjohnjiang 	if (mem == NULL)
9374418919fSjohnjiang 		return -1;
9384418919fSjohnjiang 	if (addr_to_socket(mem) != desired_socket) {
9394418919fSjohnjiang 		rte_free(mem);
9404418919fSjohnjiang 		return -1;
9414418919fSjohnjiang 	}
9424418919fSjohnjiang 	rte_free(mem);
9434418919fSjohnjiang 
9444418919fSjohnjiang 	return 0;
9454418919fSjohnjiang }
9464418919fSjohnjiang 
9474418919fSjohnjiang static int
test_alloc_socket(void)9484418919fSjohnjiang test_alloc_socket(void)
9494418919fSjohnjiang {
9504418919fSjohnjiang 	unsigned socket_count = 0;
9514418919fSjohnjiang 	unsigned i;
9524418919fSjohnjiang 
9534418919fSjohnjiang 	if (test_alloc_single_socket(SOCKET_ID_ANY) < 0)
9544418919fSjohnjiang 		return -1;
9554418919fSjohnjiang 
9564418919fSjohnjiang 	for (i = 0; i < RTE_MAX_NUMA_NODES; i++) {
9574418919fSjohnjiang 		if (is_mem_on_socket(i)) {
9584418919fSjohnjiang 			socket_count++;
9594418919fSjohnjiang 			if (test_alloc_single_socket(i) < 0) {
9604418919fSjohnjiang 				printf("Fail: rte_malloc_socket(..., %u) did not succeed\n",
9614418919fSjohnjiang 						i);
9624418919fSjohnjiang 				return -1;
9634418919fSjohnjiang 			}
9644418919fSjohnjiang 		}
9654418919fSjohnjiang 		else {
9664418919fSjohnjiang 			if (test_alloc_single_socket(i) == 0) {
9674418919fSjohnjiang 				printf("Fail: rte_malloc_socket(..., %u) succeeded\n",
9684418919fSjohnjiang 						i);
9694418919fSjohnjiang 				return -1;
9704418919fSjohnjiang 			}
9714418919fSjohnjiang 		}
9724418919fSjohnjiang 	}
9734418919fSjohnjiang 
9744418919fSjohnjiang 	/* Print warnign if only a single socket, but don't fail the test */
9754418919fSjohnjiang 	if (socket_count < 2) {
9764418919fSjohnjiang 		printf("WARNING: alloc_socket test needs memory on multiple sockets!\n");
9774418919fSjohnjiang 	}
9784418919fSjohnjiang 
9794418919fSjohnjiang 	return 0;
9804418919fSjohnjiang }
9814418919fSjohnjiang 
9824418919fSjohnjiang static int
test_malloc(void)9834418919fSjohnjiang test_malloc(void)
9844418919fSjohnjiang {
9854418919fSjohnjiang 	unsigned lcore_id;
9864418919fSjohnjiang 	int ret = 0;
9874418919fSjohnjiang 
9884418919fSjohnjiang 	if (test_str_to_size() < 0){
9894418919fSjohnjiang 		printf("test_str_to_size() failed\n");
9904418919fSjohnjiang 		return -1;
9914418919fSjohnjiang 	}
9924418919fSjohnjiang 	else printf("test_str_to_size() passed\n");
9934418919fSjohnjiang 
9944418919fSjohnjiang 	if (test_zero_aligned_alloc() < 0){
9954418919fSjohnjiang 		printf("test_zero_aligned_alloc() failed\n");
9964418919fSjohnjiang 		return -1;
9974418919fSjohnjiang 	}
9984418919fSjohnjiang 	else printf("test_zero_aligned_alloc() passed\n");
9994418919fSjohnjiang 
10004418919fSjohnjiang 	if (test_malloc_bad_params() < 0){
10014418919fSjohnjiang 		printf("test_malloc_bad_params() failed\n");
10024418919fSjohnjiang 		return -1;
10034418919fSjohnjiang 	}
10044418919fSjohnjiang 	else printf("test_malloc_bad_params() passed\n");
10054418919fSjohnjiang 
10064418919fSjohnjiang 	if (test_realloc() < 0){
10074418919fSjohnjiang 		printf("test_realloc() failed\n");
10084418919fSjohnjiang 		return -1;
10094418919fSjohnjiang 	}
10104418919fSjohnjiang 	else printf("test_realloc() passed\n");
10114418919fSjohnjiang 
10124418919fSjohnjiang 	/*----------------------------*/
1013*2d9fd380Sjfb8856606 	RTE_LCORE_FOREACH_WORKER(lcore_id) {
10144418919fSjohnjiang 		rte_eal_remote_launch(test_align_overlap_per_lcore, NULL, lcore_id);
10154418919fSjohnjiang 	}
10164418919fSjohnjiang 
1017*2d9fd380Sjfb8856606 	RTE_LCORE_FOREACH_WORKER(lcore_id) {
10184418919fSjohnjiang 		if (rte_eal_wait_lcore(lcore_id) < 0)
10194418919fSjohnjiang 			ret = -1;
10204418919fSjohnjiang 	}
10214418919fSjohnjiang 	if (ret < 0){
10224418919fSjohnjiang 		printf("test_align_overlap_per_lcore() failed\n");
10234418919fSjohnjiang 		return ret;
10244418919fSjohnjiang 	}
10254418919fSjohnjiang 	else printf("test_align_overlap_per_lcore() passed\n");
10264418919fSjohnjiang 
10274418919fSjohnjiang 	/*----------------------------*/
1028*2d9fd380Sjfb8856606 	RTE_LCORE_FOREACH_WORKER(lcore_id) {
10294418919fSjohnjiang 		rte_eal_remote_launch(test_reordered_free_per_lcore, NULL, lcore_id);
10304418919fSjohnjiang 	}
10314418919fSjohnjiang 
1032*2d9fd380Sjfb8856606 	RTE_LCORE_FOREACH_WORKER(lcore_id) {
10334418919fSjohnjiang 		if (rte_eal_wait_lcore(lcore_id) < 0)
10344418919fSjohnjiang 			ret = -1;
10354418919fSjohnjiang 	}
10364418919fSjohnjiang 	if (ret < 0){
10374418919fSjohnjiang 		printf("test_reordered_free_per_lcore() failed\n");
10384418919fSjohnjiang 		return ret;
10394418919fSjohnjiang 	}
10404418919fSjohnjiang 	else printf("test_reordered_free_per_lcore() passed\n");
10414418919fSjohnjiang 
10424418919fSjohnjiang 	/*----------------------------*/
1043*2d9fd380Sjfb8856606 	RTE_LCORE_FOREACH_WORKER(lcore_id) {
10444418919fSjohnjiang 		rte_eal_remote_launch(test_random_alloc_free, NULL, lcore_id);
10454418919fSjohnjiang 	}
10464418919fSjohnjiang 
1047*2d9fd380Sjfb8856606 	RTE_LCORE_FOREACH_WORKER(lcore_id) {
10484418919fSjohnjiang 		if (rte_eal_wait_lcore(lcore_id) < 0)
10494418919fSjohnjiang 			ret = -1;
10504418919fSjohnjiang 	}
10514418919fSjohnjiang 	if (ret < 0){
10524418919fSjohnjiang 		printf("test_random_alloc_free() failed\n");
10534418919fSjohnjiang 		return ret;
10544418919fSjohnjiang 	}
10554418919fSjohnjiang 	else printf("test_random_alloc_free() passed\n");
10564418919fSjohnjiang 
10574418919fSjohnjiang 	/*----------------------------*/
10584418919fSjohnjiang 	ret = test_rte_malloc_validate();
10594418919fSjohnjiang 	if (ret < 0){
10604418919fSjohnjiang 		printf("test_rte_malloc_validate() failed\n");
10614418919fSjohnjiang 		return ret;
10624418919fSjohnjiang 	}
10634418919fSjohnjiang 	else printf("test_rte_malloc_validate() passed\n");
10644418919fSjohnjiang 
10654418919fSjohnjiang 	ret = test_alloc_socket();
10664418919fSjohnjiang 	if (ret < 0){
10674418919fSjohnjiang 		printf("test_alloc_socket() failed\n");
10684418919fSjohnjiang 		return ret;
10694418919fSjohnjiang 	}
10704418919fSjohnjiang 	else printf("test_alloc_socket() passed\n");
10714418919fSjohnjiang 
10724418919fSjohnjiang 	ret = test_multi_alloc_statistics();
10734418919fSjohnjiang 	if (ret < 0) {
10744418919fSjohnjiang 		printf("test_multi_alloc_statistics() failed\n");
10754418919fSjohnjiang 		return ret;
10764418919fSjohnjiang 	}
10774418919fSjohnjiang 	else
10784418919fSjohnjiang 		printf("test_multi_alloc_statistics() passed\n");
10794418919fSjohnjiang 
10804418919fSjohnjiang 	return 0;
10814418919fSjohnjiang }
10824418919fSjohnjiang 
10834418919fSjohnjiang REGISTER_TEST_COMMAND(malloc_autotest, test_malloc);
1084