mirror of
git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2025-08-05 16:54:27 +00:00

'struct __qspinlock' provides a handy union of fields so that subcomponents of the lockword can be accessed by name, without having to manage shifts and masks explicitly and take endianness into account. This is useful in qspinlock.h and also potentially in arch headers, so move the 'struct __qspinlock' into 'struct qspinlock' and kill the extra definition. Signed-off-by: Will Deacon <will.deacon@arm.com> Acked-by: Peter Zijlstra (Intel) <peterz@infradead.org> Acked-by: Waiman Long <longman@redhat.com> Acked-by: Boqun Feng <boqun.feng@gmail.com> Cc: Linus Torvalds <torvalds@linux-foundation.org> Cc: Thomas Gleixner <tglx@linutronix.de> Cc: linux-arm-kernel@lists.infradead.org Cc: paulmck@linux.vnet.ibm.com Link: http://lkml.kernel.org/r/1524738868-31318-3-git-send-email-will.deacon@arm.com Signed-off-by: Ingo Molnar <mingo@kernel.org>
82 lines
2 KiB
C
82 lines
2 KiB
C
/* SPDX-License-Identifier: GPL-2.0 */
|
|
#ifndef _ASM_X86_QSPINLOCK_H
|
|
#define _ASM_X86_QSPINLOCK_H
|
|
|
|
#include <linux/jump_label.h>
|
|
#include <asm/cpufeature.h>
|
|
#include <asm-generic/qspinlock_types.h>
|
|
#include <asm/paravirt.h>
|
|
|
|
#define queued_spin_unlock queued_spin_unlock
|
|
/**
|
|
* queued_spin_unlock - release a queued spinlock
|
|
* @lock : Pointer to queued spinlock structure
|
|
*
|
|
* A smp_store_release() on the least-significant byte.
|
|
*/
|
|
static inline void native_queued_spin_unlock(struct qspinlock *lock)
|
|
{
|
|
smp_store_release(&lock->locked, 0);
|
|
}
|
|
|
|
#ifdef CONFIG_PARAVIRT_SPINLOCKS
|
|
extern void native_queued_spin_lock_slowpath(struct qspinlock *lock, u32 val);
|
|
extern void __pv_init_lock_hash(void);
|
|
extern void __pv_queued_spin_lock_slowpath(struct qspinlock *lock, u32 val);
|
|
extern void __raw_callee_save___pv_queued_spin_unlock(struct qspinlock *lock);
|
|
|
|
static inline void queued_spin_lock_slowpath(struct qspinlock *lock, u32 val)
|
|
{
|
|
pv_queued_spin_lock_slowpath(lock, val);
|
|
}
|
|
|
|
static inline void queued_spin_unlock(struct qspinlock *lock)
|
|
{
|
|
pv_queued_spin_unlock(lock);
|
|
}
|
|
|
|
#define vcpu_is_preempted vcpu_is_preempted
|
|
static inline bool vcpu_is_preempted(long cpu)
|
|
{
|
|
return pv_vcpu_is_preempted(cpu);
|
|
}
|
|
#else
|
|
static inline void queued_spin_unlock(struct qspinlock *lock)
|
|
{
|
|
native_queued_spin_unlock(lock);
|
|
}
|
|
#endif
|
|
|
|
#ifdef CONFIG_PARAVIRT
|
|
DECLARE_STATIC_KEY_TRUE(virt_spin_lock_key);
|
|
|
|
void native_pv_lock_init(void) __init;
|
|
|
|
#define virt_spin_lock virt_spin_lock
|
|
static inline bool virt_spin_lock(struct qspinlock *lock)
|
|
{
|
|
if (!static_branch_likely(&virt_spin_lock_key))
|
|
return false;
|
|
|
|
/*
|
|
* On hypervisors without PARAVIRT_SPINLOCKS support we fall
|
|
* back to a Test-and-Set spinlock, because fair locks have
|
|
* horrible lock 'holder' preemption issues.
|
|
*/
|
|
|
|
do {
|
|
while (atomic_read(&lock->val) != 0)
|
|
cpu_relax();
|
|
} while (atomic_cmpxchg(&lock->val, 0, _Q_LOCKED_VAL) != 0);
|
|
|
|
return true;
|
|
}
|
|
#else
|
|
static inline void native_pv_lock_init(void)
|
|
{
|
|
}
|
|
#endif /* CONFIG_PARAVIRT */
|
|
|
|
#include <asm-generic/qspinlock.h>
|
|
|
|
#endif /* _ASM_X86_QSPINLOCK_H */
|