summaryrefslogtreecommitdiffstats
path: root/kernel/sched/completion.c
diff options
context:
space:
mode:
authorByungchul Park <byungchul.park@lge.com>2017-08-07 09:12:56 +0200
committerIngo Molnar <mingo@kernel.org>2017-08-10 12:29:10 +0200
commitcd8084f91c02c1afd256a39aa833bff737631304 (patch)
treea2eb7a1ce13798602affca1f244dbccc583b3952 /kernel/sched/completion.c
parentlocking/lockdep: Make print_circular_bug() aware of crossrelease (diff)
downloadlinux-cd8084f91c02c1afd256a39aa833bff737631304.tar.xz
linux-cd8084f91c02c1afd256a39aa833bff737631304.zip
locking/lockdep: Apply crossrelease to completions
Although wait_for_completion() and its family can cause deadlock, the lock correctness validator could not be applied to them until now, because things like complete() are usually called in a different context from the waiting context, which violates lockdep's assumption. Thanks to CONFIG_LOCKDEP_CROSSRELEASE, we can now apply the lockdep detector to those completion operations. Applied it. Signed-off-by: Byungchul Park <byungchul.park@lge.com> Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org> Cc: Linus Torvalds <torvalds@linux-foundation.org> Cc: Peter Zijlstra <peterz@infradead.org> Cc: Thomas Gleixner <tglx@linutronix.de> Cc: akpm@linux-foundation.org Cc: boqun.feng@gmail.com Cc: kernel-team@lge.com Cc: kirill@shutemov.name Cc: npiggin@gmail.com Cc: walken@google.com Cc: willy@infradead.org Link: http://lkml.kernel.org/r/1502089981-21272-10-git-send-email-byungchul.park@lge.com Signed-off-by: Ingo Molnar <mingo@kernel.org>
Diffstat (limited to 'kernel/sched/completion.c')
-rw-r--r--kernel/sched/completion.c11
1 files changed, 11 insertions, 0 deletions
diff --git a/kernel/sched/completion.c b/kernel/sched/completion.c
index 13fc5ae9bf2f..566b6ec7b6fe 100644
--- a/kernel/sched/completion.c
+++ b/kernel/sched/completion.c
@@ -32,6 +32,12 @@ void complete(struct completion *x)
unsigned long flags;
spin_lock_irqsave(&x->wait.lock, flags);
+
+ /*
+ * Perform commit of crossrelease here.
+ */
+ complete_release_commit(x);
+
if (x->done != UINT_MAX)
x->done++;
__wake_up_locked(&x->wait, TASK_NORMAL, 1);
@@ -92,9 +98,14 @@ __wait_for_common(struct completion *x,
{
might_sleep();
+ complete_acquire(x);
+
spin_lock_irq(&x->wait.lock);
timeout = do_wait_for_common(x, action, timeout, state);
spin_unlock_irq(&x->wait.lock);
+
+ complete_release(x);
+
return timeout;
}