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