Skip to content

Commit

Permalink
completion: Replace spin_unlock_wait() with lock/unlock pair
Browse files Browse the repository at this point in the history
There is no agreed-upon definition of spin_unlock_wait()'s semantics,
and it appears that all callers could do just as well with a lock/unlock
pair.  This commit therefore replaces the spin_unlock_wait() call in
completion_done() with spin_lock() followed immediately by spin_unlock().
This should be safe from a performance perspective because the lock
will be held only the wakeup happens really quickly.

Signed-off-by: Paul E. McKenney <[email protected]>
Cc: Ingo Molnar <[email protected]>
Cc: Peter Zijlstra <[email protected]>
Cc: Will Deacon <[email protected]>
Cc: Alan Stern <[email protected]>
Cc: Andrea Parri <[email protected]>
Cc: Linus Torvalds <[email protected]>
Reviewed-by: Steven Rostedt (VMware) <[email protected]>
  • Loading branch information
paulmck committed Aug 17, 2017
1 parent 23a9b74 commit dec13c4
Showing 1 changed file with 4 additions and 7 deletions.
11 changes: 4 additions & 7 deletions kernel/sched/completion.c
Original file line number Diff line number Diff line change
Expand Up @@ -300,21 +300,18 @@ EXPORT_SYMBOL(try_wait_for_completion);
*/
bool completion_done(struct completion *x)
{
unsigned long flags;

if (!READ_ONCE(x->done))
return false;

/*
* If ->done, we need to wait for complete() to release ->wait.lock
* otherwise we can end up freeing the completion before complete()
* is done referencing it.
*
* The RMB pairs with complete()'s RELEASE of ->wait.lock and orders
* the loads of ->done and ->wait.lock such that we cannot observe
* the lock before complete() acquires it while observing the ->done
* after it's acquired the lock.
*/
smp_rmb();
spin_unlock_wait(&x->wait.lock);
spin_lock_irqsave(&x->wait.lock, flags);
spin_unlock_irqrestore(&x->wait.lock, flags);
return true;
}
EXPORT_SYMBOL(completion_done);

0 comments on commit dec13c4

Please sign in to comment.