Signed-off-by: Paolo Bonzini <pbonz...@redhat.com> --- tests/unit/meson.build | 6 +- .../{test-coroutine.c => test-coroutine.cc} | 140 +++++++++--------- 2 files changed, 76 insertions(+), 70 deletions(-) rename tests/unit/{test-coroutine.c => test-coroutine.cc} (81%)
diff --git a/tests/unit/meson.build b/tests/unit/meson.build index 4ca5fdb699..675b5323dd 100644 --- a/tests/unit/meson.build +++ b/tests/unit/meson.build @@ -168,7 +168,11 @@ slow_tests = { } foreach test_name, extra: tests - src = [test_name + '.c'] + if test_name == 'test-coroutine' + src = [test_name + '.cc'] + else + src = [test_name + '.c'] + endif deps = [qemuutil] if extra.length() > 0 # use a sourceset to quickly separate sources and deps diff --git a/tests/unit/test-coroutine.c b/tests/unit/test-coroutine.cc similarity index 81% rename from tests/unit/test-coroutine.c rename to tests/unit/test-coroutine.cc index c230c2fa6e..8f9ddc50da 100644 --- a/tests/unit/test-coroutine.c +++ b/tests/unit/test-coroutine.cc @@ -16,14 +16,14 @@ #include "qemu/coroutine_int.h" #include "qemu/lockable.h" -#if 0 /* * Check that qemu_in_coroutine() works */ -static void coroutine_fn verify_in_coroutine(void *opaque) +static CoroutineFn<void> verify_in_coroutine(void *opaque) { g_assert(qemu_in_coroutine()); + co_return; } static void test_in_coroutine(void) @@ -40,10 +40,11 @@ static void test_in_coroutine(void) * Check that qemu_coroutine_self() works */ -static void coroutine_fn verify_self(void *opaque) +static CoroutineFn<void> verify_self(void *opaque) { - Coroutine **p_co = opaque; + Coroutine **p_co = (Coroutine **)opaque; g_assert(qemu_coroutine_self() == *p_co); + co_return; } static void test_self(void) @@ -58,20 +59,20 @@ static void test_self(void) * Check that qemu_coroutine_entered() works */ -static void coroutine_fn verify_entered_step_2(void *opaque) +static CoroutineFn<void> verify_entered_step_2(void *opaque) { Coroutine *caller = (Coroutine *)opaque; g_assert(qemu_coroutine_entered(caller)); g_assert(qemu_coroutine_entered(qemu_coroutine_self())); - qemu_coroutine_yield(); + co_await qemu_coroutine_yield(); /* Once more to check it still works after yielding */ g_assert(qemu_coroutine_entered(caller)); g_assert(qemu_coroutine_entered(qemu_coroutine_self())); } -static void coroutine_fn verify_entered_step_1(void *opaque) +static CoroutineFn<void> verify_entered_step_1(void *opaque) { Coroutine *self = qemu_coroutine_self(); Coroutine *coroutine; @@ -83,6 +84,7 @@ static void coroutine_fn verify_entered_step_1(void *opaque) qemu_coroutine_enter(coroutine); g_assert(!qemu_coroutine_entered(coroutine)); qemu_coroutine_enter(coroutine); + co_return; } static void test_entered(void) @@ -104,9 +106,9 @@ typedef struct { unsigned int max; /* maximum level of nesting */ } NestData; -static void coroutine_fn nest(void *opaque) +static CoroutineFn<void> nest(void *opaque) { - NestData *nd = opaque; + NestData *nd = (NestData *)opaque; nd->n_enter++; @@ -118,6 +120,7 @@ static void coroutine_fn nest(void *opaque) } nd->n_return++; + co_return; } static void test_nesting(void) @@ -141,13 +144,13 @@ static void test_nesting(void) * Check that yield/enter transfer control correctly */ -static void coroutine_fn yield_5_times(void *opaque) +static CoroutineFn<void> yield_5_times(void *opaque) { - bool *done = opaque; + bool *done = (bool *)opaque; int i; for (i = 0; i < 5; i++) { - qemu_coroutine_yield(); + co_await qemu_coroutine_yield(); } *done = true; } @@ -166,15 +169,16 @@ static void test_yield(void) g_assert_cmpint(i, ==, 5); /* coroutine must yield 5 times */ } -static void coroutine_fn c2_fn(void *opaque) +static CoroutineFn<void> c2_fn(void *opaque) { - qemu_coroutine_yield(); + co_await qemu_coroutine_yield(); } -static void coroutine_fn c1_fn(void *opaque) +static CoroutineFn<void> c1_fn(void *opaque) { - Coroutine *c2 = opaque; + Coroutine *c2 = (Coroutine *)opaque; qemu_coroutine_enter(c2); + co_return; } static void test_no_dangling_access(void) @@ -200,34 +204,35 @@ static void test_no_dangling_access(void) static bool locked; static int done; -static void coroutine_fn mutex_fn(void *opaque) +static CoroutineFn<void> mutex_fn(void *opaque) { - CoMutex *m = opaque; - qemu_co_mutex_lock(m); + CoMutex *m = (CoMutex *)opaque; + co_await qemu_co_mutex_lock(m); assert(!locked); locked = true; - qemu_coroutine_yield(); + co_await qemu_coroutine_yield(); locked = false; - qemu_co_mutex_unlock(m); + co_await qemu_co_mutex_unlock(m); done++; } -static void coroutine_fn lockable_fn(void *opaque) +static CoroutineFn<void> lockable_fn(void *opaque) { - QemuCoLockable *x = opaque; - qemu_co_lockable_lock(x); + QemuCoLockable *x = (QemuCoLockable *)opaque; + co_await qemu_co_lockable_lock(x); assert(!locked); locked = true; - qemu_coroutine_yield(); + co_await qemu_coroutine_yield(); locked = false; - qemu_co_lockable_unlock(x); + co_await qemu_co_lockable_unlock(x); done++; } -static void do_test_co_mutex(CoroutineEntry *entry, void *opaque) +template<typename T> +static void do_test_co_mutex(CoroutineEntry *entry, const T *opaque) { - Coroutine *c1 = qemu_coroutine_create(entry, opaque); - Coroutine *c2 = qemu_coroutine_create(entry, opaque); + Coroutine *c1 = qemu_coroutine_create(entry, (void *)opaque); + Coroutine *c2 = qemu_coroutine_create(entry, (void *)opaque); done = 0; qemu_coroutine_enter(c1); @@ -284,23 +289,23 @@ static CoRwlock rwlock; * | unlock | | */ -static void coroutine_fn rwlock_yield_upgrade(void *opaque) +static CoroutineFn<void> rwlock_yield_upgrade(void *opaque) { - qemu_co_rwlock_rdlock(&rwlock); - qemu_coroutine_yield(); + co_await qemu_co_rwlock_rdlock(&rwlock); + co_await qemu_coroutine_yield(); - qemu_co_rwlock_upgrade(&rwlock); - qemu_co_rwlock_unlock(&rwlock); + co_await qemu_co_rwlock_upgrade(&rwlock); + co_await qemu_co_rwlock_unlock(&rwlock); *(bool *)opaque = true; } -static void coroutine_fn rwlock_wrlock_yield(void *opaque) +static CoroutineFn<void> rwlock_wrlock_yield(void *opaque) { - qemu_co_rwlock_wrlock(&rwlock); - qemu_coroutine_yield(); + co_await qemu_co_rwlock_wrlock(&rwlock); + co_await qemu_coroutine_yield(); - qemu_co_rwlock_unlock(&rwlock); + co_await qemu_co_rwlock_unlock(&rwlock); *(bool *)opaque = true; } @@ -326,39 +331,39 @@ static void test_co_rwlock_upgrade(void) g_assert(c2_done); } -static void coroutine_fn rwlock_rdlock_yield(void *opaque) +static CoroutineFn<void> rwlock_rdlock_yield(void *opaque) { - qemu_co_rwlock_rdlock(&rwlock); - qemu_coroutine_yield(); + co_await qemu_co_rwlock_rdlock(&rwlock); + co_await qemu_coroutine_yield(); - qemu_co_rwlock_unlock(&rwlock); - qemu_coroutine_yield(); + co_await qemu_co_rwlock_unlock(&rwlock); + co_await qemu_coroutine_yield(); *(bool *)opaque = true; } -static void coroutine_fn rwlock_wrlock_downgrade(void *opaque) +static CoroutineFn<void> rwlock_wrlock_downgrade(void *opaque) { - qemu_co_rwlock_wrlock(&rwlock); + co_await qemu_co_rwlock_wrlock(&rwlock); - qemu_co_rwlock_downgrade(&rwlock); - qemu_co_rwlock_unlock(&rwlock); + co_await qemu_co_rwlock_downgrade(&rwlock); + co_await qemu_co_rwlock_unlock(&rwlock); *(bool *)opaque = true; } -static void coroutine_fn rwlock_rdlock(void *opaque) +static CoroutineFn<void> rwlock_rdlock(void *opaque) { - qemu_co_rwlock_rdlock(&rwlock); + co_await qemu_co_rwlock_rdlock(&rwlock); - qemu_co_rwlock_unlock(&rwlock); + co_await qemu_co_rwlock_unlock(&rwlock); *(bool *)opaque = true; } -static void coroutine_fn rwlock_wrlock(void *opaque) +static CoroutineFn<void> rwlock_wrlock(void *opaque) { - qemu_co_rwlock_wrlock(&rwlock); + co_await qemu_co_rwlock_wrlock(&rwlock); - qemu_co_rwlock_unlock(&rwlock); + co_await qemu_co_rwlock_unlock(&rwlock); *(bool *)opaque = true; } @@ -428,11 +433,12 @@ static void test_co_rwlock_downgrade(void) * Check that creation, enter, and return work */ -static void coroutine_fn set_and_exit(void *opaque) +static CoroutineFn<void> set_and_exit(void *opaque) { - bool *done = opaque; + bool *done = (bool *)opaque; *done = true; + co_return; } static void test_lifecycle(void) @@ -459,7 +465,7 @@ struct coroutine_position { int state; }; static struct coroutine_position records[RECORD_SIZE]; -static unsigned record_pos; +static int record_pos; static void record_push(int func, int state) { @@ -469,11 +475,11 @@ static void record_push(int func, int state) cp->state = state; } -static void coroutine_fn co_order_test(void *opaque) +static CoroutineFn<void> co_order_test(void *opaque) { record_push(2, 1); g_assert(qemu_in_coroutine()); - qemu_coroutine_yield(); + co_await qemu_coroutine_yield(); record_push(2, 2); g_assert(qemu_in_coroutine()); } @@ -509,9 +515,10 @@ static void test_order(void) * Lifecycle benchmark */ -static void coroutine_fn empty_coroutine(void *opaque) +static CoroutineFn<void> empty_coroutine(void *opaque) { /* Do nothing */ + co_return; } static void perf_lifecycle(void) @@ -561,13 +568,13 @@ static void perf_nesting(void) * Yield benchmark */ -static void coroutine_fn yield_loop(void *opaque) +static CoroutineFn<void> yield_loop(void *opaque) { - unsigned int *counter = opaque; + unsigned int *counter = (unsigned int *)opaque; while ((*counter) > 0) { (*counter)--; - qemu_coroutine_yield(); + co_await qemu_coroutine_yield(); } } @@ -611,9 +618,9 @@ static void perf_baseline(void) g_test_message("Function call %u iterations: %f s", maxcycles, duration); } -static __attribute__((noinline)) void perf_cost_func(void *opaque) +static __attribute__((noinline)) CoroutineFn<void> perf_cost_func(void *opaque) { - qemu_coroutine_yield(); + co_await qemu_coroutine_yield(); } static void perf_cost(void) @@ -639,13 +646,11 @@ static void perf_cost(void) duration, ops, (unsigned long)(1000000000.0 * duration / maxcycles)); } -#endif int main(int argc, char **argv) { g_test_init(&argc, &argv, NULL); -#if 0 /* This test assumes there is a freelist and marks freed coroutine memory * with a sentinel value. If there is no freelist this would legitimately * crash, so skip it. @@ -653,9 +658,7 @@ int main(int argc, char **argv) if (CONFIG_COROUTINE_POOL) { g_test_add_func("/basic/no-dangling-access", test_no_dangling_access); } -#endif -#if 0 g_test_add_func("/basic/lifecycle", test_lifecycle); g_test_add_func("/basic/yield", test_yield); g_test_add_func("/basic/nesting", test_nesting); @@ -674,6 +677,5 @@ int main(int argc, char **argv) g_test_add_func("/perf/function-call", perf_baseline); g_test_add_func("/perf/cost", perf_cost); } -#endif return g_test_run(); } -- 2.35.1