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