summaryrefslogtreecommitdiffstats
path: root/sys/kern/subr_taskqueue.c
diff options
context:
space:
mode:
authorLuiz Otavio O Souza <luiz@netgate.com>2016-03-21 13:24:56 -0500
committerLuiz Otavio O Souza <luiz@netgate.com>2016-03-21 13:24:56 -0500
commit696467e74a4bcf47c2bd3444dd7c1aeedbae50bf (patch)
tree924de18265dc0be51357e1a33f5a92e945044299 /sys/kern/subr_taskqueue.c
parent07def894aa89bea6d85dd76d201343a4a2e73046 (diff)
parentceb7b147e676803c22cf6d815f543f21fd9aa926 (diff)
downloadFreeBSD-src-696467e74a4bcf47c2bd3444dd7c1aeedbae50bf.zip
FreeBSD-src-696467e74a4bcf47c2bd3444dd7c1aeedbae50bf.tar.gz
Merge remote-tracking branch 'origin/stable/10' into devel
Diffstat (limited to 'sys/kern/subr_taskqueue.c')
-rw-r--r--sys/kern/subr_taskqueue.c32
1 files changed, 22 insertions, 10 deletions
diff --git a/sys/kern/subr_taskqueue.c b/sys/kern/subr_taskqueue.c
index f104bb5..bfc941e 100644
--- a/sys/kern/subr_taskqueue.c
+++ b/sys/kern/subr_taskqueue.c
@@ -46,6 +46,9 @@ __FBSDID("$FreeBSD$");
static MALLOC_DEFINE(M_TASKQUEUE, "taskqueue", "Task Queues");
static void *taskqueue_giant_ih;
static void *taskqueue_ih;
+static void taskqueue_fast_enqueue(void *);
+static void taskqueue_swi_enqueue(void *);
+static void taskqueue_swi_giant_enqueue(void *);
struct taskqueue_busy {
struct task *tb_running;
@@ -69,7 +72,7 @@ struct taskqueue {
#define TQ_FLAGS_ACTIVE (1 << 0)
#define TQ_FLAGS_BLOCKED (1 << 1)
-#define TQ_FLAGS_PENDING (1 << 2)
+#define TQ_FLAGS_UNLOCKED_ENQUEUE (1 << 2)
#define DT_CALLOUT_ARMED (1 << 0)
@@ -97,7 +100,8 @@ _timeout_task_init(struct taskqueue *queue, struct timeout_task *timeout_task,
{
TASK_INIT(&timeout_task->t, priority, func, context);
- callout_init_mtx(&timeout_task->c, &queue->tq_mutex, 0);
+ callout_init_mtx(&timeout_task->c, &queue->tq_mutex,
+ CALLOUT_RETURNUNLOCKED);
timeout_task->q = queue;
timeout_task->f = 0;
}
@@ -128,6 +132,11 @@ _taskqueue_create(const char *name __unused, int mflags,
queue->tq_context = context;
queue->tq_spin = (mtxflags & MTX_SPIN) != 0;
queue->tq_flags |= TQ_FLAGS_ACTIVE;
+ if (enqueue == taskqueue_fast_enqueue ||
+ enqueue == taskqueue_swi_enqueue ||
+ enqueue == taskqueue_swi_giant_enqueue ||
+ enqueue == taskqueue_thread_enqueue)
+ queue->tq_flags |= TQ_FLAGS_UNLOCKED_ENQUEUE;
mtx_init(&queue->tq_mutex, mtxname, NULL, mtxflags);
return queue;
@@ -197,6 +206,7 @@ taskqueue_enqueue_locked(struct taskqueue *queue, struct task *task)
if (task->ta_pending) {
if (task->ta_pending < USHRT_MAX)
task->ta_pending++;
+ TQ_UNLOCK(queue);
return (0);
}
@@ -220,11 +230,14 @@ taskqueue_enqueue_locked(struct taskqueue *queue, struct task *task)
}
task->ta_pending = 1;
+ if ((queue->tq_flags & TQ_FLAGS_UNLOCKED_ENQUEUE) != 0)
+ TQ_UNLOCK(queue);
if ((queue->tq_flags & TQ_FLAGS_BLOCKED) == 0)
queue->tq_enqueue(queue->tq_context);
- else
- queue->tq_flags |= TQ_FLAGS_PENDING;
+ if ((queue->tq_flags & TQ_FLAGS_UNLOCKED_ENQUEUE) == 0)
+ TQ_UNLOCK(queue);
+ /* Return with lock released. */
return (0);
}
int
@@ -234,7 +247,7 @@ taskqueue_enqueue(struct taskqueue *queue, struct task *task)
TQ_LOCK(queue);
res = taskqueue_enqueue_locked(queue, task);
- TQ_UNLOCK(queue);
+ /* The lock is released inside. */
return (res);
}
@@ -251,6 +264,7 @@ taskqueue_timeout_func(void *arg)
timeout_task->f &= ~DT_CALLOUT_ARMED;
queue->tq_callouts--;
taskqueue_enqueue_locked(timeout_task->q, &timeout_task->t);
+ /* The lock is released inside. */
}
int
@@ -267,6 +281,7 @@ taskqueue_enqueue_timeout(struct taskqueue *queue,
res = timeout_task->t.ta_pending;
if (ticks == 0) {
taskqueue_enqueue_locked(queue, &timeout_task->t);
+ /* The lock is released inside. */
} else {
if ((timeout_task->f & DT_CALLOUT_ARMED) != 0) {
res++;
@@ -280,8 +295,8 @@ taskqueue_enqueue_timeout(struct taskqueue *queue,
callout_reset(&timeout_task->c, ticks,
taskqueue_timeout_func, timeout_task);
}
+ TQ_UNLOCK(queue);
}
- TQ_UNLOCK(queue);
return (res);
}
@@ -309,10 +324,8 @@ taskqueue_unblock(struct taskqueue *queue)
TQ_LOCK(queue);
queue->tq_flags &= ~TQ_FLAGS_BLOCKED;
- if (queue->tq_flags & TQ_FLAGS_PENDING) {
- queue->tq_flags &= ~TQ_FLAGS_PENDING;
+ if (!STAILQ_EMPTY(&queue->tq_queue))
queue->tq_enqueue(queue->tq_context);
- }
TQ_UNLOCK(queue);
}
@@ -596,7 +609,6 @@ taskqueue_thread_enqueue(void *context)
tqp = context;
tq = *tqp;
- TQ_ASSERT_LOCKED(tq);
wakeup_one(tq);
}
OpenPOWER on IntegriCloud