workqueue: reimplement work_on_cpu() using system_wq
Tejun Heo
maintainerPATCH 1/1 workqueue: reimplement work_on_cpu() using system_wq
Quoted 1 line
From
760824d48d8a1f302b80367681ada19836d93521Mon Sep 17 00:00:00 2001
From: Tejun Heo <[email protected]>
Date: Tue, 18 Sep 2012 12:48:43 -0700
The existing work_on_cpu() implementation is hugely inefficient. It creates a new kthread, execute that single function and then let the kthread die on each invocation.
Now that system_wq can handle concurrent executions, there's no advantage of doing this. Reimplement work_on_cpu() using system_wq which makes it simpler and way more efficient.
---
Applying to wq/for-3.7.
Thanks.
kernel/workqueue.c | 25 ++++++++----------------- 1 files changed, 8 insertions(+), 17 deletions(-)
kernel/workqueue.c +8 -17
@@ -3624,18 +3624,17 @@ static int __cpuinit workqueue_cpu_down_callback(struct notifier_block *nfb,#ifdef CONFIG_SMP struct work_for_cpu { -struct completion completion; +struct work_struct work;long (*fn)(void *);void *arg;long ret; }; -static int do_work_for_cpu (void *_wfc) +static void work_for_cpu_fn (struct work_struct *work) { -struct work_for_cpu *wfc = _wfc; + struct work_for_cpu *wfc = container_of(work, struct work_for_cpu, work); + wfc->ret = wfc->fn (wfc->arg); -complete (&wfc->completion); -return 0 ; }/**
@@ -3650,19 +3649,11 @@ static int do_work_for_cpu(void *_wfc)*/ long work_on_cpu (unsigned int cpu,long (*fn)(void *),void *arg) { -struct task_struct *sub_thread; -struct work_for_cpu wfc = { - .completion =COMPLETION_INITIALIZER_ONSTACK (wfc.completion), - .fn = fn, - .arg = arg, - }; +struct work_for_cpu wfc = { .fn = fn, .arg = arg }; - sub_thread =kthread_create (do_work_for_cpu, &wfc,"work_for_cpu" ); -if (IS_ERR (sub_thread)) -return PTR_ERR (sub_thread); -kthread_bind (sub_thread, cpu); -wake_up_process (sub_thread); -wait_for_completion (&wfc.completion); +INIT_WORK_ONSTACK (&wfc.work, work_for_cpu_fn); +schedule_work_on (cpu, &wfc.work); +flush_work (&wfc.work);return wfc.ret; }EXPORT_SYMBOL_GPL (work_on_cpu);
Signature · 1 line
1.7.7.3
Quoted 11 lines · Tejun Heo
Quoted 1 line
From
760824d48d8a1f302b80367681ada19836d93521Mon Sep 17 00:00:00 2001From: Tejun Heo <[email protected]>
Date: Tue, 18 Sep 2012 12:48:43 -0700The existing
work_on_cpu()implementation is hugely inefficient. It creates a new kthread, execute that single function and then let the kthread die on each invocation.Now that
system_wqcan handle concurrent executions, there's no advantage of doing this. Reimplementwork_on_cpu()usingsystem_wqwhich makes it simpler and way more efficient.
Makes sense. I have tested that after dropping your conversion of APM on_cpu0() and using this one instead, everything works.
Quoted 3 lines
Signed-off-by Tejun Heo <[email protected]>Cc Linus Torvalds <[email protected]>Cc Jiri Kosina <[email protected]>
Quoted 65 lines
Cc Bjorn Helgaas <[email protected]>Cc Len Brown <[email protected]>Cc Rafael J. Wysocki <[email protected]>---
Applying to wq/for-3.7.Thanks.
kernel/workqueue.c | 25 ++++++++----------------- 1 files changed, 8 insertions(+), 17 deletions(-)kernel/workqueue.c +8
-17@@ -3624,18 +3624,17 @@ static int __cpuinit workqueue_cpu_down_callback(struct notifier_block *nfb,#ifdef CONFIG_SMP struct work_for_cpu { -struct completion completion; +struct work_struct work;long (*fn)(void *);void *arg;long ret; }; -static int do_work_for_cpu (void *_wfc) +static void work_for_cpu_fn (struct work_struct *work) { -struct work_for_cpu *wfc = _wfc; + struct work_for_cpu *wfc = container_of(work, struct work_for_cpu, work); + wfc->ret = wfc->fn (wfc->arg); -complete (&wfc->completion); -return 0 ; }/** @@ -3650,19 +3649,11 @@ static int do_work_for_cpu(void *_wfc)*/ long work_on_cpu (unsigned int cpu,long (*fn)(void *),void *arg) { -struct task_struct *sub_thread; -struct work_for_cpu wfc = { - .completion =COMPLETION_INITIALIZER_ONSTACK (wfc.completion), - .fn = fn, - .arg = arg, - }; +struct work_for_cpu wfc = { .fn = fn, .arg = arg }; - sub_thread =kthread_create (do_work_for_cpu, &wfc,"work_for_cpu" ); -if (IS_ERR (sub_thread)) -return PTR_ERR (sub_thread); -kthread_bind (sub_thread, cpu); -wake_up_process (sub_thread); -wait_for_completion (&wfc.completion); +INIT_WORK_ONSTACK (&wfc.work, work_for_cpu_fn); +schedule_work_on (cpu, &wfc.work); +flush_work (&wfc.work);return wfc.ret; }EXPORT_SYMBOL_GPL (work_on_cpu);Signature · 1 line
1.7.7.3
Signature · 2 lines
Jiri Kosina SUSE Labs