xref: /dpdk/app/test/test_malloc.c (revision e0a8442ccd15bafbb7eb150c35331c8e3b828c53)
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
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
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
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
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
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
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
3793c60274cSJie Zhou test_realloc(void)
3803c60274cSJie Zhou {
3813c60274cSJie Zhou 	return TEST_SKIPPED;
3823c60274cSJie Zhou }
3833c60274cSJie Zhou #else
3843c60274cSJie Zhou 
385a9de470cSBruce Richardson static int
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
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
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
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 	rte_srand((unsigned)rte_rdtsc());
696a9de470cSBruce Richardson 
697a9de470cSBruce Richardson 	for (i = 0; i < N; i++){
698a9de470cSBruce Richardson 		unsigned free_mem = 0;
699a9de470cSBruce Richardson 		size_t allocated_size;
700a9de470cSBruce Richardson 		while (!free_mem){
701a9de470cSBruce Richardson 			const unsigned mem_size = sizeof(struct mem_list) + \
702a9de470cSBruce Richardson 					rte_rand() % (64 * 1024);
703a9de470cSBruce Richardson 			const unsigned align = 1 << (rte_rand() % 12); /* up to 4k alignment */
704a9de470cSBruce Richardson 			struct mem_list *entry = rte_malloc(NULL,
705a9de470cSBruce Richardson 					mem_size, align);
706a9de470cSBruce Richardson 			if (entry == NULL)
707a9de470cSBruce Richardson 				return -1;
708a9de470cSBruce Richardson 			if (RTE_PTR_ALIGN(entry, align)!= entry)
709a9de470cSBruce Richardson 				return -1;
710a9de470cSBruce Richardson 			if (rte_malloc_validate(entry, &allocated_size) == -1
711a9de470cSBruce Richardson 					|| allocated_size < mem_size)
712a9de470cSBruce Richardson 				return -1;
713a9de470cSBruce Richardson 			memset(entry->data, rte_lcore_id(),
714a9de470cSBruce Richardson 					mem_size - sizeof(*entry));
715a9de470cSBruce Richardson 			entry->next = list_head;
716a9de470cSBruce Richardson 			if (rte_malloc_validate(entry, NULL) == -1)
717a9de470cSBruce Richardson 				return -1;
718a9de470cSBruce Richardson 			list_head = entry;
719a9de470cSBruce Richardson 
720a9de470cSBruce Richardson 			count++;
721a9de470cSBruce Richardson 			/* switch to freeing the memory with a 20% probability */
722a9de470cSBruce Richardson 			free_mem = ((rte_rand() % 10) >= 8);
723a9de470cSBruce Richardson 		}
724a9de470cSBruce Richardson 		while (list_head){
725a9de470cSBruce Richardson 			struct mem_list *entry = list_head;
726a9de470cSBruce Richardson 			list_head = list_head->next;
727a9de470cSBruce Richardson 			rte_free(entry);
728a9de470cSBruce Richardson 		}
729a9de470cSBruce Richardson 	}
730a9de470cSBruce Richardson 	printf("Lcore %u allocated/freed %u blocks\n", rte_lcore_id(), count);
731a9de470cSBruce Richardson 	return 0;
732a9de470cSBruce Richardson }
733a9de470cSBruce Richardson 
734a9de470cSBruce Richardson #define err_return() do { \
735a9de470cSBruce Richardson 	printf("%s: %d - Error\n", __func__, __LINE__); \
736a9de470cSBruce Richardson 	goto err_return; \
737a9de470cSBruce Richardson } while (0)
738a9de470cSBruce Richardson 
739a9de470cSBruce Richardson static int
740a9de470cSBruce Richardson test_rte_malloc_validate(void)
741a9de470cSBruce Richardson {
742a9de470cSBruce Richardson 	const size_t request_size = 1024;
743a9de470cSBruce Richardson 	size_t allocated_size;
744a9de470cSBruce Richardson 	char *data_ptr = rte_malloc(NULL, request_size, RTE_CACHE_LINE_SIZE);
745a9de470cSBruce Richardson #ifdef RTE_MALLOC_DEBUG
746a9de470cSBruce Richardson 	int retval;
747a9de470cSBruce Richardson 	char *over_write_vals = NULL;
748a9de470cSBruce Richardson #endif
749a9de470cSBruce Richardson 
750a9de470cSBruce Richardson 	if (data_ptr == NULL) {
751a9de470cSBruce Richardson 		printf("%s: %d - Allocation error\n", __func__, __LINE__);
752a9de470cSBruce Richardson 		return -1;
753a9de470cSBruce Richardson 	}
754a9de470cSBruce Richardson 
755a9de470cSBruce Richardson 	/* check that a null input returns -1 */
756a9de470cSBruce Richardson 	if (rte_malloc_validate(NULL, NULL) != -1)
757a9de470cSBruce Richardson 		err_return();
758a9de470cSBruce Richardson 
759a9de470cSBruce Richardson 	/* check that we get ok on a valid pointer */
760a9de470cSBruce Richardson 	if (rte_malloc_validate(data_ptr, &allocated_size) < 0)
761a9de470cSBruce Richardson 		err_return();
762a9de470cSBruce Richardson 
763a9de470cSBruce Richardson 	/* check that the returned size is ok */
764a9de470cSBruce Richardson 	if (allocated_size < request_size)
765a9de470cSBruce Richardson 		err_return();
766a9de470cSBruce Richardson 
767a9de470cSBruce Richardson #ifdef RTE_MALLOC_DEBUG
768a9de470cSBruce Richardson 
769a9de470cSBruce Richardson 	/****** change the header to be bad */
770a9de470cSBruce Richardson 	char save_buf[64];
771a9de470cSBruce Richardson 	over_write_vals = (char *)((uintptr_t)data_ptr - sizeof(save_buf));
772a9de470cSBruce Richardson 	/* first save the data as a backup before overwriting it */
773a9de470cSBruce Richardson 	memcpy(save_buf, over_write_vals, sizeof(save_buf));
774a9de470cSBruce Richardson 	memset(over_write_vals, 1, sizeof(save_buf));
775a9de470cSBruce Richardson 	/* then run validate */
776a9de470cSBruce Richardson 	retval = rte_malloc_validate(data_ptr, NULL);
777a9de470cSBruce Richardson 	/* finally restore the data again */
778a9de470cSBruce Richardson 	memcpy(over_write_vals, save_buf, sizeof(save_buf));
779a9de470cSBruce Richardson 	/* check we previously had an error */
780a9de470cSBruce Richardson 	if (retval != -1)
781a9de470cSBruce Richardson 		err_return();
782a9de470cSBruce Richardson 
783a9de470cSBruce Richardson 	/* check all ok again */
784a9de470cSBruce Richardson 	if (rte_malloc_validate(data_ptr, &allocated_size) < 0)
785a9de470cSBruce Richardson 		err_return();
786a9de470cSBruce Richardson 
787a9de470cSBruce Richardson 	/**** change the trailer to be bad */
788a9de470cSBruce Richardson 	over_write_vals = (char *)((uintptr_t)data_ptr + allocated_size);
789a9de470cSBruce Richardson 	/* first save the data as a backup before overwriting it */
790a9de470cSBruce Richardson 	memcpy(save_buf, over_write_vals, sizeof(save_buf));
791a9de470cSBruce Richardson 	memset(over_write_vals, 1, sizeof(save_buf));
792a9de470cSBruce Richardson 	/* then run validate */
793a9de470cSBruce Richardson 	retval = rte_malloc_validate(data_ptr, NULL);
794a9de470cSBruce Richardson 	/* finally restore the data again */
795a9de470cSBruce Richardson 	memcpy(over_write_vals, save_buf, sizeof(save_buf));
796a9de470cSBruce Richardson 	if (retval != -1)
797a9de470cSBruce Richardson 		err_return();
798a9de470cSBruce Richardson 
799a9de470cSBruce Richardson 	/* check all ok again */
800a9de470cSBruce Richardson 	if (rte_malloc_validate(data_ptr, &allocated_size) < 0)
801a9de470cSBruce Richardson 		err_return();
802a9de470cSBruce Richardson #endif
803a9de470cSBruce Richardson 
804a9de470cSBruce Richardson 	rte_free(data_ptr);
805a9de470cSBruce Richardson 	return 0;
806a9de470cSBruce Richardson 
807a9de470cSBruce Richardson err_return:
808a9de470cSBruce Richardson 	/*clean up */
809a9de470cSBruce Richardson 	rte_free(data_ptr);
810a9de470cSBruce Richardson 	return -1;
811a9de470cSBruce Richardson }
812a9de470cSBruce Richardson 
813a9de470cSBruce Richardson static int
814a9de470cSBruce Richardson test_zero_aligned_alloc(void)
815a9de470cSBruce Richardson {
816a9de470cSBruce Richardson 	char *p1 = rte_malloc(NULL,1024, 0);
817a9de470cSBruce Richardson 	if (!p1)
818a9de470cSBruce Richardson 		goto err_return;
819a9de470cSBruce Richardson 	if (!rte_is_aligned(p1, RTE_CACHE_LINE_SIZE))
820a9de470cSBruce Richardson 		goto err_return;
821a9de470cSBruce Richardson 	rte_free(p1);
822a9de470cSBruce Richardson 	return 0;
823a9de470cSBruce Richardson 
824a9de470cSBruce Richardson err_return:
825a9de470cSBruce Richardson 	/*clean up */
82606c047b6SStephen Hemminger 	rte_free(p1);
827a9de470cSBruce Richardson 	return -1;
828a9de470cSBruce Richardson }
829a9de470cSBruce Richardson 
830a9de470cSBruce Richardson static int
831a9de470cSBruce Richardson test_malloc_bad_params(void)
832a9de470cSBruce Richardson {
833a9de470cSBruce Richardson 	const char *type = NULL;
834a9de470cSBruce Richardson 	size_t size = 0;
835a9de470cSBruce Richardson 	unsigned align = RTE_CACHE_LINE_SIZE;
836a9de470cSBruce Richardson 
837a9de470cSBruce Richardson 	/* rte_malloc expected to return null with inappropriate size */
838a9de470cSBruce Richardson 	char *bad_ptr = rte_malloc(type, size, align);
839a9de470cSBruce Richardson 	if (bad_ptr != NULL)
840a9de470cSBruce Richardson 		goto err_return;
841a9de470cSBruce Richardson 
8424a5a8678SAnatoly Burakov 	/* rte_realloc expected to return null with inappropriate size */
8434a5a8678SAnatoly Burakov 	bad_ptr = rte_realloc(NULL, size, align);
8444a5a8678SAnatoly Burakov 	if (bad_ptr != NULL)
8454a5a8678SAnatoly Burakov 		goto err_return;
8464a5a8678SAnatoly Burakov 
847a9de470cSBruce Richardson 	/* rte_malloc expected to return null with inappropriate alignment */
848a9de470cSBruce Richardson 	align = 17;
849a9de470cSBruce Richardson 	size = 1024;
850a9de470cSBruce Richardson 
851a9de470cSBruce Richardson 	bad_ptr = rte_malloc(type, size, align);
852a9de470cSBruce Richardson 	if (bad_ptr != NULL)
853a9de470cSBruce Richardson 		goto err_return;
854a9de470cSBruce Richardson 
8554a5a8678SAnatoly Burakov 	/* rte_realloc expected to return null with inappropriate alignment */
8564a5a8678SAnatoly Burakov 	bad_ptr = rte_realloc(NULL, size, align);
8574a5a8678SAnatoly Burakov 	if (bad_ptr != NULL)
8584a5a8678SAnatoly Burakov 		goto err_return;
8594a5a8678SAnatoly Burakov 
86017b347daSStephen Hemminger #if defined(RTE_CC_GCC) || defined(RTE_CC_CLANG)
86117b347daSStephen Hemminger 	/* this test can not be built, will get trapped at compile time! */
86217b347daSStephen Hemminger #else
863b341a09cSBing Zhao 	/* rte_malloc expected to return null with size will cause overflow */
864b341a09cSBing Zhao 	align = RTE_CACHE_LINE_SIZE;
865b341a09cSBing Zhao 	size = (size_t)-8;
866b341a09cSBing Zhao 
867b341a09cSBing Zhao 	bad_ptr = rte_malloc(type, size, align);
868b341a09cSBing Zhao 	if (bad_ptr != NULL)
869b341a09cSBing Zhao 		goto err_return;
870b341a09cSBing Zhao 
871b341a09cSBing Zhao 	bad_ptr = rte_realloc(NULL, size, align);
872b341a09cSBing Zhao 	if (bad_ptr != NULL)
873b341a09cSBing Zhao 		goto err_return;
87417b347daSStephen Hemminger #endif
875a9de470cSBruce Richardson 	return 0;
876a9de470cSBruce Richardson 
877a9de470cSBruce Richardson err_return:
878a9de470cSBruce Richardson 	/* clean up pointer */
879a9de470cSBruce Richardson 	rte_free(bad_ptr);
880a9de470cSBruce Richardson 	return -1;
881a9de470cSBruce Richardson }
882a9de470cSBruce Richardson 
883a9de470cSBruce Richardson static int
884a9de470cSBruce Richardson check_socket_mem(const struct rte_memseg_list *msl, void *arg)
885a9de470cSBruce Richardson {
886a9de470cSBruce Richardson 	int32_t *socket = arg;
887a9de470cSBruce Richardson 
888a9de470cSBruce Richardson 	if (msl->external)
889a9de470cSBruce Richardson 		return 0;
890a9de470cSBruce Richardson 
891a9de470cSBruce Richardson 	return *socket == msl->socket_id;
892a9de470cSBruce Richardson }
893a9de470cSBruce Richardson 
894a9de470cSBruce Richardson /* Check if memory is available on a specific socket */
895a9de470cSBruce Richardson static int
896a9de470cSBruce Richardson is_mem_on_socket(int32_t socket)
897a9de470cSBruce Richardson {
898a9de470cSBruce Richardson 	return rte_memseg_list_walk(check_socket_mem, &socket);
899a9de470cSBruce Richardson }
900a9de470cSBruce Richardson 
901a9de470cSBruce Richardson 
902a9de470cSBruce Richardson /*
903a9de470cSBruce Richardson  * Find what socket a memory address is on. Only works for addresses within
904a9de470cSBruce Richardson  * memsegs, not heap or stack...
905a9de470cSBruce Richardson  */
906a9de470cSBruce Richardson static int32_t
907a9de470cSBruce Richardson addr_to_socket(void * addr)
908a9de470cSBruce Richardson {
909a9de470cSBruce Richardson 	const struct rte_memseg *ms = rte_mem_virt2memseg(addr, NULL);
910a9de470cSBruce Richardson 	return ms == NULL ? -1 : ms->socket_id;
911a9de470cSBruce Richardson 
912a9de470cSBruce Richardson }
913a9de470cSBruce Richardson 
914a9de470cSBruce Richardson /* Test using rte_[c|m|zm]alloc_socket() on a specific socket */
915a9de470cSBruce Richardson static int
916a9de470cSBruce Richardson test_alloc_single_socket(int32_t socket)
917a9de470cSBruce Richardson {
918a9de470cSBruce Richardson 	const char *type = NULL;
919a9de470cSBruce Richardson 	const size_t size = 10;
920a9de470cSBruce Richardson 	const unsigned align = 0;
921a9de470cSBruce Richardson 	char *mem = NULL;
922a9de470cSBruce Richardson 	int32_t desired_socket = (socket == SOCKET_ID_ANY) ?
923a9de470cSBruce Richardson 			(int32_t)rte_socket_id() : socket;
924a9de470cSBruce Richardson 
925a9de470cSBruce Richardson 	/* Test rte_calloc_socket() */
926a9de470cSBruce Richardson 	mem = rte_calloc_socket(type, size, sizeof(char), align, socket);
927a9de470cSBruce Richardson 	if (mem == NULL)
928a9de470cSBruce Richardson 		return -1;
929a9de470cSBruce Richardson 	if (addr_to_socket(mem) != desired_socket) {
930a9de470cSBruce Richardson 		rte_free(mem);
931a9de470cSBruce Richardson 		return -1;
932a9de470cSBruce Richardson 	}
933a9de470cSBruce Richardson 	rte_free(mem);
934a9de470cSBruce Richardson 
935a9de470cSBruce Richardson 	/* Test rte_malloc_socket() */
936a9de470cSBruce Richardson 	mem = rte_malloc_socket(type, size, align, socket);
937a9de470cSBruce Richardson 	if (mem == NULL)
938a9de470cSBruce Richardson 		return -1;
939a9de470cSBruce Richardson 	if (addr_to_socket(mem) != desired_socket) {
940ec8ef136SRuifeng Wang 		rte_free(mem);
941a9de470cSBruce Richardson 		return -1;
942a9de470cSBruce Richardson 	}
943a9de470cSBruce Richardson 	rte_free(mem);
944a9de470cSBruce Richardson 
945a9de470cSBruce Richardson 	/* Test rte_zmalloc_socket() */
946a9de470cSBruce Richardson 	mem = rte_zmalloc_socket(type, size, align, socket);
947a9de470cSBruce Richardson 	if (mem == NULL)
948a9de470cSBruce Richardson 		return -1;
949a9de470cSBruce Richardson 	if (addr_to_socket(mem) != desired_socket) {
950a9de470cSBruce Richardson 		rte_free(mem);
951a9de470cSBruce Richardson 		return -1;
952a9de470cSBruce Richardson 	}
953a9de470cSBruce Richardson 	rte_free(mem);
954a9de470cSBruce Richardson 
955a9de470cSBruce Richardson 	return 0;
956a9de470cSBruce Richardson }
957a9de470cSBruce Richardson 
958a9de470cSBruce Richardson static int
959a9de470cSBruce Richardson test_alloc_socket(void)
960a9de470cSBruce Richardson {
961a9de470cSBruce Richardson 	unsigned socket_count = 0;
962a9de470cSBruce Richardson 	unsigned i;
963a9de470cSBruce Richardson 
964a9de470cSBruce Richardson 	if (test_alloc_single_socket(SOCKET_ID_ANY) < 0)
965a9de470cSBruce Richardson 		return -1;
966a9de470cSBruce Richardson 
967a9de470cSBruce Richardson 	for (i = 0; i < RTE_MAX_NUMA_NODES; i++) {
968a9de470cSBruce Richardson 		if (is_mem_on_socket(i)) {
969a9de470cSBruce Richardson 			socket_count++;
970a9de470cSBruce Richardson 			if (test_alloc_single_socket(i) < 0) {
971a9de470cSBruce Richardson 				printf("Fail: rte_malloc_socket(..., %u) did not succeed\n",
972a9de470cSBruce Richardson 						i);
973a9de470cSBruce Richardson 				return -1;
974a9de470cSBruce Richardson 			}
975a9de470cSBruce Richardson 		}
976a9de470cSBruce Richardson 		else {
977a9de470cSBruce Richardson 			if (test_alloc_single_socket(i) == 0) {
978a9de470cSBruce Richardson 				printf("Fail: rte_malloc_socket(..., %u) succeeded\n",
979a9de470cSBruce Richardson 						i);
980a9de470cSBruce Richardson 				return -1;
981a9de470cSBruce Richardson 			}
982a9de470cSBruce Richardson 		}
983a9de470cSBruce Richardson 	}
984a9de470cSBruce Richardson 
9854a6672c2SStephen Hemminger 	/* Print warning if only a single socket, but don't fail the test */
986a9de470cSBruce Richardson 	if (socket_count < 2) {
987a9de470cSBruce Richardson 		printf("WARNING: alloc_socket test needs memory on multiple sockets!\n");
988a9de470cSBruce Richardson 	}
989a9de470cSBruce Richardson 
990a9de470cSBruce Richardson 	return 0;
991a9de470cSBruce Richardson }
992a9de470cSBruce Richardson 
993a9de470cSBruce Richardson static int
994a9de470cSBruce Richardson test_malloc(void)
995a9de470cSBruce Richardson {
996a9de470cSBruce Richardson 	unsigned lcore_id;
997a9de470cSBruce Richardson 	int ret = 0;
998a9de470cSBruce Richardson 
999a9de470cSBruce Richardson 	if (test_str_to_size() < 0){
1000a9de470cSBruce Richardson 		printf("test_str_to_size() failed\n");
1001a9de470cSBruce Richardson 		return -1;
1002a9de470cSBruce Richardson 	}
1003a9de470cSBruce Richardson 	else printf("test_str_to_size() passed\n");
1004a9de470cSBruce Richardson 
1005a9de470cSBruce Richardson 	if (test_zero_aligned_alloc() < 0){
1006a9de470cSBruce Richardson 		printf("test_zero_aligned_alloc() failed\n");
1007a9de470cSBruce Richardson 		return -1;
1008a9de470cSBruce Richardson 	}
1009a9de470cSBruce Richardson 	else printf("test_zero_aligned_alloc() passed\n");
1010a9de470cSBruce Richardson 
1011a9de470cSBruce Richardson 	if (test_malloc_bad_params() < 0){
1012a9de470cSBruce Richardson 		printf("test_malloc_bad_params() failed\n");
1013a9de470cSBruce Richardson 		return -1;
1014a9de470cSBruce Richardson 	}
1015a9de470cSBruce Richardson 	else printf("test_malloc_bad_params() passed\n");
1016a9de470cSBruce Richardson 
1017a9de470cSBruce Richardson 	if (test_realloc() < 0){
1018a9de470cSBruce Richardson 		printf("test_realloc() failed\n");
1019a9de470cSBruce Richardson 		return -1;
1020a9de470cSBruce Richardson 	}
1021a9de470cSBruce Richardson 	else printf("test_realloc() passed\n");
1022a9de470cSBruce Richardson 
1023a9de470cSBruce Richardson 	/*----------------------------*/
1024cb056611SStephen Hemminger 	RTE_LCORE_FOREACH_WORKER(lcore_id) {
1025a9de470cSBruce Richardson 		rte_eal_remote_launch(test_align_overlap_per_lcore, NULL, lcore_id);
1026a9de470cSBruce Richardson 	}
1027a9de470cSBruce Richardson 
1028cb056611SStephen Hemminger 	RTE_LCORE_FOREACH_WORKER(lcore_id) {
1029a9de470cSBruce Richardson 		if (rte_eal_wait_lcore(lcore_id) < 0)
1030a9de470cSBruce Richardson 			ret = -1;
1031a9de470cSBruce Richardson 	}
1032a9de470cSBruce Richardson 	if (ret < 0){
1033a9de470cSBruce Richardson 		printf("test_align_overlap_per_lcore() failed\n");
1034a9de470cSBruce Richardson 		return ret;
1035a9de470cSBruce Richardson 	}
1036a9de470cSBruce Richardson 	else printf("test_align_overlap_per_lcore() passed\n");
1037a9de470cSBruce Richardson 
1038a9de470cSBruce Richardson 	/*----------------------------*/
1039cb056611SStephen Hemminger 	RTE_LCORE_FOREACH_WORKER(lcore_id) {
1040a9de470cSBruce Richardson 		rte_eal_remote_launch(test_reordered_free_per_lcore, NULL, lcore_id);
1041a9de470cSBruce Richardson 	}
1042a9de470cSBruce Richardson 
1043cb056611SStephen Hemminger 	RTE_LCORE_FOREACH_WORKER(lcore_id) {
1044a9de470cSBruce Richardson 		if (rte_eal_wait_lcore(lcore_id) < 0)
1045a9de470cSBruce Richardson 			ret = -1;
1046a9de470cSBruce Richardson 	}
1047a9de470cSBruce Richardson 	if (ret < 0){
1048a9de470cSBruce Richardson 		printf("test_reordered_free_per_lcore() failed\n");
1049a9de470cSBruce Richardson 		return ret;
1050a9de470cSBruce Richardson 	}
1051a9de470cSBruce Richardson 	else printf("test_reordered_free_per_lcore() passed\n");
1052a9de470cSBruce Richardson 
1053a9de470cSBruce Richardson 	/*----------------------------*/
1054cb056611SStephen Hemminger 	RTE_LCORE_FOREACH_WORKER(lcore_id) {
1055a9de470cSBruce Richardson 		rte_eal_remote_launch(test_random_alloc_free, NULL, lcore_id);
1056a9de470cSBruce Richardson 	}
1057a9de470cSBruce Richardson 
1058cb056611SStephen Hemminger 	RTE_LCORE_FOREACH_WORKER(lcore_id) {
1059a9de470cSBruce Richardson 		if (rte_eal_wait_lcore(lcore_id) < 0)
1060a9de470cSBruce Richardson 			ret = -1;
1061a9de470cSBruce Richardson 	}
1062a9de470cSBruce Richardson 	if (ret < 0){
1063a9de470cSBruce Richardson 		printf("test_random_alloc_free() failed\n");
1064a9de470cSBruce Richardson 		return ret;
1065a9de470cSBruce Richardson 	}
1066a9de470cSBruce Richardson 	else printf("test_random_alloc_free() passed\n");
1067a9de470cSBruce Richardson 
1068a9de470cSBruce Richardson 	/*----------------------------*/
1069a9de470cSBruce Richardson 	ret = test_rte_malloc_validate();
1070a9de470cSBruce Richardson 	if (ret < 0){
1071a9de470cSBruce Richardson 		printf("test_rte_malloc_validate() failed\n");
1072a9de470cSBruce Richardson 		return ret;
1073a9de470cSBruce Richardson 	}
1074a9de470cSBruce Richardson 	else printf("test_rte_malloc_validate() passed\n");
1075a9de470cSBruce Richardson 
1076a9de470cSBruce Richardson 	ret = test_alloc_socket();
1077a9de470cSBruce Richardson 	if (ret < 0){
1078a9de470cSBruce Richardson 		printf("test_alloc_socket() failed\n");
1079a9de470cSBruce Richardson 		return ret;
1080a9de470cSBruce Richardson 	}
1081a9de470cSBruce Richardson 	else printf("test_alloc_socket() passed\n");
1082a9de470cSBruce Richardson 
1083a9de470cSBruce Richardson 	ret = test_multi_alloc_statistics();
1084a9de470cSBruce Richardson 	if (ret < 0) {
1085a9de470cSBruce Richardson 		printf("test_multi_alloc_statistics() failed\n");
1086a9de470cSBruce Richardson 		return ret;
1087a9de470cSBruce Richardson 	}
1088a9de470cSBruce Richardson 	else
1089a9de470cSBruce Richardson 		printf("test_multi_alloc_statistics() passed\n");
1090a9de470cSBruce Richardson 
1091a9de470cSBruce Richardson 	return 0;
1092a9de470cSBruce Richardson }
1093a9de470cSBruce Richardson 
1094*e0a8442cSBruce Richardson REGISTER_FAST_TEST(malloc_autotest, false, true, test_malloc);
1095