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