]>
Commit | Line | Data |
---|---|---|
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 | |
41 | static uint32_t g_ut_num_threads; | |
11fdf7f2 TL |
42 | |
43 | int allocate_threads(int num_threads); | |
44 | void free_threads(void); | |
45 | void poll_threads(void); | |
9f95a23c | 46 | bool poll_thread(uintptr_t thread_id); |
11fdf7f2 TL |
47 | |
48 | struct ut_msg { | |
9f95a23c | 49 | spdk_msg_fn fn; |
11fdf7f2 TL |
50 | void *ctx; |
51 | TAILQ_ENTRY(ut_msg) link; | |
52 | }; | |
53 | ||
54 | struct ut_thread { | |
55 | struct spdk_thread *thread; | |
56 | struct spdk_io_channel *ch; | |
11fdf7f2 TL |
57 | }; |
58 | ||
59 | struct ut_thread *g_ut_threads; | |
60 | ||
11fdf7f2 TL |
61 | #define INVALID_THREAD 0x1000 |
62 | ||
9f95a23c | 63 | static uint64_t g_thread_id = INVALID_THREAD; |
11fdf7f2 TL |
64 | |
65 | static void | |
66 | set_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 | ||
77 | int | |
78 | allocate_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 | ||
101 | void | |
102 | free_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 | 120 | bool |
11fdf7f2 TL |
121 | poll_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 | ||
142 | void | |
143 | poll_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 | } |