diff options
author | Scott Long <scottl@FreeBSD.org> | 2008-03-25 22:38:45 +0000 |
---|---|---|
committer | Scott Long <scottl@FreeBSD.org> | 2008-03-25 22:38:45 +0000 |
commit | 478cfc73007fe0a6938401dc156265116dfb7270 (patch) | |
tree | 25ea898a84ae97aa0796cd38dd10df57607241df | |
parent | 2e76e92b45e1ac029309bd9f28d1bfeab9d1c953 (diff) | |
download | src-478cfc73007fe0a6938401dc156265116dfb7270.tar.gz src-478cfc73007fe0a6938401dc156265116dfb7270.zip |
Implement taskqueue_block() and taskqueue_unblock(). These functions allow
the owner of a queue to block and unblock execution of the tasks in the
queue while allowing tasks to continue to be added queue. Combining this
with taskqueue_drain() allows a queue to be safely disabled. The unblock
function may run (or schedule to run) the queue when it is called, just as
calling taskqueue_enqueue() would.
Reviewed by: jhb, sam
Notes
Notes:
svn path=/head/; revision=177621
-rw-r--r-- | sys/kern/subr_taskqueue.c | 29 | ||||
-rw-r--r-- | sys/sys/taskqueue.h | 2 |
2 files changed, 30 insertions, 1 deletions
diff --git a/sys/kern/subr_taskqueue.c b/sys/kern/subr_taskqueue.c index c3ddb5f38765..76648611c2d2 100644 --- a/sys/kern/subr_taskqueue.c +++ b/sys/kern/subr_taskqueue.c @@ -63,6 +63,8 @@ struct taskqueue { }; #define TQ_FLAGS_ACTIVE (1 << 0) +#define TQ_FLAGS_BLOCKED (1 << 1) +#define TQ_FLAGS_PENDING (1 << 2) static __inline void TQ_LOCK(struct taskqueue *tq) @@ -224,7 +226,10 @@ taskqueue_enqueue(struct taskqueue *queue, struct task *task) } task->ta_pending = 1; - queue->tq_enqueue(queue->tq_context); + if ((queue->tq_flags & TQ_FLAGS_BLOCKED) == 0) + queue->tq_enqueue(queue->tq_context); + else + queue->tq_flags |= TQ_FLAGS_PENDING; TQ_UNLOCK(queue); @@ -232,6 +237,28 @@ taskqueue_enqueue(struct taskqueue *queue, struct task *task) } void +taskqueue_block(struct taskqueue *queue) +{ + + TQ_LOCK(queue); + queue->tq_flags |= TQ_FLAGS_BLOCKED; + TQ_UNLOCK(queue); +} + +void +taskqueue_unblock(struct taskqueue *queue) +{ + + TQ_LOCK(queue); + queue->tq_flags &= ~TQ_FLAGS_BLOCKED; + if (queue->tq_flags & TQ_FLAGS_PENDING) { + queue->tq_flags &= ~TQ_FLAGS_PENDING; + queue->tq_enqueue(queue->tq_context); + } + TQ_UNLOCK(queue); +} + +void taskqueue_run(struct taskqueue *queue) { struct task *task; diff --git a/sys/sys/taskqueue.h b/sys/sys/taskqueue.h index c980fc187565..4065a58b3ed1 100644 --- a/sys/sys/taskqueue.h +++ b/sys/sys/taskqueue.h @@ -58,6 +58,8 @@ void taskqueue_drain(struct taskqueue *queue, struct task *task); struct taskqueue *taskqueue_find(const char *name); void taskqueue_free(struct taskqueue *queue); void taskqueue_run(struct taskqueue *queue); +void taskqueue_block(struct taskqueue *queue); +void taskqueue_unblock(struct taskqueue *queue); /* * Functions for dedicated thread taskqueues |