From 2a2856e88e341e027a3014b109118332e0b59ee5 Mon Sep 17 00:00:00 2001 From: Krzysztof Chruscinski Date: Thu, 19 May 2022 14:05:25 +0200 Subject: [PATCH] tests: kernel: workq: work: Fix potential race in the test Test was setting up timer for 1 system tick and then work was cancelled. It was assumed that work will be cancelled before timer expires. This is the case for low frequency system clock (e.g. qemu targets using 100Hz) but there are cases when system clock has higher frequency (32kHz on nRF). In that case, timer was occasionally expiring before cancellation and test was randomly failing. Signed-off-by: Krzysztof Chruscinski --- tests/kernel/workq/work/src/main.c | 23 +++++++++++++++++++---- 1 file changed, 19 insertions(+), 4 deletions(-) diff --git a/tests/kernel/workq/work/src/main.c b/tests/kernel/workq/work/src/main.c index 7ac2c163cb4..c17f12240ec 100644 --- a/tests/kernel/workq/work/src/main.c +++ b/tests/kernel/workq/work/src/main.c @@ -694,6 +694,7 @@ static void test_1cpu_running_cancel(void) { struct test_running_cancel_timer *ctx = &test_running_cancel_ctx; struct k_work *wp = &ctx->work; + static const uint32_t ms_timeout = 10; int rc; /* Reset state and use the blocking handler */ @@ -713,7 +714,7 @@ static void test_1cpu_running_cancel(void) ctx->submit_rc = INT_MAX; ctx->busy_rc = INT_MAX; k_timer_init(&ctx->timer, test_running_cancel_cb, NULL); - k_timer_start(&ctx->timer, K_TICKS(1), K_NO_WAIT); + k_timer_start(&ctx->timer, K_MSEC(ms_timeout), K_NO_WAIT); /* Cancellation should not complete. */ zassert_equal(k_work_cancel(wp), K_WORK_RUNNING | K_WORK_CANCELING, @@ -722,6 +723,13 @@ static void test_1cpu_running_cancel(void) /* Handler should not have run. */ zassert_equal(coophi_counter(), 0, NULL); + /* Busy wait until timer expires. Thread context is blocked so cancelling + * of work won't be completed. + */ + k_busy_wait(1000 * (ms_timeout + 1)); + + zassert_equal(k_timer_status_get(&ctx->timer), 1, NULL); + /* Wait for cancellation to complete. */ zassert_true(k_work_cancel_sync(wp, &work_sync), NULL); @@ -730,8 +738,7 @@ static void test_1cpu_running_cancel(void) zassert_equal(rc, 0, NULL); /* Handler should have detected running and canceling. */ - zassert_equal(ctx->busy_rc, K_WORK_RUNNING | K_WORK_CANCELING, - NULL); + zassert_equal(ctx->busy_rc, K_WORK_RUNNING | K_WORK_CANCELING, NULL); /* Attempt to submit while cancelling should have been * rejected. @@ -750,6 +757,7 @@ static void test_1cpu_running_cancel_sync(void) { struct test_running_cancel_timer *ctx = &test_running_cancel_ctx; struct k_work *wp = &ctx->work; + static const uint32_t ms_timeout = 10; int rc; /* Reset state and use the blocking handler */ @@ -769,7 +777,7 @@ static void test_1cpu_running_cancel_sync(void) ctx->submit_rc = INT_MAX; ctx->busy_rc = INT_MAX; k_timer_init(&ctx->timer, test_running_cancel_cb, NULL); - k_timer_start(&ctx->timer, K_TICKS(1), K_NO_WAIT); + k_timer_start(&ctx->timer, K_MSEC(ms_timeout), K_NO_WAIT); /* Cancellation should wait. */ zassert_true(k_work_cancel_sync(wp, &work_sync), NULL); @@ -777,6 +785,13 @@ static void test_1cpu_running_cancel_sync(void) /* Handler should have run. */ zassert_equal(coophi_counter(), 1, NULL); + /* Busy wait until timer expires. Thread context is blocked so cancelling + * of work won't be completed. + */ + k_busy_wait(1000 * (ms_timeout + 1)); + + zassert_equal(k_timer_status_get(&ctx->timer), 1, NULL); + /* Verify completion */ rc = k_sem_take(&sync_sem, K_NO_WAIT); zassert_equal(rc, 0, NULL);