diff options
author | Peter Maydell <peter.maydell@linaro.org> | 2018-03-27 17:11:33 +0100 |
---|---|---|
committer | Peter Maydell <peter.maydell@linaro.org> | 2018-03-27 17:11:33 +0100 |
commit | 6cf38cbf2961c57bd85022cf9adf7ef85dae0f02 (patch) | |
tree | 834a4d30e1dc544b425d52dd429f2191b99539c9 /tests | |
parent | dfe732fb68ef9195517f4f380a477d58a054edc1 (diff) | |
parent | f5a53faad4bfbf1b86012a13055d2a1a774a42b6 (diff) |
Merge remote-tracking branch 'remotes/stefanha/tags/block-pull-request' into staging
# gpg: Signature made Tue 27 Mar 2018 15:41:11 BST
# gpg: using RSA key 9CA4ABB381AB73C8
# gpg: Good signature from "Stefan Hajnoczi <stefanha@redhat.com>"
# gpg: aka "Stefan Hajnoczi <stefanha@gmail.com>"
# Primary key fingerprint: 8695 A8BF D3F9 7CDA AC35 775A 9CA4 ABB3 81AB 73C8
* remotes/stefanha/tags/block-pull-request:
MAINTAINERS: add include/block/aio-wait.h
coroutine: add test-aio coroutine queue chaining test case
coroutine: avoid co_queue_wakeup recursion
queue: add QSIMPLEQ_PREPEND()
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Diffstat (limited to 'tests')
-rw-r--r-- | tests/test-aio.c | 63 |
1 files changed, 51 insertions, 12 deletions
diff --git a/tests/test-aio.c b/tests/test-aio.c index 54e20d6ab1..86fb73b3d5 100644 --- a/tests/test-aio.c +++ b/tests/test-aio.c @@ -16,6 +16,8 @@ #include "qemu/timer.h" #include "qemu/sockets.h" #include "qemu/error-report.h" +#include "qemu/coroutine.h" +#include "qemu/main-loop.h" static AioContext *ctx; @@ -827,24 +829,59 @@ static void test_source_timer_schedule(void) timer_del(&data.timer); } +/* + * Check that aio_co_enter() can chain many times + * + * Two coroutines should be able to invoke each other via aio_co_enter() many + * times without hitting a limit like stack exhaustion. In other words, the + * calls should be chained instead of nested. + */ -/* End of tests. */ +typedef struct { + Coroutine *other; + unsigned i; + unsigned max; +} ChainData; -int main(int argc, char **argv) +static void coroutine_fn chain(void *opaque) { - Error *local_error = NULL; - GSource *src; + ChainData *data = opaque; - init_clocks(NULL); + for (data->i = 0; data->i < data->max; data->i++) { + /* Queue up the other coroutine... */ + aio_co_enter(ctx, data->other); - ctx = aio_context_new(&local_error); - if (!ctx) { - error_reportf_err(local_error, "Failed to create AIO Context: "); - exit(1); + /* ...and give control to it */ + qemu_coroutine_yield(); } - src = aio_get_g_source(ctx); - g_source_attach(src, NULL); - g_source_unref(src); +} + +static void test_queue_chaining(void) +{ + /* This number of iterations hit stack exhaustion in the past: */ + ChainData data_a = { .max = 25000 }; + ChainData data_b = { .max = 25000 }; + + data_b.other = qemu_coroutine_create(chain, &data_a); + data_a.other = qemu_coroutine_create(chain, &data_b); + + qemu_coroutine_enter(data_b.other); + + g_assert_cmpint(data_a.i, ==, data_a.max); + g_assert_cmpint(data_b.i, ==, data_b.max - 1); + + /* Allow the second coroutine to terminate */ + qemu_coroutine_enter(data_a.other); + + g_assert_cmpint(data_b.i, ==, data_b.max); +} + +/* End of tests. */ + +int main(int argc, char **argv) +{ + qemu_init_main_loop(&error_fatal); + ctx = qemu_get_aio_context(); while (g_main_context_iteration(NULL, false)); @@ -864,6 +901,8 @@ int main(int argc, char **argv) g_test_add_func("/aio/external-client", test_aio_external_client); g_test_add_func("/aio/timer/schedule", test_timer_schedule); + g_test_add_func("/aio/coroutine/queue-chaining", test_queue_chaining); + g_test_add_func("/aio-gsource/flush", test_source_flush); g_test_add_func("/aio-gsource/bh/schedule", test_source_bh_schedule); g_test_add_func("/aio-gsource/bh/schedule10", test_source_bh_schedule10); |