diff options
| -rw-r--r-- | sys/dev/acpica/Osd/OsdSchedule.c | 25 | ||||
| -rw-r--r-- | sys/dev/em/if_em.c | 10 | ||||
| -rw-r--r-- | sys/kern/subr_taskqueue.c | 72 | ||||
| -rw-r--r-- | sys/sys/taskqueue.h | 24 |
4 files changed, 71 insertions, 60 deletions
diff --git a/sys/dev/acpica/Osd/OsdSchedule.c b/sys/dev/acpica/Osd/OsdSchedule.c index f1e84e4de48b..1e8aecab2526 100644 --- a/sys/dev/acpica/Osd/OsdSchedule.c +++ b/sys/dev/acpica/Osd/OsdSchedule.c @@ -65,31 +65,8 @@ struct acpi_task_ctx { void *at_context; }; -/* - * Private task queue definition for ACPI - */ -static struct proc * -acpi_task_start_threads(struct taskqueue **tqp) -{ - struct proc *acpi_kthread_proc; - int err, i; - - KASSERT(*tqp != NULL, ("acpi taskqueue not created before threads")); - - /* Start one or more threads to service our taskqueue. */ - for (i = 0; i < acpi_max_threads; i++) { - err = kthread_create(taskqueue_thread_loop, tqp, &acpi_kthread_proc, - 0, 0, "acpi_task%d", i); - if (err) { - printf("%s: kthread_create failed (%d)\n", __func__, err); - break; - } - } - return (acpi_kthread_proc); -} - TASKQUEUE_DEFINE(acpi, taskqueue_thread_enqueue, &taskqueue_acpi, - taskqueue_acpi_proc = acpi_task_start_threads(&taskqueue_acpi)); + taskqueue_start_threads(&taskqueue_acpi, 3, PWAIT, "acpi_task")); /* * Bounce through this wrapper function since ACPI-CA doesn't understand diff --git a/sys/dev/em/if_em.c b/sys/dev/em/if_em.c index 676460aebfc7..33fdb44eb448 100644 --- a/sys/dev/em/if_em.c +++ b/sys/dev/em/if_em.c @@ -2053,13 +2053,9 @@ em_allocate_intr(struct adapter *adapter) TASK_INIT(&adapter->link_task, 0, em_handle_link, adapter); adapter->tq = taskqueue_create_fast("em_taskq", M_NOWAIT, taskqueue_thread_enqueue, - &adapter->tq, &adapter->tqproc); - kthread_create(taskqueue_thread_loop, - &adapter->tq, &adapter->tqproc, - 0, 0, "%s taskq", device_get_nameunit(adapter->dev)); - mtx_lock_spin(&sched_lock); - sched_prio(FIRST_THREAD_IN_PROC(adapter->tqproc), PI_NET); - mtx_unlock_spin(&sched_lock); + &adapter->tq); + taskqueue_start_threads(&adapter->tq, 1, PI_NET, "%s taskq", + device_get_nameunit(adapter->dev)); } #endif if (adapter->int_handler_tag == NULL) { diff --git a/sys/kern/subr_taskqueue.c b/sys/kern/subr_taskqueue.c index 3cc82927dc53..72c75a409279 100644 --- a/sys/kern/subr_taskqueue.c +++ b/sys/kern/subr_taskqueue.c @@ -37,8 +37,10 @@ __FBSDID("$FreeBSD$"); #include <sys/malloc.h> #include <sys/mutex.h> #include <sys/proc.h> +#include <sys/sched.h> #include <sys/taskqueue.h> #include <sys/unistd.h> +#include <machine/stdarg.h> static MALLOC_DEFINE(M_TASKQUEUE, "taskqueue", "Task Queues"); static void *taskqueue_giant_ih; @@ -55,9 +57,13 @@ struct taskqueue { struct task *tq_running; struct mtx tq_mutex; struct proc **tq_pproc; + int tq_pcount; int tq_spin; + int tq_flags; }; +#define TQ_FLAGS_ACTIVE (1 << 0) + static __inline void TQ_LOCK(struct taskqueue *tq) { @@ -100,7 +106,6 @@ SYSINIT(taskqueue_list, SI_SUB_INTRINSIC, SI_ORDER_ANY, init_taskqueue_list, static struct taskqueue * _taskqueue_create(const char *name, int mflags, taskqueue_enqueue_fn enqueue, void *context, - struct proc **pp, int mtxflags, const char *mtxname) { struct taskqueue *queue; @@ -113,8 +118,8 @@ _taskqueue_create(const char *name, int mflags, queue->tq_name = name; queue->tq_enqueue = enqueue; queue->tq_context = context; - queue->tq_pproc = pp; queue->tq_spin = (mtxflags & MTX_SPIN) != 0; + queue->tq_flags |= TQ_FLAGS_ACTIVE; mtx_init(&queue->tq_mutex, mtxname, NULL, mtxflags); mtx_lock(&taskqueue_queues_mutex); @@ -126,10 +131,9 @@ _taskqueue_create(const char *name, int mflags, struct taskqueue * taskqueue_create(const char *name, int mflags, - taskqueue_enqueue_fn enqueue, void *context, - struct proc **pp) + taskqueue_enqueue_fn enqueue, void *context) { - return _taskqueue_create(name, mflags, enqueue, context, pp, + return _taskqueue_create(name, mflags, enqueue, context, MTX_DEF, "taskqueue"); } @@ -139,13 +143,10 @@ taskqueue_create(const char *name, int mflags, static void taskqueue_terminate(struct proc **pp, struct taskqueue *tq) { - struct proc *p; - p = *pp; - *pp = NULL; - if (p) { - wakeup_one(tq); - TQ_SLEEP(tq, p, &tq->tq_mutex, PWAIT, "taskqueue_destroy", 0); + while (tq->tq_pcount > 0) { + wakeup(tq); + TQ_SLEEP(tq, pp, &tq->tq_mutex, PWAIT, "taskqueue_destroy", 0); } } @@ -158,9 +159,11 @@ taskqueue_free(struct taskqueue *queue) mtx_unlock(&taskqueue_queues_mutex); TQ_LOCK(queue); + queue->tq_flags &= ~TQ_FLAGS_ACTIVE; taskqueue_run(queue); taskqueue_terminate(queue->tq_pproc, queue); mtx_destroy(&queue->tq_mutex); + free(queue->tq_pproc, M_TASKQUEUE); free(queue, M_TASKQUEUE); } @@ -306,6 +309,43 @@ taskqueue_swi_giant_run(void *dummy) taskqueue_run(taskqueue_swi_giant); } +int +taskqueue_start_threads(struct taskqueue **tqp, int count, int pri, + const char *name, ...) +{ + va_list ap; + struct taskqueue *tq; + char ktname[MAXCOMLEN]; + int i; + + if (count <= 0) + return (EINVAL); + tq = *tqp; + + if ((tq->tq_pproc = malloc(sizeof(struct proc *) * count, M_TASKQUEUE, + M_NOWAIT | M_ZERO)) == NULL) + return (ENOMEM); + + va_start(ap, name); + vsnprintf(ktname, MAXCOMLEN, name, ap); + va_end(ap); + + for (i = 0; i < count; i++) { + if (count == 1) + kthread_create(taskqueue_thread_loop, tqp, + &tq->tq_pproc[i], 0, 0, ktname); + else + kthread_create(taskqueue_thread_loop, tqp, + &tq->tq_pproc[i], 0, 0, "%s_%d", ktname, i); + mtx_lock_spin(&sched_lock); + sched_prio(FIRST_THREAD_IN_PROC(tq->tq_pproc[i]), pri); + mtx_unlock_spin(&sched_lock); + tq->tq_pcount++; + } + + return (0); +} + void taskqueue_thread_loop(void *arg) { @@ -317,10 +357,11 @@ taskqueue_thread_loop(void *arg) do { taskqueue_run(tq); TQ_SLEEP(tq, tq, &tq->tq_mutex, curthread->td_priority, "-", 0); - } while (*tq->tq_pproc != NULL); + } while ((tq->tq_flags & TQ_FLAGS_ACTIVE) != 0); /* rendezvous with thread that asked us to terminate */ - wakeup_one(tq); + tq->tq_pcount--; + wakeup_one(tq->tq_pproc); TQ_UNLOCK(tq); kthread_exit(0); } @@ -349,10 +390,9 @@ TASKQUEUE_DEFINE_THREAD(thread); struct taskqueue * taskqueue_create_fast(const char *name, int mflags, - taskqueue_enqueue_fn enqueue, void *context, - struct proc **pp) + taskqueue_enqueue_fn enqueue, void *context) { - return _taskqueue_create(name, mflags, enqueue, context, pp, + return _taskqueue_create(name, mflags, enqueue, context, MTX_SPIN, "fast_taskqueue"); } diff --git a/sys/sys/taskqueue.h b/sys/sys/taskqueue.h index 59ac30988793..6d6d9ad6997e 100644 --- a/sys/sys/taskqueue.h +++ b/sys/sys/taskqueue.h @@ -50,7 +50,9 @@ typedef void (*taskqueue_enqueue_fn)(void *context); struct proc; struct taskqueue *taskqueue_create(const char *name, int mflags, taskqueue_enqueue_fn enqueue, - void *context, struct proc **); + void *context); +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); void taskqueue_drain(struct taskqueue *queue, struct task *task); struct taskqueue *taskqueue_find(const char *name); @@ -89,10 +91,8 @@ struct taskqueue *taskqueue_##name; \ static void \ taskqueue_define_##name(void *arg) \ { \ - static struct proc *taskqueue_##name##_proc; \ taskqueue_##name = \ - taskqueue_create(#name, M_NOWAIT, (enqueue), (context), \ - &taskqueue_##name##_proc); \ + taskqueue_create(#name, M_NOWAIT, (enqueue), (context)); \ init; \ } \ \ @@ -102,8 +102,8 @@ SYSINIT(taskqueue_##name, SI_SUB_CONFIGURE, SI_ORDER_SECOND, \ struct __hack #define TASKQUEUE_DEFINE_THREAD(name) \ TASKQUEUE_DEFINE(name, taskqueue_thread_enqueue, &taskqueue_##name, \ - kthread_create(taskqueue_thread_loop, &taskqueue_##name, \ - &taskqueue_##name##_proc, 0, 0, #name " taskq")) + taskqueue_start_threads(&taskqueue_##name, 1, PWAIT, \ + "%s taskq", #name)) /* * Define and initialise a global taskqueue that uses spin mutexes. @@ -115,10 +115,9 @@ struct taskqueue *taskqueue_##name; \ static void \ taskqueue_define_##name(void *arg) \ { \ - static struct proc *taskqueue_##name##_proc; \ taskqueue_##name = \ - taskqueue_create_fast(#name, M_NOWAIT, (enqueue), (context),\ - &taskqueue_##name##_proc); \ + taskqueue_create_fast(#name, M_NOWAIT, (enqueue), \ + (context)); \ init; \ } \ \ @@ -128,9 +127,8 @@ SYSINIT(taskqueue_##name, SI_SUB_CONFIGURE, SI_ORDER_SECOND, \ struct __hack #define TASKQUEUE_FAST_DEFINE_THREAD(name) \ TASKQUEUE_FAST_DEFINE(name, taskqueue_thread_enqueue, \ - &taskqueue_##name, kthread_create(taskqueue_thread_loop, \ - &taskqueue_##name, &taskqueue_##name##_proc, 0, 0, \ - #name " fast taskq")) + &taskqueue_##name, taskqueue_start_threads(&taskqueue_##name \ + 1, PWAIT, "%s taskq", #name)) /* * These queues are serviced by software interrupt handlers. To enqueue @@ -156,6 +154,6 @@ TASKQUEUE_DECLARE(fast); int taskqueue_enqueue_fast(struct taskqueue *queue, struct task *task); struct taskqueue *taskqueue_create_fast(const char *name, int mflags, taskqueue_enqueue_fn enqueue, - void *context, struct proc **); + void *context); #endif /* !_SYS_TASKQUEUE_H_ */ |
