diff options
author | Tim Chase <[email protected]> | 2016-02-08 13:20:05 -0600 |
---|---|---|
committer | Brian Behlendorf <[email protected]> | 2016-03-17 09:52:35 -0700 |
commit | 7bb5d92de8c4d795e9b393aa5ea9c9ad3e43b199 (patch) | |
tree | 9b1b4108cf4aeefe78150a7d498502c1048a13fb /module/spl | |
parent | a6ae97caed620b0e9e0575346062c751f6f15483 (diff) |
Allow spawning a new thread for TQ_NOQUEUE dispatch with dynamic taskq
When a TQ_NOQUEUE dispatch is done on a dynamic taskq, allow another
thread to be spawned. This will cause TQ_NOQUEUE to behave similarly
as it does with non-dynamic taskqs.
Add support for TQ_NOQUEUE to taskq_dispatch_ent().
Signed-off-by: Tim Chase <[email protected]>
Signed-off-by: Brian Behlendorf <[email protected]>
Closes #530
Diffstat (limited to 'module/spl')
-rw-r--r-- | module/spl/spl-taskq.c | 22 |
1 files changed, 18 insertions, 4 deletions
diff --git a/module/spl/spl-taskq.c b/module/spl/spl-taskq.c index 56034c899..bfcf651af 100644 --- a/module/spl/spl-taskq.c +++ b/module/spl/spl-taskq.c @@ -562,16 +562,22 @@ taskq_dispatch(taskq_t *tq, task_func_t func, void *arg, uint_t flags) /* Do not queue the task unless there is idle thread for it */ ASSERT(tq->tq_nactive <= tq->tq_nthreads); - if ((flags & TQ_NOQUEUE) && (tq->tq_nactive == tq->tq_nthreads)) - goto out; + if ((flags & TQ_NOQUEUE) && (tq->tq_nactive == tq->tq_nthreads)) { + /* Dynamic taskq may be able to spawn another thread */ + if (!(tq->tq_flags & TASKQ_DYNAMIC) || taskq_thread_spawn(tq) == 0) + goto out; + } if ((t = task_alloc(tq, flags, &irqflags)) == NULL) goto out; spin_lock(&t->tqent_lock); + /* Queue to the front of the list to enforce TQ_NOQUEUE semantics */ + if (flags & TQ_NOQUEUE) + list_add(&t->tqent_list, &tq->tq_prio_list); /* Queue to the priority list instead of the pending list */ - if (flags & TQ_FRONT) + else if (flags & TQ_FRONT) list_add_tail(&t->tqent_list, &tq->tq_prio_list); else list_add_tail(&t->tqent_list, &tq->tq_pend_list); @@ -593,7 +599,7 @@ taskq_dispatch(taskq_t *tq, task_func_t func, void *arg, uint_t flags) wake_up(&tq->tq_work_waitq); out: /* Spawn additional taskq threads if required. */ - if (tq->tq_nactive == tq->tq_nthreads) + if (!(flags & TQ_NOQUEUE) && tq->tq_nactive == tq->tq_nthreads) (void) taskq_thread_spawn(tq); spin_unlock_irqrestore(&tq->tq_lock, irqflags); @@ -665,6 +671,13 @@ taskq_dispatch_ent(taskq_t *tq, task_func_t func, void *arg, uint_t flags, goto out; } + if ((flags & TQ_NOQUEUE) && (tq->tq_nactive == tq->tq_nthreads)) { + /* Dynamic taskq may be able to spawn another thread */ + if (!(tq->tq_flags & TASKQ_DYNAMIC) || taskq_thread_spawn(tq) == 0) + goto out2; + flags |= TQ_FRONT; + } + spin_lock(&t->tqent_lock); /* @@ -693,6 +706,7 @@ out: /* Spawn additional taskq threads if required. */ if (tq->tq_nactive == tq->tq_nthreads) (void) taskq_thread_spawn(tq); +out2: spin_unlock_irqrestore(&tq->tq_lock, irqflags); } EXPORT_SYMBOL(taskq_dispatch_ent); |