Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 8198f75d authored by Linux Build Service Account's avatar Linux Build Service Account Committed by Gerrit - the friendly Code Review server
Browse files

Merge "rwsem: fix missed wakeup due to reordering of load"

parents 7aaa3c34 c2878c13
Loading
Loading
Loading
Loading
+35 −0
Original line number Diff line number Diff line
@@ -510,6 +510,41 @@ struct rw_semaphore *rwsem_wake(struct rw_semaphore *sem)
{
	unsigned long flags;

	/*
	 * If a spinner is present, there is a chance that the load of
	 * rwsem_has_spinner() in rwsem_wake() can be reordered with
	 * respect to decrement of rwsem count in __up_write() leading
	 * to wakeup being missed.
	 *
	 * spinning writer                  up_write caller
	 * ---------------                  -----------------------
	 * [S] osq_unlock()                 [L] osq
	 *  spin_lock(wait_lock)
	 *  sem->count=0xFFFFFFFF00000001
	 *            +0xFFFFFFFF00000000
	 *  count=sem->count
	 *  MB
	 *                                   sem->count=0xFFFFFFFE00000001
	 *                                             -0xFFFFFFFF00000001
	 *                                   RMB
	 *                                   spin_trylock(wait_lock)
	 *                                   return
	 * rwsem_try_write_lock(count)
	 * spin_unlock(wait_lock)
	 * schedule()
	 *
	 * Reordering of atomic_long_sub_return_release() in __up_write()
	 * and rwsem_has_spinner() in rwsem_wake() can cause missing of
	 * wakeup in up_write() context. In spinning writer, sem->count
	 * and local variable count is 0XFFFFFFFE00000001. It would result
	 * in rwsem_try_write_lock() failing to acquire rwsem and spinning
	 * writer going to sleep in rwsem_down_write_failed().
	 *
	 * The smp_rmb() here is to make sure that the spinner state is
	 * consulted after sem->count is updated in up_write context.
	 */
	smp_rmb();

	/*
	 * If a spinner is present, it is not necessary to do the wakeup.
	 * Try to do wakeup only if the trylock succeeds to minimize