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 <tim@onlight.com> Signed-off-by: Brian Behlendorf <behlendorf1@llnl.gov> Closes #530
This commit is contained in:
parent
a6ae97caed
commit
7bb5d92de8
|
@ -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 */
|
/* Do not queue the task unless there is idle thread for it */
|
||||||
ASSERT(tq->tq_nactive <= tq->tq_nthreads);
|
ASSERT(tq->tq_nactive <= tq->tq_nthreads);
|
||||||
if ((flags & TQ_NOQUEUE) && (tq->tq_nactive == tq->tq_nthreads))
|
if ((flags & TQ_NOQUEUE) && (tq->tq_nactive == tq->tq_nthreads)) {
|
||||||
goto out;
|
/* 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)
|
if ((t = task_alloc(tq, flags, &irqflags)) == NULL)
|
||||||
goto out;
|
goto out;
|
||||||
|
|
||||||
spin_lock(&t->tqent_lock);
|
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 */
|
/* 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);
|
list_add_tail(&t->tqent_list, &tq->tq_prio_list);
|
||||||
else
|
else
|
||||||
list_add_tail(&t->tqent_list, &tq->tq_pend_list);
|
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);
|
wake_up(&tq->tq_work_waitq);
|
||||||
out:
|
out:
|
||||||
/* Spawn additional taskq threads if required. */
|
/* 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);
|
(void) taskq_thread_spawn(tq);
|
||||||
|
|
||||||
spin_unlock_irqrestore(&tq->tq_lock, irqflags);
|
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;
|
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);
|
spin_lock(&t->tqent_lock);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -693,6 +706,7 @@ out:
|
||||||
/* Spawn additional taskq threads if required. */
|
/* Spawn additional taskq threads if required. */
|
||||||
if (tq->tq_nactive == tq->tq_nthreads)
|
if (tq->tq_nactive == tq->tq_nthreads)
|
||||||
(void) taskq_thread_spawn(tq);
|
(void) taskq_thread_spawn(tq);
|
||||||
|
out2:
|
||||||
spin_unlock_irqrestore(&tq->tq_lock, irqflags);
|
spin_unlock_irqrestore(&tq->tq_lock, irqflags);
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL(taskq_dispatch_ent);
|
EXPORT_SYMBOL(taskq_dispatch_ent);
|
||||||
|
|
Loading…
Reference in New Issue