Commit 499e2d44 authored by Andrew Morton's avatar Andrew Morton Committed by Linus Torvalds

[PATCH] speedup flush_workqueue for singlethread_workqueue

From: "Anil" <anil.s.keshavamurthy@intel.com>

In flush_workqueue() for a single_threaded_worqueue case the code flushes the
same cpu_workqueue_struct for each online_cpu.

Change things so that we only perform the flush once in this case.
Signed-off-by: default avatarAndrew Morton <akpm@osdl.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@osdl.org>
parent ace476bb
...@@ -218,6 +218,33 @@ static int worker_thread(void *__cwq) ...@@ -218,6 +218,33 @@ static int worker_thread(void *__cwq)
return 0; return 0;
} }
static void flush_cpu_workqueue(struct cpu_workqueue_struct *cwq)
{
if (cwq->thread == current) {
/*
* Probably keventd trying to flush its own queue. So simply run
* it by hand rather than deadlocking.
*/
run_workqueue(cwq);
} else {
DEFINE_WAIT(wait);
long sequence_needed;
spin_lock_irq(&cwq->lock);
sequence_needed = cwq->insert_sequence;
while (sequence_needed - cwq->remove_sequence > 0) {
prepare_to_wait(&cwq->work_done, &wait,
TASK_UNINTERRUPTIBLE);
spin_unlock_irq(&cwq->lock);
schedule();
spin_lock_irq(&cwq->lock);
}
finish_wait(&cwq->work_done, &wait);
spin_unlock_irq(&cwq->lock);
}
}
/* /*
* flush_workqueue - ensure that any scheduled work has run to completion. * flush_workqueue - ensure that any scheduled work has run to completion.
* *
...@@ -234,42 +261,19 @@ static int worker_thread(void *__cwq) ...@@ -234,42 +261,19 @@ static int worker_thread(void *__cwq)
*/ */
void fastcall flush_workqueue(struct workqueue_struct *wq) void fastcall flush_workqueue(struct workqueue_struct *wq)
{ {
struct cpu_workqueue_struct *cwq;
int cpu;
might_sleep(); might_sleep();
lock_cpu_hotplug(); lock_cpu_hotplug();
for_each_online_cpu(cpu) {
DEFINE_WAIT(wait);
long sequence_needed;
if (is_single_threaded(wq))
cwq = wq->cpu_wq + 0; /* Always use cpu 0's area. */
else
cwq = wq->cpu_wq + cpu;
if (cwq->thread == current) { if (is_single_threaded(wq)) {
/* /* Always use cpu 0's area. */
* Probably keventd trying to flush its own queue. flush_cpu_workqueue(wq->cpu_wq + 0);
* So simply run it by hand rather than deadlocking. } else {
*/ int cpu;
run_workqueue(cwq);
continue;
}
spin_lock_irq(&cwq->lock);
sequence_needed = cwq->insert_sequence;
while (sequence_needed - cwq->remove_sequence > 0) { for_each_online_cpu(cpu)
prepare_to_wait(&cwq->work_done, &wait, flush_cpu_workqueue(wq->cpu_wq + cpu);
TASK_UNINTERRUPTIBLE);
spin_unlock_irq(&cwq->lock);
schedule();
spin_lock_irq(&cwq->lock);
}
finish_wait(&cwq->work_done, &wait);
spin_unlock_irq(&cwq->lock);
} }
unlock_cpu_hotplug(); unlock_cpu_hotplug();
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment