aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorNed Bass <[email protected]>2012-01-19 10:33:19 -0800
committerBrian Behlendorf <[email protected]>2012-01-19 14:42:49 -0800
commit3c6ed5410beb7a4f9e0c042229eb63c4c11a5fc9 (patch)
tree771bf4bc28c99a21adf88de2aaa9c31c802b83ff
parent0bb43ca2823ab55a74565f6e17e2c36749cff3b9 (diff)
Taskq locking optimizations
Testing has shown that tq->tq_lock can be highly contended when a large number of small work items are dispatched. The lock hold time is reduced by the following changes: 1) Use exclusive threads in the work_waitq When a single work item is dispatched we only need to wake a single thread to service it. The current implementation uses non-exclusive threads so all threads are woken when the dispatcher calls wake_up(). If a large number of threads are in the queue this overhead can become non-negligible. 2) Conditionally add/remove threads from work waitq Taskq threads need only add themselves to the work wait queue if there are no pending work items. Signed-off-by: Brian Behlendorf <[email protected]> Issue #32
-rw-r--r--module/spl/spl-taskq.c4
1 files changed, 2 insertions, 2 deletions
diff --git a/module/spl/spl-taskq.c b/module/spl/spl-taskq.c
index ece99aad6..0b3b3a131 100644
--- a/module/spl/spl-taskq.c
+++ b/module/spl/spl-taskq.c
@@ -454,17 +454,17 @@ taskq_thread(void *args)
while (!kthread_should_stop()) {
- add_wait_queue(&tq->tq_work_waitq, &wait);
if (list_empty(&tq->tq_pend_list) &&
list_empty(&tq->tq_prio_list)) {
+ add_wait_queue_exclusive(&tq->tq_work_waitq, &wait);
spin_unlock_irqrestore(&tq->tq_lock, tq->tq_lock_flags);
schedule();
spin_lock_irqsave(&tq->tq_lock, tq->tq_lock_flags);
+ remove_wait_queue(&tq->tq_work_waitq, &wait);
} else {
__set_current_state(TASK_RUNNING);
}
- remove_wait_queue(&tq->tq_work_waitq, &wait);
if (!list_empty(&tq->tq_prio_list))
pend_list = &tq->tq_prio_list;