LinuxKPI: Add cancel_work() function.

Cancel a work not waiting for it to finish.

Sponsored by:	Serenity Cyber Security, LLC
Reviewed by:	manu, kib
MFC after:	1 week
Differential Revision:	https://reviews.freebsd.org/D42811
This commit is contained in:
Vladimir Kondratyev 2023-12-24 11:19:59 +03:00
parent 64e30cba3f
commit 1b2f43a742
2 changed files with 36 additions and 0 deletions

View file

@ -188,6 +188,9 @@ do { \
#define delayed_work_pending(dwork) \
linux_work_pending(&(dwork)->work)
#define cancel_work(work) \
linux_cancel_work(work)
#define cancel_delayed_work(dwork) \
linux_cancel_delayed_work(dwork)
@ -243,6 +246,7 @@ extern void linux_destroy_workqueue(struct workqueue_struct *);
extern bool linux_queue_work_on(int cpu, struct workqueue_struct *, struct work_struct *);
extern bool linux_queue_delayed_work_on(int cpu, struct workqueue_struct *,
struct delayed_work *, unsigned delay);
extern bool linux_cancel_work(struct work_struct *);
extern bool linux_cancel_delayed_work(struct delayed_work *);
extern bool linux_cancel_work_sync(struct work_struct *);
extern bool linux_cancel_delayed_work_sync(struct delayed_work *);

View file

@ -360,6 +360,38 @@ linux_delayed_work_timer_fn(void *arg)
}
}
/*
* This function cancels the given work structure in a
* non-blocking fashion. It returns non-zero if the work was
* successfully cancelled. Else the work may still be busy or already
* cancelled.
*/
bool
linux_cancel_work(struct work_struct *work)
{
static const uint8_t states[WORK_ST_MAX] __aligned(8) = {
[WORK_ST_IDLE] = WORK_ST_IDLE, /* NOP */
[WORK_ST_TIMER] = WORK_ST_TIMER, /* can't happen */
[WORK_ST_TASK] = WORK_ST_IDLE, /* cancel */
[WORK_ST_EXEC] = WORK_ST_EXEC, /* NOP */
[WORK_ST_CANCEL] = WORK_ST_IDLE, /* can't happen */
};
struct taskqueue *tq;
MPASS(atomic_read(&work->state) != WORK_ST_TIMER);
MPASS(atomic_read(&work->state) != WORK_ST_CANCEL);
switch (linux_update_state(&work->state, states)) {
case WORK_ST_TASK:
tq = work->work_queue->taskqueue;
if (taskqueue_cancel(tq, &work->work_task, NULL) == 0)
return (true);
/* FALLTHROUGH */
default:
return (false);
}
}
/*
* This function cancels the given work structure in a synchronous
* fashion. It returns non-zero if the work was successfully