]> git.proxmox.com Git - ceph.git/blame - ceph/src/spdk/test/common/lib/ut_multithread.c
import 15.2.0 Octopus source
[ceph.git] / ceph / src / spdk / test / common / lib / ut_multithread.c
CommitLineData
11fdf7f2
TL
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_cunit.h"
35#include "spdk/thread.h"
36#include "spdk_internal/mock.h"
9f95a23c
TL
37#include "spdk_internal/thread.h"
38
39#include "common/lib/test_env.c"
11fdf7f2
TL
40
41static uint32_t g_ut_num_threads;
11fdf7f2
TL
42
43int allocate_threads(int num_threads);
44void free_threads(void);
45void poll_threads(void);
9f95a23c 46bool poll_thread(uintptr_t thread_id);
11fdf7f2
TL
47
48struct ut_msg {
9f95a23c 49 spdk_msg_fn fn;
11fdf7f2
TL
50 void *ctx;
51 TAILQ_ENTRY(ut_msg) link;
52};
53
54struct ut_thread {
55 struct spdk_thread *thread;
56 struct spdk_io_channel *ch;
11fdf7f2
TL
57};
58
59struct ut_thread *g_ut_threads;
60
11fdf7f2
TL
61#define INVALID_THREAD 0x1000
62
9f95a23c 63static uint64_t g_thread_id = INVALID_THREAD;
11fdf7f2
TL
64
65static void
66set_thread(uintptr_t thread_id)
67{
68 g_thread_id = thread_id;
69 if (thread_id == INVALID_THREAD) {
9f95a23c 70 spdk_set_thread(NULL);
11fdf7f2 71 } else {
9f95a23c 72 spdk_set_thread(g_ut_threads[thread_id].thread);
11fdf7f2 73 }
9f95a23c 74
11fdf7f2
TL
75}
76
77int
78allocate_threads(int num_threads)
79{
80 struct spdk_thread *thread;
81 uint32_t i;
82
9f95a23c
TL
83 spdk_thread_lib_init(NULL, 0);
84
11fdf7f2
TL
85 g_ut_num_threads = num_threads;
86
87 g_ut_threads = calloc(num_threads, sizeof(*g_ut_threads));
9f95a23c 88 assert(g_ut_threads != NULL);
11fdf7f2
TL
89
90 for (i = 0; i < g_ut_num_threads; i++) {
91 set_thread(i);
9f95a23c
TL
92 thread = spdk_thread_create(NULL, NULL);
93 assert(thread != NULL);
11fdf7f2 94 g_ut_threads[i].thread = thread;
11fdf7f2
TL
95 }
96
97 set_thread(INVALID_THREAD);
98 return 0;
99}
100
101void
102free_threads(void)
103{
104 uint32_t i;
105
106 for (i = 0; i < g_ut_num_threads; i++) {
107 set_thread(i);
9f95a23c
TL
108 spdk_thread_exit(g_ut_threads[i].thread);
109 spdk_thread_destroy(g_ut_threads[i].thread);
110 g_ut_threads[i].thread = NULL;
11fdf7f2
TL
111 }
112
113 g_ut_num_threads = 0;
114 free(g_ut_threads);
115 g_ut_threads = NULL;
11fdf7f2 116
9f95a23c 117 spdk_thread_lib_fini();
11fdf7f2
TL
118}
119
9f95a23c 120bool
11fdf7f2
TL
121poll_thread(uintptr_t thread_id)
122{
9f95a23c 123 bool busy = false;
11fdf7f2 124 struct ut_thread *thread = &g_ut_threads[thread_id];
11fdf7f2 125 uintptr_t original_thread_id;
11fdf7f2 126
9f95a23c
TL
127 assert(thread_id != (uintptr_t)INVALID_THREAD);
128 assert(thread_id < g_ut_num_threads);
11fdf7f2
TL
129
130 original_thread_id = g_thread_id;
9f95a23c 131 set_thread(INVALID_THREAD);
11fdf7f2 132
9f95a23c
TL
133 while (spdk_thread_poll(thread->thread, 0, 0) > 0) {
134 busy = true;
11fdf7f2
TL
135 }
136
11fdf7f2
TL
137 set_thread(original_thread_id);
138
9f95a23c 139 return busy;
11fdf7f2
TL
140}
141
142void
143poll_threads(void)
144{
11fdf7f2 145 while (true) {
9f95a23c 146 bool busy = false;
11fdf7f2 147
9f95a23c
TL
148 for (uint32_t i = 0; i < g_ut_num_threads; i++) {
149 busy = busy || poll_thread(i);
11fdf7f2
TL
150 }
151
9f95a23c 152 if (!busy) {
11fdf7f2
TL
153 break;
154 }
155 }
156}