aboutsummaryrefslogtreecommitdiffstats
path: root/kernel/workqueue.c
diff options
context:
space:
mode:
authorTejun Heo <tj@kernel.org>2012-08-03 13:30:47 -0400
committerTejun Heo <tj@kernel.org>2012-08-03 13:30:47 -0400
commit8376fe22c7e79c7e90857d39f82aeae6cad6c4b8 (patch)
tree3a77fda11324a25abfe1ffe3ea0eba28a4fac03f /kernel/workqueue.c
parentbbb68dfaba73e8338fe0f1dc711cc1d261daec87 (diff)
workqueue: implement mod_delayed_work[_on]()
Workqueue was lacking a mechanism to modify the timeout of an already pending delayed_work. delayed_work users have been working around this using several methods - using an explicit timer + work item, messing directly with delayed_work->timer, and canceling before re-queueing, all of which are error-prone and/or ugly. This patch implements mod_delayed_work[_on]() which behaves similarly to mod_timer() - if the delayed_work is idle, it's queued with the given delay; otherwise, its timeout is modified to the new value. Zero @delay guarantees immediate execution. v2: Updated to reflect try_to_grab_pending() changes. Now safe to be called from bh context. Signed-off-by: Tejun Heo <tj@kernel.org> Cc: Linus Torvalds <torvalds@linux-foundation.org> Cc: Andrew Morton <akpm@linux-foundation.org> Cc: Ingo Molnar <mingo@redhat.com>
Diffstat (limited to 'kernel/workqueue.c')
-rw-r--r--kernel/workqueue.c53
1 files changed, 53 insertions, 0 deletions
diff --git a/kernel/workqueue.c b/kernel/workqueue.c
index b4a4e05c89e1..41ae2c0979fe 100644
--- a/kernel/workqueue.c
+++ b/kernel/workqueue.c
@@ -1414,6 +1414,59 @@ bool queue_delayed_work(struct workqueue_struct *wq,
1414EXPORT_SYMBOL_GPL(queue_delayed_work); 1414EXPORT_SYMBOL_GPL(queue_delayed_work);
1415 1415
1416/** 1416/**
1417 * mod_delayed_work_on - modify delay of or queue a delayed work on specific CPU
1418 * @cpu: CPU number to execute work on
1419 * @wq: workqueue to use
1420 * @dwork: work to queue
1421 * @delay: number of jiffies to wait before queueing
1422 *
1423 * If @dwork is idle, equivalent to queue_delayed_work_on(); otherwise,
1424 * modify @dwork's timer so that it expires after @delay. If @delay is
1425 * zero, @work is guaranteed to be scheduled immediately regardless of its
1426 * current state.
1427 *
1428 * Returns %false if @dwork was idle and queued, %true if @dwork was
1429 * pending and its timer was modified.
1430 *
1431 * This function is safe to call from any context other than IRQ handler.
1432 * See try_to_grab_pending() for details.
1433 */
1434bool mod_delayed_work_on(int cpu, struct workqueue_struct *wq,
1435 struct delayed_work *dwork, unsigned long delay)
1436{
1437 unsigned long flags;
1438 int ret;
1439
1440 do {
1441 ret = try_to_grab_pending(&dwork->work, true, &flags);
1442 } while (unlikely(ret == -EAGAIN));
1443
1444 if (likely(ret >= 0)) {
1445 __queue_delayed_work(cpu, wq, dwork, delay);
1446 local_irq_restore(flags);
1447 }
1448
1449 /* -ENOENT from try_to_grab_pending() becomes %true */
1450 return ret;
1451}
1452EXPORT_SYMBOL_GPL(mod_delayed_work_on);
1453
1454/**
1455 * mod_delayed_work - modify delay of or queue a delayed work
1456 * @wq: workqueue to use
1457 * @dwork: work to queue
1458 * @delay: number of jiffies to wait before queueing
1459 *
1460 * mod_delayed_work_on() on local CPU.
1461 */
1462bool mod_delayed_work(struct workqueue_struct *wq, struct delayed_work *dwork,
1463 unsigned long delay)
1464{
1465 return mod_delayed_work_on(WORK_CPU_UNBOUND, wq, dwork, delay);
1466}
1467EXPORT_SYMBOL_GPL(mod_delayed_work);
1468
1469/**
1417 * worker_enter_idle - enter idle state 1470 * worker_enter_idle - enter idle state
1418 * @worker: worker which is entering idle state 1471 * @worker: worker which is entering idle state
1419 * 1472 *