kernel: Add k_delayed_work_pending to check if work has been submitted

Add k_delayed_work_pending similar to k_work_pending to check if the
delayed work item has been submitted but not yet completed.
This would compliment the API since using k_work_pending or
k_delayed_work_remaining_get is not enough to check this condition.
This is because the timeout could have run out, but the timeout handler
not yet processed and put the work into the workqueue.

Signed-off-by: Joakim Andersson <joakim.andersson@nordicsemi.no>
This commit is contained in:
Joakim Andersson 2020-02-14 15:06:19 +01:00 committed by Carles Cufí
parent ed642dcd24
commit ea9590448d
3 changed files with 57 additions and 0 deletions

View file

@ -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.
*

View file

@ -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 */

View file

@ -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),