linux/arch/x86/include/asm/atomic_64.h
<<
>>
Prefs
   1#ifndef _ASM_X86_ATOMIC_64_H
   2#define _ASM_X86_ATOMIC_64_H
   3
   4#include <linux/types.h>
   5#include <asm/alternative.h>
   6#include <asm/cmpxchg.h>
   7
   8/*
   9 * Atomic operations that C can't guarantee us.  Useful for
  10 * resource counting etc..
  11 */
  12
  13#define ATOMIC_INIT(i)  { (i) }
  14
  15/**
  16 * atomic_read - read atomic variable
  17 * @v: pointer of type atomic_t
  18 *
  19 * Atomically reads the value of @v.
  20 */
  21#define atomic_read(v)          ((v)->counter)
  22
  23/**
  24 * atomic_set - set atomic variable
  25 * @v: pointer of type atomic_t
  26 * @i: required value
  27 *
  28 * Atomically sets the value of @v to @i.
  29 */
  30#define atomic_set(v, i)                (((v)->counter) = (i))
  31
  32/**
  33 * atomic_add - add integer to atomic variable
  34 * @i: integer value to add
  35 * @v: pointer of type atomic_t
  36 *
  37 * Atomically adds @i to @v.
  38 */
  39static inline void atomic_add(int i, atomic_t *v)
  40{
  41        asm volatile(LOCK_PREFIX "addl %1,%0"
  42                     : "=m" (v->counter)
  43                     : "ir" (i), "m" (v->counter));
  44}
  45
  46/**
  47 * atomic_sub - subtract the atomic variable
  48 * @i: integer value to subtract
  49 * @v: pointer of type atomic_t
  50 *
  51 * Atomically subtracts @i from @v.
  52 */
  53static inline void atomic_sub(int i, atomic_t *v)
  54{
  55        asm volatile(LOCK_PREFIX "subl %1,%0"
  56                     : "=m" (v->counter)
  57                     : "ir" (i), "m" (v->counter));
  58}
  59
  60/**
  61 * atomic_sub_and_test - subtract value from variable and test result
  62 * @i: integer value to subtract
  63 * @v: pointer of type atomic_t
  64 *
  65 * Atomically subtracts @i from @v and returns
  66 * true if the result is zero, or false for all
  67 * other cases.
  68 */
  69static inline int atomic_sub_and_test(int i, atomic_t *v)
  70{
  71        unsigned char c;
  72
  73        asm volatile(LOCK_PREFIX "subl %2,%0; sete %1"
  74                     : "=m" (v->counter), "=qm" (c)
  75                     : "ir" (i), "m" (v->counter) : "memory");
  76        return c;
  77}
  78
  79/**
  80 * atomic_inc - increment atomic variable
  81 * @v: pointer of type atomic_t
  82 *
  83 * Atomically increments @v by 1.
  84 */
  85static inline void atomic_inc(atomic_t *v)
  86{
  87        asm volatile(LOCK_PREFIX "incl %0"
  88                     : "=m" (v->counter)
  89                     : "m" (v->counter));
  90}
  91
  92/**
  93 * atomic_dec - decrement atomic variable
  94 * @v: pointer of type atomic_t
  95 *
  96 * Atomically decrements @v by 1.
  97 */
  98static inline void atomic_dec(atomic_t *v)
  99{
 100        asm volatile(LOCK_PREFIX "decl %0"
 101                     : "=m" (v->counter)
 102                     : "m" (v->counter));
 103}
 104
 105/**
 106 * atomic_dec_and_test - decrement and test
 107 * @v: pointer of type atomic_t
 108 *
 109 * Atomically decrements @v by 1 and
 110 * returns true if the result is 0, or false for all other
 111 * cases.
 112 */
 113static inline int atomic_dec_and_test(atomic_t *v)
 114{
 115        unsigned char c;
 116
 117        asm volatile(LOCK_PREFIX "decl %0; sete %1"
 118                     : "=m" (v->counter), "=qm" (c)
 119                     : "m" (v->counter) : "memory");
 120        return c != 0;
 121}
 122
 123/**
 124 * atomic_inc_and_test - increment and test
 125 * @v: pointer of type atomic_t
 126 *
 127 * Atomically increments @v by 1
 128 * and returns true if the result is zero, or false for all
 129 * other cases.
 130 */
 131static inline int atomic_inc_and_test(atomic_t *v)
 132{
 133        unsigned char c;
 134
 135        asm volatile(LOCK_PREFIX "incl %0; sete %1"
 136                     : "=m" (v->counter), "=qm" (c)
 137                     : "m" (v->counter) : "memory");
 138        return c != 0;
 139}
 140
 141/**
 142 * atomic_add_negative - add and test if negative
 143 * @i: integer value to add
 144 * @v: pointer of type atomic_t
 145 *
 146 * Atomically adds @i to @v and returns true
 147 * if the result is negative, or false when
 148 * result is greater than or equal to zero.
 149 */
 150static inline int atomic_add_negative(int i, atomic_t *v)
 151{
 152        unsigned char c;
 153
 154        asm volatile(LOCK_PREFIX "addl %2,%0; sets %1"
 155                     : "=m" (v->counter), "=qm" (c)
 156                     : "ir" (i), "m" (v->counter) : "memory");
 157        return c;
 158}
 159
 160/**
 161 * atomic_add_return - add and return
 162 * @i: integer value to add
 163 * @v: pointer of type atomic_t
 164 *
 165 * Atomically adds @i to @v and returns @i + @v
 166 */
 167static inline int atomic_add_return(int i, atomic_t *v)
 168{
 169        int __i = i;
 170        asm volatile(LOCK_PREFIX "xaddl %0, %1"
 171                     : "+r" (i), "+m" (v->counter)
 172                     : : "memory");
 173        return i + __i;
 174}
 175
 176static inline int atomic_sub_return(int i, atomic_t *v)
 177{
 178        return atomic_add_return(-i, v);
 179}
 180
 181#define atomic_inc_return(v)  (atomic_add_return(1, v))
 182#define atomic_dec_return(v)  (atomic_sub_return(1, v))
 183
 184/* The 64-bit atomic type */
 185
 186#define ATOMIC64_INIT(i)        { (i) }
 187
 188/**
 189 * atomic64_read - read atomic64 variable
 190 * @v: pointer of type atomic64_t
 191 *
 192 * Atomically reads the value of @v.
 193 * Doesn't imply a read memory barrier.
 194 */
 195#define atomic64_read(v)                ((v)->counter)
 196
 197/**
 198 * atomic64_set - set atomic64 variable
 199 * @v: pointer to type atomic64_t
 200 * @i: required value
 201 *
 202 * Atomically sets the value of @v to @i.
 203 */
 204#define atomic64_set(v, i)              (((v)->counter) = (i))
 205
 206/**
 207 * atomic64_add - add integer to atomic64 variable
 208 * @i: integer value to add
 209 * @v: pointer to type atomic64_t
 210 *
 211 * Atomically adds @i to @v.
 212 */
 213static inline void atomic64_add(long i, atomic64_t *v)
 214{
 215        asm volatile(LOCK_PREFIX "addq %1,%0"
 216                     : "=m" (v->counter)
 217                     : "er" (i), "m" (v->counter));
 218}
 219
 220/**
 221 * atomic64_sub - subtract the atomic64 variable
 222 * @i: integer value to subtract
 223 * @v: pointer to type atomic64_t
 224 *
 225 * Atomically subtracts @i from @v.
 226 */
 227static inline void atomic64_sub(long i, atomic64_t *v)
 228{
 229        asm volatile(LOCK_PREFIX "subq %1,%0"
 230                     : "=m" (v->counter)
 231                     : "er" (i), "m" (v->counter));
 232}
 233
 234/**
 235 * atomic64_sub_and_test - subtract value from variable and test result
 236 * @i: integer value to subtract
 237 * @v: pointer to type atomic64_t
 238 *
 239 * Atomically subtracts @i from @v and returns
 240 * true if the result is zero, or false for all
 241 * other cases.
 242 */
 243static inline int atomic64_sub_and_test(long i, atomic64_t *v)
 244{
 245        unsigned char c;
 246
 247        asm volatile(LOCK_PREFIX "subq %2,%0; sete %1"
 248                     : "=m" (v->counter), "=qm" (c)
 249                     : "er" (i), "m" (v->counter) : "memory");
 250        return c;
 251}
 252
 253/**
 254 * atomic64_inc - increment atomic64 variable
 255 * @v: pointer to type atomic64_t
 256 *
 257 * Atomically increments @v by 1.
 258 */
 259static inline void atomic64_inc(atomic64_t *v)
 260{
 261        asm volatile(LOCK_PREFIX "incq %0"
 262                     : "=m" (v->counter)
 263                     : "m" (v->counter));
 264}
 265
 266/**
 267 * atomic64_dec - decrement atomic64 variable
 268 * @v: pointer to type atomic64_t
 269 *
 270 * Atomically decrements @v by 1.
 271 */
 272static inline void atomic64_dec(atomic64_t *v)
 273{
 274        asm volatile(LOCK_PREFIX "decq %0"
 275                     : "=m" (v->counter)
 276                     : "m" (v->counter));
 277}
 278
 279/**
 280 * atomic64_dec_and_test - decrement and test
 281 * @v: pointer to type atomic64_t
 282 *
 283 * Atomically decrements @v by 1 and
 284 * returns true if the result is 0, or false for all other
 285 * cases.
 286 */
 287static inline int atomic64_dec_and_test(atomic64_t *v)
 288{
 289        unsigned char c;
 290
 291        asm volatile(LOCK_PREFIX "decq %0; sete %1"
 292                     : "=m" (v->counter), "=qm" (c)
 293                     : "m" (v->counter) : "memory");
 294        return c != 0;
 295}
 296
 297/**
 298 * atomic64_inc_and_test - increment and test
 299 * @v: pointer to type atomic64_t
 300 *
 301 * Atomically increments @v by 1
 302 * and returns true if the result is zero, or false for all
 303 * other cases.
 304 */
 305static inline int atomic64_inc_and_test(atomic64_t *v)
 306{
 307        unsigned char c;
 308
 309        asm volatile(LOCK_PREFIX "incq %0; sete %1"
 310                     : "=m" (v->counter), "=qm" (c)
 311                     : "m" (v->counter) : "memory");
 312        return c != 0;
 313}
 314
 315/**
 316 * atomic64_add_negative - add and test if negative
 317 * @i: integer value to add
 318 * @v: pointer to type atomic64_t
 319 *
 320 * Atomically adds @i to @v and returns true
 321 * if the result is negative, or false when
 322 * result is greater than or equal to zero.
 323 */
 324static inline int atomic64_add_negative(long i, atomic64_t *v)
 325{
 326        unsigned char c;
 327
 328        asm volatile(LOCK_PREFIX "addq %2,%0; sets %1"
 329                     : "=m" (v->counter), "=qm" (c)
 330                     : "er" (i), "m" (v->counter) : "memory");
 331        return c;
 332}
 333
 334/**
 335 * atomic64_add_return - add and return
 336 * @i: integer value to add
 337 * @v: pointer to type atomic64_t
 338 *
 339 * Atomically adds @i to @v and returns @i + @v
 340 */
 341static inline long atomic64_add_return(long i, atomic64_t *v)
 342{
 343        long __i = i;
 344        asm volatile(LOCK_PREFIX "xaddq %0, %1;"
 345                     : "+r" (i), "+m" (v->counter)
 346                     : : "memory");
 347        return i + __i;
 348}
 349
 350static inline long atomic64_sub_return(long i, atomic64_t *v)
 351{
 352        return atomic64_add_return(-i, v);
 353}
 354
 355#define atomic64_inc_return(v)  (atomic64_add_return(1, (v)))
 356#define atomic64_dec_return(v)  (atomic64_sub_return(1, (v)))
 357
 358#define atomic64_cmpxchg(v, old, new) (cmpxchg(&((v)->counter), (old), (new)))
 359#define atomic64_xchg(v, new) (xchg(&((v)->counter), new))
 360
 361#define atomic_cmpxchg(v, old, new) (cmpxchg(&((v)->counter), (old), (new)))
 362#define atomic_xchg(v, new) (xchg(&((v)->counter), (new)))
 363
 364/**
 365 * atomic_add_unless - add unless the number is a given value
 366 * @v: pointer of type atomic_t
 367 * @a: the amount to add to v...
 368 * @u: ...unless v is equal to u.
 369 *
 370 * Atomically adds @a to @v, so long as it was not @u.
 371 * Returns non-zero if @v was not @u, and zero otherwise.
 372 */
 373static inline int atomic_add_unless(atomic_t *v, int a, int u)
 374{
 375        int c, old;
 376        c = atomic_read(v);
 377        for (;;) {
 378                if (unlikely(c == (u)))
 379                        break;
 380                old = atomic_cmpxchg((v), c, c + (a));
 381                if (likely(old == c))
 382                        break;
 383                c = old;
 384        }
 385        return c != (u);
 386}
 387
 388#define atomic_inc_not_zero(v) atomic_add_unless((v), 1, 0)
 389
 390/**
 391 * atomic64_add_unless - add unless the number is a given value
 392 * @v: pointer of type atomic64_t
 393 * @a: the amount to add to v...
 394 * @u: ...unless v is equal to u.
 395 *
 396 * Atomically adds @a to @v, so long as it was not @u.
 397 * Returns non-zero if @v was not @u, and zero otherwise.
 398 */
 399static inline int atomic64_add_unless(atomic64_t *v, long a, long u)
 400{
 401        long c, old;
 402        c = atomic64_read(v);
 403        for (;;) {
 404                if (unlikely(c == (u)))
 405                        break;
 406                old = atomic64_cmpxchg((v), c, c + (a));
 407                if (likely(old == c))
 408                        break;
 409                c = old;
 410        }
 411        return c != (u);
 412}
 413
 414/**
 415 * atomic_inc_short - increment of a short integer
 416 * @v: pointer to type int
 417 *
 418 * Atomically adds 1 to @v
 419 * Returns the new value of @u
 420 */
 421static inline short int atomic_inc_short(short int *v)
 422{
 423        asm(LOCK_PREFIX "addw $1, %0" : "+m" (*v));
 424        return *v;
 425}
 426
 427/**
 428 * atomic_or_long - OR of two long integers
 429 * @v1: pointer to type unsigned long
 430 * @v2: pointer to type unsigned long
 431 *
 432 * Atomically ORs @v1 and @v2
 433 * Returns the result of the OR
 434 */
 435static inline void atomic_or_long(unsigned long *v1, unsigned long v2)
 436{
 437        asm(LOCK_PREFIX "orq %1, %0" : "+m" (*v1) : "r" (v2));
 438}
 439
 440#define atomic64_inc_not_zero(v) atomic64_add_unless((v), 1, 0)
 441
 442/* These are x86-specific, used by some header files */
 443#define atomic_clear_mask(mask, addr)                                   \
 444        asm volatile(LOCK_PREFIX "andl %0,%1"                           \
 445                     : : "r" (~(mask)), "m" (*(addr)) : "memory")
 446
 447#define atomic_set_mask(mask, addr)                                     \
 448        asm volatile(LOCK_PREFIX "orl %0,%1"                            \
 449                     : : "r" ((unsigned)(mask)), "m" (*(addr))          \
 450                     : "memory")
 451
 452/* Atomic operations are already serializing on x86 */
 453#define smp_mb__before_atomic_dec()     barrier()
 454#define smp_mb__after_atomic_dec()      barrier()
 455#define smp_mb__before_atomic_inc()     barrier()
 456#define smp_mb__after_atomic_inc()      barrier()
 457
 458#include <asm-generic/atomic.h>
 459#endif /* _ASM_X86_ATOMIC_64_H */
 460
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.