diff --git a/include/kernel.h b/include/kernel.h index bd4cf2fa833..74905215b07 100644 --- a/include/kernel.h +++ b/include/kernel.h @@ -3233,6 +3233,25 @@ static inline bool k_work_pending(struct k_work *work) return atomic_test_bit(work->flags, K_WORK_STATE_PENDING); } +/** + * @brief Check if a delayed work item is pending. + * + * This routine indicates if the work item @a work is pending in a workqueue's + * queue or waiting for the delay timeout. + * + * @note Checking if the delayed work is pending gives no guarantee that the + * work will still be pending when this information is used. It is up to + * the caller to make sure that this information is used in a safe manner. + * + * @note Can be called by ISRs. + * + * @param work Address of delayed work item. + * + * @return true if work item is waiting for the delay to expire or pending on a + * work queue, or false if it is not pending. + */ +bool k_delayed_work_pending(struct k_delayed_work *work); + /** * @brief Start a workqueue. * diff --git a/kernel/work_q.c b/kernel/work_q.c index a0706d67946..d14e6bf72cc 100644 --- a/kernel/work_q.c +++ b/kernel/work_q.c @@ -143,4 +143,10 @@ int k_delayed_work_cancel(struct k_delayed_work *work) return ret; } +bool k_delayed_work_pending(struct k_delayed_work *work) +{ + return !z_is_inactive_timeout(&work->timeout) || + k_work_pending(&work->work); +} + #endif /* CONFIG_SYS_CLOCK_EXISTS */ diff --git a/tests/kernel/workq/work_queue/src/main.c b/tests/kernel/workq/work_queue/src/main.c index 6802aaaf5f4..f55bf965e02 100644 --- a/tests/kernel/workq/work_queue/src/main.c +++ b/tests/kernel/workq/work_queue/src/main.c @@ -316,6 +316,37 @@ static void test_delayed_cancel(void) check_results(0); } +static void test_delayed_pending(void) +{ + TC_PRINT("Starting delayed pending test\n"); + + k_delayed_work_init(&delayed_tests[0].work, delayed_work_handler); + + zassert_false(k_delayed_work_pending(&delayed_tests[0].work), NULL); + + TC_PRINT(" - Check pending delayed work when in workqueue\n"); + k_delayed_work_submit(&delayed_tests[0].work, K_NO_WAIT); + zassert_true(k_delayed_work_pending(&delayed_tests[0].work), NULL); + + k_msleep(1); + zassert_false(k_delayed_work_pending(&delayed_tests[0].work), NULL); + + TC_PRINT(" - Checking results\n"); + check_results(1); + reset_results(); + + TC_PRINT(" - Check pending delayed work with timeout\n"); + k_delayed_work_submit(&delayed_tests[0].work, K_MSEC(WORK_ITEM_WAIT)); + zassert_true(k_delayed_work_pending(&delayed_tests[0].work), NULL); + + k_msleep(WORK_ITEM_WAIT_ALIGNED); + zassert_false(k_delayed_work_pending(&delayed_tests[0].work), NULL); + + TC_PRINT(" - Checking results\n"); + check_results(1); + reset_results(); +} + static void delayed_resubmit_work_handler(struct k_work *work) { struct delayed_test_item *ti = @@ -758,6 +789,7 @@ void test_main(void) ztest_1cpu_unit_test(test_delayed_resubmit), ztest_1cpu_unit_test(test_delayed_resubmit_thread), ztest_1cpu_unit_test(test_delayed_cancel), + ztest_1cpu_unit_test(test_delayed_pending), ztest_1cpu_unit_test(test_triggered), ztest_1cpu_unit_test(test_already_triggered), ztest_1cpu_unit_test(test_triggered_resubmit),