Branch data Line data Source code
1 : : /* SPDX-License-Identifier: GPL-2.0-or-later */ 2 : : /* 3 : : * Queued spinlock 4 : : * 5 : : * (C) Copyright 2013-2015 Hewlett-Packard Development Company, L.P. 6 : : * (C) Copyright 2015 Hewlett-Packard Enterprise Development LP 7 : : * 8 : : * Authors: Waiman Long <waiman.long@hpe.com> 9 : : */ 10 : : #ifndef __ASM_GENERIC_QSPINLOCK_H 11 : : #define __ASM_GENERIC_QSPINLOCK_H 12 : : 13 : : #include <asm-generic/qspinlock_types.h> 14 : : 15 : : /** 16 : : * queued_spin_is_locked - is the spinlock locked? 17 : : * @lock: Pointer to queued spinlock structure 18 : : * Return: 1 if it is locked, 0 otherwise 19 : : */ 20 : 1152353 : static __always_inline int queued_spin_is_locked(struct qspinlock *lock) 21 : : { 22 : : /* 23 : : * Any !0 state indicates it is locked, even if _Q_LOCKED_VAL 24 : : * isn't immediately observable. 25 : : */ 26 : 1152353 : return atomic_read(&lock->val); 27 : : } 28 : : 29 : : /** 30 : : * queued_spin_value_unlocked - is the spinlock structure unlocked? 31 : : * @lock: queued spinlock structure 32 : : * Return: 1 if it is unlocked, 0 otherwise 33 : : * 34 : : * N.B. Whenever there are tasks waiting for the lock, it is considered 35 : : * locked wrt the lockref code to avoid lock stealing by the lockref 36 : : * code and change things underneath the lock. This also allows some 37 : : * optimizations to be applied without conflict with lockref. 38 : : */ 39 : 18114221 : static __always_inline int queued_spin_value_unlocked(struct qspinlock lock) 40 : : { 41 [ + - + - : 18114221 : return !atomic_read(&lock.val); + - - - - - + - + - ] 42 : : } 43 : : 44 : : /** 45 : : * queued_spin_is_contended - check if the lock is contended 46 : : * @lock : Pointer to queued spinlock structure 47 : : * Return: 1 if lock contended, 0 otherwise 48 : : */ 49 : 30657 : static __always_inline int queued_spin_is_contended(struct qspinlock *lock) 50 : : { 51 [ + - ]: 30657 : return atomic_read(&lock->val) & ~_Q_LOCKED_MASK; 52 : : } 53 : : /** 54 : : * queued_spin_trylock - try to acquire the queued spinlock 55 : : * @lock : Pointer to queued spinlock structure 56 : : * Return: 1 if lock acquired, 0 if failed 57 : : */ 58 : 489421 : static __always_inline int queued_spin_trylock(struct qspinlock *lock) 59 : : { 60 [ # # ]: 489421 : u32 val = atomic_read(&lock->val); 61 : : 62 [ + - # # ]: 489421 : if (unlikely(val)) 63 : : return 0; 64 : : 65 [ # # # # ]: 489421 : return likely(atomic_try_cmpxchg_acquire(&lock->val, &val, _Q_LOCKED_VAL)); 66 : : } 67 : : 68 : : extern void queued_spin_lock_slowpath(struct qspinlock *lock, u32 val); 69 : : 70 : : /** 71 : : * queued_spin_lock - acquire a queued spinlock 72 : : * @lock: Pointer to queued spinlock structure 73 : : */ 74 : 33650060 : static __always_inline void queued_spin_lock(struct qspinlock *lock) 75 : : { 76 : 33650060 : u32 val = 0; 77 : : 78 [ + - # # : 33650060 : if (likely(atomic_try_cmpxchg_acquire(&lock->val, &val, _Q_LOCKED_VAL))) # # # # # # # # # # ] 79 : 33650060 : return; 80 : : 81 : 0 : queued_spin_lock_slowpath(lock, val); 82 : : } 83 : : 84 : : #ifndef queued_spin_unlock 85 : : /** 86 : : * queued_spin_unlock - release a queued spinlock 87 : : * @lock : Pointer to queued spinlock structure 88 : : */ 89 : 60966216 : static __always_inline void queued_spin_unlock(struct qspinlock *lock) 90 : : { 91 : : /* 92 : : * unlock() needs release semantics: 93 : : */ 94 [ # # ]: 60793166 : smp_store_release(&lock->locked, 0); 95 : 0 : } 96 : : #endif 97 : : 98 : : #ifndef virt_spin_lock 99 : : static __always_inline bool virt_spin_lock(struct qspinlock *lock) 100 : : { 101 : : return false; 102 : : } 103 : : #endif 104 : : 105 : : /* 106 : : * Remapping spinlock architecture specific functions to the corresponding 107 : : * queued spinlock functions. 108 : : */ 109 : : #define arch_spin_is_locked(l) queued_spin_is_locked(l) 110 : : #define arch_spin_is_contended(l) queued_spin_is_contended(l) 111 : : #define arch_spin_value_unlocked(l) queued_spin_value_unlocked(l) 112 : : #define arch_spin_lock(l) queued_spin_lock(l) 113 : : #define arch_spin_trylock(l) queued_spin_trylock(l) 114 : : #define arch_spin_unlock(l) queued_spin_unlock(l) 115 : : 116 : : #endif /* __ASM_GENERIC_QSPINLOCK_H */