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