summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--sys/dev/acpica/Osd/OsdSchedule.c25
-rw-r--r--sys/dev/em/if_em.c10
-rw-r--r--sys/kern/subr_taskqueue.c72
-rw-r--r--sys/sys/taskqueue.h24
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_ */