Linux Kernel  3.7.1
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
bitops.h
Go to the documentation of this file.
1 /*
2  * Copyright (C) 2004-2006 Atmel Corporation
3  *
4  * This program is free software; you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License version 2 as
6  * published by the Free Software Foundation.
7  */
8 #ifndef __ASM_AVR32_BITOPS_H
9 #define __ASM_AVR32_BITOPS_H
10 
11 #ifndef _LINUX_BITOPS_H
12 #error only <linux/bitops.h> can be included directly
13 #endif
14 
15 #include <asm/byteorder.h>
16 
17 /*
18  * clear_bit() doesn't provide any barrier for the compiler
19  */
20 #define smp_mb__before_clear_bit() barrier()
21 #define smp_mb__after_clear_bit() barrier()
22 
23 /*
24  * set_bit - Atomically set a bit in memory
25  * @nr: the bit to set
26  * @addr: the address to start counting from
27  *
28  * This function is atomic and may not be reordered. See __set_bit()
29  * if you do not require the atomic guarantees.
30  *
31  * Note that @nr may be almost arbitrarily large; this function is not
32  * restricted to acting on a single-word quantity.
33  */
34 static inline void set_bit(int nr, volatile void * addr)
35 {
36  unsigned long *p = ((unsigned long *)addr) + nr / BITS_PER_LONG;
37  unsigned long tmp;
38 
39  if (__builtin_constant_p(nr)) {
40  asm volatile(
41  "1: ssrf 5\n"
42  " ld.w %0, %2\n"
43  " sbr %0, %3\n"
44  " stcond %1, %0\n"
45  " brne 1b"
46  : "=&r"(tmp), "=o"(*p)
47  : "m"(*p), "i"(nr)
48  : "cc");
49  } else {
50  unsigned long mask = 1UL << (nr % BITS_PER_LONG);
51  asm volatile(
52  "1: ssrf 5\n"
53  " ld.w %0, %2\n"
54  " or %0, %3\n"
55  " stcond %1, %0\n"
56  " brne 1b"
57  : "=&r"(tmp), "=o"(*p)
58  : "m"(*p), "r"(mask)
59  : "cc");
60  }
61 }
62 
63 /*
64  * clear_bit - Clears a bit in memory
65  * @nr: Bit to clear
66  * @addr: Address to start counting from
67  *
68  * clear_bit() is atomic and may not be reordered. However, it does
69  * not contain a memory barrier, so if it is used for locking purposes,
70  * you should call smp_mb__before_clear_bit() and/or smp_mb__after_clear_bit()
71  * in order to ensure changes are visible on other processors.
72  */
73 static inline void clear_bit(int nr, volatile void * addr)
74 {
75  unsigned long *p = ((unsigned long *)addr) + nr / BITS_PER_LONG;
76  unsigned long tmp;
77 
78  if (__builtin_constant_p(nr)) {
79  asm volatile(
80  "1: ssrf 5\n"
81  " ld.w %0, %2\n"
82  " cbr %0, %3\n"
83  " stcond %1, %0\n"
84  " brne 1b"
85  : "=&r"(tmp), "=o"(*p)
86  : "m"(*p), "i"(nr)
87  : "cc");
88  } else {
89  unsigned long mask = 1UL << (nr % BITS_PER_LONG);
90  asm volatile(
91  "1: ssrf 5\n"
92  " ld.w %0, %2\n"
93  " andn %0, %3\n"
94  " stcond %1, %0\n"
95  " brne 1b"
96  : "=&r"(tmp), "=o"(*p)
97  : "m"(*p), "r"(mask)
98  : "cc");
99  }
100 }
101 
102 /*
103  * change_bit - Toggle a bit in memory
104  * @nr: Bit to change
105  * @addr: Address to start counting from
106  *
107  * change_bit() is atomic and may not be reordered.
108  * Note that @nr may be almost arbitrarily large; this function is not
109  * restricted to acting on a single-word quantity.
110  */
111 static inline void change_bit(int nr, volatile void * addr)
112 {
113  unsigned long *p = ((unsigned long *)addr) + nr / BITS_PER_LONG;
114  unsigned long mask = 1UL << (nr % BITS_PER_LONG);
115  unsigned long tmp;
116 
117  asm volatile(
118  "1: ssrf 5\n"
119  " ld.w %0, %2\n"
120  " eor %0, %3\n"
121  " stcond %1, %0\n"
122  " brne 1b"
123  : "=&r"(tmp), "=o"(*p)
124  : "m"(*p), "r"(mask)
125  : "cc");
126 }
127 
128 /*
129  * test_and_set_bit - Set a bit and return its old value
130  * @nr: Bit to set
131  * @addr: Address to count from
132  *
133  * This operation is atomic and cannot be reordered.
134  * It also implies a memory barrier.
135  */
136 static inline int test_and_set_bit(int nr, volatile void * addr)
137 {
138  unsigned long *p = ((unsigned long *)addr) + nr / BITS_PER_LONG;
139  unsigned long mask = 1UL << (nr % BITS_PER_LONG);
140  unsigned long tmp, old;
141 
142  if (__builtin_constant_p(nr)) {
143  asm volatile(
144  "1: ssrf 5\n"
145  " ld.w %0, %3\n"
146  " mov %2, %0\n"
147  " sbr %0, %4\n"
148  " stcond %1, %0\n"
149  " brne 1b"
150  : "=&r"(tmp), "=o"(*p), "=&r"(old)
151  : "m"(*p), "i"(nr)
152  : "memory", "cc");
153  } else {
154  asm volatile(
155  "1: ssrf 5\n"
156  " ld.w %2, %3\n"
157  " or %0, %2, %4\n"
158  " stcond %1, %0\n"
159  " brne 1b"
160  : "=&r"(tmp), "=o"(*p), "=&r"(old)
161  : "m"(*p), "r"(mask)
162  : "memory", "cc");
163  }
164 
165  return (old & mask) != 0;
166 }
167 
168 /*
169  * test_and_clear_bit - Clear a bit and return its old value
170  * @nr: Bit to clear
171  * @addr: Address to count from
172  *
173  * This operation is atomic and cannot be reordered.
174  * It also implies a memory barrier.
175  */
176 static inline int test_and_clear_bit(int nr, volatile void * addr)
177 {
178  unsigned long *p = ((unsigned long *)addr) + nr / BITS_PER_LONG;
179  unsigned long mask = 1UL << (nr % BITS_PER_LONG);
180  unsigned long tmp, old;
181 
182  if (__builtin_constant_p(nr)) {
183  asm volatile(
184  "1: ssrf 5\n"
185  " ld.w %0, %3\n"
186  " mov %2, %0\n"
187  " cbr %0, %4\n"
188  " stcond %1, %0\n"
189  " brne 1b"
190  : "=&r"(tmp), "=o"(*p), "=&r"(old)
191  : "m"(*p), "i"(nr)
192  : "memory", "cc");
193  } else {
194  asm volatile(
195  "1: ssrf 5\n"
196  " ld.w %0, %3\n"
197  " mov %2, %0\n"
198  " andn %0, %4\n"
199  " stcond %1, %0\n"
200  " brne 1b"
201  : "=&r"(tmp), "=o"(*p), "=&r"(old)
202  : "m"(*p), "r"(mask)
203  : "memory", "cc");
204  }
205 
206  return (old & mask) != 0;
207 }
208 
209 /*
210  * test_and_change_bit - Change a bit and return its old value
211  * @nr: Bit to change
212  * @addr: Address to count from
213  *
214  * This operation is atomic and cannot be reordered.
215  * It also implies a memory barrier.
216  */
217 static inline int test_and_change_bit(int nr, volatile void * addr)
218 {
219  unsigned long *p = ((unsigned long *)addr) + nr / BITS_PER_LONG;
220  unsigned long mask = 1UL << (nr % BITS_PER_LONG);
221  unsigned long tmp, old;
222 
223  asm volatile(
224  "1: ssrf 5\n"
225  " ld.w %2, %3\n"
226  " eor %0, %2, %4\n"
227  " stcond %1, %0\n"
228  " brne 1b"
229  : "=&r"(tmp), "=o"(*p), "=&r"(old)
230  : "m"(*p), "r"(mask)
231  : "memory", "cc");
232 
233  return (old & mask) != 0;
234 }
235 
237 
238 /* Find First bit Set */
239 static inline unsigned long __ffs(unsigned long word)
240 {
241  unsigned long result;
242 
243  asm("brev %1\n\t"
244  "clz %0,%1"
245  : "=r"(result), "=&r"(word)
246  : "1"(word));
247  return result;
248 }
249 
250 /* Find First Zero */
251 static inline unsigned long ffz(unsigned long word)
252 {
253  return __ffs(~word);
254 }
255 
256 /* Find Last bit Set */
257 static inline int fls(unsigned long word)
258 {
259  unsigned long result;
260 
261  asm("clz %0,%1" : "=r"(result) : "r"(word));
262  return 32 - result;
263 }
264 
265 static inline int __fls(unsigned long word)
266 {
267  return fls(word) - 1;
268 }
269 
270 unsigned long find_first_zero_bit(const unsigned long *addr,
271  unsigned long size);
272 #define find_first_zero_bit find_first_zero_bit
273 
274 unsigned long find_next_zero_bit(const unsigned long *addr,
275  unsigned long size,
276  unsigned long offset);
277 #define find_next_zero_bit find_next_zero_bit
278 
279 unsigned long find_first_bit(const unsigned long *addr,
280  unsigned long size);
281 #define find_first_bit find_first_bit
282 
283 unsigned long find_next_bit(const unsigned long *addr,
284  unsigned long size,
285  unsigned long offset);
286 #define find_next_bit find_next_bit
287 
288 /*
289  * ffs: find first bit set. This is defined the same way as
290  * the libc and compiler builtin ffs routines, therefore
291  * differs in spirit from the above ffz (man ffs).
292  *
293  * The difference is that bit numbering starts at 1, and if no bit is set,
294  * the function returns 0.
295  */
296 static inline int ffs(unsigned long word)
297 {
298  if(word == 0)
299  return 0;
300  return __ffs(word) + 1;
301 }
302 
306 #include <asm-generic/bitops/lock.h>
307 
308 extern unsigned long find_next_zero_bit_le(const void *addr,
309  unsigned long size, unsigned long offset);
310 #define find_next_zero_bit_le find_next_zero_bit_le
311 
312 extern unsigned long find_next_bit_le(const void *addr,
313  unsigned long size, unsigned long offset);
314 #define find_next_bit_le find_next_bit_le
315 
316 #include <asm-generic/bitops/le.h>
318 
319 #endif /* __ASM_AVR32_BITOPS_H */