diff options
Diffstat (limited to 'kernel/locking/rwsem-xadd.c')
| -rw-r--r-- | kernel/locking/rwsem-xadd.c | 28 | 
1 files changed, 28 insertions, 0 deletions
| diff --git a/kernel/locking/rwsem-xadd.c b/kernel/locking/rwsem-xadd.c index 02f660666ab8..e795908f3607 100644 --- a/kernel/locking/rwsem-xadd.c +++ b/kernel/locking/rwsem-xadd.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0  /* rwsem.c: R/W semaphores: contention handling functions   *   * Written by David Howells ([email protected]). @@ -613,6 +614,33 @@ struct rw_semaphore *rwsem_wake(struct rw_semaphore *sem)  	DEFINE_WAKE_Q(wake_q);  	/* +	* __rwsem_down_write_failed_common(sem) +	*   rwsem_optimistic_spin(sem) +	*     osq_unlock(sem->osq) +	*   ... +	*   atomic_long_add_return(&sem->count) +	* +	*      - VS - +	* +	*              __up_write() +	*                if (atomic_long_sub_return_release(&sem->count) < 0) +	*                  rwsem_wake(sem) +	*                    osq_is_locked(&sem->osq) +	* +	* And __up_write() must observe !osq_is_locked() when it observes the +	* atomic_long_add_return() in order to not miss a wakeup. +	* +	* This boils down to: +	* +	* [S.rel] X = 1                [RmW] r0 = (Y += 0) +	*         MB                         RMB +	* [RmW]   Y += 1               [L]   r1 = X +	* +	* exists (r0=1 /\ r1=0) +	*/ +	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  	 * spinlock contention which may introduce too much delay in the |