/*1* Copyright 2010 Tilera Corporation. All Rights Reserved.2*3* This program is free software; you can redistribute it and/or4* modify it under the terms of the GNU General Public License5* as published by the Free Software Foundation, version 2.6*7* This program is distributed in the hope that it will be useful, but8* WITHOUT ANY WARRANTY; without even the implied warranty of9* MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or10* NON INFRINGEMENT. See the GNU General Public License for11* more details.12*13* Atomic primitives.14*/1516#ifndef _ASM_TILE_ATOMIC_H17#define _ASM_TILE_ATOMIC_H1819#ifndef __ASSEMBLY__2021#include <linux/compiler.h>22#include <asm/system.h>2324#define ATOMIC_INIT(i) { (i) }2526/**27* atomic_read - read atomic variable28* @v: pointer of type atomic_t29*30* Atomically reads the value of @v.31*/32static inline int atomic_read(const atomic_t *v)33{34return ACCESS_ONCE(v->counter);35}3637/**38* atomic_sub_return - subtract integer and return39* @v: pointer of type atomic_t40* @i: integer value to subtract41*42* Atomically subtracts @i from @v and returns @v - @i43*/44#define atomic_sub_return(i, v) atomic_add_return((int)(-(i)), (v))4546/**47* atomic_sub - subtract integer from atomic variable48* @i: integer value to subtract49* @v: pointer of type atomic_t50*51* Atomically subtracts @i from @v.52*/53#define atomic_sub(i, v) atomic_add((int)(-(i)), (v))5455/**56* atomic_sub_and_test - subtract value from variable and test result57* @i: integer value to subtract58* @v: pointer of type atomic_t59*60* Atomically subtracts @i from @v and returns true if the result is61* zero, or false for all other cases.62*/63#define atomic_sub_and_test(i, v) (atomic_sub_return((i), (v)) == 0)6465/**66* atomic_inc_return - increment memory and return67* @v: pointer of type atomic_t68*69* Atomically increments @v by 1 and returns the new value.70*/71#define atomic_inc_return(v) atomic_add_return(1, (v))7273/**74* atomic_dec_return - decrement memory and return75* @v: pointer of type atomic_t76*77* Atomically decrements @v by 1 and returns the new value.78*/79#define atomic_dec_return(v) atomic_sub_return(1, (v))8081/**82* atomic_inc - increment atomic variable83* @v: pointer of type atomic_t84*85* Atomically increments @v by 1.86*/87#define atomic_inc(v) atomic_add(1, (v))8889/**90* atomic_dec - decrement atomic variable91* @v: pointer of type atomic_t92*93* Atomically decrements @v by 1.94*/95#define atomic_dec(v) atomic_sub(1, (v))9697/**98* atomic_dec_and_test - decrement and test99* @v: pointer of type atomic_t100*101* Atomically decrements @v by 1 and returns true if the result is 0.102*/103#define atomic_dec_and_test(v) (atomic_dec_return(v) == 0)104105/**106* atomic_inc_and_test - increment and test107* @v: pointer of type atomic_t108*109* Atomically increments @v by 1 and returns true if the result is 0.110*/111#define atomic_inc_and_test(v) (atomic_inc_return(v) == 0)112113/**114* atomic_add_negative - add and test if negative115* @v: pointer of type atomic_t116* @i: integer value to add117*118* Atomically adds @i to @v and returns true if the result is119* negative, or false when result is greater than or equal to zero.120*/121#define atomic_add_negative(i, v) (atomic_add_return((i), (v)) < 0)122123/**124* atomic_inc_not_zero - increment unless the number is zero125* @v: pointer of type atomic_t126*127* Atomically increments @v by 1, so long as @v is non-zero.128* Returns non-zero if @v was non-zero, and zero otherwise.129*/130#define atomic_inc_not_zero(v) atomic_add_unless((v), 1, 0)131132/* Nonexistent functions intended to cause link errors. */133extern unsigned long __xchg_called_with_bad_pointer(void);134extern unsigned long __cmpxchg_called_with_bad_pointer(void);135136#define xchg(ptr, x) \137({ \138typeof(*(ptr)) __x; \139switch (sizeof(*(ptr))) { \140case 4: \141__x = (typeof(__x))(typeof(__x-__x))atomic_xchg( \142(atomic_t *)(ptr), \143(u32)(typeof((x)-(x)))(x)); \144break; \145case 8: \146__x = (typeof(__x))(typeof(__x-__x))atomic64_xchg( \147(atomic64_t *)(ptr), \148(u64)(typeof((x)-(x)))(x)); \149break; \150default: \151__xchg_called_with_bad_pointer(); \152} \153__x; \154})155156#define cmpxchg(ptr, o, n) \157({ \158typeof(*(ptr)) __x; \159switch (sizeof(*(ptr))) { \160case 4: \161__x = (typeof(__x))(typeof(__x-__x))atomic_cmpxchg( \162(atomic_t *)(ptr), \163(u32)(typeof((o)-(o)))(o), \164(u32)(typeof((n)-(n)))(n)); \165break; \166case 8: \167__x = (typeof(__x))(typeof(__x-__x))atomic64_cmpxchg( \168(atomic64_t *)(ptr), \169(u64)(typeof((o)-(o)))(o), \170(u64)(typeof((n)-(n)))(n)); \171break; \172default: \173__cmpxchg_called_with_bad_pointer(); \174} \175__x; \176})177178#define tas(ptr) (xchg((ptr), 1))179180#endif /* __ASSEMBLY__ */181182#ifndef __tilegx__183#include <asm/atomic_32.h>184#else185#include <asm/atomic_64.h>186#endif187188/* Provide the appropriate atomic_long_t definitions. */189#ifndef __ASSEMBLY__190#include <asm-generic/atomic-long.h>191#endif192193#endif /* _ASM_TILE_ATOMIC_H */194195196