diff options
author | Stephen Rothwell <sfr@canb.auug.org.au> | 2010-03-15 14:53:31 +1100 |
---|---|---|
committer | Stephen Rothwell <sfr@canb.auug.org.au> | 2010-03-15 14:53:31 +1100 |
commit | 98d18c7d511450cbaa9ee95cc8c3f22b6d1fe8b2 (patch) | |
tree | 5ccc33789f7453398adb8994a50f308edf297934 | |
parent | 506d00c3279189b46e3df8d384f2fd3cf3ed730d (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); |