work_q: Make k_delayed_work_cancel cancel work already pending
This has been a limitation caused by k_fifo which could only remove items from the beggining, but with the change to use k_queue in k_work_q it is now possible to remove items from any position with use of k_queue_remove. Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
This commit is contained in:
parent
adb581be8e
commit
c1fa82b3c6
3 changed files with 18 additions and 14 deletions
|
@ -2049,7 +2049,7 @@ static inline void k_work_submit_to_queue(struct k_work_q *work_q,
|
|||
struct k_work *work)
|
||||
{
|
||||
if (!atomic_test_and_set_bit(work->flags, K_WORK_STATE_PENDING)) {
|
||||
k_fifo_put(&work_q->queue, work);
|
||||
k_queue_append(&work_q->queue, work);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -27,6 +27,9 @@ static void work_q_main(void *work_q_ptr, void *p2, void *p3)
|
|||
k_work_handler_t handler;
|
||||
|
||||
work = k_queue_get(&work_q->queue, K_FOREVER);
|
||||
if (!work) {
|
||||
continue;
|
||||
}
|
||||
|
||||
handler = work->handler;
|
||||
|
||||
|
@ -60,8 +63,6 @@ static void work_timeout(struct _timeout *t)
|
|||
|
||||
/* submit work to workqueue */
|
||||
k_work_submit_to_queue(w->work_q, &w->work);
|
||||
/* detach from workqueue, for cancel to return appropriate status */
|
||||
w->work_q = NULL;
|
||||
}
|
||||
|
||||
void k_delayed_work_init(struct k_delayed_work *work, k_work_handler_t handler)
|
||||
|
@ -116,18 +117,20 @@ int k_delayed_work_cancel(struct k_delayed_work *work)
|
|||
{
|
||||
int key = irq_lock();
|
||||
|
||||
if (k_work_pending(&work->work)) {
|
||||
irq_unlock(key);
|
||||
return -EINPROGRESS;
|
||||
}
|
||||
|
||||
if (!work->work_q) {
|
||||
irq_unlock(key);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* Abort timeout, if it has expired this will do nothing */
|
||||
_abort_timeout(&work->timeout);
|
||||
if (k_work_pending(&work->work)) {
|
||||
/* Remove from the queue if already submitted */
|
||||
if (!k_queue_remove(&work->work_q->queue, &work->work)) {
|
||||
irq_unlock(key);
|
||||
return -EINVAL;
|
||||
}
|
||||
} else {
|
||||
_abort_timeout(&work->timeout);
|
||||
}
|
||||
|
||||
/* Detach from workqueue */
|
||||
work->work_q = NULL;
|
||||
|
|
|
@ -124,10 +124,10 @@ static void tdelayed_work_cancel(void *data)
|
|||
* >t0: cancel delayed_work[0], expected cancellation success
|
||||
* >t0+TIMEOUT: handling delayed_work_sleepy, which do k_sleep TIMEOUT
|
||||
* pending delayed_work[1], check pending flag, expected 1
|
||||
* cancel delayed_work[1], expected -EINPROGRESS
|
||||
* cancel delayed_work[1], expected 0
|
||||
* >t0+2*TIMEOUT: delayed_work_sleepy completed
|
||||
* delayed_work[1] completed
|
||||
* cancel delayed_work_sleepy, expected -EINVAL
|
||||
* cancel delayed_work_sleepy, expected 0
|
||||
*/
|
||||
zassert_true(ret == 0, NULL);
|
||||
/**TESTPOINT: delayed work cancel when countdown*/
|
||||
|
@ -143,7 +143,8 @@ static void tdelayed_work_cancel(void *data)
|
|||
NULL);
|
||||
/**TESTPOINT: delayed work cancel when pending*/
|
||||
ret = k_delayed_work_cancel(&delayed_work[1]);
|
||||
zassert_equal(ret, -EINPROGRESS, NULL);
|
||||
zassert_equal(ret, 0, NULL);
|
||||
k_sem_give(&sync_sema);
|
||||
/*wait for completed work_sleepy and delayed_work[1]*/
|
||||
k_sleep(TIMEOUT);
|
||||
/**TESTPOINT: check pending when work completed*/
|
||||
|
@ -151,7 +152,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, -EINVAL, NULL);
|
||||
zassert_equal(ret, 0, NULL);
|
||||
}
|
||||
/*work items not cancelled: delayed_work[1], delayed_work_sleepy*/
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue