diff options
Diffstat (limited to 'kernel/locking/rwsem-xadd.c')
-rw-r--r-- | kernel/locking/rwsem-xadd.c | 27 |
1 files changed, 27 insertions, 0 deletions
diff --git a/kernel/locking/rwsem-xadd.c b/kernel/locking/rwsem-xadd.c index 02f660666ab8..1fefe6dcafd7 100644 --- a/kernel/locking/rwsem-xadd.c +++ b/kernel/locking/rwsem-xadd.c | |||
@@ -613,6 +613,33 @@ struct rw_semaphore *rwsem_wake(struct rw_semaphore *sem) | |||
613 | DEFINE_WAKE_Q(wake_q); | 613 | DEFINE_WAKE_Q(wake_q); |
614 | 614 | ||
615 | /* | 615 | /* |
616 | * __rwsem_down_write_failed_common(sem) | ||
617 | * rwsem_optimistic_spin(sem) | ||
618 | * osq_unlock(sem->osq) | ||
619 | * ... | ||
620 | * atomic_long_add_return(&sem->count) | ||
621 | * | ||
622 | * - VS - | ||
623 | * | ||
624 | * __up_write() | ||
625 | * if (atomic_long_sub_return_release(&sem->count) < 0) | ||
626 | * rwsem_wake(sem) | ||
627 | * osq_is_locked(&sem->osq) | ||
628 | * | ||
629 | * And __up_write() must observe !osq_is_locked() when it observes the | ||
630 | * atomic_long_add_return() in order to not miss a wakeup. | ||
631 | * | ||
632 | * This boils down to: | ||
633 | * | ||
634 | * [S.rel] X = 1 [RmW] r0 = (Y += 0) | ||
635 | * MB RMB | ||
636 | * [RmW] Y += 1 [L] r1 = X | ||
637 | * | ||
638 | * exists (r0=1 /\ r1=0) | ||
639 | */ | ||
640 | smp_rmb(); | ||
641 | |||
642 | /* | ||
616 | * If a spinner is present, it is not necessary to do the wakeup. | 643 | * If a spinner is present, it is not necessary to do the wakeup. |
617 | * Try to do wakeup only if the trylock succeeds to minimize | 644 | * Try to do wakeup only if the trylock succeeds to minimize |
618 | * spinlock contention which may introduce too much delay in the | 645 | * spinlock contention which may introduce too much delay in the |