xref: /spdk/test/common/lib/test_env.c (revision 94a84ae98590bea46939eb1dcd7a9876bd393b54)
1 /*-
2  *   BSD LICENSE
3  *
4  *   Copyright (c) Intel Corporation.
5  *   All rights reserved.
6  *
7  *   Redistribution and use in source and binary forms, with or without
8  *   modification, are permitted provided that the following conditions
9  *   are met:
10  *
11  *     * Redistributions of source code must retain the above copyright
12  *       notice, this list of conditions and the following disclaimer.
13  *     * Redistributions in binary form must reproduce the above copyright
14  *       notice, this list of conditions and the following disclaimer in
15  *       the documentation and/or other materials provided with the
16  *       distribution.
17  *     * Neither the name of Intel Corporation nor the names of its
18  *       contributors may be used to endorse or promote products derived
19  *       from this software without specific prior written permission.
20  *
21  *   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22  *   "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23  *   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
24  *   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
25  *   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
26  *   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
27  *   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
28  *   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
29  *   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
30  *   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
31  *   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32  */
33 
34 #include "spdk/stdinc.h"
35 
36 #include "spdk_internal/mock.h"
37 
38 #include "spdk/env.h"
39 #include "spdk/queue.h"
40 #include "spdk/util.h"
41 
42 static uint32_t g_ut_num_cores;
43 static bool *g_ut_cores;
44 
45 void allocate_cores(uint32_t num_cores);
46 void free_cores(void);
47 
48 DEFINE_STUB(spdk_process_is_primary, bool, (void), true)
49 DEFINE_STUB(spdk_memzone_lookup, void *, (const char *name), NULL)
50 DEFINE_STUB(spdk_pci_nvme_get_driver, struct spdk_pci_driver *, (void), NULL)
51 DEFINE_STUB(spdk_pci_ioat_get_driver, struct spdk_pci_driver *, (void), NULL)
52 DEFINE_STUB(spdk_pci_virtio_get_driver, struct spdk_pci_driver *, (void), NULL)
53 
54 void
55 allocate_cores(uint32_t num_cores)
56 {
57 	uint32_t i;
58 
59 	g_ut_num_cores = num_cores;
60 
61 	g_ut_cores = calloc(num_cores, sizeof(bool));
62 	assert(g_ut_cores != NULL);
63 
64 	for (i = 0; i < num_cores; i++) {
65 		g_ut_cores[i] = true;
66 	}
67 }
68 
69 void
70 free_cores(void)
71 {
72 	free(g_ut_cores);
73 	g_ut_cores = NULL;
74 	g_ut_num_cores = 0;
75 }
76 
77 static uint32_t
78 ut_get_next_core(uint32_t i)
79 {
80 	i++;
81 
82 	while (i < g_ut_num_cores) {
83 		if (!g_ut_cores[i]) {
84 			i++;
85 			continue;
86 		}
87 		break;
88 	}
89 
90 	if (i < g_ut_num_cores) {
91 		return i;
92 	} else {
93 		return UINT32_MAX;
94 	}
95 }
96 
97 uint32_t
98 spdk_env_get_first_core(void)
99 {
100 	return ut_get_next_core(-1);
101 }
102 
103 uint32_t
104 spdk_env_get_next_core(uint32_t prev_core)
105 {
106 	return ut_get_next_core(prev_core);
107 }
108 
109 uint32_t
110 spdk_env_get_core_count(void)
111 {
112 	return g_ut_num_cores;
113 }
114 
115 uint32_t
116 spdk_env_get_last_core(void)
117 {
118 	uint32_t i;
119 	uint32_t last_core = UINT32_MAX;
120 
121 	SPDK_ENV_FOREACH_CORE(i) {
122 		last_core = i;
123 	}
124 
125 	return last_core;
126 }
127 
128 DEFINE_RETURN_MOCK(spdk_env_get_current_core, uint32_t);
129 uint32_t
130 spdk_env_get_current_core(void)
131 {
132 	HANDLE_RETURN_MOCK(spdk_env_get_current_core);
133 
134 	return UINT32_MAX;
135 }
136 
137 DEFINE_RETURN_MOCK(spdk_env_get_socket_id, uint32_t);
138 uint32_t
139 spdk_env_get_socket_id(uint32_t core)
140 {
141 	HANDLE_RETURN_MOCK(spdk_env_get_socket_id);
142 
143 	return SPDK_ENV_SOCKET_ID_ANY;
144 }
145 
146 /*
147  * These mocks don't use the DEFINE_STUB macros because
148  * their default implementation is more complex.
149  */
150 
151 DEFINE_RETURN_MOCK(spdk_memzone_reserve, void *);
152 void *
153 spdk_memzone_reserve(const char *name, size_t len, int socket_id, unsigned flags)
154 {
155 	HANDLE_RETURN_MOCK(spdk_memzone_reserve);
156 
157 	return malloc(len);
158 }
159 
160 DEFINE_RETURN_MOCK(spdk_memzone_reserve_aligned, void *);
161 void *
162 spdk_memzone_reserve_aligned(const char *name, size_t len, int socket_id,
163 			     unsigned flags, unsigned align)
164 {
165 	HANDLE_RETURN_MOCK(spdk_memzone_reserve_aligned);
166 
167 	return malloc(len);
168 }
169 
170 DEFINE_RETURN_MOCK(spdk_malloc, void *);
171 void *
172 spdk_malloc(size_t size, size_t align, uint64_t *phys_addr, int socket_id, uint32_t flags)
173 {
174 	HANDLE_RETURN_MOCK(spdk_malloc);
175 
176 	void *buf = NULL;
177 
178 	if (align == 0) {
179 		align = 8;
180 	}
181 
182 	if (posix_memalign(&buf, align, size)) {
183 		return NULL;
184 	}
185 	if (phys_addr) {
186 		*phys_addr = (uint64_t)buf;
187 	}
188 
189 	return buf;
190 }
191 
192 DEFINE_RETURN_MOCK(spdk_zmalloc, void *);
193 void *
194 spdk_zmalloc(size_t size, size_t align, uint64_t *phys_addr, int socket_id, uint32_t flags)
195 {
196 	HANDLE_RETURN_MOCK(spdk_zmalloc);
197 
198 	void *buf = spdk_malloc(size, align, phys_addr, -1, 1);
199 
200 	if (buf != NULL) {
201 		memset(buf, 0, size);
202 	}
203 	return buf;
204 }
205 
206 DEFINE_RETURN_MOCK(spdk_dma_malloc, void *);
207 void *
208 spdk_dma_malloc(size_t size, size_t align, uint64_t *phys_addr)
209 {
210 	HANDLE_RETURN_MOCK(spdk_dma_malloc);
211 
212 	return spdk_malloc(size, align, phys_addr, -1, 1);
213 }
214 
215 DEFINE_RETURN_MOCK(spdk_realloc, void *);
216 void *
217 spdk_realloc(void *buf, size_t size, size_t align)
218 {
219 	HANDLE_RETURN_MOCK(spdk_realloc);
220 
221 	return realloc(buf, size);
222 }
223 
224 DEFINE_RETURN_MOCK(spdk_dma_zmalloc, void *);
225 void *
226 spdk_dma_zmalloc(size_t size, size_t align, uint64_t *phys_addr)
227 {
228 	HANDLE_RETURN_MOCK(spdk_dma_zmalloc);
229 
230 	return spdk_zmalloc(size, align, phys_addr, -1, 1);
231 }
232 
233 DEFINE_RETURN_MOCK(spdk_dma_malloc_socket, void *);
234 void *
235 spdk_dma_malloc_socket(size_t size, size_t align, uint64_t *phys_addr, int socket_id)
236 {
237 	HANDLE_RETURN_MOCK(spdk_dma_malloc_socket);
238 
239 	return spdk_dma_malloc(size, align, phys_addr);
240 }
241 
242 DEFINE_RETURN_MOCK(spdk_dma_zmalloc_socket, void *);
243 void *
244 spdk_dma_zmalloc_socket(size_t size, size_t align, uint64_t *phys_addr, int socket_id)
245 {
246 	HANDLE_RETURN_MOCK(spdk_dma_zmalloc_socket);
247 
248 	return spdk_dma_zmalloc(size, align, phys_addr);
249 }
250 
251 DEFINE_RETURN_MOCK(spdk_dma_realloc, void *);
252 void *
253 spdk_dma_realloc(void *buf, size_t size, size_t align, uint64_t *phys_addr)
254 {
255 	HANDLE_RETURN_MOCK(spdk_dma_realloc);
256 
257 	return realloc(buf, size);
258 }
259 
260 void
261 spdk_free(void *buf)
262 {
263 	/* fix for false-positives in *certain* static analysis tools. */
264 	assert((uintptr_t)buf != UINTPTR_MAX);
265 	free(buf);
266 }
267 
268 void
269 spdk_dma_free(void *buf)
270 {
271 	return spdk_free(buf);
272 }
273 
274 #ifndef UNIT_TEST_NO_VTOPHYS
275 DEFINE_RETURN_MOCK(spdk_vtophys, uint64_t);
276 uint64_t
277 spdk_vtophys(void *buf, uint64_t *size)
278 {
279 	HANDLE_RETURN_MOCK(spdk_vtophys);
280 
281 	return (uintptr_t)buf;
282 }
283 #endif
284 
285 void
286 spdk_memzone_dump(FILE *f)
287 {
288 	return;
289 }
290 
291 DEFINE_RETURN_MOCK(spdk_memzone_free, int);
292 int
293 spdk_memzone_free(const char *name)
294 {
295 	HANDLE_RETURN_MOCK(spdk_memzone_free);
296 
297 	return 0;
298 }
299 
300 struct test_mempool {
301 	size_t	count;
302 	size_t	ele_size;
303 };
304 
305 DEFINE_RETURN_MOCK(spdk_mempool_create, struct spdk_mempool *);
306 struct spdk_mempool *
307 spdk_mempool_create(const char *name, size_t count,
308 		    size_t ele_size, size_t cache_size, int socket_id)
309 {
310 	struct test_mempool *mp;
311 
312 	HANDLE_RETURN_MOCK(spdk_mempool_create);
313 
314 	mp = calloc(1, sizeof(*mp));
315 	if (mp == NULL) {
316 		return NULL;
317 	}
318 
319 	mp->count = count;
320 	mp->ele_size = ele_size;
321 
322 	return (struct spdk_mempool *)mp;
323 }
324 
325 void
326 spdk_mempool_free(struct spdk_mempool *_mp)
327 {
328 	struct test_mempool *mp = (struct test_mempool *)_mp;
329 
330 	free(mp);
331 }
332 
333 DEFINE_RETURN_MOCK(spdk_mempool_get, void *);
334 void *
335 spdk_mempool_get(struct spdk_mempool *_mp)
336 {
337 	struct test_mempool *mp = (struct test_mempool *)_mp;
338 	size_t ele_size = 0x10000;
339 	void *buf;
340 
341 	HANDLE_RETURN_MOCK(spdk_mempool_get);
342 
343 	if (mp && mp->count == 0) {
344 		return NULL;
345 	}
346 
347 	if (mp) {
348 		ele_size = mp->ele_size;
349 	}
350 
351 	if (posix_memalign(&buf, 64, spdk_align32pow2(ele_size))) {
352 		return NULL;
353 	} else {
354 		if (mp) {
355 			mp->count--;
356 		}
357 		return buf;
358 	}
359 }
360 
361 int
362 spdk_mempool_get_bulk(struct spdk_mempool *mp, void **ele_arr, size_t count)
363 {
364 	for (size_t i = 0; i < count; i++) {
365 		ele_arr[i] = spdk_mempool_get(mp);
366 		if (ele_arr[i] == NULL) {
367 			return -1;
368 		}
369 	}
370 	return 0;
371 }
372 
373 void
374 spdk_mempool_put(struct spdk_mempool *_mp, void *ele)
375 {
376 	struct test_mempool *mp = (struct test_mempool *)_mp;
377 
378 	if (mp) {
379 		mp->count++;
380 	}
381 	free(ele);
382 }
383 
384 void
385 spdk_mempool_put_bulk(struct spdk_mempool *mp, void **ele_arr, size_t count)
386 {
387 	for (size_t i = 0; i < count; i++) {
388 		spdk_mempool_put(mp, ele_arr[i]);
389 	}
390 }
391 
392 DEFINE_RETURN_MOCK(spdk_mempool_count, size_t);
393 size_t
394 spdk_mempool_count(const struct spdk_mempool *_mp)
395 {
396 	struct test_mempool *mp = (struct test_mempool *)_mp;
397 
398 	HANDLE_RETURN_MOCK(spdk_mempool_count);
399 
400 	if (mp) {
401 		return mp->count;
402 	} else {
403 		return 1024;
404 	}
405 }
406 
407 struct spdk_ring_ele {
408 	void *ele;
409 	TAILQ_ENTRY(spdk_ring_ele) link;
410 };
411 
412 struct spdk_ring {
413 	TAILQ_HEAD(, spdk_ring_ele) elements;
414 	pthread_mutex_t lock;
415 	size_t count;
416 };
417 
418 DEFINE_RETURN_MOCK(spdk_ring_create, struct spdk_ring *);
419 struct spdk_ring *
420 spdk_ring_create(enum spdk_ring_type type, size_t count, int socket_id)
421 {
422 	struct spdk_ring *ring;
423 
424 	HANDLE_RETURN_MOCK(spdk_ring_create);
425 
426 	ring = calloc(1, sizeof(*ring));
427 	if (!ring) {
428 		return NULL;
429 	}
430 
431 	if (pthread_mutex_init(&ring->lock, NULL)) {
432 		free(ring);
433 		return NULL;
434 	}
435 
436 	TAILQ_INIT(&ring->elements);
437 	return ring;
438 }
439 
440 void
441 spdk_ring_free(struct spdk_ring *ring)
442 {
443 	struct spdk_ring_ele *ele, *tmp;
444 
445 	if (!ring) {
446 		return;
447 	}
448 
449 	TAILQ_FOREACH_SAFE(ele, &ring->elements, link, tmp) {
450 		free(ele);
451 	}
452 
453 	pthread_mutex_destroy(&ring->lock);
454 	free(ring);
455 }
456 
457 DEFINE_RETURN_MOCK(spdk_ring_enqueue, size_t);
458 size_t
459 spdk_ring_enqueue(struct spdk_ring *ring, void **objs, size_t count,
460 		  size_t *free_space)
461 {
462 	struct spdk_ring_ele *ele;
463 	size_t i;
464 
465 	HANDLE_RETURN_MOCK(spdk_ring_enqueue);
466 
467 	pthread_mutex_lock(&ring->lock);
468 
469 	for (i = 0; i < count; i++) {
470 		ele = calloc(1, sizeof(*ele));
471 		if (!ele) {
472 			break;
473 		}
474 
475 		ele->ele = objs[i];
476 		TAILQ_INSERT_TAIL(&ring->elements, ele, link);
477 		ring->count++;
478 	}
479 
480 	pthread_mutex_unlock(&ring->lock);
481 	return i;
482 }
483 
484 DEFINE_RETURN_MOCK(spdk_ring_dequeue, size_t);
485 size_t
486 spdk_ring_dequeue(struct spdk_ring *ring, void **objs, size_t count)
487 {
488 	struct spdk_ring_ele *ele, *tmp;
489 	size_t i = 0;
490 
491 	HANDLE_RETURN_MOCK(spdk_ring_dequeue);
492 
493 	if (count == 0) {
494 		return 0;
495 	}
496 
497 	pthread_mutex_lock(&ring->lock);
498 
499 	TAILQ_FOREACH_SAFE(ele, &ring->elements, link, tmp) {
500 		TAILQ_REMOVE(&ring->elements, ele, link);
501 		ring->count--;
502 		objs[i] = ele->ele;
503 		free(ele);
504 		i++;
505 		if (i >= count) {
506 			break;
507 		}
508 	}
509 
510 	pthread_mutex_unlock(&ring->lock);
511 	return i;
512 
513 }
514 
515 
516 DEFINE_RETURN_MOCK(spdk_ring_count, size_t);
517 size_t
518 spdk_ring_count(struct spdk_ring *ring)
519 {
520 	HANDLE_RETURN_MOCK(spdk_ring_count);
521 	return ring->count;
522 }
523 
524 DEFINE_RETURN_MOCK(spdk_get_ticks, uint64_t);
525 uint64_t
526 spdk_get_ticks(void)
527 {
528 	HANDLE_RETURN_MOCK(spdk_get_ticks);
529 
530 	return ut_spdk_get_ticks;
531 }
532 
533 DEFINE_RETURN_MOCK(spdk_get_ticks_hz, uint64_t);
534 uint64_t
535 spdk_get_ticks_hz(void)
536 {
537 	HANDLE_RETURN_MOCK(spdk_get_ticks_hz);
538 
539 	return 1000000;
540 }
541 
542 void
543 spdk_delay_us(unsigned int us)
544 {
545 	/* spdk_get_ticks_hz is 1000000, meaning 1 tick per us. */
546 	ut_spdk_get_ticks += us;
547 }
548 
549 #ifndef UNIT_TEST_NO_PCI_ADDR
550 DEFINE_RETURN_MOCK(spdk_pci_addr_parse, int);
551 int
552 spdk_pci_addr_parse(struct spdk_pci_addr *addr, const char *bdf)
553 {
554 	unsigned domain, bus, dev, func;
555 
556 	HANDLE_RETURN_MOCK(spdk_pci_addr_parse);
557 
558 	if (addr == NULL || bdf == NULL) {
559 		return -EINVAL;
560 	}
561 
562 	if ((sscanf(bdf, "%x:%x:%x.%x", &domain, &bus, &dev, &func) == 4) ||
563 	    (sscanf(bdf, "%x.%x.%x.%x", &domain, &bus, &dev, &func) == 4)) {
564 		/* Matched a full address - all variables are initialized */
565 	} else if (sscanf(bdf, "%x:%x:%x", &domain, &bus, &dev) == 3) {
566 		func = 0;
567 	} else if ((sscanf(bdf, "%x:%x.%x", &bus, &dev, &func) == 3) ||
568 		   (sscanf(bdf, "%x.%x.%x", &bus, &dev, &func) == 3)) {
569 		domain = 0;
570 	} else if ((sscanf(bdf, "%x:%x", &bus, &dev) == 2) ||
571 		   (sscanf(bdf, "%x.%x", &bus, &dev) == 2)) {
572 		domain = 0;
573 		func = 0;
574 	} else {
575 		return -EINVAL;
576 	}
577 
578 	if (bus > 0xFF || dev > 0x1F || func > 7) {
579 		return -EINVAL;
580 	}
581 
582 	addr->domain = domain;
583 	addr->bus = bus;
584 	addr->dev = dev;
585 	addr->func = func;
586 
587 	return 0;
588 }
589 
590 DEFINE_RETURN_MOCK(spdk_pci_addr_fmt, int);
591 int
592 spdk_pci_addr_fmt(char *bdf, size_t sz, const struct spdk_pci_addr *addr)
593 {
594 	int rc;
595 
596 	HANDLE_RETURN_MOCK(spdk_pci_addr_fmt);
597 
598 	rc = snprintf(bdf, sz, "%04x:%02x:%02x.%x",
599 		      addr->domain, addr->bus,
600 		      addr->dev, addr->func);
601 
602 	if (rc > 0 && (size_t)rc < sz) {
603 		return 0;
604 	}
605 
606 	return -1;
607 }
608 
609 DEFINE_RETURN_MOCK(spdk_pci_addr_compare, int);
610 int
611 spdk_pci_addr_compare(const struct spdk_pci_addr *a1, const struct spdk_pci_addr *a2)
612 {
613 	HANDLE_RETURN_MOCK(spdk_pci_addr_compare);
614 
615 	if (a1->domain > a2->domain) {
616 		return 1;
617 	} else if (a1->domain < a2->domain) {
618 		return -1;
619 	} else if (a1->bus > a2->bus) {
620 		return 1;
621 	} else if (a1->bus < a2->bus) {
622 		return -1;
623 	} else if (a1->dev > a2->dev) {
624 		return 1;
625 	} else if (a1->dev < a2->dev) {
626 		return -1;
627 	} else if (a1->func > a2->func) {
628 		return 1;
629 	} else if (a1->func < a2->func) {
630 		return -1;
631 	}
632 
633 	return 0;
634 }
635 #endif
636