aboutsummaryrefslogtreecommitdiffstats
path: root/kernel
diff options
context:
space:
mode:
authorZhang Rui <rui.zhang@intel.com>2008-07-24 00:28:39 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2008-07-24 13:47:23 -0400
commitc1a220e7acf8ad2c03504891f4a70cd9c32c904b (patch)
tree902104a5a5debb5b881d7af4110ad1258ea5b0bd /kernel
parent0d83304c7e7bd3b05be90281b3a47841bc8f057a (diff)
pm: introduce new interfaces schedule_work_on() and queue_work_on()
This interface allows adding a job on a specific cpu. Although a work struct on a cpu will be scheduled to other cpu if the cpu dies, there is a recursion if a work task tries to offline the cpu it's running on. we need to schedule the task to a specific cpu in this case. http://bugzilla.kernel.org/show_bug.cgi?id=10897 [oleg@tv-sign.ru: cleanups] Signed-off-by: Zhang Rui <rui.zhang@intel.com> Tested-by: Rus <harbour@sfinx.od.ua> Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl> Acked-by: Pavel Machek <pavel@ucw.cz> Signed-off-by: Oleg Nesterov <oleg@tv-sign.ru> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'kernel')
-rw-r--r--kernel/workqueue.c39
1 files changed, 38 insertions, 1 deletions
diff --git a/kernel/workqueue.c b/kernel/workqueue.c
index a6d36346d10a..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. */
144static void __queue_work(struct cpu_workqueue_struct *cwq, 143static 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}
176EXPORT_SYMBOL_GPL(queue_work); 175EXPORT_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 */
188int
189queue_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}
200EXPORT_SYMBOL_GPL(queue_work_on);
201
178static void delayed_work_timer_fn(unsigned long __data) 202static 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;
@@ -553,6 +577,19 @@ int schedule_work(struct work_struct *work)
553} 577}
554EXPORT_SYMBOL(schedule_work); 578EXPORT_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 */
587int schedule_work_on(int cpu, struct work_struct *work)
588{
589 return queue_work_on(cpu, keventd_wq, work);
590}
591EXPORT_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