aboutsummaryrefslogtreecommitdiff
path: root/sys/kern/subr_taskqueue.c
diff options
context:
space:
mode:
authorKip Macy <kmacy@FreeBSD.org>2008-07-18 07:10:33 +0000
committerKip Macy <kmacy@FreeBSD.org>2008-07-18 07:10:33 +0000
commit694382c8eba00ea564c1d13f70b889a3a9375f43 (patch)
treeee7e56a5f8c27659506d9791205f24797e2a155a /sys/kern/subr_taskqueue.c
parent2976b312a16b228a947bf2aaa1eedec12fe17da2 (diff)
downloadsrc-694382c8eba00ea564c1d13f70b889a3a9375f43.tar.gz
src-694382c8eba00ea564c1d13f70b889a3a9375f43.zip
Notes
Diffstat (limited to 'sys/kern/subr_taskqueue.c')
-rw-r--r--sys/kern/subr_taskqueue.c203
1 files changed, 27 insertions, 176 deletions
diff --git a/sys/kern/subr_taskqueue.c b/sys/kern/subr_taskqueue.c
index 9ca4a31753e7..050d7131fb16 100644
--- a/sys/kern/subr_taskqueue.c
+++ b/sys/kern/subr_taskqueue.c
@@ -32,7 +32,6 @@ __FBSDID("$FreeBSD$");
#include <sys/bus.h>
#include <sys/interrupt.h>
#include <sys/kernel.h>
-#include <sys/ktr.h>
#include <sys/kthread.h>
#include <sys/lock.h>
#include <sys/malloc.h>
@@ -49,8 +48,6 @@ static void *taskqueue_ih;
static STAILQ_HEAD(taskqueue_list, taskqueue) taskqueue_queues;
static struct mtx taskqueue_queues_mutex;
-STAILQ_HEAD(task_head, task);
-
struct taskqueue {
STAILQ_ENTRY(taskqueue) tq_link;
STAILQ_HEAD(, task) tq_queue;
@@ -61,35 +58,31 @@ struct taskqueue {
struct mtx tq_mutex;
struct thread **tq_threads;
int tq_tcount;
+ int tq_spin;
int tq_flags;
};
#define TQ_FLAGS_ACTIVE (1 << 0)
#define TQ_FLAGS_BLOCKED (1 << 1)
#define TQ_FLAGS_PENDING (1 << 2)
-#define TQ_FLAGS_SPIN (1 << 3)
-#define TQ_FLAGS_NOWAKEUP (1 << 4)
-#define TQ_FLAGS_RUNNING (1 << 5)
-
-#define TQ_LOCK(tq) \
-do { \
- \
- if (tq->tq_flags & TQ_FLAGS_SPIN) \
- mtx_lock_spin(&tq->tq_mutex); \
- else \
- mtx_lock(&tq->tq_mutex); \
-} while (0)
-
-
-#define TQ_UNLOCK(tq) \
-do { \
- \
- if (tq->tq_flags & TQ_FLAGS_SPIN) \
- mtx_unlock_spin(&tq->tq_mutex); \
- else \
- mtx_unlock(&tq->tq_mutex); \
-} while (0)
+static __inline void
+TQ_LOCK(struct taskqueue *tq)
+{
+ if (tq->tq_spin)
+ mtx_lock_spin(&tq->tq_mutex);
+ else
+ mtx_lock(&tq->tq_mutex);
+}
+
+static __inline void
+TQ_UNLOCK(struct taskqueue *tq)
+{
+ if (tq->tq_spin)
+ mtx_unlock_spin(&tq->tq_mutex);
+ else
+ mtx_unlock(&tq->tq_mutex);
+}
static void init_taskqueue_list(void *data);
@@ -97,7 +90,7 @@ static __inline int
TQ_SLEEP(struct taskqueue *tq, void *p, struct mtx *m, int pri, const char *wm,
int t)
{
- if (tq->tq_flags & TQ_FLAGS_SPIN)
+ if (tq->tq_spin)
return (msleep_spin(p, m, wm, t));
return (msleep(p, m, pri, wm, t));
}
@@ -118,18 +111,17 @@ _taskqueue_create(const char *name, int mflags,
int mtxflags, const char *mtxname)
{
struct taskqueue *queue;
- int spin;
-
-
+
queue = malloc(sizeof(struct taskqueue), M_TASKQUEUE, mflags | M_ZERO);
if (!queue)
return 0;
- spin = ((mtxflags & MTX_SPIN) ? TQ_FLAGS_SPIN : 0);
+
STAILQ_INIT(&queue->tq_queue);
queue->tq_name = name;
queue->tq_enqueue = enqueue;
queue->tq_context = context;
- queue->tq_flags |= TQ_FLAGS_ACTIVE | spin;
+ 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);
@@ -208,14 +200,8 @@ taskqueue_enqueue(struct taskqueue *queue, struct task *task)
/*
* Count multiple enqueues.
*/
- if (task->ta_pending || (task->ta_flags & TA_REFERENCED)) {
+ if (task->ta_pending) {
task->ta_pending++;
- /*
- * overflow
- */
- if (task->ta_pending == 0)
- task->ta_pending--;
-
TQ_UNLOCK(queue);
return 0;
}
@@ -240,9 +226,9 @@ taskqueue_enqueue(struct taskqueue *queue, struct task *task)
}
task->ta_pending = 1;
- if ((queue->tq_flags & (TQ_FLAGS_BLOCKED|TQ_FLAGS_RUNNING)) == 0)
+ if ((queue->tq_flags & TQ_FLAGS_BLOCKED) == 0)
queue->tq_enqueue(queue->tq_context);
- else if (queue->tq_flags & TQ_FLAGS_BLOCKED)
+ else
queue->tq_flags |= TQ_FLAGS_PENDING;
TQ_UNLOCK(queue);
@@ -311,7 +297,7 @@ taskqueue_run(struct taskqueue *queue)
void
taskqueue_drain(struct taskqueue *queue, struct task *task)
{
- if (queue->tq_flags & TQ_FLAGS_SPIN) { /* XXX */
+ if (queue->tq_spin) { /* XXX */
mtx_lock_spin(&queue->tq_mutex);
while (task->ta_pending != 0 || task == queue->tq_running)
msleep_spin(task, &queue->tq_mutex, "-", 0);
@@ -479,138 +465,3 @@ taskqueue_fast_run(void *dummy)
TASKQUEUE_FAST_DEFINE(fast, taskqueue_fast_enqueue, 0,
swi_add(NULL, "Fast task queue", taskqueue_fast_run, NULL,
SWI_TQ_FAST, INTR_MPSAFE, &taskqueue_fast_ih));
-
-static void
-taskqueue_run_drv(void *arg)
-{
- struct task *task, *tmp;
- struct task_head current;
- int restarts = 0;
- struct taskqueue *queue = (struct taskqueue *) arg;
-
- STAILQ_INIT(&current);
- /*
- * First we move all of the tasks off of the taskqueue's list
- * on to current on the stack to avoided repeated serialization
- */
- mtx_lock_spin(&queue->tq_mutex);
- queue->tq_flags |= TQ_FLAGS_RUNNING;
-restart:
- STAILQ_CONCAT(&current, &queue->tq_queue);
- STAILQ_FOREACH(task, &current, ta_link) {
- /*
- * to let taskqueue_enqueue_fast know that this task
- * has been dequeued but is referenced
- * clear pending so that if pending is later set we know that it
- * it needs to be re-enqueued even if the task doesn't return
- * TA_NO_DEQUEUE
- */
- task->ta_ppending = task->ta_pending;
- task->ta_pending = 0;
- task->ta_flags |= TA_REFERENCED;
- }
- mtx_unlock_spin(&queue->tq_mutex);
- STAILQ_FOREACH(task, &current, ta_link) {
- task->ta_rc = task->ta_drv_func(task->ta_context, task->ta_ppending);
-
- }
- /*
- * We've gotten here so we know that we've run the tasks that were
- * on the taskqueue list on the first pass
- */
- mtx_lock_spin(&queue->tq_mutex);
- STAILQ_FOREACH_SAFE(task, &current, ta_link, tmp) {
- if (task->ta_rc != TA_NO_DEQUEUE && task->ta_pending == 0) {
- STAILQ_REMOVE(&current, task, task, ta_link);
- task->ta_flags &= ~TA_REFERENCED;
- }
- task->ta_ppending = 0;
- task->ta_rc = 0;
- }
- /*
- * restart if there are any tasks in the list
- */
- if (STAILQ_FIRST(&current) || STAILQ_FIRST(&queue->tq_queue)) {
- restarts++;
- goto restart;
- }
- queue->tq_flags &= ~TQ_FLAGS_RUNNING;
- mtx_unlock_spin(&queue->tq_mutex);
- CTR2(KTR_INTR, "queue=%s returning from taskqueue_run_drv after %d restarts", queue->tq_name, restarts);
-}
-
-static void
-taskqueue_drv_schedule(void *context)
-{
- swi_sched(context, 0);
-}
-
-struct taskqueue *
-taskqueue_define_drv(void *arg, const char *name)
-{
- struct taskqueue *tq;
- struct thread *td;
-
- tq = malloc(sizeof(struct taskqueue), M_TASKQUEUE,
- M_NOWAIT | M_ZERO);
- if (!tq) {
- printf("%s: Unable to allocate fast drv task queue!\n",
- __func__);
- return (NULL);
- }
-
- STAILQ_INIT(&tq->tq_queue);
- tq->tq_name = name;
- tq->tq_enqueue = taskqueue_drv_schedule;
- tq->tq_flags = (TQ_FLAGS_ACTIVE | TQ_FLAGS_SPIN | TQ_FLAGS_NOWAKEUP);
- mtx_init(&tq->tq_mutex, name, NULL, MTX_SPIN);
-
- mtx_lock(&taskqueue_queues_mutex);
- STAILQ_INSERT_TAIL(&taskqueue_queues, tq, tq_link);
- mtx_unlock(&taskqueue_queues_mutex);
-
- swi_add(NULL, name, taskqueue_run_drv,
- tq, SWI_NET, INTR_MPSAFE, &tq->tq_context);
- td = intr_handler_thread((struct intr_handler *) tq->tq_context);
- return (tq);
-}
-
-struct intr_handler *
-taskqueue_drv_handler(struct taskqueue *tq)
-{
- return ((struct intr_handler *) tq->tq_context);
-}
-
-struct thread *
-taskqueue_drv_thread(void *context)
-{
- struct taskqueue *tq = (struct taskqueue *) context;
-
- return (intr_handler_thread((struct intr_handler *) tq->tq_context));
-}
-
-/*
- * Caller must make sure that there must not be any new tasks getting queued
- * before calling this.
- */
-void
-taskqueue_free_drv(struct taskqueue *queue)
-{
- struct intr_thread *ithd;
- struct intr_event *ie;
-
- mtx_lock(&taskqueue_queues_mutex);
- STAILQ_REMOVE(&taskqueue_queues, queue, taskqueue, tq_link);
- mtx_unlock(&taskqueue_queues_mutex);
-
- ie = ((struct intr_handler *)(queue->tq_context))->ih_event;
- ithd = ie->ie_thread;
- swi_remove(queue->tq_context);
- intr_event_destroy(ie);
-
- mtx_lock_spin(&queue->tq_mutex);
- taskqueue_run(queue);
- mtx_destroy(&queue->tq_mutex);
- free(queue, M_TASKQUEUE);
-}
-