diff options
author | Luiz Otavio O Souza <luiz@netgate.com> | 2016-03-21 13:24:56 -0500 |
---|---|---|
committer | Luiz Otavio O Souza <luiz@netgate.com> | 2016-03-21 13:24:56 -0500 |
commit | 696467e74a4bcf47c2bd3444dd7c1aeedbae50bf (patch) | |
tree | 924de18265dc0be51357e1a33f5a92e945044299 /sys/kern/subr_taskqueue.c | |
parent | 07def894aa89bea6d85dd76d201343a4a2e73046 (diff) | |
parent | ceb7b147e676803c22cf6d815f543f21fd9aa926 (diff) | |
download | FreeBSD-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.c | 32 |
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); } |