xref: /openbmc/linux/include/linux/bit_spinlock.h (revision b2441318)
1b2441318SGreg Kroah-Hartman /* SPDX-License-Identifier: GPL-2.0 */
2fb1c8f93SIngo Molnar #ifndef __LINUX_BIT_SPINLOCK_H
3fb1c8f93SIngo Molnar #define __LINUX_BIT_SPINLOCK_H
4fb1c8f93SIngo Molnar 
5626d6074SNick Piggin #include <linux/kernel.h>
6626d6074SNick Piggin #include <linux/preempt.h>
760063497SArun Sharma #include <linux/atomic.h>
8187f1882SPaul Gortmaker #include <linux/bug.h>
9626d6074SNick Piggin 
10fb1c8f93SIngo Molnar /*
11fb1c8f93SIngo Molnar  *  bit-based spin_lock()
12fb1c8f93SIngo Molnar  *
13fb1c8f93SIngo Molnar  * Don't use this unless you really need to: spin_lock() and spin_unlock()
14fb1c8f93SIngo Molnar  * are significantly faster.
15fb1c8f93SIngo Molnar  */
bit_spin_lock(int bitnum,unsigned long * addr)16fb1c8f93SIngo Molnar static inline void bit_spin_lock(int bitnum, unsigned long *addr)
17fb1c8f93SIngo Molnar {
18fb1c8f93SIngo Molnar 	/*
19fb1c8f93SIngo Molnar 	 * Assuming the lock is uncontended, this never enters
20fb1c8f93SIngo Molnar 	 * the body of the outer loop. If it is contended, then
21fb1c8f93SIngo Molnar 	 * within the inner loop a non-atomic test is used to
22fb1c8f93SIngo Molnar 	 * busywait with less bus contention for a good time to
23fb1c8f93SIngo Molnar 	 * attempt to acquire the lock bit.
24fb1c8f93SIngo Molnar 	 */
25fb1c8f93SIngo Molnar 	preempt_disable();
26fb1c8f93SIngo Molnar #if defined(CONFIG_SMP) || defined(CONFIG_DEBUG_SPINLOCK)
27b8dc93cbSNick Piggin 	while (unlikely(test_and_set_bit_lock(bitnum, addr))) {
28fb1c8f93SIngo Molnar 		preempt_enable();
293dd2ee48SLinus Torvalds 		do {
30fb1c8f93SIngo Molnar 			cpu_relax();
313dd2ee48SLinus Torvalds 		} while (test_bit(bitnum, addr));
32fb1c8f93SIngo Molnar 		preempt_disable();
33fb1c8f93SIngo Molnar 	}
34fb1c8f93SIngo Molnar #endif
35fb1c8f93SIngo Molnar 	__acquire(bitlock);
36fb1c8f93SIngo Molnar }
37fb1c8f93SIngo Molnar 
38fb1c8f93SIngo Molnar /*
39fb1c8f93SIngo Molnar  * Return true if it was acquired
40fb1c8f93SIngo Molnar  */
bit_spin_trylock(int bitnum,unsigned long * addr)41fb1c8f93SIngo Molnar static inline int bit_spin_trylock(int bitnum, unsigned long *addr)
42fb1c8f93SIngo Molnar {
43fb1c8f93SIngo Molnar 	preempt_disable();
44fb1c8f93SIngo Molnar #if defined(CONFIG_SMP) || defined(CONFIG_DEBUG_SPINLOCK)
45b8dc93cbSNick Piggin 	if (unlikely(test_and_set_bit_lock(bitnum, addr))) {
46fb1c8f93SIngo Molnar 		preempt_enable();
47fb1c8f93SIngo Molnar 		return 0;
48fb1c8f93SIngo Molnar 	}
49fb1c8f93SIngo Molnar #endif
50fb1c8f93SIngo Molnar 	__acquire(bitlock);
51fb1c8f93SIngo Molnar 	return 1;
52fb1c8f93SIngo Molnar }
53fb1c8f93SIngo Molnar 
54fb1c8f93SIngo Molnar /*
55fb1c8f93SIngo Molnar  *  bit-based spin_unlock()
56fb1c8f93SIngo Molnar  */
bit_spin_unlock(int bitnum,unsigned long * addr)57fb1c8f93SIngo Molnar static inline void bit_spin_unlock(int bitnum, unsigned long *addr)
58fb1c8f93SIngo Molnar {
59b8dc93cbSNick Piggin #ifdef CONFIG_DEBUG_SPINLOCK
60fb1c8f93SIngo Molnar 	BUG_ON(!test_bit(bitnum, addr));
61b8dc93cbSNick Piggin #endif
62b8dc93cbSNick Piggin #if defined(CONFIG_SMP) || defined(CONFIG_DEBUG_SPINLOCK)
63b8dc93cbSNick Piggin 	clear_bit_unlock(bitnum, addr);
64b8dc93cbSNick Piggin #endif
65b8dc93cbSNick Piggin 	preempt_enable();
66b8dc93cbSNick Piggin 	__release(bitlock);
67b8dc93cbSNick Piggin }
68b8dc93cbSNick Piggin 
69b8dc93cbSNick Piggin /*
70b8dc93cbSNick Piggin  *  bit-based spin_unlock()
71b8dc93cbSNick Piggin  *  non-atomic version, which can be used eg. if the bit lock itself is
72b8dc93cbSNick Piggin  *  protecting the rest of the flags in the word.
73b8dc93cbSNick Piggin  */
__bit_spin_unlock(int bitnum,unsigned long * addr)74b8dc93cbSNick Piggin static inline void __bit_spin_unlock(int bitnum, unsigned long *addr)
75b8dc93cbSNick Piggin {
76b8dc93cbSNick Piggin #ifdef CONFIG_DEBUG_SPINLOCK
77b8dc93cbSNick Piggin 	BUG_ON(!test_bit(bitnum, addr));
78b8dc93cbSNick Piggin #endif
79b8dc93cbSNick Piggin #if defined(CONFIG_SMP) || defined(CONFIG_DEBUG_SPINLOCK)
80b8dc93cbSNick Piggin 	__clear_bit_unlock(bitnum, addr);
81fb1c8f93SIngo Molnar #endif
82fb1c8f93SIngo Molnar 	preempt_enable();
83fb1c8f93SIngo Molnar 	__release(bitlock);
84fb1c8f93SIngo Molnar }
85fb1c8f93SIngo Molnar 
86fb1c8f93SIngo Molnar /*
87fb1c8f93SIngo Molnar  * Return true if the lock is held.
88fb1c8f93SIngo Molnar  */
bit_spin_is_locked(int bitnum,unsigned long * addr)89fb1c8f93SIngo Molnar static inline int bit_spin_is_locked(int bitnum, unsigned long *addr)
90fb1c8f93SIngo Molnar {
91fb1c8f93SIngo Molnar #if defined(CONFIG_SMP) || defined(CONFIG_DEBUG_SPINLOCK)
92fb1c8f93SIngo Molnar 	return test_bit(bitnum, addr);
93bdd4e85dSFrederic Weisbecker #elif defined CONFIG_PREEMPT_COUNT
94fb1c8f93SIngo Molnar 	return preempt_count();
95fb1c8f93SIngo Molnar #else
96fb1c8f93SIngo Molnar 	return 1;
97fb1c8f93SIngo Molnar #endif
98fb1c8f93SIngo Molnar }
99fb1c8f93SIngo Molnar 
100fb1c8f93SIngo Molnar #endif /* __LINUX_BIT_SPINLOCK_H */
101fb1c8f93SIngo Molnar 
102