Commit 593d2759 authored by Alex Kogan's avatar Alex Kogan Committed by Wei Li
Browse files

locking/qspinlock: Refactor the qspinlock slow path

maillist inclusion
category: feature
bugzilla: https://gitee.com/openeuler/kernel/issues/I8T8XV

Reference: https://lore.kernel.org/linux-arm-kernel/20210514200743.3026725-3-alex.kogan@oracle.com



--------------------------------

Move some of the code manipulating the spin lock into separate functions.
This would allow easier integration of alternative ways to manipulate
that lock.

Signed-off-by: default avatarAlex Kogan <alex.kogan@oracle.com>
Reviewed-by: default avatarSteve Sistare <steven.sistare@oracle.com>
Reviewed-by: default avatarWaiman Long <longman@redhat.com>
Signed-off-by: default avatarWei Li <liwei391@huawei.com>
parent a1aced2b
Loading
Loading
Loading
Loading
+36 −2
Original line number Diff line number Diff line
@@ -290,6 +290,34 @@ static __always_inline u32 __pv_wait_head_or_lock(struct qspinlock *lock,
#define queued_spin_lock_slowpath	native_queued_spin_lock_slowpath
#endif

/*
 * __try_clear_tail - try to clear tail by setting the lock value to
 * _Q_LOCKED_VAL.
 * @lock: Pointer to the queued spinlock structure
 * @val: Current value of the lock
 * @node: Pointer to the MCS node of the lock holder
 */
static __always_inline bool __try_clear_tail(struct qspinlock *lock,
					     u32 val,
					     struct mcs_spinlock *node)
{
	return atomic_try_cmpxchg_relaxed(&lock->val, &val, _Q_LOCKED_VAL);
}

/*
 * __mcs_lock_handoff - pass the MCS lock to the next waiter
 * @node: Pointer to the MCS node of the lock holder
 * @next: Pointer to the MCS node of the first waiter in the MCS queue
 */
static __always_inline void __mcs_lock_handoff(struct mcs_spinlock *node,
					       struct mcs_spinlock *next)
{
	arch_mcs_lock_handoff(&next->locked, 1);
}

#define try_clear_tail		__try_clear_tail
#define mcs_lock_handoff	__mcs_lock_handoff

#endif /* _GEN_PV_LOCK_SLOWPATH */

/**
@@ -536,7 +564,7 @@ void __lockfunc queued_spin_lock_slowpath(struct qspinlock *lock, u32 val)
	 *       PENDING will make the uncontended transition fail.
	 */
	if ((val & _Q_TAIL_MASK) == tail) {
		if (atomic_try_cmpxchg_relaxed(&lock->val, &val, _Q_LOCKED_VAL))
		if (try_clear_tail(lock, val, node))
			goto release; /* No contention */
	}

@@ -553,7 +581,7 @@ void __lockfunc queued_spin_lock_slowpath(struct qspinlock *lock, u32 val)
	if (!next)
		next = smp_cond_load_relaxed(&node->next, (VAL));

	arch_mcs_lock_handoff(&next->locked, 1);
	mcs_lock_handoff(node, next);
	pv_kick_node(lock, next);

release:
@@ -580,6 +608,12 @@ EXPORT_SYMBOL(queued_spin_lock_slowpath);
#undef pv_kick_node
#undef pv_wait_head_or_lock

#undef try_clear_tail
#define try_clear_tail		__try_clear_tail

#undef mcs_lock_handoff
#define mcs_lock_handoff			__mcs_lock_handoff

#undef  queued_spin_lock_slowpath
#define queued_spin_lock_slowpath	__pv_queued_spin_lock_slowpath