1 /* SPDX-License-Identifier: GPL-2.0 */ 1 2 3 /* 4 * 'Generic' ticket-lock implementation. 5 * 6 * It relies on atomic_fetch_add() having well 7 * guarantees under contention. If your archit 8 * to a test-and-set lock. 9 * 10 * It also relies on atomic_fetch_add() being 11 * sub-word of the value. This is generally tr 12 * you'd be hard pressed to find anything usef 13 * about this. If your architecture cannot do 14 * a test-and-set. 15 * 16 * It further assumes atomic_*_release() + ato 17 * uses atomic_fetch_add() which is RCsc to cr 18 * a full fence after the spin to upgrade the 19 * atomic_cond_read_acquire(). 20 * 21 * The implementation uses smp_cond_load_acqui 22 * architecture has WFE like instructions to s 23 * modifications be sure to implement that (se 24 * 25 */ 26 27 #ifndef __ASM_GENERIC_SPINLOCK_H 28 #define __ASM_GENERIC_SPINLOCK_H 29 30 #include <linux/atomic.h> 31 #include <asm-generic/spinlock_types.h> 32 33 static __always_inline void arch_spin_lock(arc 34 { 35 u32 val = atomic_fetch_add(1<<16, lock 36 u16 ticket = val >> 16; 37 38 if (ticket == (u16)val) 39 return; 40 41 /* 42 * atomic_cond_read_acquire() is RCpc, 43 * custom cond_read_rcsc() here we jus 44 * need the prior reads before subsequ 45 * smb_mb(), but as atomic_cond_read_a 46 * have no outstanding writes due to t 47 * orderings are free. 48 */ 49 atomic_cond_read_acquire(lock, ticket 50 smp_mb(); 51 } 52 53 static __always_inline bool arch_spin_trylock( 54 { 55 u32 old = atomic_read(lock); 56 57 if ((old >> 16) != (old & 0xffff)) 58 return false; 59 60 return atomic_try_cmpxchg(lock, &old, 61 } 62 63 static __always_inline void arch_spin_unlock(a 64 { 65 u16 *ptr = (u16 *)lock + IS_ENABLED(CO 66 u32 val = atomic_read(lock); 67 68 smp_store_release(ptr, (u16)val + 1); 69 } 70 71 static __always_inline int arch_spin_value_unl 72 { 73 u32 val = lock.counter; 74 75 return ((val >> 16) == (val & 0xffff)) 76 } 77 78 static __always_inline int arch_spin_is_locked 79 { 80 arch_spinlock_t val = READ_ONCE(*lock) 81 82 return !arch_spin_value_unlocked(val); 83 } 84 85 static __always_inline int arch_spin_is_conten 86 { 87 u32 val = atomic_read(lock); 88 89 return (s16)((val >> 16) - (val & 0xff 90 } 91 92 #include <asm/qrwlock.h> 93 94 #endif /* __ASM_GENERIC_SPINLOCK_H */ 95
Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.