diff options
Diffstat (limited to 'kernel/workqueue.c')
-rw-r--r-- | kernel/workqueue.c | 45 |
1 files changed, 41 insertions, 4 deletions
diff --git a/kernel/workqueue.c b/kernel/workqueue.c index ce7799540c91..6fd158b21026 100644 --- a/kernel/workqueue.c +++ b/kernel/workqueue.c | |||
@@ -140,7 +140,6 @@ static void insert_work(struct cpu_workqueue_struct *cwq, | |||
140 | wake_up(&cwq->more_work); | 140 | wake_up(&cwq->more_work); |
141 | } | 141 | } |
142 | 142 | ||
143 | /* Preempt must be disabled. */ | ||
144 | static void __queue_work(struct cpu_workqueue_struct *cwq, | 143 | static void __queue_work(struct cpu_workqueue_struct *cwq, |
145 | struct work_struct *work) | 144 | struct work_struct *work) |
146 | { | 145 | { |
@@ -175,6 +174,31 @@ int queue_work(struct workqueue_struct *wq, struct work_struct *work) | |||
175 | } | 174 | } |
176 | EXPORT_SYMBOL_GPL(queue_work); | 175 | EXPORT_SYMBOL_GPL(queue_work); |
177 | 176 | ||
177 | /** | ||
178 | * queue_work_on - queue work on specific cpu | ||
179 | * @cpu: CPU number to execute work on | ||
180 | * @wq: workqueue to use | ||
181 | * @work: work to queue | ||
182 | * | ||
183 | * Returns 0 if @work was already on a queue, non-zero otherwise. | ||
184 | * | ||
185 | * We queue the work to a specific CPU, the caller must ensure it | ||
186 | * can't go away. | ||
187 | */ | ||
188 | int | ||
189 | queue_work_on(int cpu, struct workqueue_struct *wq, struct work_struct *work) | ||
190 | { | ||
191 | int ret = 0; | ||
192 | |||
193 | if (!test_and_set_bit(WORK_STRUCT_PENDING, work_data_bits(work))) { | ||
194 | BUG_ON(!list_empty(&work->entry)); | ||
195 | __queue_work(wq_per_cpu(wq, cpu), work); | ||
196 | ret = 1; | ||
197 | } | ||
198 | return ret; | ||
199 | } | ||
200 | EXPORT_SYMBOL_GPL(queue_work_on); | ||
201 | |||
178 | static void delayed_work_timer_fn(unsigned long __data) | 202 | static void delayed_work_timer_fn(unsigned long __data) |
179 | { | 203 | { |
180 | struct delayed_work *dwork = (struct delayed_work *)__data; | 204 | struct delayed_work *dwork = (struct delayed_work *)__data; |
@@ -397,7 +421,7 @@ void flush_workqueue(struct workqueue_struct *wq) | |||
397 | might_sleep(); | 421 | might_sleep(); |
398 | lock_acquire(&wq->lockdep_map, 0, 0, 0, 2, _THIS_IP_); | 422 | lock_acquire(&wq->lockdep_map, 0, 0, 0, 2, _THIS_IP_); |
399 | lock_release(&wq->lockdep_map, 1, _THIS_IP_); | 423 | lock_release(&wq->lockdep_map, 1, _THIS_IP_); |
400 | for_each_cpu_mask(cpu, *cpu_map) | 424 | for_each_cpu_mask_nr(cpu, *cpu_map) |
401 | flush_cpu_workqueue(per_cpu_ptr(wq->cpu_wq, cpu)); | 425 | flush_cpu_workqueue(per_cpu_ptr(wq->cpu_wq, cpu)); |
402 | } | 426 | } |
403 | EXPORT_SYMBOL_GPL(flush_workqueue); | 427 | EXPORT_SYMBOL_GPL(flush_workqueue); |
@@ -477,7 +501,7 @@ static void wait_on_work(struct work_struct *work) | |||
477 | wq = cwq->wq; | 501 | wq = cwq->wq; |
478 | cpu_map = wq_cpu_map(wq); | 502 | cpu_map = wq_cpu_map(wq); |
479 | 503 | ||
480 | for_each_cpu_mask(cpu, *cpu_map) | 504 | for_each_cpu_mask_nr(cpu, *cpu_map) |
481 | wait_on_cpu_work(per_cpu_ptr(wq->cpu_wq, cpu), work); | 505 | wait_on_cpu_work(per_cpu_ptr(wq->cpu_wq, cpu), work); |
482 | } | 506 | } |
483 | 507 | ||
@@ -553,6 +577,19 @@ int schedule_work(struct work_struct *work) | |||
553 | } | 577 | } |
554 | EXPORT_SYMBOL(schedule_work); | 578 | EXPORT_SYMBOL(schedule_work); |
555 | 579 | ||
580 | /* | ||
581 | * schedule_work_on - put work task on a specific cpu | ||
582 | * @cpu: cpu to put the work task on | ||
583 | * @work: job to be done | ||
584 | * | ||
585 | * This puts a job on a specific cpu | ||
586 | */ | ||
587 | int schedule_work_on(int cpu, struct work_struct *work) | ||
588 | { | ||
589 | return queue_work_on(cpu, keventd_wq, work); | ||
590 | } | ||
591 | EXPORT_SYMBOL(schedule_work_on); | ||
592 | |||
556 | /** | 593 | /** |
557 | * schedule_delayed_work - put work task in global workqueue after delay | 594 | * schedule_delayed_work - put work task in global workqueue after delay |
558 | * @dwork: job to be done | 595 | * @dwork: job to be done |
@@ -813,7 +850,7 @@ void destroy_workqueue(struct workqueue_struct *wq) | |||
813 | list_del(&wq->list); | 850 | list_del(&wq->list); |
814 | spin_unlock(&workqueue_lock); | 851 | spin_unlock(&workqueue_lock); |
815 | 852 | ||
816 | for_each_cpu_mask(cpu, *cpu_map) | 853 | for_each_cpu_mask_nr(cpu, *cpu_map) |
817 | cleanup_workqueue_thread(per_cpu_ptr(wq->cpu_wq, cpu)); | 854 | cleanup_workqueue_thread(per_cpu_ptr(wq->cpu_wq, cpu)); |
818 | put_online_cpus(); | 855 | put_online_cpus(); |
819 | 856 | ||