15abbbbf0b0cd4abf5898136d0c345dc99b859c8cBrian Gerst#ifndef _ASM_X86_ATOMIC_H
25abbbbf0b0cd4abf5898136d0c345dc99b859c8cBrian Gerst#define _ASM_X86_ATOMIC_H
35abbbbf0b0cd4abf5898136d0c345dc99b859c8cBrian Gerst
45abbbbf0b0cd4abf5898136d0c345dc99b859c8cBrian Gerst#include <linux/compiler.h>
55abbbbf0b0cd4abf5898136d0c345dc99b859c8cBrian Gerst#include <linux/types.h>
65abbbbf0b0cd4abf5898136d0c345dc99b859c8cBrian Gerst#include <asm/processor.h>
75abbbbf0b0cd4abf5898136d0c345dc99b859c8cBrian Gerst#include <asm/alternative.h>
85abbbbf0b0cd4abf5898136d0c345dc99b859c8cBrian Gerst#include <asm/cmpxchg.h>
90c44c2d0f459cd7e275242b72f500137c4fa834dPeter Zijlstra#include <asm/rmwcc.h>
10d00a569284b1340c16fe2c148099e077ea09ebc9Peter Zijlstra#include <asm/barrier.h>
115abbbbf0b0cd4abf5898136d0c345dc99b859c8cBrian Gerst
125abbbbf0b0cd4abf5898136d0c345dc99b859c8cBrian Gerst/*
135abbbbf0b0cd4abf5898136d0c345dc99b859c8cBrian Gerst * Atomic operations that C can't guarantee us.  Useful for
145abbbbf0b0cd4abf5898136d0c345dc99b859c8cBrian Gerst * resource counting etc..
155abbbbf0b0cd4abf5898136d0c345dc99b859c8cBrian Gerst */
165abbbbf0b0cd4abf5898136d0c345dc99b859c8cBrian Gerst
175abbbbf0b0cd4abf5898136d0c345dc99b859c8cBrian Gerst#define ATOMIC_INIT(i)	{ (i) }
185abbbbf0b0cd4abf5898136d0c345dc99b859c8cBrian Gerst
195abbbbf0b0cd4abf5898136d0c345dc99b859c8cBrian Gerst/**
205abbbbf0b0cd4abf5898136d0c345dc99b859c8cBrian Gerst * atomic_read - read atomic variable
215abbbbf0b0cd4abf5898136d0c345dc99b859c8cBrian Gerst * @v: pointer of type atomic_t
225abbbbf0b0cd4abf5898136d0c345dc99b859c8cBrian Gerst *
235abbbbf0b0cd4abf5898136d0c345dc99b859c8cBrian Gerst * Atomically reads the value of @v.
245abbbbf0b0cd4abf5898136d0c345dc99b859c8cBrian Gerst */
255abbbbf0b0cd4abf5898136d0c345dc99b859c8cBrian Gerststatic inline int atomic_read(const atomic_t *v)
265abbbbf0b0cd4abf5898136d0c345dc99b859c8cBrian Gerst{
272291059c852706c6f5ffb400366042b7625066cdPranith Kumar	return ACCESS_ONCE((v)->counter);
285abbbbf0b0cd4abf5898136d0c345dc99b859c8cBrian Gerst}
295abbbbf0b0cd4abf5898136d0c345dc99b859c8cBrian Gerst
305abbbbf0b0cd4abf5898136d0c345dc99b859c8cBrian Gerst/**
315abbbbf0b0cd4abf5898136d0c345dc99b859c8cBrian Gerst * atomic_set - set atomic variable
325abbbbf0b0cd4abf5898136d0c345dc99b859c8cBrian Gerst * @v: pointer of type atomic_t
335abbbbf0b0cd4abf5898136d0c345dc99b859c8cBrian Gerst * @i: required value
345abbbbf0b0cd4abf5898136d0c345dc99b859c8cBrian Gerst *
355abbbbf0b0cd4abf5898136d0c345dc99b859c8cBrian Gerst * Atomically sets the value of @v to @i.
365abbbbf0b0cd4abf5898136d0c345dc99b859c8cBrian Gerst */
375abbbbf0b0cd4abf5898136d0c345dc99b859c8cBrian Gerststatic inline void atomic_set(atomic_t *v, int i)
385abbbbf0b0cd4abf5898136d0c345dc99b859c8cBrian Gerst{
395abbbbf0b0cd4abf5898136d0c345dc99b859c8cBrian Gerst	v->counter = i;
405abbbbf0b0cd4abf5898136d0c345dc99b859c8cBrian Gerst}
415abbbbf0b0cd4abf5898136d0c345dc99b859c8cBrian Gerst
425abbbbf0b0cd4abf5898136d0c345dc99b859c8cBrian Gerst/**
435abbbbf0b0cd4abf5898136d0c345dc99b859c8cBrian Gerst * atomic_add - add integer to atomic variable
445abbbbf0b0cd4abf5898136d0c345dc99b859c8cBrian Gerst * @i: integer value to add
455abbbbf0b0cd4abf5898136d0c345dc99b859c8cBrian Gerst * @v: pointer of type atomic_t
465abbbbf0b0cd4abf5898136d0c345dc99b859c8cBrian Gerst *
475abbbbf0b0cd4abf5898136d0c345dc99b859c8cBrian Gerst * Atomically adds @i to @v.
485abbbbf0b0cd4abf5898136d0c345dc99b859c8cBrian Gerst */
495abbbbf0b0cd4abf5898136d0c345dc99b859c8cBrian Gerststatic inline void atomic_add(int i, atomic_t *v)
505abbbbf0b0cd4abf5898136d0c345dc99b859c8cBrian Gerst{
515abbbbf0b0cd4abf5898136d0c345dc99b859c8cBrian Gerst	asm volatile(LOCK_PREFIX "addl %1,%0"
525abbbbf0b0cd4abf5898136d0c345dc99b859c8cBrian Gerst		     : "+m" (v->counter)
535abbbbf0b0cd4abf5898136d0c345dc99b859c8cBrian Gerst		     : "ir" (i));
545abbbbf0b0cd4abf5898136d0c345dc99b859c8cBrian Gerst}
555abbbbf0b0cd4abf5898136d0c345dc99b859c8cBrian Gerst
565abbbbf0b0cd4abf5898136d0c345dc99b859c8cBrian Gerst/**
575abbbbf0b0cd4abf5898136d0c345dc99b859c8cBrian Gerst * atomic_sub - subtract integer from atomic variable
585abbbbf0b0cd4abf5898136d0c345dc99b859c8cBrian Gerst * @i: integer value to subtract
595abbbbf0b0cd4abf5898136d0c345dc99b859c8cBrian Gerst * @v: pointer of type atomic_t
605abbbbf0b0cd4abf5898136d0c345dc99b859c8cBrian Gerst *
615abbbbf0b0cd4abf5898136d0c345dc99b859c8cBrian Gerst * Atomically subtracts @i from @v.
625abbbbf0b0cd4abf5898136d0c345dc99b859c8cBrian Gerst */
635abbbbf0b0cd4abf5898136d0c345dc99b859c8cBrian Gerststatic inline void atomic_sub(int i, atomic_t *v)
645abbbbf0b0cd4abf5898136d0c345dc99b859c8cBrian Gerst{
655abbbbf0b0cd4abf5898136d0c345dc99b859c8cBrian Gerst	asm volatile(LOCK_PREFIX "subl %1,%0"
665abbbbf0b0cd4abf5898136d0c345dc99b859c8cBrian Gerst		     : "+m" (v->counter)
675abbbbf0b0cd4abf5898136d0c345dc99b859c8cBrian Gerst		     : "ir" (i));
685abbbbf0b0cd4abf5898136d0c345dc99b859c8cBrian Gerst}
695abbbbf0b0cd4abf5898136d0c345dc99b859c8cBrian Gerst
705abbbbf0b0cd4abf5898136d0c345dc99b859c8cBrian Gerst/**
715abbbbf0b0cd4abf5898136d0c345dc99b859c8cBrian Gerst * atomic_sub_and_test - subtract value from variable and test result
725abbbbf0b0cd4abf5898136d0c345dc99b859c8cBrian Gerst * @i: integer value to subtract
735abbbbf0b0cd4abf5898136d0c345dc99b859c8cBrian Gerst * @v: pointer of type atomic_t
745abbbbf0b0cd4abf5898136d0c345dc99b859c8cBrian Gerst *
755abbbbf0b0cd4abf5898136d0c345dc99b859c8cBrian Gerst * Atomically subtracts @i from @v and returns
765abbbbf0b0cd4abf5898136d0c345dc99b859c8cBrian Gerst * true if the result is zero, or false for all
775abbbbf0b0cd4abf5898136d0c345dc99b859c8cBrian Gerst * other cases.
785abbbbf0b0cd4abf5898136d0c345dc99b859c8cBrian Gerst */
795abbbbf0b0cd4abf5898136d0c345dc99b859c8cBrian Gerststatic inline int atomic_sub_and_test(int i, atomic_t *v)
805abbbbf0b0cd4abf5898136d0c345dc99b859c8cBrian Gerst{
81e0f6dec35f9286e78879fe1ac92803fd69fc4fdcH. Peter Anvin	GEN_BINARY_RMWcc(LOCK_PREFIX "subl", v->counter, "er", i, "%0", "e");
825abbbbf0b0cd4abf5898136d0c345dc99b859c8cBrian Gerst}
835abbbbf0b0cd4abf5898136d0c345dc99b859c8cBrian Gerst
845abbbbf0b0cd4abf5898136d0c345dc99b859c8cBrian Gerst/**
855abbbbf0b0cd4abf5898136d0c345dc99b859c8cBrian Gerst * atomic_inc - increment atomic variable
865abbbbf0b0cd4abf5898136d0c345dc99b859c8cBrian Gerst * @v: pointer of type atomic_t
875abbbbf0b0cd4abf5898136d0c345dc99b859c8cBrian Gerst *
885abbbbf0b0cd4abf5898136d0c345dc99b859c8cBrian Gerst * Atomically increments @v by 1.
895abbbbf0b0cd4abf5898136d0c345dc99b859c8cBrian Gerst */
905abbbbf0b0cd4abf5898136d0c345dc99b859c8cBrian Gerststatic inline void atomic_inc(atomic_t *v)
915abbbbf0b0cd4abf5898136d0c345dc99b859c8cBrian Gerst{
925abbbbf0b0cd4abf5898136d0c345dc99b859c8cBrian Gerst	asm volatile(LOCK_PREFIX "incl %0"
935abbbbf0b0cd4abf5898136d0c345dc99b859c8cBrian Gerst		     : "+m" (v->counter));
945abbbbf0b0cd4abf5898136d0c345dc99b859c8cBrian Gerst}
955abbbbf0b0cd4abf5898136d0c345dc99b859c8cBrian Gerst
965abbbbf0b0cd4abf5898136d0c345dc99b859c8cBrian Gerst/**
975abbbbf0b0cd4abf5898136d0c345dc99b859c8cBrian Gerst * atomic_dec - decrement atomic variable
985abbbbf0b0cd4abf5898136d0c345dc99b859c8cBrian Gerst * @v: pointer of type atomic_t
995abbbbf0b0cd4abf5898136d0c345dc99b859c8cBrian Gerst *
1005abbbbf0b0cd4abf5898136d0c345dc99b859c8cBrian Gerst * Atomically decrements @v by 1.
1015abbbbf0b0cd4abf5898136d0c345dc99b859c8cBrian Gerst */
1025abbbbf0b0cd4abf5898136d0c345dc99b859c8cBrian Gerststatic inline void atomic_dec(atomic_t *v)
1035abbbbf0b0cd4abf5898136d0c345dc99b859c8cBrian Gerst{
1045abbbbf0b0cd4abf5898136d0c345dc99b859c8cBrian Gerst	asm volatile(LOCK_PREFIX "decl %0"
1055abbbbf0b0cd4abf5898136d0c345dc99b859c8cBrian Gerst		     : "+m" (v->counter));
1065abbbbf0b0cd4abf5898136d0c345dc99b859c8cBrian Gerst}
1075abbbbf0b0cd4abf5898136d0c345dc99b859c8cBrian Gerst
1085abbbbf0b0cd4abf5898136d0c345dc99b859c8cBrian Gerst/**
1095abbbbf0b0cd4abf5898136d0c345dc99b859c8cBrian Gerst * atomic_dec_and_test - decrement and test
1105abbbbf0b0cd4abf5898136d0c345dc99b859c8cBrian Gerst * @v: pointer of type atomic_t
1115abbbbf0b0cd4abf5898136d0c345dc99b859c8cBrian Gerst *
1125abbbbf0b0cd4abf5898136d0c345dc99b859c8cBrian Gerst * Atomically decrements @v by 1 and
1135abbbbf0b0cd4abf5898136d0c345dc99b859c8cBrian Gerst * returns true if the result is 0, or false for all other
1145abbbbf0b0cd4abf5898136d0c345dc99b859c8cBrian Gerst * cases.
1155abbbbf0b0cd4abf5898136d0c345dc99b859c8cBrian Gerst */
1165abbbbf0b0cd4abf5898136d0c345dc99b859c8cBrian Gerststatic inline int atomic_dec_and_test(atomic_t *v)
1175abbbbf0b0cd4abf5898136d0c345dc99b859c8cBrian Gerst{
1180c44c2d0f459cd7e275242b72f500137c4fa834dPeter Zijlstra	GEN_UNARY_RMWcc(LOCK_PREFIX "decl", v->counter, "%0", "e");
1195abbbbf0b0cd4abf5898136d0c345dc99b859c8cBrian Gerst}
1205abbbbf0b0cd4abf5898136d0c345dc99b859c8cBrian Gerst
1215abbbbf0b0cd4abf5898136d0c345dc99b859c8cBrian Gerst/**
1225abbbbf0b0cd4abf5898136d0c345dc99b859c8cBrian Gerst * atomic_inc_and_test - increment and test
1235abbbbf0b0cd4abf5898136d0c345dc99b859c8cBrian Gerst * @v: pointer of type atomic_t
1245abbbbf0b0cd4abf5898136d0c345dc99b859c8cBrian Gerst *
1255abbbbf0b0cd4abf5898136d0c345dc99b859c8cBrian Gerst * Atomically increments @v by 1
1265abbbbf0b0cd4abf5898136d0c345dc99b859c8cBrian Gerst * and returns true if the result is zero, or false for all
1275abbbbf0b0cd4abf5898136d0c345dc99b859c8cBrian Gerst * other cases.
1285abbbbf0b0cd4abf5898136d0c345dc99b859c8cBrian Gerst */
1295abbbbf0b0cd4abf5898136d0c345dc99b859c8cBrian Gerststatic inline int atomic_inc_and_test(atomic_t *v)
1305abbbbf0b0cd4abf5898136d0c345dc99b859c8cBrian Gerst{
1310c44c2d0f459cd7e275242b72f500137c4fa834dPeter Zijlstra	GEN_UNARY_RMWcc(LOCK_PREFIX "incl", v->counter, "%0", "e");
1325abbbbf0b0cd4abf5898136d0c345dc99b859c8cBrian Gerst}
1335abbbbf0b0cd4abf5898136d0c345dc99b859c8cBrian Gerst
1345abbbbf0b0cd4abf5898136d0c345dc99b859c8cBrian Gerst/**
1355abbbbf0b0cd4abf5898136d0c345dc99b859c8cBrian Gerst * atomic_add_negative - add and test if negative
1365abbbbf0b0cd4abf5898136d0c345dc99b859c8cBrian Gerst * @i: integer value to add
1375abbbbf0b0cd4abf5898136d0c345dc99b859c8cBrian Gerst * @v: pointer of type atomic_t
1385abbbbf0b0cd4abf5898136d0c345dc99b859c8cBrian Gerst *
1395abbbbf0b0cd4abf5898136d0c345dc99b859c8cBrian Gerst * Atomically adds @i to @v and returns true
1405abbbbf0b0cd4abf5898136d0c345dc99b859c8cBrian Gerst * if the result is negative, or false when
1415abbbbf0b0cd4abf5898136d0c345dc99b859c8cBrian Gerst * result is greater than or equal to zero.
1425abbbbf0b0cd4abf5898136d0c345dc99b859c8cBrian Gerst */
1435abbbbf0b0cd4abf5898136d0c345dc99b859c8cBrian Gerststatic inline int atomic_add_negative(int i, atomic_t *v)
1445abbbbf0b0cd4abf5898136d0c345dc99b859c8cBrian Gerst{
145e0f6dec35f9286e78879fe1ac92803fd69fc4fdcH. Peter Anvin	GEN_BINARY_RMWcc(LOCK_PREFIX "addl", v->counter, "er", i, "%0", "s");
1465abbbbf0b0cd4abf5898136d0c345dc99b859c8cBrian Gerst}
1475abbbbf0b0cd4abf5898136d0c345dc99b859c8cBrian Gerst
1485abbbbf0b0cd4abf5898136d0c345dc99b859c8cBrian Gerst/**
1495abbbbf0b0cd4abf5898136d0c345dc99b859c8cBrian Gerst * atomic_add_return - add integer and return
1505abbbbf0b0cd4abf5898136d0c345dc99b859c8cBrian Gerst * @i: integer value to add
1515abbbbf0b0cd4abf5898136d0c345dc99b859c8cBrian Gerst * @v: pointer of type atomic_t
1525abbbbf0b0cd4abf5898136d0c345dc99b859c8cBrian Gerst *
1535abbbbf0b0cd4abf5898136d0c345dc99b859c8cBrian Gerst * Atomically adds @i to @v and returns @i + @v
1545abbbbf0b0cd4abf5898136d0c345dc99b859c8cBrian Gerst */
1555abbbbf0b0cd4abf5898136d0c345dc99b859c8cBrian Gerststatic inline int atomic_add_return(int i, atomic_t *v)
1565abbbbf0b0cd4abf5898136d0c345dc99b859c8cBrian Gerst{
1578b8bc2f7311c3223213dbe346d9cc2e299fdb5ebJeremy Fitzhardinge	return i + xadd(&v->counter, i);
1585abbbbf0b0cd4abf5898136d0c345dc99b859c8cBrian Gerst}
1595abbbbf0b0cd4abf5898136d0c345dc99b859c8cBrian Gerst
1605abbbbf0b0cd4abf5898136d0c345dc99b859c8cBrian Gerst/**
1615abbbbf0b0cd4abf5898136d0c345dc99b859c8cBrian Gerst * atomic_sub_return - subtract integer and return
1625abbbbf0b0cd4abf5898136d0c345dc99b859c8cBrian Gerst * @v: pointer of type atomic_t
1635abbbbf0b0cd4abf5898136d0c345dc99b859c8cBrian Gerst * @i: integer value to subtract
1645abbbbf0b0cd4abf5898136d0c345dc99b859c8cBrian Gerst *
1655abbbbf0b0cd4abf5898136d0c345dc99b859c8cBrian Gerst * Atomically subtracts @i from @v and returns @v - @i
1665abbbbf0b0cd4abf5898136d0c345dc99b859c8cBrian Gerst */
1675abbbbf0b0cd4abf5898136d0c345dc99b859c8cBrian Gerststatic inline int atomic_sub_return(int i, atomic_t *v)
1685abbbbf0b0cd4abf5898136d0c345dc99b859c8cBrian Gerst{
1695abbbbf0b0cd4abf5898136d0c345dc99b859c8cBrian Gerst	return atomic_add_return(-i, v);
1705abbbbf0b0cd4abf5898136d0c345dc99b859c8cBrian Gerst}
1715abbbbf0b0cd4abf5898136d0c345dc99b859c8cBrian Gerst
1725abbbbf0b0cd4abf5898136d0c345dc99b859c8cBrian Gerst#define atomic_inc_return(v)  (atomic_add_return(1, v))
1735abbbbf0b0cd4abf5898136d0c345dc99b859c8cBrian Gerst#define atomic_dec_return(v)  (atomic_sub_return(1, v))
1745abbbbf0b0cd4abf5898136d0c345dc99b859c8cBrian Gerst
1755abbbbf0b0cd4abf5898136d0c345dc99b859c8cBrian Gerststatic inline int atomic_cmpxchg(atomic_t *v, int old, int new)
1765abbbbf0b0cd4abf5898136d0c345dc99b859c8cBrian Gerst{
1775abbbbf0b0cd4abf5898136d0c345dc99b859c8cBrian Gerst	return cmpxchg(&v->counter, old, new);
1785abbbbf0b0cd4abf5898136d0c345dc99b859c8cBrian Gerst}
1795abbbbf0b0cd4abf5898136d0c345dc99b859c8cBrian Gerst
1805abbbbf0b0cd4abf5898136d0c345dc99b859c8cBrian Gerststatic inline int atomic_xchg(atomic_t *v, int new)
1815abbbbf0b0cd4abf5898136d0c345dc99b859c8cBrian Gerst{
1825abbbbf0b0cd4abf5898136d0c345dc99b859c8cBrian Gerst	return xchg(&v->counter, new);
1835abbbbf0b0cd4abf5898136d0c345dc99b859c8cBrian Gerst}
1845abbbbf0b0cd4abf5898136d0c345dc99b859c8cBrian Gerst
1855abbbbf0b0cd4abf5898136d0c345dc99b859c8cBrian Gerst/**
186f24219b4e90cf70ec4a211b17fbabc725a0ddf3cArun Sharma * __atomic_add_unless - add unless the number is already a given value
1875abbbbf0b0cd4abf5898136d0c345dc99b859c8cBrian Gerst * @v: pointer of type atomic_t
1885abbbbf0b0cd4abf5898136d0c345dc99b859c8cBrian Gerst * @a: the amount to add to v...
1895abbbbf0b0cd4abf5898136d0c345dc99b859c8cBrian Gerst * @u: ...unless v is equal to u.
1905abbbbf0b0cd4abf5898136d0c345dc99b859c8cBrian Gerst *
1915abbbbf0b0cd4abf5898136d0c345dc99b859c8cBrian Gerst * Atomically adds @a to @v, so long as @v was not already @u.
192f24219b4e90cf70ec4a211b17fbabc725a0ddf3cArun Sharma * Returns the old value of @v.
1935abbbbf0b0cd4abf5898136d0c345dc99b859c8cBrian Gerst */
194f24219b4e90cf70ec4a211b17fbabc725a0ddf3cArun Sharmastatic inline int __atomic_add_unless(atomic_t *v, int a, int u)
1955abbbbf0b0cd4abf5898136d0c345dc99b859c8cBrian Gerst{
1965abbbbf0b0cd4abf5898136d0c345dc99b859c8cBrian Gerst	int c, old;
1975abbbbf0b0cd4abf5898136d0c345dc99b859c8cBrian Gerst	c = atomic_read(v);
1985abbbbf0b0cd4abf5898136d0c345dc99b859c8cBrian Gerst	for (;;) {
1995abbbbf0b0cd4abf5898136d0c345dc99b859c8cBrian Gerst		if (unlikely(c == (u)))
2005abbbbf0b0cd4abf5898136d0c345dc99b859c8cBrian Gerst			break;
2015abbbbf0b0cd4abf5898136d0c345dc99b859c8cBrian Gerst		old = atomic_cmpxchg((v), c, c + (a));
2025abbbbf0b0cd4abf5898136d0c345dc99b859c8cBrian Gerst		if (likely(old == c))
2035abbbbf0b0cd4abf5898136d0c345dc99b859c8cBrian Gerst			break;
2045abbbbf0b0cd4abf5898136d0c345dc99b859c8cBrian Gerst		c = old;
2055abbbbf0b0cd4abf5898136d0c345dc99b859c8cBrian Gerst	}
206f24219b4e90cf70ec4a211b17fbabc725a0ddf3cArun Sharma	return c;
2075abbbbf0b0cd4abf5898136d0c345dc99b859c8cBrian Gerst}
2085abbbbf0b0cd4abf5898136d0c345dc99b859c8cBrian Gerst
2095abbbbf0b0cd4abf5898136d0c345dc99b859c8cBrian Gerst/**
2105abbbbf0b0cd4abf5898136d0c345dc99b859c8cBrian Gerst * atomic_inc_short - increment of a short integer
2115abbbbf0b0cd4abf5898136d0c345dc99b859c8cBrian Gerst * @v: pointer to type int
2125abbbbf0b0cd4abf5898136d0c345dc99b859c8cBrian Gerst *
2135abbbbf0b0cd4abf5898136d0c345dc99b859c8cBrian Gerst * Atomically adds 1 to @v
2145abbbbf0b0cd4abf5898136d0c345dc99b859c8cBrian Gerst * Returns the new value of @u
2155abbbbf0b0cd4abf5898136d0c345dc99b859c8cBrian Gerst */
2165abbbbf0b0cd4abf5898136d0c345dc99b859c8cBrian Gerststatic inline short int atomic_inc_short(short int *v)
2175abbbbf0b0cd4abf5898136d0c345dc99b859c8cBrian Gerst{
2185abbbbf0b0cd4abf5898136d0c345dc99b859c8cBrian Gerst	asm(LOCK_PREFIX "addw $1, %0" : "+m" (*v));
2195abbbbf0b0cd4abf5898136d0c345dc99b859c8cBrian Gerst	return *v;
2205abbbbf0b0cd4abf5898136d0c345dc99b859c8cBrian Gerst}
2215abbbbf0b0cd4abf5898136d0c345dc99b859c8cBrian Gerst
2225abbbbf0b0cd4abf5898136d0c345dc99b859c8cBrian Gerst/* These are x86-specific, used by some header files */
2235abbbbf0b0cd4abf5898136d0c345dc99b859c8cBrian Gerst#define atomic_clear_mask(mask, addr)				\
2245abbbbf0b0cd4abf5898136d0c345dc99b859c8cBrian Gerst	asm volatile(LOCK_PREFIX "andl %0,%1"			\
2255abbbbf0b0cd4abf5898136d0c345dc99b859c8cBrian Gerst		     : : "r" (~(mask)), "m" (*(addr)) : "memory")
2265abbbbf0b0cd4abf5898136d0c345dc99b859c8cBrian Gerst
2275abbbbf0b0cd4abf5898136d0c345dc99b859c8cBrian Gerst#define atomic_set_mask(mask, addr)				\
2285abbbbf0b0cd4abf5898136d0c345dc99b859c8cBrian Gerst	asm volatile(LOCK_PREFIX "orl %0,%1"			\
2295abbbbf0b0cd4abf5898136d0c345dc99b859c8cBrian Gerst		     : : "r" ((unsigned)(mask)), "m" (*(addr))	\
2305abbbbf0b0cd4abf5898136d0c345dc99b859c8cBrian Gerst		     : "memory")
2315abbbbf0b0cd4abf5898136d0c345dc99b859c8cBrian Gerst
23296a388de5dc53a8b234b3fd41f3ae2cedc9ffd42Thomas Gleixner#ifdef CONFIG_X86_32
233a1ce39288e6fbefdd8d607021d02384eb4a20b99David Howells# include <asm/atomic64_32.h>
23496a388de5dc53a8b234b3fd41f3ae2cedc9ffd42Thomas Gleixner#else
235a1ce39288e6fbefdd8d607021d02384eb4a20b99David Howells# include <asm/atomic64_64.h>
23696a388de5dc53a8b234b3fd41f3ae2cedc9ffd42Thomas Gleixner#endif
2375abbbbf0b0cd4abf5898136d0c345dc99b859c8cBrian Gerst
2385abbbbf0b0cd4abf5898136d0c345dc99b859c8cBrian Gerst#endif /* _ASM_X86_ATOMIC_H */
239