at v3.0-rc7 194 lines 5.1 kB view raw
1/* 2 * Copyright 2010 Tilera Corporation. All Rights Reserved. 3 * 4 * This program is free software; you can redistribute it and/or 5 * modify it under the terms of the GNU General Public License 6 * as published by the Free Software Foundation, version 2. 7 * 8 * This program is distributed in the hope that it will be useful, but 9 * WITHOUT ANY WARRANTY; without even the implied warranty of 10 * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or 11 * NON INFRINGEMENT. See the GNU General Public License for 12 * more details. 13 * 14 * Atomic primitives. 15 */ 16 17#ifndef _ASM_TILE_ATOMIC_H 18#define _ASM_TILE_ATOMIC_H 19 20#ifndef __ASSEMBLY__ 21 22#include <linux/compiler.h> 23#include <asm/system.h> 24 25#define ATOMIC_INIT(i) { (i) } 26 27/** 28 * atomic_read - read atomic variable 29 * @v: pointer of type atomic_t 30 * 31 * Atomically reads the value of @v. 32 */ 33static inline int atomic_read(const atomic_t *v) 34{ 35 return ACCESS_ONCE(v->counter); 36} 37 38/** 39 * atomic_sub_return - subtract integer and return 40 * @v: pointer of type atomic_t 41 * @i: integer value to subtract 42 * 43 * Atomically subtracts @i from @v and returns @v - @i 44 */ 45#define atomic_sub_return(i, v) atomic_add_return((int)(-(i)), (v)) 46 47/** 48 * atomic_sub - subtract integer from atomic variable 49 * @i: integer value to subtract 50 * @v: pointer of type atomic_t 51 * 52 * Atomically subtracts @i from @v. 53 */ 54#define atomic_sub(i, v) atomic_add((int)(-(i)), (v)) 55 56/** 57 * atomic_sub_and_test - subtract value from variable and test result 58 * @i: integer value to subtract 59 * @v: pointer of type atomic_t 60 * 61 * Atomically subtracts @i from @v and returns true if the result is 62 * zero, or false for all other cases. 63 */ 64#define atomic_sub_and_test(i, v) (atomic_sub_return((i), (v)) == 0) 65 66/** 67 * atomic_inc_return - increment memory and return 68 * @v: pointer of type atomic_t 69 * 70 * Atomically increments @v by 1 and returns the new value. 71 */ 72#define atomic_inc_return(v) atomic_add_return(1, (v)) 73 74/** 75 * atomic_dec_return - decrement memory and return 76 * @v: pointer of type atomic_t 77 * 78 * Atomically decrements @v by 1 and returns the new value. 79 */ 80#define atomic_dec_return(v) atomic_sub_return(1, (v)) 81 82/** 83 * atomic_inc - increment atomic variable 84 * @v: pointer of type atomic_t 85 * 86 * Atomically increments @v by 1. 87 */ 88#define atomic_inc(v) atomic_add(1, (v)) 89 90/** 91 * atomic_dec - decrement atomic variable 92 * @v: pointer of type atomic_t 93 * 94 * Atomically decrements @v by 1. 95 */ 96#define atomic_dec(v) atomic_sub(1, (v)) 97 98/** 99 * atomic_dec_and_test - decrement and test 100 * @v: pointer of type atomic_t 101 * 102 * Atomically decrements @v by 1 and returns true if the result is 0. 103 */ 104#define atomic_dec_and_test(v) (atomic_dec_return(v) == 0) 105 106/** 107 * atomic_inc_and_test - increment and test 108 * @v: pointer of type atomic_t 109 * 110 * Atomically increments @v by 1 and returns true if the result is 0. 111 */ 112#define atomic_inc_and_test(v) (atomic_inc_return(v) == 0) 113 114/** 115 * atomic_add_negative - add and test if negative 116 * @v: pointer of type atomic_t 117 * @i: integer value to add 118 * 119 * Atomically adds @i to @v and returns true if the result is 120 * negative, or false when result is greater than or equal to zero. 121 */ 122#define atomic_add_negative(i, v) (atomic_add_return((i), (v)) < 0) 123 124/** 125 * atomic_inc_not_zero - increment unless the number is zero 126 * @v: pointer of type atomic_t 127 * 128 * Atomically increments @v by 1, so long as @v is non-zero. 129 * Returns non-zero if @v was non-zero, and zero otherwise. 130 */ 131#define atomic_inc_not_zero(v) atomic_add_unless((v), 1, 0) 132 133/* Nonexistent functions intended to cause link errors. */ 134extern unsigned long __xchg_called_with_bad_pointer(void); 135extern unsigned long __cmpxchg_called_with_bad_pointer(void); 136 137#define xchg(ptr, x) \ 138 ({ \ 139 typeof(*(ptr)) __x; \ 140 switch (sizeof(*(ptr))) { \ 141 case 4: \ 142 __x = (typeof(__x))(typeof(__x-__x))atomic_xchg( \ 143 (atomic_t *)(ptr), \ 144 (u32)(typeof((x)-(x)))(x)); \ 145 break; \ 146 case 8: \ 147 __x = (typeof(__x))(typeof(__x-__x))atomic64_xchg( \ 148 (atomic64_t *)(ptr), \ 149 (u64)(typeof((x)-(x)))(x)); \ 150 break; \ 151 default: \ 152 __xchg_called_with_bad_pointer(); \ 153 } \ 154 __x; \ 155 }) 156 157#define cmpxchg(ptr, o, n) \ 158 ({ \ 159 typeof(*(ptr)) __x; \ 160 switch (sizeof(*(ptr))) { \ 161 case 4: \ 162 __x = (typeof(__x))(typeof(__x-__x))atomic_cmpxchg( \ 163 (atomic_t *)(ptr), \ 164 (u32)(typeof((o)-(o)))(o), \ 165 (u32)(typeof((n)-(n)))(n)); \ 166 break; \ 167 case 8: \ 168 __x = (typeof(__x))(typeof(__x-__x))atomic64_cmpxchg( \ 169 (atomic64_t *)(ptr), \ 170 (u64)(typeof((o)-(o)))(o), \ 171 (u64)(typeof((n)-(n)))(n)); \ 172 break; \ 173 default: \ 174 __cmpxchg_called_with_bad_pointer(); \ 175 } \ 176 __x; \ 177 }) 178 179#define tas(ptr) (xchg((ptr), 1)) 180 181#endif /* __ASSEMBLY__ */ 182 183#ifndef __tilegx__ 184#include <asm/atomic_32.h> 185#else 186#include <asm/atomic_64.h> 187#endif 188 189/* Provide the appropriate atomic_long_t definitions. */ 190#ifndef __ASSEMBLY__ 191#include <asm-generic/atomic-long.h> 192#endif 193 194#endif /* _ASM_TILE_ATOMIC_H */