diff options
Diffstat (limited to 'kernel/workqueue.c')
-rw-r--r-- | kernel/workqueue.c | 21 |
1 files changed, 19 insertions, 2 deletions
diff --git a/kernel/workqueue.c b/kernel/workqueue.c index addfe2df93b1..f61a2fecf281 100644 --- a/kernel/workqueue.c +++ b/kernel/workqueue.c | |||
@@ -667,21 +667,38 @@ EXPORT_SYMBOL(schedule_delayed_work_on); | |||
667 | int schedule_on_each_cpu(work_func_t func) | 667 | int schedule_on_each_cpu(work_func_t func) |
668 | { | 668 | { |
669 | int cpu; | 669 | int cpu; |
670 | int orig = -1; | ||
670 | struct work_struct *works; | 671 | struct work_struct *works; |
671 | 672 | ||
672 | works = alloc_percpu(struct work_struct); | 673 | works = alloc_percpu(struct work_struct); |
673 | if (!works) | 674 | if (!works) |
674 | return -ENOMEM; | 675 | return -ENOMEM; |
675 | 676 | ||
677 | /* | ||
678 | * when running in keventd don't schedule a work item on itself. | ||
679 | * Can just call directly because the work queue is already bound. | ||
680 | * This also is faster. | ||
681 | * Make this a generic parameter for other workqueues? | ||
682 | */ | ||
683 | if (current_is_keventd()) { | ||
684 | orig = raw_smp_processor_id(); | ||
685 | INIT_WORK(per_cpu_ptr(works, orig), func); | ||
686 | func(per_cpu_ptr(works, orig)); | ||
687 | } | ||
688 | |||
676 | get_online_cpus(); | 689 | get_online_cpus(); |
677 | for_each_online_cpu(cpu) { | 690 | for_each_online_cpu(cpu) { |
678 | struct work_struct *work = per_cpu_ptr(works, cpu); | 691 | struct work_struct *work = per_cpu_ptr(works, cpu); |
679 | 692 | ||
693 | if (cpu == orig) | ||
694 | continue; | ||
680 | INIT_WORK(work, func); | 695 | INIT_WORK(work, func); |
681 | schedule_work_on(cpu, work); | 696 | schedule_work_on(cpu, work); |
682 | } | 697 | } |
683 | for_each_online_cpu(cpu) | 698 | for_each_online_cpu(cpu) { |
684 | flush_work(per_cpu_ptr(works, cpu)); | 699 | if (cpu != orig) |
700 | flush_work(per_cpu_ptr(works, cpu)); | ||
701 | } | ||
685 | put_online_cpus(); | 702 | put_online_cpus(); |
686 | free_percpu(works); | 703 | free_percpu(works); |
687 | return 0; | 704 | return 0; |