File: /Users/paulross/dev/linux/linux-3.13/arch/x86/include/asm/atomic64_64.h

Green shading in the line number column means the source is part of the translation unit, red means it is conditionally excluded. Highlighted line numbers link to the translation unit page. Highlighted macros link to the macro page.

       1: #ifndef _ASM_X86_ATOMIC64_64_H
       2: #define _ASM_X86_ATOMIC64_64_H
       3: 
       4: #include <linux/types.h>
       5: #include <asm/alternative.h>
       6: #include <asm/cmpxchg.h>
       7: 
       8: /* The 64-bit atomic type */
       9: 
      10: #define ATOMIC64_INIT(i)    { (i) }
      11: 
      12: /**
      13:  * atomic64_read - read atomic64 variable
      14:  * @v: pointer of type atomic64_t
      15:  *
      16:  * Atomically reads the value of @v.
      17:  * Doesn't imply a read memory barrier.
      18:  */
      19: static inline long atomic64_read(const atomic64_t *v)
      20: {
      21:     return (*(volatile long *)&(v)->counter);
      22: }
      23: 
      24: /**
      25:  * atomic64_set - set atomic64 variable
      26:  * @v: pointer to type atomic64_t
      27:  * @i: required value
      28:  *
      29:  * Atomically sets the value of @v to @i.
      30:  */
      31: static inline void atomic64_set(atomic64_t *v, long i)
      32: {
      33:     v->counter = i;
      34: }
      35: 
      36: /**
      37:  * atomic64_add - add integer to atomic64 variable
      38:  * @i: integer value to add
      39:  * @v: pointer to type atomic64_t
      40:  *
      41:  * Atomically adds @i to @v.
      42:  */
      43: static inline void atomic64_add(long i, atomic64_t *v)
      44: {
      45:     asm volatile(LOCK_PREFIX "addq %1,%0"
      46:              : "=m" (v->counter)
      47:              : "er" (i), "m" (v->counter));
      48: }
      49: 
      50: /**
      51:  * atomic64_sub - subtract the atomic64 variable
      52:  * @i: integer value to subtract
      53:  * @v: pointer to type atomic64_t
      54:  *
      55:  * Atomically subtracts @i from @v.
      56:  */
      57: static inline void atomic64_sub(long i, atomic64_t *v)
      58: {
      59:     asm volatile(LOCK_PREFIX "subq %1,%0"
      60:              : "=m" (v->counter)
      61:              : "er" (i), "m" (v->counter));
      62: }
      63: 
      64: /**
      65:  * atomic64_sub_and_test - subtract value from variable and test result
      66:  * @i: integer value to subtract
      67:  * @v: pointer to type atomic64_t
      68:  *
      69:  * Atomically subtracts @i from @v and returns
      70:  * true if the result is zero, or false for all
      71:  * other cases.
      72:  */
      73: static inline int atomic64_sub_and_test(long i, atomic64_t *v)
      74: {
      75:     GEN_BINARY_RMWcc(LOCK_PREFIX "subq", v->counter, "er", i, "%0", "e");
      76: }
      77: 
      78: /**
      79:  * atomic64_inc - increment atomic64 variable
      80:  * @v: pointer to type atomic64_t
      81:  *
      82:  * Atomically increments @v by 1.
      83:  */
      84: static inline void atomic64_inc(atomic64_t *v)
      85: {
      86:     asm volatile(LOCK_PREFIX "incq %0"
      87:              : "=m" (v->counter)
      88:              : "m" (v->counter));
      89: }
      90: 
      91: /**
      92:  * atomic64_dec - decrement atomic64 variable
      93:  * @v: pointer to type atomic64_t
      94:  *
      95:  * Atomically decrements @v by 1.
      96:  */
      97: static inline void atomic64_dec(atomic64_t *v)
      98: {
      99:     asm volatile(LOCK_PREFIX "decq %0"
     100:              : "=m" (v->counter)
     101:              : "m" (v->counter));
     102: }
     103: 
     104: /**
     105:  * atomic64_dec_and_test - decrement and test
     106:  * @v: pointer to type atomic64_t
     107:  *
     108:  * Atomically decrements @v by 1 and
     109:  * returns true if the result is 0, or false for all other
     110:  * cases.
     111:  */
     112: static inline int atomic64_dec_and_test(atomic64_t *v)
     113: {
     114:     GEN_UNARY_RMWcc(LOCK_PREFIX "decq", v->counter, "%0", "e");
     115: }
     116: 
     117: /**
     118:  * atomic64_inc_and_test - increment and test
     119:  * @v: pointer to type atomic64_t
     120:  *
     121:  * Atomically increments @v by 1
     122:  * and returns true if the result is zero, or false for all
     123:  * other cases.
     124:  */
     125: static inline int atomic64_inc_and_test(atomic64_t *v)
     126: {
     127:     GEN_UNARY_RMWcc(LOCK_PREFIX "incq", v->counter, "%0", "e");
     128: }
     129: 
     130: /**
     131:  * atomic64_add_negative - add and test if negative
     132:  * @i: integer value to add
     133:  * @v: pointer to type atomic64_t
     134:  *
     135:  * Atomically adds @i to @v and returns true
     136:  * if the result is negative, or false when
     137:  * result is greater than or equal to zero.
     138:  */
     139: static inline int atomic64_add_negative(long i, atomic64_t *v)
     140: {
     141:     GEN_BINARY_RMWcc(LOCK_PREFIX "addq", v->counter, "er", i, "%0", "s");
     142: }
     143: 
     144: /**
     145:  * atomic64_add_return - add and return
     146:  * @i: integer value to add
     147:  * @v: pointer to type atomic64_t
     148:  *
     149:  * Atomically adds @i to @v and returns @i + @v
     150:  */
     151: static inline long atomic64_add_return(long i, atomic64_t *v)
     152: {
     153:     return i + xadd(&v->counter, i);
     154: }
     155: 
     156: static inline long atomic64_sub_return(long i, atomic64_t *v)
     157: {
     158:     return atomic64_add_return(-i, v);
     159: }
     160: 
     161: #define atomic64_inc_return(v)  (atomic64_add_return(1, (v)))
     162: #define atomic64_dec_return(v)  (atomic64_sub_return(1, (v)))
     163: 
     164: static inline long atomic64_cmpxchg(atomic64_t *v, long old, long new)
     165: {
     166:     return cmpxchg(&v->counter, old, new);
     167: }
     168: 
     169: static inline long atomic64_xchg(atomic64_t *v, long new)
     170: {
     171:     return xchg(&v->counter, new);
     172: }
     173: 
     174: /**
     175:  * atomic64_add_unless - add unless the number is a given value
     176:  * @v: pointer of type atomic64_t
     177:  * @a: the amount to add to v...
     178:  * @u: ...unless v is equal to u.
     179:  *
     180:  * Atomically adds @a to @v, so long as it was not @u.
     181:  * Returns the old value of @v.
     182:  */
     183: static inline int atomic64_add_unless(atomic64_t *v, long a, long u)
     184: {
     185:     long c, old;
     186:     c = atomic64_read(v);
     187:     for (;;) {
     188:         if (unlikely(c == (u)))
     189:             break;
     190:         old = atomic64_cmpxchg((v), c, c + (a));
     191:         if (likely(old == c))
     192:             break;
     193:         c = old;
     194:     }
     195:     return c != (u);
     196: }
     197: 
     198: #define atomic64_inc_not_zero(v) atomic64_add_unless((v), 1, 0)
     199: 
     200: /*
     201:  * atomic64_dec_if_positive - decrement by 1 if old value positive
     202:  * @v: pointer of type atomic_t
     203:  *
     204:  * The function returns the old value of *v minus 1, even if
     205:  * the atomic variable, v, was not decremented.
     206:  */
     207: static inline long atomic64_dec_if_positive(atomic64_t *v)
     208: {
     209:     long c, old, dec;
     210:     c = atomic64_read(v);
     211:     for (;;) {
     212:         dec = c - 1;
     213:         if (unlikely(dec < 0))
     214:             break;
     215:         old = atomic64_cmpxchg((v), c, dec);
     216:         if (likely(old == c))
     217:             break;
     218:         c = old;
     219:     }
     220:     return dec;
     221: }
     222: 
     223: #endif /* _ASM_X86_ATOMIC64_64_H */
     224: