From 168e43b16351f101394d15d49e28c5a8e4f2365b Mon Sep 17 00:00:00 2001 From: Andi Kleen Date: Wed, 14 Oct 2009 06:22:47 +0200 Subject: [PATCH] --- yaml --- r: 167855 b: refs/heads/master c: 65a64464349883891e21e74af16c05d6e1eeb4e9 h: refs/heads/master i: 167853: 993d59c57b9b8d391219aabc9278667dbb8dabea 167851: 24175a792c6700e8fa1510eeb8373f2643d7ff97 167847: eb241d318794f447c9df2c93c1b5699be531d84e 167839: 042fadb73163812dba46a7aad5ada1e48fcfdc1d v: v3 --- [refs] | 2 +- trunk/kernel/workqueue.c | 21 +++++++++++++++++++-- 2 files changed, 20 insertions(+), 3 deletions(-) diff --git a/[refs] b/[refs] index 2aa96c78e46d..393d4cf66ef5 100644 --- a/[refs] +++ b/[refs] @@ -1,2 +1,2 @@ --- -refs/heads/master: 5d5429af066b8896e903d829ac143711ed2c25f2 +refs/heads/master: 65a64464349883891e21e74af16c05d6e1eeb4e9 diff --git a/trunk/kernel/workqueue.c b/trunk/kernel/workqueue.c index addfe2df93b1..f61a2fecf281 100644 --- a/trunk/kernel/workqueue.c +++ b/trunk/kernel/workqueue.c @@ -667,21 +667,38 @@ EXPORT_SYMBOL(schedule_delayed_work_on); int schedule_on_each_cpu(work_func_t func) { int cpu; + int orig = -1; struct work_struct *works; works = alloc_percpu(struct work_struct); if (!works) return -ENOMEM; + /* + * when running in keventd don't schedule a work item on itself. + * Can just call directly because the work queue is already bound. + * This also is faster. + * Make this a generic parameter for other workqueues? + */ + if (current_is_keventd()) { + orig = raw_smp_processor_id(); + INIT_WORK(per_cpu_ptr(works, orig), func); + func(per_cpu_ptr(works, orig)); + } + get_online_cpus(); for_each_online_cpu(cpu) { struct work_struct *work = per_cpu_ptr(works, cpu); + if (cpu == orig) + continue; INIT_WORK(work, func); schedule_work_on(cpu, work); } - for_each_online_cpu(cpu) - flush_work(per_cpu_ptr(works, cpu)); + for_each_online_cpu(cpu) { + if (cpu != orig) + flush_work(per_cpu_ptr(works, cpu)); + } put_online_cpus(); free_percpu(works); return 0;