root / tests / test-thread-pool.c @ b7fcff01
History | View | Annotate | Download (5.5 kB)
1 | 74c856e9 | Paolo Bonzini | #include <glib.h> |
---|---|---|---|
2 | 74c856e9 | Paolo Bonzini | #include "qemu-common.h" |
3 | 737e150e | Paolo Bonzini | #include "block/aio.h" |
4 | 737e150e | Paolo Bonzini | #include "block/thread-pool.h" |
5 | 737e150e | Paolo Bonzini | #include "block/block.h" |
6 | dae21b98 | Alex Bligh | #include "qemu/timer.h" |
7 | 74c856e9 | Paolo Bonzini | |
8 | c4d9d196 | Stefan Hajnoczi | static AioContext *ctx;
|
9 | c4d9d196 | Stefan Hajnoczi | static ThreadPool *pool;
|
10 | 74c856e9 | Paolo Bonzini | static int active; |
11 | 74c856e9 | Paolo Bonzini | |
12 | 74c856e9 | Paolo Bonzini | typedef struct { |
13 | 74c856e9 | Paolo Bonzini | BlockDriverAIOCB *aiocb; |
14 | 74c856e9 | Paolo Bonzini | int n;
|
15 | 74c856e9 | Paolo Bonzini | int ret;
|
16 | 74c856e9 | Paolo Bonzini | } WorkerTestData; |
17 | 74c856e9 | Paolo Bonzini | |
18 | 74c856e9 | Paolo Bonzini | static int worker_cb(void *opaque) |
19 | 74c856e9 | Paolo Bonzini | { |
20 | 74c856e9 | Paolo Bonzini | WorkerTestData *data = opaque; |
21 | 5444e768 | Paolo Bonzini | return atomic_fetch_inc(&data->n);
|
22 | 74c856e9 | Paolo Bonzini | } |
23 | 74c856e9 | Paolo Bonzini | |
24 | 74c856e9 | Paolo Bonzini | static int long_cb(void *opaque) |
25 | 74c856e9 | Paolo Bonzini | { |
26 | 74c856e9 | Paolo Bonzini | WorkerTestData *data = opaque; |
27 | 5444e768 | Paolo Bonzini | atomic_inc(&data->n); |
28 | 74c856e9 | Paolo Bonzini | g_usleep(2000000);
|
29 | 5444e768 | Paolo Bonzini | atomic_inc(&data->n); |
30 | 74c856e9 | Paolo Bonzini | return 0; |
31 | 74c856e9 | Paolo Bonzini | } |
32 | 74c856e9 | Paolo Bonzini | |
33 | 74c856e9 | Paolo Bonzini | static void done_cb(void *opaque, int ret) |
34 | 74c856e9 | Paolo Bonzini | { |
35 | 74c856e9 | Paolo Bonzini | WorkerTestData *data = opaque; |
36 | 74c856e9 | Paolo Bonzini | g_assert_cmpint(data->ret, ==, -EINPROGRESS); |
37 | 74c856e9 | Paolo Bonzini | data->ret = ret; |
38 | 74c856e9 | Paolo Bonzini | data->aiocb = NULL;
|
39 | 74c856e9 | Paolo Bonzini | |
40 | 74c856e9 | Paolo Bonzini | /* Callbacks are serialized, so no need to use atomic ops. */
|
41 | 74c856e9 | Paolo Bonzini | active--; |
42 | 74c856e9 | Paolo Bonzini | } |
43 | 74c856e9 | Paolo Bonzini | |
44 | 74c856e9 | Paolo Bonzini | static void test_submit(void) |
45 | 74c856e9 | Paolo Bonzini | { |
46 | 74c856e9 | Paolo Bonzini | WorkerTestData data = { .n = 0 };
|
47 | c4d9d196 | Stefan Hajnoczi | thread_pool_submit(pool, worker_cb, &data); |
48 | 35ecde26 | Stefan Hajnoczi | while (data.n == 0) { |
49 | 35ecde26 | Stefan Hajnoczi | aio_poll(ctx, true);
|
50 | 35ecde26 | Stefan Hajnoczi | } |
51 | 74c856e9 | Paolo Bonzini | g_assert_cmpint(data.n, ==, 1);
|
52 | 74c856e9 | Paolo Bonzini | } |
53 | 74c856e9 | Paolo Bonzini | |
54 | 74c856e9 | Paolo Bonzini | static void test_submit_aio(void) |
55 | 74c856e9 | Paolo Bonzini | { |
56 | 74c856e9 | Paolo Bonzini | WorkerTestData data = { .n = 0, .ret = -EINPROGRESS };
|
57 | c4d9d196 | Stefan Hajnoczi | data.aiocb = thread_pool_submit_aio(pool, worker_cb, &data, |
58 | c4d9d196 | Stefan Hajnoczi | done_cb, &data); |
59 | 74c856e9 | Paolo Bonzini | |
60 | 74c856e9 | Paolo Bonzini | /* The callbacks are not called until after the first wait. */
|
61 | 74c856e9 | Paolo Bonzini | active = 1;
|
62 | 74c856e9 | Paolo Bonzini | g_assert_cmpint(data.ret, ==, -EINPROGRESS); |
63 | 35ecde26 | Stefan Hajnoczi | while (data.ret == -EINPROGRESS) {
|
64 | 35ecde26 | Stefan Hajnoczi | aio_poll(ctx, true);
|
65 | 35ecde26 | Stefan Hajnoczi | } |
66 | 74c856e9 | Paolo Bonzini | g_assert_cmpint(active, ==, 0);
|
67 | 74c856e9 | Paolo Bonzini | g_assert_cmpint(data.n, ==, 1);
|
68 | 74c856e9 | Paolo Bonzini | g_assert_cmpint(data.ret, ==, 0);
|
69 | 74c856e9 | Paolo Bonzini | } |
70 | 74c856e9 | Paolo Bonzini | |
71 | 74c856e9 | Paolo Bonzini | static void co_test_cb(void *opaque) |
72 | 74c856e9 | Paolo Bonzini | { |
73 | 74c856e9 | Paolo Bonzini | WorkerTestData *data = opaque; |
74 | 74c856e9 | Paolo Bonzini | |
75 | 74c856e9 | Paolo Bonzini | active = 1;
|
76 | 74c856e9 | Paolo Bonzini | data->n = 0;
|
77 | 74c856e9 | Paolo Bonzini | data->ret = -EINPROGRESS; |
78 | c4d9d196 | Stefan Hajnoczi | thread_pool_submit_co(pool, worker_cb, data); |
79 | 74c856e9 | Paolo Bonzini | |
80 | 74c856e9 | Paolo Bonzini | /* The test continues in test_submit_co, after qemu_coroutine_enter... */
|
81 | 74c856e9 | Paolo Bonzini | |
82 | 74c856e9 | Paolo Bonzini | g_assert_cmpint(data->n, ==, 1);
|
83 | 74c856e9 | Paolo Bonzini | data->ret = 0;
|
84 | 74c856e9 | Paolo Bonzini | active--; |
85 | 74c856e9 | Paolo Bonzini | |
86 | 8a805c22 | Stefan Hajnoczi | /* The test continues in test_submit_co, after qemu_aio_wait_all... */
|
87 | 74c856e9 | Paolo Bonzini | } |
88 | 74c856e9 | Paolo Bonzini | |
89 | 74c856e9 | Paolo Bonzini | static void test_submit_co(void) |
90 | 74c856e9 | Paolo Bonzini | { |
91 | 74c856e9 | Paolo Bonzini | WorkerTestData data; |
92 | 74c856e9 | Paolo Bonzini | Coroutine *co = qemu_coroutine_create(co_test_cb); |
93 | 74c856e9 | Paolo Bonzini | |
94 | 74c856e9 | Paolo Bonzini | qemu_coroutine_enter(co, &data); |
95 | 74c856e9 | Paolo Bonzini | |
96 | 74c856e9 | Paolo Bonzini | /* Back here once the worker has started. */
|
97 | 74c856e9 | Paolo Bonzini | |
98 | 74c856e9 | Paolo Bonzini | g_assert_cmpint(active, ==, 1);
|
99 | 74c856e9 | Paolo Bonzini | g_assert_cmpint(data.ret, ==, -EINPROGRESS); |
100 | 74c856e9 | Paolo Bonzini | |
101 | 8a805c22 | Stefan Hajnoczi | /* qemu_aio_wait_all will execute the rest of the coroutine. */
|
102 | 74c856e9 | Paolo Bonzini | |
103 | 35ecde26 | Stefan Hajnoczi | while (data.ret == -EINPROGRESS) {
|
104 | 35ecde26 | Stefan Hajnoczi | aio_poll(ctx, true);
|
105 | 35ecde26 | Stefan Hajnoczi | } |
106 | 74c856e9 | Paolo Bonzini | |
107 | 74c856e9 | Paolo Bonzini | /* Back here after the coroutine has finished. */
|
108 | 74c856e9 | Paolo Bonzini | |
109 | 74c856e9 | Paolo Bonzini | g_assert_cmpint(active, ==, 0);
|
110 | 74c856e9 | Paolo Bonzini | g_assert_cmpint(data.ret, ==, 0);
|
111 | 74c856e9 | Paolo Bonzini | } |
112 | 74c856e9 | Paolo Bonzini | |
113 | 74c856e9 | Paolo Bonzini | static void test_submit_many(void) |
114 | 74c856e9 | Paolo Bonzini | { |
115 | 74c856e9 | Paolo Bonzini | WorkerTestData data[100];
|
116 | 74c856e9 | Paolo Bonzini | int i;
|
117 | 74c856e9 | Paolo Bonzini | |
118 | 74c856e9 | Paolo Bonzini | /* Start more work items than there will be threads. */
|
119 | 74c856e9 | Paolo Bonzini | for (i = 0; i < 100; i++) { |
120 | 74c856e9 | Paolo Bonzini | data[i].n = 0;
|
121 | 74c856e9 | Paolo Bonzini | data[i].ret = -EINPROGRESS; |
122 | c4d9d196 | Stefan Hajnoczi | thread_pool_submit_aio(pool, worker_cb, &data[i], done_cb, &data[i]); |
123 | 74c856e9 | Paolo Bonzini | } |
124 | 74c856e9 | Paolo Bonzini | |
125 | 74c856e9 | Paolo Bonzini | active = 100;
|
126 | 74c856e9 | Paolo Bonzini | while (active > 0) { |
127 | c4d9d196 | Stefan Hajnoczi | aio_poll(ctx, true);
|
128 | 74c856e9 | Paolo Bonzini | } |
129 | 74c856e9 | Paolo Bonzini | for (i = 0; i < 100; i++) { |
130 | 74c856e9 | Paolo Bonzini | g_assert_cmpint(data[i].n, ==, 1);
|
131 | 74c856e9 | Paolo Bonzini | g_assert_cmpint(data[i].ret, ==, 0);
|
132 | 74c856e9 | Paolo Bonzini | } |
133 | 74c856e9 | Paolo Bonzini | } |
134 | 74c856e9 | Paolo Bonzini | |
135 | 74c856e9 | Paolo Bonzini | static void test_cancel(void) |
136 | 74c856e9 | Paolo Bonzini | { |
137 | 74c856e9 | Paolo Bonzini | WorkerTestData data[100];
|
138 | d60478c5 | Paolo Bonzini | int num_canceled;
|
139 | 74c856e9 | Paolo Bonzini | int i;
|
140 | 74c856e9 | Paolo Bonzini | |
141 | 74c856e9 | Paolo Bonzini | /* Start more work items than there will be threads, to ensure
|
142 | 74c856e9 | Paolo Bonzini | * the pool is full.
|
143 | 74c856e9 | Paolo Bonzini | */
|
144 | 74c856e9 | Paolo Bonzini | test_submit_many(); |
145 | 74c856e9 | Paolo Bonzini | |
146 | 74c856e9 | Paolo Bonzini | /* Start long running jobs, to ensure we can cancel some. */
|
147 | 74c856e9 | Paolo Bonzini | for (i = 0; i < 100; i++) { |
148 | 74c856e9 | Paolo Bonzini | data[i].n = 0;
|
149 | 74c856e9 | Paolo Bonzini | data[i].ret = -EINPROGRESS; |
150 | c4d9d196 | Stefan Hajnoczi | data[i].aiocb = thread_pool_submit_aio(pool, long_cb, &data[i], |
151 | 74c856e9 | Paolo Bonzini | done_cb, &data[i]); |
152 | 74c856e9 | Paolo Bonzini | } |
153 | 74c856e9 | Paolo Bonzini | |
154 | 74c856e9 | Paolo Bonzini | /* Starting the threads may be left to a bottom half. Let it
|
155 | 74c856e9 | Paolo Bonzini | * run, but do not waste too much time...
|
156 | 74c856e9 | Paolo Bonzini | */
|
157 | 74c856e9 | Paolo Bonzini | active = 100;
|
158 | c4d9d196 | Stefan Hajnoczi | aio_notify(ctx); |
159 | c4d9d196 | Stefan Hajnoczi | aio_poll(ctx, false);
|
160 | 74c856e9 | Paolo Bonzini | |
161 | 74c856e9 | Paolo Bonzini | /* Wait some time for the threads to start, with some sanity
|
162 | 74c856e9 | Paolo Bonzini | * testing on the behavior of the scheduler...
|
163 | 74c856e9 | Paolo Bonzini | */
|
164 | 74c856e9 | Paolo Bonzini | g_assert_cmpint(active, ==, 100);
|
165 | 74c856e9 | Paolo Bonzini | g_usleep(1000000);
|
166 | 74c856e9 | Paolo Bonzini | g_assert_cmpint(active, >, 50);
|
167 | 74c856e9 | Paolo Bonzini | |
168 | 74c856e9 | Paolo Bonzini | /* Cancel the jobs that haven't been started yet. */
|
169 | d60478c5 | Paolo Bonzini | num_canceled = 0;
|
170 | 74c856e9 | Paolo Bonzini | for (i = 0; i < 100; i++) { |
171 | 5444e768 | Paolo Bonzini | if (atomic_cmpxchg(&data[i].n, 0, 3) == 0) { |
172 | 74c856e9 | Paolo Bonzini | data[i].ret = -ECANCELED; |
173 | 74c856e9 | Paolo Bonzini | bdrv_aio_cancel(data[i].aiocb); |
174 | 74c856e9 | Paolo Bonzini | active--; |
175 | d60478c5 | Paolo Bonzini | num_canceled++; |
176 | 74c856e9 | Paolo Bonzini | } |
177 | 74c856e9 | Paolo Bonzini | } |
178 | d60478c5 | Paolo Bonzini | g_assert_cmpint(active, >, 0);
|
179 | d60478c5 | Paolo Bonzini | g_assert_cmpint(num_canceled, <, 100);
|
180 | 74c856e9 | Paolo Bonzini | |
181 | 74c856e9 | Paolo Bonzini | /* Canceling the others will be a blocking operation. */
|
182 | 74c856e9 | Paolo Bonzini | for (i = 0; i < 100; i++) { |
183 | 74c856e9 | Paolo Bonzini | if (data[i].n != 3) { |
184 | 74c856e9 | Paolo Bonzini | bdrv_aio_cancel(data[i].aiocb); |
185 | 74c856e9 | Paolo Bonzini | } |
186 | 74c856e9 | Paolo Bonzini | } |
187 | 74c856e9 | Paolo Bonzini | |
188 | 74c856e9 | Paolo Bonzini | /* Finish execution and execute any remaining callbacks. */
|
189 | 35ecde26 | Stefan Hajnoczi | while (active > 0) { |
190 | 35ecde26 | Stefan Hajnoczi | aio_poll(ctx, true);
|
191 | 35ecde26 | Stefan Hajnoczi | } |
192 | 74c856e9 | Paolo Bonzini | g_assert_cmpint(active, ==, 0);
|
193 | 74c856e9 | Paolo Bonzini | for (i = 0; i < 100; i++) { |
194 | 74c856e9 | Paolo Bonzini | if (data[i].n == 3) { |
195 | 74c856e9 | Paolo Bonzini | g_assert_cmpint(data[i].ret, ==, -ECANCELED); |
196 | 74c856e9 | Paolo Bonzini | g_assert(data[i].aiocb != NULL);
|
197 | 74c856e9 | Paolo Bonzini | } else {
|
198 | 74c856e9 | Paolo Bonzini | g_assert_cmpint(data[i].n, ==, 2);
|
199 | 74c856e9 | Paolo Bonzini | g_assert_cmpint(data[i].ret, ==, 0);
|
200 | 74c856e9 | Paolo Bonzini | g_assert(data[i].aiocb == NULL);
|
201 | 74c856e9 | Paolo Bonzini | } |
202 | 74c856e9 | Paolo Bonzini | } |
203 | 74c856e9 | Paolo Bonzini | } |
204 | 74c856e9 | Paolo Bonzini | |
205 | 74c856e9 | Paolo Bonzini | int main(int argc, char **argv) |
206 | 74c856e9 | Paolo Bonzini | { |
207 | c4d9d196 | Stefan Hajnoczi | int ret;
|
208 | c4d9d196 | Stefan Hajnoczi | |
209 | dae21b98 | Alex Bligh | init_clocks(); |
210 | dae21b98 | Alex Bligh | |
211 | c4d9d196 | Stefan Hajnoczi | ctx = aio_context_new(); |
212 | c4d9d196 | Stefan Hajnoczi | pool = aio_get_thread_pool(ctx); |
213 | 74c856e9 | Paolo Bonzini | |
214 | 74c856e9 | Paolo Bonzini | g_test_init(&argc, &argv, NULL);
|
215 | 74c856e9 | Paolo Bonzini | g_test_add_func("/thread-pool/submit", test_submit);
|
216 | 74c856e9 | Paolo Bonzini | g_test_add_func("/thread-pool/submit-aio", test_submit_aio);
|
217 | 74c856e9 | Paolo Bonzini | g_test_add_func("/thread-pool/submit-co", test_submit_co);
|
218 | 74c856e9 | Paolo Bonzini | g_test_add_func("/thread-pool/submit-many", test_submit_many);
|
219 | 74c856e9 | Paolo Bonzini | g_test_add_func("/thread-pool/cancel", test_cancel);
|
220 | c4d9d196 | Stefan Hajnoczi | |
221 | c4d9d196 | Stefan Hajnoczi | ret = g_test_run(); |
222 | c4d9d196 | Stefan Hajnoczi | |
223 | c4d9d196 | Stefan Hajnoczi | aio_context_unref(ctx); |
224 | c4d9d196 | Stefan Hajnoczi | return ret;
|
225 | 74c856e9 | Paolo Bonzini | } |