taskq: add taskq_try_dispatch_ent()

Non-blocking form of taskq_dispatch_ent(), returns false if it can't
acquire the taskq lock.

Signed-off-by: Rob Norris <rob.norris@klarasystems.com>
This commit is contained in:
Rob Norris 2023-10-23 12:26:26 +11:00
parent 2fec57bf03
commit c85d31a88b
6 changed files with 74 additions and 11 deletions

View File

@ -91,6 +91,8 @@ extern taskqid_t taskq_dispatch_delay(taskq_t *, task_func_t, void *,
uint_t, clock_t); uint_t, clock_t);
extern void taskq_dispatch_ent(taskq_t *, task_func_t, void *, uint_t, extern void taskq_dispatch_ent(taskq_t *, task_func_t, void *, uint_t,
taskq_ent_t *); taskq_ent_t *);
extern boolean_t taskq_try_dispatch_ent(taskq_t *, task_func_t, void *, uint_t,
taskq_ent_t *);
extern int taskq_empty_ent(taskq_ent_t *); extern int taskq_empty_ent(taskq_ent_t *);
taskq_t *taskq_create(const char *, int, pri_t, int, int, uint_t); taskq_t *taskq_create(const char *, int, pri_t, int, int, uint_t);
taskq_t *taskq_create_instance(const char *, int, int, pri_t, int, int, uint_t); taskq_t *taskq_create_instance(const char *, int, int, pri_t, int, int, uint_t);

View File

@ -146,6 +146,8 @@ extern taskqid_t taskq_dispatch_delay(taskq_t *, task_func_t, void *,
uint_t, clock_t); uint_t, clock_t);
extern void taskq_dispatch_ent(taskq_t *, task_func_t, void *, uint_t, extern void taskq_dispatch_ent(taskq_t *, task_func_t, void *, uint_t,
taskq_ent_t *); taskq_ent_t *);
extern boolean_t taskq_try_dispatch_ent(taskq_t *, task_func_t, void *, uint_t,
taskq_ent_t *);
extern int taskq_empty_ent(taskq_ent_t *); extern int taskq_empty_ent(taskq_ent_t *);
extern void taskq_init_ent(taskq_ent_t *); extern void taskq_init_ent(taskq_ent_t *);
extern taskq_t *taskq_create(const char *, int, pri_t, int, int, uint_t); extern taskq_t *taskq_create(const char *, int, pri_t, int, int, uint_t);

View File

@ -503,6 +503,8 @@ extern taskqid_t taskq_dispatch_delay(taskq_t *, task_func_t, void *, uint_t,
clock_t); clock_t);
extern void taskq_dispatch_ent(taskq_t *, task_func_t, void *, uint_t, extern void taskq_dispatch_ent(taskq_t *, task_func_t, void *, uint_t,
taskq_ent_t *); taskq_ent_t *);
extern boolean_t taskq_try_dispatch_ent(taskq_t *, task_func_t, void *, uint_t,
taskq_ent_t *);
extern int taskq_empty_ent(taskq_ent_t *); extern int taskq_empty_ent(taskq_ent_t *);
extern void taskq_init_ent(taskq_ent_t *); extern void taskq_init_ent(taskq_ent_t *);
extern void taskq_destroy(taskq_t *); extern void taskq_destroy(taskq_t *);

View File

@ -156,8 +156,8 @@ taskq_init_ent(taskq_ent_t *t)
t->tqent_flags = 0; t->tqent_flags = 0;
} }
void static void
taskq_dispatch_ent(taskq_t *tq, task_func_t func, void *arg, uint_t flags, taskq_dispatch_ent_impl(taskq_t *tq, task_func_t func, void *arg, uint_t flags,
taskq_ent_t *t) taskq_ent_t *t)
{ {
ASSERT(func != NULL); ASSERT(func != NULL);
@ -170,7 +170,6 @@ taskq_dispatch_ent(taskq_t *tq, task_func_t func, void *arg, uint_t flags,
/* /*
* Enqueue the task to the underlying queue. * Enqueue the task to the underlying queue.
*/ */
mutex_enter(&tq->tq_lock);
if (flags & TQ_FRONT) { if (flags & TQ_FRONT) {
t->tqent_next = tq->tq_task.tqent_next; t->tqent_next = tq->tq_task.tqent_next;
@ -184,9 +183,28 @@ taskq_dispatch_ent(taskq_t *tq, task_func_t func, void *arg, uint_t flags,
t->tqent_func = func; t->tqent_func = func;
t->tqent_arg = arg; t->tqent_arg = arg;
cv_signal(&tq->tq_dispatch_cv); cv_signal(&tq->tq_dispatch_cv);
}
void
taskq_dispatch_ent(taskq_t *tq, task_func_t func, void *arg, uint_t flags,
taskq_ent_t *t)
{
mutex_enter(&tq->tq_lock);
taskq_dispatch_ent_impl(tq, func, arg, flags, t);
mutex_exit(&tq->tq_lock); mutex_exit(&tq->tq_lock);
} }
boolean_t
taskq_try_dispatch_ent(taskq_t *tq, task_func_t func, void *arg, uint_t flags,
taskq_ent_t *t)
{
if (!mutex_tryenter(&tq->tq_lock))
return (B_FALSE);
taskq_dispatch_ent_impl(tq, func, arg, flags, t);
mutex_exit(&tq->tq_lock);
return (B_TRUE);
}
void void
taskq_wait(taskq_t *tq) taskq_wait(taskq_t *tq)
{ {

View File

@ -411,6 +411,15 @@ taskq_dispatch_ent(taskq_t *tq, task_func_t func, void *arg, uint32_t flags,
taskqueue_enqueue(tq->tq_queue, &task->tqent_task); taskqueue_enqueue(tq->tq_queue, &task->tqent_task);
} }
boolean_t
taskq_dispatch_ent(taskq_t *tq, task_func_t func, void *arg, uint32_t flags,
taskq_ent_t *task)
{
/* XXX: implement me -- robn, 2023-10-23 */
taskq_dispatch_ent(tq, func, arg, flags, task);
return (B_TRUE);
}
void void
taskq_wait(taskq_t *tq) taskq_wait(taskq_t *tq)
{ {

View File

@ -673,17 +673,13 @@ out:
} }
EXPORT_SYMBOL(taskq_dispatch_delay); EXPORT_SYMBOL(taskq_dispatch_delay);
void static void
taskq_dispatch_ent(taskq_t *tq, task_func_t func, void *arg, uint_t flags, taskq_dispatch_ent_impl(taskq_t *tq, task_func_t func, void *arg, uint_t flags,
taskq_ent_t *t) taskq_ent_t *t)
{ {
unsigned long irqflags;
ASSERT(tq); ASSERT(tq);
ASSERT(func); ASSERT(func);
spin_lock_irqsave_nested(&tq->tq_lock, irqflags,
tq->tq_lock_class);
/* Taskq being destroyed and all tasks drained */ /* Taskq being destroyed and all tasks drained */
if (!(tq->tq_flags & TASKQ_ACTIVE)) { if (!(tq->tq_flags & TASKQ_ACTIVE)) {
t->tqent_id = TASKQID_INVALID; t->tqent_id = TASKQID_INVALID;
@ -694,7 +690,7 @@ taskq_dispatch_ent(taskq_t *tq, task_func_t func, void *arg, uint_t flags,
/* Dynamic taskq may be able to spawn another thread */ /* Dynamic taskq may be able to spawn another thread */
if (!(tq->tq_flags & TASKQ_DYNAMIC) || if (!(tq->tq_flags & TASKQ_DYNAMIC) ||
taskq_thread_spawn(tq) == 0) taskq_thread_spawn(tq) == 0)
goto out2; return;
flags |= TQ_FRONT; flags |= TQ_FRONT;
} }
@ -734,11 +730,45 @@ 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: }
void
taskq_dispatch_ent(taskq_t *tq, task_func_t func, void *arg, uint_t flags,
taskq_ent_t *t)
{
unsigned long irqflags;
spin_lock_irqsave_nested(&tq->tq_lock, irqflags,
tq->tq_lock_class);
taskq_dispatch_ent_impl(tq, func, arg, flags, t);
spin_unlock_irqrestore(&tq->tq_lock, irqflags); spin_unlock_irqrestore(&tq->tq_lock, irqflags);
} }
EXPORT_SYMBOL(taskq_dispatch_ent); EXPORT_SYMBOL(taskq_dispatch_ent);
boolean_t
taskq_try_dispatch_ent(taskq_t *tq, task_func_t func, void *arg, uint_t flags,
taskq_ent_t *t)
{
unsigned long irqflags;
/*
* XXX I don't _think_ losing _nested matters, because I think its
* only related to lockdep, and we don't have access to that anyway
* -- robn, 2023-10-23
*/
if (!spin_trylock_irqsave(&tq->tq_lock, irqflags))
return (B_FALSE);
taskq_dispatch_ent_impl(tq, func, arg, flags, t);
spin_unlock_irqrestore(&tq->tq_lock, irqflags);
return (B_TRUE);
}
EXPORT_SYMBOL(taskq_try_dispatch_ent);
int int
taskq_empty_ent(taskq_ent_t *t) taskq_empty_ent(taskq_ent_t *t)
{ {