diff --git a/include/kernel.h b/include/kernel.h index 196a94e78a2e..9e70c05cc211 100644 --- a/include/kernel.h +++ b/include/kernel.h @@ -3114,7 +3114,8 @@ extern int k_delayed_work_submit_to_queue(struct k_work_q *work_q, * @param work Address of delayed work item. * * @retval 0 Work item countdown canceled. - * @retval -EINVAL Work item is being processed or has completed its work. + * @retval -EINVAL Work item is being processed. + * @retval -EALREADY Work item has already been completed. * @req K-DWORK-001 */ extern int k_delayed_work_cancel(struct k_delayed_work *work); diff --git a/kernel/work_q.c b/kernel/work_q.c index 7023f70f07da..845a2670c8a3 100644 --- a/kernel/work_q.c +++ b/kernel/work_q.c @@ -56,7 +56,7 @@ void k_delayed_work_init(struct k_delayed_work *work, k_work_handler_t handler) static int work_cancel(struct k_delayed_work *work) { CHECKIF(work->work_q == NULL) { - return -EAGAIN; + return -EALREADY; } if (k_work_pending(&work->work)) { @@ -65,7 +65,11 @@ static int work_cancel(struct k_delayed_work *work) return -EINVAL; } } else { - (void)z_abort_timeout(&work->timeout); + int err = z_abort_timeout(&work->timeout); + + if (err) { + return -EALREADY; + } } /* Detach from workqueue */ @@ -92,7 +96,10 @@ int k_delayed_work_submit_to_queue(struct k_work_q *work_q, /* Cancel if work has been submitted */ if (work->work_q == work_q) { err = work_cancel(work); - if (err < 0) { + /* -EALREADY indicates the work has already completed so this + * is likely a recurring work. + */ + if (err < 0 && err != -EALREADY) { goto done; } } diff --git a/tests/kernel/workq/work_queue_api/src/main.c b/tests/kernel/workq/work_queue_api/src/main.c index c28f6ab2c546..612fa409ebc0 100644 --- a/tests/kernel/workq/work_queue_api/src/main.c +++ b/tests/kernel/workq/work_queue_api/src/main.c @@ -205,7 +205,7 @@ static void tdelayed_work_cancel(void *data) (struct k_work *)&delayed_work_sleepy), NULL); /**TESTPOINT: delayed work cancel when completed*/ ret = k_delayed_work_cancel(&delayed_work_sleepy); - zassert_equal(ret, 0, NULL); + zassert_not_equal(ret, 0, NULL); } /*work items not cancelled: delayed_work[1], delayed_work_sleepy*/ }