diff options
author | Stephen Rothwell <sfr@canb.auug.org.au> | 2010-03-24 15:07:45 +1100 |
---|---|---|
committer | Stephen Rothwell <sfr@canb.auug.org.au> | 2010-03-24 15:07:45 +1100 |
commit | 6cf4ec0bb8e695b2ea72d11f8ef84cd54dc0d166 (patch) | |
tree | 14d27aa938d7d4ccb387b6127c35a6932ba4466a | |
parent | fe2d20190f29750f68b56daa975c98169238dc92 (diff) | |
parent | 5ab0fec5e715dd22e9d30d9f2eb1f0bbb05fb001 (diff) |
Merge remote branch 'workqueues/for-next'
-rw-r--r-- | kernel/workqueue.c | 27 |
1 files changed, 26 insertions, 1 deletions
diff --git a/kernel/workqueue.c b/kernel/workqueue.c index dee48658805c..b156dd6c87f3 100644 --- a/kernel/workqueue.c +++ b/kernel/workqueue.c @@ -482,7 +482,8 @@ static int flush_cpu_workqueue(struct cpu_workqueue_struct *cwq) int active = 0; struct wq_barrier barr; - WARN_ON(cwq->thread == current); + if (WARN_ON(cwq->thread == current)) + return 1; spin_lock_irq(&cwq->lock); if (!list_empty(&cwq->worklist) || cwq->current_work != NULL) { @@ -845,6 +846,30 @@ int schedule_on_each_cpu(work_func_t func) return 0; } +/** + * flush_scheduled_work - ensure that any scheduled work has run to completion. + * + * Forces execution of the kernel-global workqueue and blocks until its + * completion. + * + * Think twice before calling this function! It's very easy to get into + * trouble if you don't take great care. Either of the following situations + * will lead to deadlock: + * + * One of the work items currently on the workqueue needs to acquire + * a lock held by your code or its caller. + * + * Your code is running in the context of a work routine. + * + * They will be detected by lockdep when they occur, but the first might not + * occur very often. It depends on what work items are on the workqueue and + * what locks they need, which you have no control over. + * + * In most situations flushing the entire workqueue is overkill; you merely + * need to know that a particular work item isn't queued and isn't running. + * In such cases you should use cancel_delayed_work_sync() or + * cancel_work_sync() instead. + */ void flush_scheduled_work(void) { flush_workqueue(keventd_wq); |