blob: a13e9bc76eece8d29372ad0605f2bfd1f2383d9f [file] [log] [blame]
Matthew Wilcox1366c372016-03-17 14:21:45 -07001#ifndef _ASM_GENERIC_BITOPS_NON_ATOMIC_H_
2#define _ASM_GENERIC_BITOPS_NON_ATOMIC_H_
3
4#include <linux/types.h>
Matthew Wilcox06295732016-12-14 15:08:29 -08005#include <linux/bitops/find.h>
6#include <linux/bitops/hweight.h>
7#include <linux/kernel.h>
Matthew Wilcox1366c372016-03-17 14:21:45 -07008
Matthew Wilcox06295732016-12-14 15:08:29 -08009#define BIT_MASK(nr) (1UL << ((nr) % BITS_PER_LONG))
10#define BIT_WORD(nr) ((nr) / BITS_PER_LONG)
11#define BITS_PER_BYTE 8
12#define BITS_TO_LONGS(nr) DIV_ROUND_UP(nr, BITS_PER_BYTE * sizeof(long))
Matthew Wilcox1366c372016-03-17 14:21:45 -070013
14/**
15 * __set_bit - Set a bit in memory
16 * @nr: the bit to set
17 * @addr: the address to start counting from
18 *
19 * Unlike set_bit(), this function is non-atomic and may be reordered.
20 * If it's called on the same region of memory simultaneously, the effect
21 * may be that only one operation succeeds.
22 */
23static inline void __set_bit(int nr, volatile unsigned long *addr)
24{
Matthew Wilcox06295732016-12-14 15:08:29 -080025 unsigned long mask = BIT_MASK(nr);
26 unsigned long *p = ((unsigned long *)addr) + BIT_WORD(nr);
Matthew Wilcox1366c372016-03-17 14:21:45 -070027
28 *p |= mask;
29}
30
31static inline void __clear_bit(int nr, volatile unsigned long *addr)
32{
Matthew Wilcox06295732016-12-14 15:08:29 -080033 unsigned long mask = BIT_MASK(nr);
34 unsigned long *p = ((unsigned long *)addr) + BIT_WORD(nr);
Matthew Wilcox1366c372016-03-17 14:21:45 -070035
36 *p &= ~mask;
37}
38
39/**
40 * __change_bit - Toggle a bit in memory
41 * @nr: the bit to change
42 * @addr: the address to start counting from
43 *
44 * Unlike change_bit(), this function is non-atomic and may be reordered.
45 * If it's called on the same region of memory simultaneously, the effect
46 * may be that only one operation succeeds.
47 */
48static inline void __change_bit(int nr, volatile unsigned long *addr)
49{
Matthew Wilcox06295732016-12-14 15:08:29 -080050 unsigned long mask = BIT_MASK(nr);
51 unsigned long *p = ((unsigned long *)addr) + BIT_WORD(nr);
Matthew Wilcox1366c372016-03-17 14:21:45 -070052
53 *p ^= mask;
54}
55
56/**
57 * __test_and_set_bit - Set a bit and return its old value
58 * @nr: Bit to set
59 * @addr: Address to count from
60 *
61 * This operation is non-atomic and can be reordered.
62 * If two examples of this operation race, one can appear to succeed
63 * but actually fail. You must protect multiple accesses with a lock.
64 */
65static inline int __test_and_set_bit(int nr, volatile unsigned long *addr)
66{
Matthew Wilcox06295732016-12-14 15:08:29 -080067 unsigned long mask = BIT_MASK(nr);
68 unsigned long *p = ((unsigned long *)addr) + BIT_WORD(nr);
Matthew Wilcox1366c372016-03-17 14:21:45 -070069 unsigned long old = *p;
70
71 *p = old | mask;
72 return (old & mask) != 0;
73}
74
75/**
76 * __test_and_clear_bit - Clear a bit and return its old value
77 * @nr: Bit to clear
78 * @addr: Address to count from
79 *
80 * This operation is non-atomic and can be reordered.
81 * If two examples of this operation race, one can appear to succeed
82 * but actually fail. You must protect multiple accesses with a lock.
83 */
84static inline int __test_and_clear_bit(int nr, volatile unsigned long *addr)
85{
Matthew Wilcox06295732016-12-14 15:08:29 -080086 unsigned long mask = BIT_MASK(nr);
87 unsigned long *p = ((unsigned long *)addr) + BIT_WORD(nr);
Matthew Wilcox1366c372016-03-17 14:21:45 -070088 unsigned long old = *p;
89
90 *p = old & ~mask;
91 return (old & mask) != 0;
92}
93
94/* WARNING: non atomic and it can be reordered! */
95static inline int __test_and_change_bit(int nr,
96 volatile unsigned long *addr)
97{
Matthew Wilcox06295732016-12-14 15:08:29 -080098 unsigned long mask = BIT_MASK(nr);
99 unsigned long *p = ((unsigned long *)addr) + BIT_WORD(nr);
Matthew Wilcox1366c372016-03-17 14:21:45 -0700100 unsigned long old = *p;
101
102 *p = old ^ mask;
103 return (old & mask) != 0;
104}
105
106/**
107 * test_bit - Determine whether a bit is set
108 * @nr: bit number to test
109 * @addr: Address to start counting from
110 */
111static inline int test_bit(int nr, const volatile unsigned long *addr)
112{
Matthew Wilcox06295732016-12-14 15:08:29 -0800113 return 1UL & (addr[BIT_WORD(nr)] >> (nr & (BITS_PER_LONG-1)));
Matthew Wilcox1366c372016-03-17 14:21:45 -0700114}
115
116/**
117 * __ffs - find first bit in word.
118 * @word: The word to search
119 *
120 * Undefined if no bit exists, so code should check against 0 first.
121 */
122static inline unsigned long __ffs(unsigned long word)
123{
124 int num = 0;
125
126 if ((word & 0xffffffff) == 0) {
127 num += 32;
128 word >>= 32;
129 }
130 if ((word & 0xffff) == 0) {
131 num += 16;
132 word >>= 16;
133 }
134 if ((word & 0xff) == 0) {
135 num += 8;
136 word >>= 8;
137 }
138 if ((word & 0xf) == 0) {
139 num += 4;
140 word >>= 4;
141 }
142 if ((word & 0x3) == 0) {
143 num += 2;
144 word >>= 2;
145 }
146 if ((word & 0x1) == 0)
147 num += 1;
148 return num;
149}
150
151unsigned long find_next_bit(const unsigned long *addr,
152 unsigned long size,
153 unsigned long offset);
154
Matthew Wilcox06295732016-12-14 15:08:29 -0800155static inline unsigned long hweight_long(unsigned long w)
156{
157 return sizeof(w) == 4 ? hweight32(w) : hweight64(w);
158}
159
Matthew Wilcox1366c372016-03-17 14:21:45 -0700160#endif /* _ASM_GENERIC_BITOPS_NON_ATOMIC_H_ */