diff options
author | Michal Marek <mmarek@suse.cz> | 2010-08-04 07:59:13 -0400 |
---|---|---|
committer | Michal Marek <mmarek@suse.cz> | 2010-08-04 07:59:13 -0400 |
commit | 772320e84588dcbe1600ffb83e5f328f2209ac2a (patch) | |
tree | a7de21b79340aeaa17c58126f6b801b82c77b53a /kernel/workqueue.c | |
parent | 1ce53adf13a54375d2a5c7cdbe341b2558389615 (diff) | |
parent | 9fe6206f400646a2322096b56c59891d530e8d51 (diff) |
Merge commit 'v2.6.35' into kbuild/kbuild
Conflicts:
arch/powerpc/Makefile
Diffstat (limited to 'kernel/workqueue.c')
-rw-r--r-- | kernel/workqueue.c | 47 |
1 files changed, 41 insertions, 6 deletions
diff --git a/kernel/workqueue.c b/kernel/workqueue.c index dee48658805c..327d2deb4451 100644 --- a/kernel/workqueue.c +++ b/kernel/workqueue.c | |||
@@ -229,6 +229,16 @@ static inline void set_wq_data(struct work_struct *work, | |||
229 | atomic_long_set(&work->data, new); | 229 | atomic_long_set(&work->data, new); |
230 | } | 230 | } |
231 | 231 | ||
232 | /* | ||
233 | * Clear WORK_STRUCT_PENDING and the workqueue on which it was queued. | ||
234 | */ | ||
235 | static inline void clear_wq_data(struct work_struct *work) | ||
236 | { | ||
237 | unsigned long flags = *work_data_bits(work) & | ||
238 | (1UL << WORK_STRUCT_STATIC); | ||
239 | atomic_long_set(&work->data, flags); | ||
240 | } | ||
241 | |||
232 | static inline | 242 | static inline |
233 | struct cpu_workqueue_struct *get_wq_data(struct work_struct *work) | 243 | struct cpu_workqueue_struct *get_wq_data(struct work_struct *work) |
234 | { | 244 | { |
@@ -671,7 +681,7 @@ static int __cancel_work_timer(struct work_struct *work, | |||
671 | wait_on_work(work); | 681 | wait_on_work(work); |
672 | } while (unlikely(ret < 0)); | 682 | } while (unlikely(ret < 0)); |
673 | 683 | ||
674 | work_clear_pending(work); | 684 | clear_wq_data(work); |
675 | return ret; | 685 | return ret; |
676 | } | 686 | } |
677 | 687 | ||
@@ -774,7 +784,7 @@ void flush_delayed_work(struct delayed_work *dwork) | |||
774 | { | 784 | { |
775 | if (del_timer_sync(&dwork->timer)) { | 785 | if (del_timer_sync(&dwork->timer)) { |
776 | struct cpu_workqueue_struct *cwq; | 786 | struct cpu_workqueue_struct *cwq; |
777 | cwq = wq_per_cpu(keventd_wq, get_cpu()); | 787 | cwq = wq_per_cpu(get_wq_data(&dwork->work)->wq, get_cpu()); |
778 | __queue_work(cwq, &dwork->work); | 788 | __queue_work(cwq, &dwork->work); |
779 | put_cpu(); | 789 | put_cpu(); |
780 | } | 790 | } |
@@ -845,6 +855,30 @@ int schedule_on_each_cpu(work_func_t func) | |||
845 | return 0; | 855 | return 0; |
846 | } | 856 | } |
847 | 857 | ||
858 | /** | ||
859 | * flush_scheduled_work - ensure that any scheduled work has run to completion. | ||
860 | * | ||
861 | * Forces execution of the kernel-global workqueue and blocks until its | ||
862 | * completion. | ||
863 | * | ||
864 | * Think twice before calling this function! It's very easy to get into | ||
865 | * trouble if you don't take great care. Either of the following situations | ||
866 | * will lead to deadlock: | ||
867 | * | ||
868 | * One of the work items currently on the workqueue needs to acquire | ||
869 | * a lock held by your code or its caller. | ||
870 | * | ||
871 | * Your code is running in the context of a work routine. | ||
872 | * | ||
873 | * They will be detected by lockdep when they occur, but the first might not | ||
874 | * occur very often. It depends on what work items are on the workqueue and | ||
875 | * what locks they need, which you have no control over. | ||
876 | * | ||
877 | * In most situations flushing the entire workqueue is overkill; you merely | ||
878 | * need to know that a particular work item isn't queued and isn't running. | ||
879 | * In such cases you should use cancel_delayed_work_sync() or | ||
880 | * cancel_work_sync() instead. | ||
881 | */ | ||
848 | void flush_scheduled_work(void) | 882 | void flush_scheduled_work(void) |
849 | { | 883 | { |
850 | flush_workqueue(keventd_wq); | 884 | flush_workqueue(keventd_wq); |
@@ -1076,7 +1110,7 @@ static int __devinit workqueue_cpu_callback(struct notifier_block *nfb, | |||
1076 | unsigned int cpu = (unsigned long)hcpu; | 1110 | unsigned int cpu = (unsigned long)hcpu; |
1077 | struct cpu_workqueue_struct *cwq; | 1111 | struct cpu_workqueue_struct *cwq; |
1078 | struct workqueue_struct *wq; | 1112 | struct workqueue_struct *wq; |
1079 | int ret = NOTIFY_OK; | 1113 | int err = 0; |
1080 | 1114 | ||
1081 | action &= ~CPU_TASKS_FROZEN; | 1115 | action &= ~CPU_TASKS_FROZEN; |
1082 | 1116 | ||
@@ -1090,12 +1124,13 @@ undo: | |||
1090 | 1124 | ||
1091 | switch (action) { | 1125 | switch (action) { |
1092 | case CPU_UP_PREPARE: | 1126 | case CPU_UP_PREPARE: |
1093 | if (!create_workqueue_thread(cwq, cpu)) | 1127 | err = create_workqueue_thread(cwq, cpu); |
1128 | if (!err) | ||
1094 | break; | 1129 | break; |
1095 | printk(KERN_ERR "workqueue [%s] for %i failed\n", | 1130 | printk(KERN_ERR "workqueue [%s] for %i failed\n", |
1096 | wq->name, cpu); | 1131 | wq->name, cpu); |
1097 | action = CPU_UP_CANCELED; | 1132 | action = CPU_UP_CANCELED; |
1098 | ret = NOTIFY_BAD; | 1133 | err = -ENOMEM; |
1099 | goto undo; | 1134 | goto undo; |
1100 | 1135 | ||
1101 | case CPU_ONLINE: | 1136 | case CPU_ONLINE: |
@@ -1116,7 +1151,7 @@ undo: | |||
1116 | cpumask_clear_cpu(cpu, cpu_populated_map); | 1151 | cpumask_clear_cpu(cpu, cpu_populated_map); |
1117 | } | 1152 | } |
1118 | 1153 | ||
1119 | return ret; | 1154 | return notifier_from_errno(err); |
1120 | } | 1155 | } |
1121 | 1156 | ||
1122 | #ifdef CONFIG_SMP | 1157 | #ifdef CONFIG_SMP |