18c2ecf20Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0 */
28c2ecf20Sopenharmony_ci#ifndef _ASM_GENERIC_BITOPS_NON_ATOMIC_H_
38c2ecf20Sopenharmony_ci#define _ASM_GENERIC_BITOPS_NON_ATOMIC_H_
48c2ecf20Sopenharmony_ci
58c2ecf20Sopenharmony_ci#include <asm/types.h>
68c2ecf20Sopenharmony_ci
78c2ecf20Sopenharmony_ci/**
88c2ecf20Sopenharmony_ci * __set_bit - Set a bit in memory
98c2ecf20Sopenharmony_ci * @nr: the bit to set
108c2ecf20Sopenharmony_ci * @addr: the address to start counting from
118c2ecf20Sopenharmony_ci *
128c2ecf20Sopenharmony_ci * Unlike set_bit(), this function is non-atomic and may be reordered.
138c2ecf20Sopenharmony_ci * If it's called on the same region of memory simultaneously, the effect
148c2ecf20Sopenharmony_ci * may be that only one operation succeeds.
158c2ecf20Sopenharmony_ci */
168c2ecf20Sopenharmony_cistatic inline void __set_bit(int nr, volatile unsigned long *addr)
178c2ecf20Sopenharmony_ci{
188c2ecf20Sopenharmony_ci	unsigned long mask = BIT_MASK(nr);
198c2ecf20Sopenharmony_ci	unsigned long *p = ((unsigned long *)addr) + BIT_WORD(nr);
208c2ecf20Sopenharmony_ci
218c2ecf20Sopenharmony_ci	*p  |= mask;
228c2ecf20Sopenharmony_ci}
238c2ecf20Sopenharmony_ci
248c2ecf20Sopenharmony_cistatic inline void __clear_bit(int nr, volatile unsigned long *addr)
258c2ecf20Sopenharmony_ci{
268c2ecf20Sopenharmony_ci	unsigned long mask = BIT_MASK(nr);
278c2ecf20Sopenharmony_ci	unsigned long *p = ((unsigned long *)addr) + BIT_WORD(nr);
288c2ecf20Sopenharmony_ci
298c2ecf20Sopenharmony_ci	*p &= ~mask;
308c2ecf20Sopenharmony_ci}
318c2ecf20Sopenharmony_ci
328c2ecf20Sopenharmony_ci/**
338c2ecf20Sopenharmony_ci * __change_bit - Toggle a bit in memory
348c2ecf20Sopenharmony_ci * @nr: the bit to change
358c2ecf20Sopenharmony_ci * @addr: the address to start counting from
368c2ecf20Sopenharmony_ci *
378c2ecf20Sopenharmony_ci * Unlike change_bit(), this function is non-atomic and may be reordered.
388c2ecf20Sopenharmony_ci * If it's called on the same region of memory simultaneously, the effect
398c2ecf20Sopenharmony_ci * may be that only one operation succeeds.
408c2ecf20Sopenharmony_ci */
418c2ecf20Sopenharmony_cistatic inline void __change_bit(int nr, volatile unsigned long *addr)
428c2ecf20Sopenharmony_ci{
438c2ecf20Sopenharmony_ci	unsigned long mask = BIT_MASK(nr);
448c2ecf20Sopenharmony_ci	unsigned long *p = ((unsigned long *)addr) + BIT_WORD(nr);
458c2ecf20Sopenharmony_ci
468c2ecf20Sopenharmony_ci	*p ^= mask;
478c2ecf20Sopenharmony_ci}
488c2ecf20Sopenharmony_ci
498c2ecf20Sopenharmony_ci/**
508c2ecf20Sopenharmony_ci * __test_and_set_bit - Set a bit and return its old value
518c2ecf20Sopenharmony_ci * @nr: Bit to set
528c2ecf20Sopenharmony_ci * @addr: Address to count from
538c2ecf20Sopenharmony_ci *
548c2ecf20Sopenharmony_ci * This operation is non-atomic and can be reordered.
558c2ecf20Sopenharmony_ci * If two examples of this operation race, one can appear to succeed
568c2ecf20Sopenharmony_ci * but actually fail.  You must protect multiple accesses with a lock.
578c2ecf20Sopenharmony_ci */
588c2ecf20Sopenharmony_cistatic inline int __test_and_set_bit(int nr, volatile unsigned long *addr)
598c2ecf20Sopenharmony_ci{
608c2ecf20Sopenharmony_ci	unsigned long mask = BIT_MASK(nr);
618c2ecf20Sopenharmony_ci	unsigned long *p = ((unsigned long *)addr) + BIT_WORD(nr);
628c2ecf20Sopenharmony_ci	unsigned long old = *p;
638c2ecf20Sopenharmony_ci
648c2ecf20Sopenharmony_ci	*p = old | mask;
658c2ecf20Sopenharmony_ci	return (old & mask) != 0;
668c2ecf20Sopenharmony_ci}
678c2ecf20Sopenharmony_ci
688c2ecf20Sopenharmony_ci/**
698c2ecf20Sopenharmony_ci * __test_and_clear_bit - Clear a bit and return its old value
708c2ecf20Sopenharmony_ci * @nr: Bit to clear
718c2ecf20Sopenharmony_ci * @addr: Address to count from
728c2ecf20Sopenharmony_ci *
738c2ecf20Sopenharmony_ci * This operation is non-atomic and can be reordered.
748c2ecf20Sopenharmony_ci * If two examples of this operation race, one can appear to succeed
758c2ecf20Sopenharmony_ci * but actually fail.  You must protect multiple accesses with a lock.
768c2ecf20Sopenharmony_ci */
778c2ecf20Sopenharmony_cistatic inline int __test_and_clear_bit(int nr, volatile unsigned long *addr)
788c2ecf20Sopenharmony_ci{
798c2ecf20Sopenharmony_ci	unsigned long mask = BIT_MASK(nr);
808c2ecf20Sopenharmony_ci	unsigned long *p = ((unsigned long *)addr) + BIT_WORD(nr);
818c2ecf20Sopenharmony_ci	unsigned long old = *p;
828c2ecf20Sopenharmony_ci
838c2ecf20Sopenharmony_ci	*p = old & ~mask;
848c2ecf20Sopenharmony_ci	return (old & mask) != 0;
858c2ecf20Sopenharmony_ci}
868c2ecf20Sopenharmony_ci
878c2ecf20Sopenharmony_ci/* WARNING: non atomic and it can be reordered! */
888c2ecf20Sopenharmony_cistatic inline int __test_and_change_bit(int nr,
898c2ecf20Sopenharmony_ci					    volatile unsigned long *addr)
908c2ecf20Sopenharmony_ci{
918c2ecf20Sopenharmony_ci	unsigned long mask = BIT_MASK(nr);
928c2ecf20Sopenharmony_ci	unsigned long *p = ((unsigned long *)addr) + BIT_WORD(nr);
938c2ecf20Sopenharmony_ci	unsigned long old = *p;
948c2ecf20Sopenharmony_ci
958c2ecf20Sopenharmony_ci	*p = old ^ mask;
968c2ecf20Sopenharmony_ci	return (old & mask) != 0;
978c2ecf20Sopenharmony_ci}
988c2ecf20Sopenharmony_ci
998c2ecf20Sopenharmony_ci/**
1008c2ecf20Sopenharmony_ci * test_bit - Determine whether a bit is set
1018c2ecf20Sopenharmony_ci * @nr: bit number to test
1028c2ecf20Sopenharmony_ci * @addr: Address to start counting from
1038c2ecf20Sopenharmony_ci */
1048c2ecf20Sopenharmony_cistatic inline int test_bit(int nr, const volatile unsigned long *addr)
1058c2ecf20Sopenharmony_ci{
1068c2ecf20Sopenharmony_ci	return 1UL & (addr[BIT_WORD(nr)] >> (nr & (BITS_PER_LONG-1)));
1078c2ecf20Sopenharmony_ci}
1088c2ecf20Sopenharmony_ci
1098c2ecf20Sopenharmony_ci#endif /* _ASM_GENERIC_BITOPS_NON_ATOMIC_H_ */
110