xref: /linux/arch/mips/include/asm/atomic.h (revision 33619f0d3ff715a2a5499520967d526ad931d70d)
1 /*
2  * Atomic operations that C can't guarantee us.  Useful for
3  * resource counting etc..
4  *
5  * But use these as seldom as possible since they are much more slower
6  * than regular operations.
7  *
8  * This file is subject to the terms and conditions of the GNU General Public
9  * License.  See the file "COPYING" in the main directory of this archive
10  * for more details.
11  *
12  * Copyright (C) 1996, 97, 99, 2000, 03, 04, 06 by Ralf Baechle
13  */
14 #ifndef _ASM_ATOMIC_H
15 #define _ASM_ATOMIC_H
16 
17 #include <linux/irqflags.h>
18 #include <linux/types.h>
19 #include <asm/barrier.h>
20 #include <asm/cpu-features.h>
21 #include <asm/war.h>
22 #include <asm/system.h>
23 
24 #define ATOMIC_INIT(i)    { (i) }
25 
26 /*
27  * atomic_read - read atomic variable
28  * @v: pointer of type atomic_t
29  *
30  * Atomically reads the value of @v.
31  */
32 #define atomic_read(v)		(*(volatile int *)&(v)->counter)
33 
34 /*
35  * atomic_set - set atomic variable
36  * @v: pointer of type atomic_t
37  * @i: required value
38  *
39  * Atomically sets the value of @v to @i.
40  */
41 #define atomic_set(v, i)		((v)->counter = (i))
42 
43 /*
44  * atomic_add - add integer to atomic variable
45  * @i: integer value to add
46  * @v: pointer of type atomic_t
47  *
48  * Atomically adds @i to @v.
49  */
50 static __inline__ void atomic_add(int i, atomic_t * v)
51 {
52 	if (kernel_uses_llsc && R10000_LLSC_WAR) {
53 		int temp;
54 
55 		__asm__ __volatile__(
56 		"	.set	mips3					\n"
57 		"1:	ll	%0, %1		# atomic_add		\n"
58 		"	addu	%0, %2					\n"
59 		"	sc	%0, %1					\n"
60 		"	beqzl	%0, 1b					\n"
61 		"	.set	mips0					\n"
62 		: "=&r" (temp), "=m" (v->counter)
63 		: "Ir" (i), "m" (v->counter));
64 	} else if (kernel_uses_llsc) {
65 		int temp;
66 
67 		do {
68 			__asm__ __volatile__(
69 			"	.set	mips3				\n"
70 			"	ll	%0, %1		# atomic_add	\n"
71 			"	addu	%0, %2				\n"
72 			"	sc	%0, %1				\n"
73 			"	.set	mips0				\n"
74 			: "=&r" (temp), "=m" (v->counter)
75 			: "Ir" (i), "m" (v->counter));
76 		} while (unlikely(!temp));
77 	} else {
78 		unsigned long flags;
79 
80 		raw_local_irq_save(flags);
81 		v->counter += i;
82 		raw_local_irq_restore(flags);
83 	}
84 }
85 
86 /*
87  * atomic_sub - subtract the atomic variable
88  * @i: integer value to subtract
89  * @v: pointer of type atomic_t
90  *
91  * Atomically subtracts @i from @v.
92  */
93 static __inline__ void atomic_sub(int i, atomic_t * v)
94 {
95 	if (kernel_uses_llsc && R10000_LLSC_WAR) {
96 		int temp;
97 
98 		__asm__ __volatile__(
99 		"	.set	mips3					\n"
100 		"1:	ll	%0, %1		# atomic_sub		\n"
101 		"	subu	%0, %2					\n"
102 		"	sc	%0, %1					\n"
103 		"	beqzl	%0, 1b					\n"
104 		"	.set	mips0					\n"
105 		: "=&r" (temp), "=m" (v->counter)
106 		: "Ir" (i), "m" (v->counter));
107 	} else if (kernel_uses_llsc) {
108 		int temp;
109 
110 		do {
111 			__asm__ __volatile__(
112 			"	.set	mips3				\n"
113 			"	ll	%0, %1		# atomic_sub	\n"
114 			"	subu	%0, %2				\n"
115 			"	sc	%0, %1				\n"
116 			"	.set	mips0				\n"
117 			: "=&r" (temp), "=m" (v->counter)
118 			: "Ir" (i), "m" (v->counter));
119 		} while (unlikely(!temp));
120 	} else {
121 		unsigned long flags;
122 
123 		raw_local_irq_save(flags);
124 		v->counter -= i;
125 		raw_local_irq_restore(flags);
126 	}
127 }
128 
129 /*
130  * Same as above, but return the result value
131  */
132 static __inline__ int atomic_add_return(int i, atomic_t * v)
133 {
134 	int result;
135 
136 	smp_mb__before_llsc();
137 
138 	if (kernel_uses_llsc && R10000_LLSC_WAR) {
139 		int temp;
140 
141 		__asm__ __volatile__(
142 		"	.set	mips3					\n"
143 		"1:	ll	%1, %2		# atomic_add_return	\n"
144 		"	addu	%0, %1, %3				\n"
145 		"	sc	%0, %2					\n"
146 		"	beqzl	%0, 1b					\n"
147 		"	addu	%0, %1, %3				\n"
148 		"	.set	mips0					\n"
149 		: "=&r" (result), "=&r" (temp), "=m" (v->counter)
150 		: "Ir" (i), "m" (v->counter)
151 		: "memory");
152 	} else if (kernel_uses_llsc) {
153 		int temp;
154 
155 		do {
156 			__asm__ __volatile__(
157 			"	.set	mips3				\n"
158 			"	ll	%1, %2	# atomic_add_return	\n"
159 			"	addu	%0, %1, %3			\n"
160 			"	sc	%0, %2				\n"
161 			"	.set	mips0				\n"
162 			: "=&r" (result), "=&r" (temp), "=m" (v->counter)
163 			: "Ir" (i), "m" (v->counter)
164 			: "memory");
165 		} while (unlikely(!result));
166 
167 		result = temp + i;
168 	} else {
169 		unsigned long flags;
170 
171 		raw_local_irq_save(flags);
172 		result = v->counter;
173 		result += i;
174 		v->counter = result;
175 		raw_local_irq_restore(flags);
176 	}
177 
178 	smp_llsc_mb();
179 
180 	return result;
181 }
182 
183 static __inline__ int atomic_sub_return(int i, atomic_t * v)
184 {
185 	int result;
186 
187 	smp_mb__before_llsc();
188 
189 	if (kernel_uses_llsc && R10000_LLSC_WAR) {
190 		int temp;
191 
192 		__asm__ __volatile__(
193 		"	.set	mips3					\n"
194 		"1:	ll	%1, %2		# atomic_sub_return	\n"
195 		"	subu	%0, %1, %3				\n"
196 		"	sc	%0, %2					\n"
197 		"	beqzl	%0, 1b					\n"
198 		"	subu	%0, %1, %3				\n"
199 		"	.set	mips0					\n"
200 		: "=&r" (result), "=&r" (temp), "=m" (v->counter)
201 		: "Ir" (i), "m" (v->counter)
202 		: "memory");
203 
204 		result = temp - i;
205 	} else if (kernel_uses_llsc) {
206 		int temp;
207 
208 		do {
209 			__asm__ __volatile__(
210 			"	.set	mips3				\n"
211 			"	ll	%1, %2	# atomic_sub_return	\n"
212 			"	subu	%0, %1, %3			\n"
213 			"	sc	%0, %2				\n"
214 			"	.set	mips0				\n"
215 			: "=&r" (result), "=&r" (temp), "=m" (v->counter)
216 			: "Ir" (i), "m" (v->counter)
217 			: "memory");
218 		} while (unlikely(!result));
219 
220 		result = temp - i;
221 	} else {
222 		unsigned long flags;
223 
224 		raw_local_irq_save(flags);
225 		result = v->counter;
226 		result -= i;
227 		v->counter = result;
228 		raw_local_irq_restore(flags);
229 	}
230 
231 	smp_llsc_mb();
232 
233 	return result;
234 }
235 
236 /*
237  * atomic_sub_if_positive - conditionally subtract integer from atomic variable
238  * @i: integer value to subtract
239  * @v: pointer of type atomic_t
240  *
241  * Atomically test @v and subtract @i if @v is greater or equal than @i.
242  * The function returns the old value of @v minus @i.
243  */
244 static __inline__ int atomic_sub_if_positive(int i, atomic_t * v)
245 {
246 	int result;
247 
248 	smp_mb__before_llsc();
249 
250 	if (kernel_uses_llsc && R10000_LLSC_WAR) {
251 		int temp;
252 
253 		__asm__ __volatile__(
254 		"	.set	mips3					\n"
255 		"1:	ll	%1, %2		# atomic_sub_if_positive\n"
256 		"	subu	%0, %1, %3				\n"
257 		"	bltz	%0, 1f					\n"
258 		"	sc	%0, %2					\n"
259 		"	.set	noreorder				\n"
260 		"	beqzl	%0, 1b					\n"
261 		"	 subu	%0, %1, %3				\n"
262 		"	.set	reorder					\n"
263 		"1:							\n"
264 		"	.set	mips0					\n"
265 		: "=&r" (result), "=&r" (temp), "=m" (v->counter)
266 		: "Ir" (i), "m" (v->counter)
267 		: "memory");
268 	} else if (kernel_uses_llsc) {
269 		int temp;
270 
271 		__asm__ __volatile__(
272 		"	.set	mips3					\n"
273 		"1:	ll	%1, %2		# atomic_sub_if_positive\n"
274 		"	subu	%0, %1, %3				\n"
275 		"	bltz	%0, 1f					\n"
276 		"	sc	%0, %2					\n"
277 		"	.set	noreorder				\n"
278 		"	beqz	%0, 1b					\n"
279 		"	 subu	%0, %1, %3				\n"
280 		"	.set	reorder					\n"
281 		"1:							\n"
282 		"	.set	mips0					\n"
283 		: "=&r" (result), "=&r" (temp), "=m" (v->counter)
284 		: "Ir" (i), "m" (v->counter)
285 		: "memory");
286 	} else {
287 		unsigned long flags;
288 
289 		raw_local_irq_save(flags);
290 		result = v->counter;
291 		result -= i;
292 		if (result >= 0)
293 			v->counter = result;
294 		raw_local_irq_restore(flags);
295 	}
296 
297 	smp_llsc_mb();
298 
299 	return result;
300 }
301 
302 #define atomic_cmpxchg(v, o, n) (cmpxchg(&((v)->counter), (o), (n)))
303 #define atomic_xchg(v, new) (xchg(&((v)->counter), (new)))
304 
305 /**
306  * atomic_add_unless - add unless the number is a given value
307  * @v: pointer of type atomic_t
308  * @a: the amount to add to v...
309  * @u: ...unless v is equal to u.
310  *
311  * Atomically adds @a to @v, so long as it was not @u.
312  * Returns non-zero if @v was not @u, and zero otherwise.
313  */
314 static __inline__ int atomic_add_unless(atomic_t *v, int a, int u)
315 {
316 	int c, old;
317 	c = atomic_read(v);
318 	for (;;) {
319 		if (unlikely(c == (u)))
320 			break;
321 		old = atomic_cmpxchg((v), c, c + (a));
322 		if (likely(old == c))
323 			break;
324 		c = old;
325 	}
326 	return c != (u);
327 }
328 #define atomic_inc_not_zero(v) atomic_add_unless((v), 1, 0)
329 
330 #define atomic_dec_return(v) atomic_sub_return(1, (v))
331 #define atomic_inc_return(v) atomic_add_return(1, (v))
332 
333 /*
334  * atomic_sub_and_test - subtract value from variable and test result
335  * @i: integer value to subtract
336  * @v: pointer of type atomic_t
337  *
338  * Atomically subtracts @i from @v and returns
339  * true if the result is zero, or false for all
340  * other cases.
341  */
342 #define atomic_sub_and_test(i, v) (atomic_sub_return((i), (v)) == 0)
343 
344 /*
345  * atomic_inc_and_test - increment and test
346  * @v: pointer of type atomic_t
347  *
348  * Atomically increments @v by 1
349  * and returns true if the result is zero, or false for all
350  * other cases.
351  */
352 #define atomic_inc_and_test(v) (atomic_inc_return(v) == 0)
353 
354 /*
355  * atomic_dec_and_test - decrement by 1 and test
356  * @v: pointer of type atomic_t
357  *
358  * Atomically decrements @v by 1 and
359  * returns true if the result is 0, or false for all other
360  * cases.
361  */
362 #define atomic_dec_and_test(v) (atomic_sub_return(1, (v)) == 0)
363 
364 /*
365  * atomic_dec_if_positive - decrement by 1 if old value positive
366  * @v: pointer of type atomic_t
367  */
368 #define atomic_dec_if_positive(v)	atomic_sub_if_positive(1, v)
369 
370 /*
371  * atomic_inc - increment atomic variable
372  * @v: pointer of type atomic_t
373  *
374  * Atomically increments @v by 1.
375  */
376 #define atomic_inc(v) atomic_add(1, (v))
377 
378 /*
379  * atomic_dec - decrement and test
380  * @v: pointer of type atomic_t
381  *
382  * Atomically decrements @v by 1.
383  */
384 #define atomic_dec(v) atomic_sub(1, (v))
385 
386 /*
387  * atomic_add_negative - add and test if negative
388  * @v: pointer of type atomic_t
389  * @i: integer value to add
390  *
391  * Atomically adds @i to @v and returns true
392  * if the result is negative, or false when
393  * result is greater than or equal to zero.
394  */
395 #define atomic_add_negative(i, v) (atomic_add_return(i, (v)) < 0)
396 
397 #ifdef CONFIG_64BIT
398 
399 #define ATOMIC64_INIT(i)    { (i) }
400 
401 /*
402  * atomic64_read - read atomic variable
403  * @v: pointer of type atomic64_t
404  *
405  */
406 #define atomic64_read(v)	(*(volatile long *)&(v)->counter)
407 
408 /*
409  * atomic64_set - set atomic variable
410  * @v: pointer of type atomic64_t
411  * @i: required value
412  */
413 #define atomic64_set(v, i)	((v)->counter = (i))
414 
415 /*
416  * atomic64_add - add integer to atomic variable
417  * @i: integer value to add
418  * @v: pointer of type atomic64_t
419  *
420  * Atomically adds @i to @v.
421  */
422 static __inline__ void atomic64_add(long i, atomic64_t * v)
423 {
424 	if (kernel_uses_llsc && R10000_LLSC_WAR) {
425 		long temp;
426 
427 		__asm__ __volatile__(
428 		"	.set	mips3					\n"
429 		"1:	lld	%0, %1		# atomic64_add		\n"
430 		"	daddu	%0, %2					\n"
431 		"	scd	%0, %1					\n"
432 		"	beqzl	%0, 1b					\n"
433 		"	.set	mips0					\n"
434 		: "=&r" (temp), "=m" (v->counter)
435 		: "Ir" (i), "m" (v->counter));
436 	} else if (kernel_uses_llsc) {
437 		long temp;
438 
439 		do {
440 			__asm__ __volatile__(
441 			"	.set	mips3				\n"
442 			"	lld	%0, %1		# atomic64_add	\n"
443 			"	daddu	%0, %2				\n"
444 			"	scd	%0, %1				\n"
445 			"	.set	mips0				\n"
446 			: "=&r" (temp), "=m" (v->counter)
447 			: "Ir" (i), "m" (v->counter));
448 		} while (unlikely(!temp));
449 	} else {
450 		unsigned long flags;
451 
452 		raw_local_irq_save(flags);
453 		v->counter += i;
454 		raw_local_irq_restore(flags);
455 	}
456 }
457 
458 /*
459  * atomic64_sub - subtract the atomic variable
460  * @i: integer value to subtract
461  * @v: pointer of type atomic64_t
462  *
463  * Atomically subtracts @i from @v.
464  */
465 static __inline__ void atomic64_sub(long i, atomic64_t * v)
466 {
467 	if (kernel_uses_llsc && R10000_LLSC_WAR) {
468 		long temp;
469 
470 		__asm__ __volatile__(
471 		"	.set	mips3					\n"
472 		"1:	lld	%0, %1		# atomic64_sub		\n"
473 		"	dsubu	%0, %2					\n"
474 		"	scd	%0, %1					\n"
475 		"	beqzl	%0, 1b					\n"
476 		"	.set	mips0					\n"
477 		: "=&r" (temp), "=m" (v->counter)
478 		: "Ir" (i), "m" (v->counter));
479 	} else if (kernel_uses_llsc) {
480 		long temp;
481 
482 		do {
483 			__asm__ __volatile__(
484 			"	.set	mips3				\n"
485 			"	lld	%0, %1		# atomic64_sub	\n"
486 			"	dsubu	%0, %2				\n"
487 			"	scd	%0, %1				\n"
488 			"	.set	mips0				\n"
489 			: "=&r" (temp), "=m" (v->counter)
490 			: "Ir" (i), "m" (v->counter));
491 		} while (unlikely(!temp));
492 	} else {
493 		unsigned long flags;
494 
495 		raw_local_irq_save(flags);
496 		v->counter -= i;
497 		raw_local_irq_restore(flags);
498 	}
499 }
500 
501 /*
502  * Same as above, but return the result value
503  */
504 static __inline__ long atomic64_add_return(long i, atomic64_t * v)
505 {
506 	long result;
507 
508 	smp_mb__before_llsc();
509 
510 	if (kernel_uses_llsc && R10000_LLSC_WAR) {
511 		long temp;
512 
513 		__asm__ __volatile__(
514 		"	.set	mips3					\n"
515 		"1:	lld	%1, %2		# atomic64_add_return	\n"
516 		"	daddu	%0, %1, %3				\n"
517 		"	scd	%0, %2					\n"
518 		"	beqzl	%0, 1b					\n"
519 		"	daddu	%0, %1, %3				\n"
520 		"	.set	mips0					\n"
521 		: "=&r" (result), "=&r" (temp), "=m" (v->counter)
522 		: "Ir" (i), "m" (v->counter)
523 		: "memory");
524 	} else if (kernel_uses_llsc) {
525 		long temp;
526 
527 		do {
528 			__asm__ __volatile__(
529 			"	.set	mips3				\n"
530 			"	lld	%1, %2	# atomic64_add_return	\n"
531 			"	daddu	%0, %1, %3			\n"
532 			"	scd	%0, %2				\n"
533 			"	.set	mips0				\n"
534 			: "=&r" (result), "=&r" (temp), "=m" (v->counter)
535 			: "Ir" (i), "m" (v->counter)
536 			: "memory");
537 		} while (unlikely(!result));
538 
539 		result = temp + i;
540 	} else {
541 		unsigned long flags;
542 
543 		raw_local_irq_save(flags);
544 		result = v->counter;
545 		result += i;
546 		v->counter = result;
547 		raw_local_irq_restore(flags);
548 	}
549 
550 	smp_llsc_mb();
551 
552 	return result;
553 }
554 
555 static __inline__ long atomic64_sub_return(long i, atomic64_t * v)
556 {
557 	long result;
558 
559 	smp_mb__before_llsc();
560 
561 	if (kernel_uses_llsc && R10000_LLSC_WAR) {
562 		long temp;
563 
564 		__asm__ __volatile__(
565 		"	.set	mips3					\n"
566 		"1:	lld	%1, %2		# atomic64_sub_return	\n"
567 		"	dsubu	%0, %1, %3				\n"
568 		"	scd	%0, %2					\n"
569 		"	beqzl	%0, 1b					\n"
570 		"	dsubu	%0, %1, %3				\n"
571 		"	.set	mips0					\n"
572 		: "=&r" (result), "=&r" (temp), "=m" (v->counter)
573 		: "Ir" (i), "m" (v->counter)
574 		: "memory");
575 	} else if (kernel_uses_llsc) {
576 		long temp;
577 
578 		do {
579 			__asm__ __volatile__(
580 			"	.set	mips3				\n"
581 			"	lld	%1, %2	# atomic64_sub_return	\n"
582 			"	dsubu	%0, %1, %3			\n"
583 			"	scd	%0, %2				\n"
584 			"	.set	mips0				\n"
585 			: "=&r" (result), "=&r" (temp), "=m" (v->counter)
586 			: "Ir" (i), "m" (v->counter)
587 			: "memory");
588 		} while (unlikely(!result));
589 
590 		result = temp - i;
591 	} else {
592 		unsigned long flags;
593 
594 		raw_local_irq_save(flags);
595 		result = v->counter;
596 		result -= i;
597 		v->counter = result;
598 		raw_local_irq_restore(flags);
599 	}
600 
601 	smp_llsc_mb();
602 
603 	return result;
604 }
605 
606 /*
607  * atomic64_sub_if_positive - conditionally subtract integer from atomic variable
608  * @i: integer value to subtract
609  * @v: pointer of type atomic64_t
610  *
611  * Atomically test @v and subtract @i if @v is greater or equal than @i.
612  * The function returns the old value of @v minus @i.
613  */
614 static __inline__ long atomic64_sub_if_positive(long i, atomic64_t * v)
615 {
616 	long result;
617 
618 	smp_mb__before_llsc();
619 
620 	if (kernel_uses_llsc && R10000_LLSC_WAR) {
621 		long temp;
622 
623 		__asm__ __volatile__(
624 		"	.set	mips3					\n"
625 		"1:	lld	%1, %2		# atomic64_sub_if_positive\n"
626 		"	dsubu	%0, %1, %3				\n"
627 		"	bltz	%0, 1f					\n"
628 		"	scd	%0, %2					\n"
629 		"	.set	noreorder				\n"
630 		"	beqzl	%0, 1b					\n"
631 		"	 dsubu	%0, %1, %3				\n"
632 		"	.set	reorder					\n"
633 		"1:							\n"
634 		"	.set	mips0					\n"
635 		: "=&r" (result), "=&r" (temp), "=m" (v->counter)
636 		: "Ir" (i), "m" (v->counter)
637 		: "memory");
638 	} else if (kernel_uses_llsc) {
639 		long temp;
640 
641 		__asm__ __volatile__(
642 		"	.set	mips3					\n"
643 		"1:	lld	%1, %2		# atomic64_sub_if_positive\n"
644 		"	dsubu	%0, %1, %3				\n"
645 		"	bltz	%0, 1f					\n"
646 		"	scd	%0, %2					\n"
647 		"	.set	noreorder				\n"
648 		"	beqz	%0, 1b					\n"
649 		"	 dsubu	%0, %1, %3				\n"
650 		"	.set	reorder					\n"
651 		"1:							\n"
652 		"	.set	mips0					\n"
653 		: "=&r" (result), "=&r" (temp), "=m" (v->counter)
654 		: "Ir" (i), "m" (v->counter)
655 		: "memory");
656 	} else {
657 		unsigned long flags;
658 
659 		raw_local_irq_save(flags);
660 		result = v->counter;
661 		result -= i;
662 		if (result >= 0)
663 			v->counter = result;
664 		raw_local_irq_restore(flags);
665 	}
666 
667 	smp_llsc_mb();
668 
669 	return result;
670 }
671 
672 #define atomic64_cmpxchg(v, o, n) \
673 	((__typeof__((v)->counter))cmpxchg(&((v)->counter), (o), (n)))
674 #define atomic64_xchg(v, new) (xchg(&((v)->counter), (new)))
675 
676 /**
677  * atomic64_add_unless - add unless the number is a given value
678  * @v: pointer of type atomic64_t
679  * @a: the amount to add to v...
680  * @u: ...unless v is equal to u.
681  *
682  * Atomically adds @a to @v, so long as it was not @u.
683  * Returns non-zero if @v was not @u, and zero otherwise.
684  */
685 static __inline__ int atomic64_add_unless(atomic64_t *v, long a, long u)
686 {
687 	long c, old;
688 	c = atomic64_read(v);
689 	for (;;) {
690 		if (unlikely(c == (u)))
691 			break;
692 		old = atomic64_cmpxchg((v), c, c + (a));
693 		if (likely(old == c))
694 			break;
695 		c = old;
696 	}
697 	return c != (u);
698 }
699 
700 #define atomic64_inc_not_zero(v) atomic64_add_unless((v), 1, 0)
701 
702 #define atomic64_dec_return(v) atomic64_sub_return(1, (v))
703 #define atomic64_inc_return(v) atomic64_add_return(1, (v))
704 
705 /*
706  * atomic64_sub_and_test - subtract value from variable and test result
707  * @i: integer value to subtract
708  * @v: pointer of type atomic64_t
709  *
710  * Atomically subtracts @i from @v and returns
711  * true if the result is zero, or false for all
712  * other cases.
713  */
714 #define atomic64_sub_and_test(i, v) (atomic64_sub_return((i), (v)) == 0)
715 
716 /*
717  * atomic64_inc_and_test - increment and test
718  * @v: pointer of type atomic64_t
719  *
720  * Atomically increments @v by 1
721  * and returns true if the result is zero, or false for all
722  * other cases.
723  */
724 #define atomic64_inc_and_test(v) (atomic64_inc_return(v) == 0)
725 
726 /*
727  * atomic64_dec_and_test - decrement by 1 and test
728  * @v: pointer of type atomic64_t
729  *
730  * Atomically decrements @v by 1 and
731  * returns true if the result is 0, or false for all other
732  * cases.
733  */
734 #define atomic64_dec_and_test(v) (atomic64_sub_return(1, (v)) == 0)
735 
736 /*
737  * atomic64_dec_if_positive - decrement by 1 if old value positive
738  * @v: pointer of type atomic64_t
739  */
740 #define atomic64_dec_if_positive(v)	atomic64_sub_if_positive(1, v)
741 
742 /*
743  * atomic64_inc - increment atomic variable
744  * @v: pointer of type atomic64_t
745  *
746  * Atomically increments @v by 1.
747  */
748 #define atomic64_inc(v) atomic64_add(1, (v))
749 
750 /*
751  * atomic64_dec - decrement and test
752  * @v: pointer of type atomic64_t
753  *
754  * Atomically decrements @v by 1.
755  */
756 #define atomic64_dec(v) atomic64_sub(1, (v))
757 
758 /*
759  * atomic64_add_negative - add and test if negative
760  * @v: pointer of type atomic64_t
761  * @i: integer value to add
762  *
763  * Atomically adds @i to @v and returns true
764  * if the result is negative, or false when
765  * result is greater than or equal to zero.
766  */
767 #define atomic64_add_negative(i, v) (atomic64_add_return(i, (v)) < 0)
768 
769 #else /* !CONFIG_64BIT */
770 
771 #include <asm-generic/atomic64.h>
772 
773 #endif /* CONFIG_64BIT */
774 
775 /*
776  * atomic*_return operations are serializing but not the non-*_return
777  * versions.
778  */
779 #define smp_mb__before_atomic_dec()	smp_mb__before_llsc()
780 #define smp_mb__after_atomic_dec()	smp_llsc_mb()
781 #define smp_mb__before_atomic_inc()	smp_mb__before_llsc()
782 #define smp_mb__after_atomic_inc()	smp_llsc_mb()
783 
784 #include <asm-generic/atomic-long.h>
785 
786 #endif /* _ASM_ATOMIC_H */
787