Add a taskqueue_cancel(9) to cancel a pending task without waiting for

it to run as taskqueue_drain(9) does.

Requested by:	hselasky
Original code:	jeff
Reviewed by:	jhb
MFC after:	2 weeks
This commit is contained in:
Matthew D Fleming 2010-11-08 20:56:31 +00:00
parent 75ba301116
commit f46276a9b0
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=215011
4 changed files with 48 additions and 0 deletions

View file

@ -1212,6 +1212,7 @@ MLINKS+=sysctl_ctx_init.9 sysctl_ctx_entry_add.9 \
sysctl_ctx_init.9 sysctl_ctx_entry_find.9 \
sysctl_ctx_init.9 sysctl_ctx_free.9
MLINKS+=taskqueue.9 TASK_INIT.9 \
taskqueue.9 taskqueue_cancel.9 \
taskqueue.9 taskqueue_create.9 \
taskqueue.9 taskqueue_create_fast.9 \
taskqueue.9 TASKQUEUE_DECLARE.9 \

View file

@ -63,6 +63,8 @@ struct task {
.Fn taskqueue_enqueue "struct taskqueue *queue" "struct task *task"
.Ft int
.Fn taskqueue_enqueue_fast "struct taskqueue *queue" "struct task *task"
.Ft int
.Fn taskqueue_cancel "struct taskqueue *queue" "struct task *task" "u_int *pendp"
.Ft void
.Fn taskqueue_drain "struct taskqueue *queue" "struct task *task"
.Ft int
@ -162,6 +164,31 @@ is called on the task pointer passed to
.Fn taskqueue_enqueue .
.Pp
The
.Fn taskqueue_cancel
function is used to cancel a task.
The
.Va ta_pending
count is cleared, and the old value returned in the reference
parameter
.Fa pendp ,
if it is non- Dv NULL .
If the task is currently running,
.Dv EBUSY
is returned, otherwise 0.
To implement a blocking
.Fn taskqueue_cancel
that waits for a running task to finish, it could look like:
.Bd -literal -offset indent
while (taskqueue_cancel(tq, task, NULL) != 0)
taskqueue_drain(tq, task);
.Ed
.Pp
Note that, as with
.Fn taskqueue_drain ,
the caller is responsible for ensuring that the task is not re-enqueued
after being canceled.
.Pp
The
.Fn taskqueue_drain
function is used to wait for the task to finish.
There is no guarantee that the task will not be

View file

@ -275,6 +275,24 @@ task_is_running(struct taskqueue *queue, struct task *task)
return (0);
}
int
taskqueue_cancel(struct taskqueue *queue, struct task *task, u_int *pendp)
{
u_int pending;
int error;
TQ_LOCK(queue);
if ((pending = task->ta_pending) > 0)
STAILQ_REMOVE(&queue->tq_queue, task, task, ta_link);
task->ta_pending = 0;
error = task_is_running(queue, task) ? EBUSY : 0;
TQ_UNLOCK(queue);
if (pendp != NULL)
*pendp = pending;
return (error);
}
void
taskqueue_drain(struct taskqueue *queue, struct task *task)
{

View file

@ -54,6 +54,8 @@ struct taskqueue *taskqueue_create(const char *name, int mflags,
int taskqueue_start_threads(struct taskqueue **tqp, int count, int pri,
const char *name, ...) __printflike(4, 5);
int taskqueue_enqueue(struct taskqueue *queue, struct task *task);
int taskqueue_cancel(struct taskqueue *queue, struct task *task,
u_int *pendp);
void taskqueue_drain(struct taskqueue *queue, struct task *task);
void taskqueue_free(struct taskqueue *queue);
void taskqueue_run(struct taskqueue *queue);