^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) /* SPDX-License-Identifier: GPL-2.0 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) #ifndef _ASM_GENERIC_BITOPS_LOCK_H_
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) #define _ASM_GENERIC_BITOPS_LOCK_H_
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) #include <linux/atomic.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) #include <linux/compiler.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) #include <asm/barrier.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) * test_and_set_bit_lock - Set a bit and return its old value, for lock
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) * @nr: Bit to set
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) * @addr: Address to count from
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) * This operation is atomic and provides acquire barrier semantics if
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) * the returned value is 0.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) * It can be used to implement bit locks.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) static inline int test_and_set_bit_lock(unsigned int nr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) volatile unsigned long *p)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) long old;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) unsigned long mask = BIT_MASK(nr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) p += BIT_WORD(nr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) if (READ_ONCE(*p) & mask)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) old = atomic_long_fetch_or_acquire(mask, (atomic_long_t *)p);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) return !!(old & mask);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) * clear_bit_unlock - Clear a bit in memory, for unlock
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) * @nr: the bit to set
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) * @addr: the address to start counting from
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) * This operation is atomic and provides release barrier semantics.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) static inline void clear_bit_unlock(unsigned int nr, volatile unsigned long *p)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) p += BIT_WORD(nr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) atomic_long_fetch_andnot_release(BIT_MASK(nr), (atomic_long_t *)p);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) * __clear_bit_unlock - Clear a bit in memory, for unlock
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) * @nr: the bit to set
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) * @addr: the address to start counting from
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) * A weaker form of clear_bit_unlock() as used by __bit_lock_unlock(). If all
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) * the bits in the word are protected by this lock some archs can use weaker
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) * ops to safely unlock.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) * See for example x86's implementation.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) static inline void __clear_bit_unlock(unsigned int nr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) volatile unsigned long *p)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) unsigned long old;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) p += BIT_WORD(nr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) old = READ_ONCE(*p);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) old &= ~BIT_MASK(nr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) atomic_long_set_release((atomic_long_t *)p, old);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) * clear_bit_unlock_is_negative_byte - Clear a bit in memory and test if bottom
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) * byte is negative, for unlock.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) * @nr: the bit to clear
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) * @addr: the address to start counting from
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) * This is a bit of a one-trick-pony for the filemap code, which clears
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) * PG_locked and tests PG_waiters,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) #ifndef clear_bit_unlock_is_negative_byte
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) static inline bool clear_bit_unlock_is_negative_byte(unsigned int nr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) volatile unsigned long *p)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) long old;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) unsigned long mask = BIT_MASK(nr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) p += BIT_WORD(nr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) old = atomic_long_fetch_andnot_release(mask, (atomic_long_t *)p);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) return !!(old & BIT(7));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) #define clear_bit_unlock_is_negative_byte clear_bit_unlock_is_negative_byte
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) #endif /* _ASM_GENERIC_BITOPS_LOCK_H_ */