linux/arch/tile/include/asm/atomic.h
<<
>>
Prefs
   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#include <asm/cmpxchg.h>
  21
  22#ifndef __ASSEMBLY__
  23
  24#include <linux/compiler.h>
  25#include <linux/types.h>
  26
  27#define ATOMIC_INIT(i)  { (i) }
  28
  29/**
  30 * atomic_read - read atomic variable
  31 * @v: pointer of type atomic_t
  32 *
  33 * Atomically reads the value of @v.
  34 */
  35static inline int atomic_read(const atomic_t *v)
  36{
  37        return ACCESS_ONCE(v->counter);
  38}
  39
  40/**
  41 * atomic_sub_return - subtract integer and return
  42 * @v: pointer of type atomic_t
  43 * @i: integer value to subtract
  44 *
  45 * Atomically subtracts @i from @v and returns @v - @i
  46 */
  47#define atomic_sub_return(i, v)         atomic_add_return((int)(-(i)), (v))
  48
  49/**
  50 * atomic_sub - subtract integer from atomic variable
  51 * @i: integer value to subtract
  52 * @v: pointer of type atomic_t
  53 *
  54 * Atomically subtracts @i from @v.
  55 */
  56#define atomic_sub(i, v)                atomic_add((int)(-(i)), (v))
  57
  58/**
  59 * atomic_sub_and_test - subtract value from variable and test result
  60 * @i: integer value to subtract
  61 * @v: pointer of type atomic_t
  62 *
  63 * Atomically subtracts @i from @v and returns true if the result is
  64 * zero, or false for all other cases.
  65 */
  66#define atomic_sub_and_test(i, v)       (atomic_sub_return((i), (v)) == 0)
  67
  68/**
  69 * atomic_inc_return - increment memory and return
  70 * @v: pointer of type atomic_t
  71 *
  72 * Atomically increments @v by 1 and returns the new value.
  73 */
  74#define atomic_inc_return(v)            atomic_add_return(1, (v))
  75
  76/**
  77 * atomic_dec_return - decrement memory and return
  78 * @v: pointer of type atomic_t
  79 *
  80 * Atomically decrements @v by 1 and returns the new value.
  81 */
  82#define atomic_dec_return(v)            atomic_sub_return(1, (v))
  83
  84/**
  85 * atomic_inc - increment atomic variable
  86 * @v: pointer of type atomic_t
  87 *
  88 * Atomically increments @v by 1.
  89 */
  90#define atomic_inc(v)                   atomic_add(1, (v))
  91
  92/**
  93 * atomic_dec - decrement atomic variable
  94 * @v: pointer of type atomic_t
  95 *
  96 * Atomically decrements @v by 1.
  97 */
  98#define atomic_dec(v)                   atomic_sub(1, (v))
  99
 100/**
 101 * atomic_dec_and_test - decrement and test
 102 * @v: pointer of type atomic_t
 103 *
 104 * Atomically decrements @v by 1 and returns true if the result is 0.
 105 */
 106#define atomic_dec_and_test(v)          (atomic_dec_return(v) == 0)
 107
 108/**
 109 * atomic_inc_and_test - increment and test
 110 * @v: pointer of type atomic_t
 111 *
 112 * Atomically increments @v by 1 and returns true if the result is 0.
 113 */
 114#define atomic_inc_and_test(v)          (atomic_inc_return(v) == 0)
 115
 116/**
 117 * atomic_xchg - atomically exchange contents of memory with a new value
 118 * @v: pointer of type atomic_t
 119 * @i: integer value to store in memory
 120 *
 121 * Atomically sets @v to @i and returns old @v
 122 */
 123static inline int atomic_xchg(atomic_t *v, int n)
 124{
 125        return xchg(&v->counter, n);
 126}
 127
 128/**
 129 * atomic_cmpxchg - atomically exchange contents of memory if it matches
 130 * @v: pointer of type atomic_t
 131 * @o: old value that memory should have
 132 * @n: new value to write to memory if it matches
 133 *
 134 * Atomically checks if @v holds @o and replaces it with @n if so.
 135 * Returns the old value at @v.
 136 */
 137static inline int atomic_cmpxchg(atomic_t *v, int o, int n)
 138{
 139        return cmpxchg(&v->counter, o, n);
 140}
 141
 142/**
 143 * atomic_add_negative - add and test if negative
 144 * @v: pointer of type atomic_t
 145 * @i: integer value to add
 146 *
 147 * Atomically adds @i to @v and returns true if the result is
 148 * negative, or false when result is greater than or equal to zero.
 149 */
 150#define atomic_add_negative(i, v)       (atomic_add_return((i), (v)) < 0)
 151
 152#endif /* __ASSEMBLY__ */
 153
 154#ifndef __tilegx__
 155#include <asm/atomic_32.h>
 156#else
 157#include <asm/atomic_64.h>
 158#endif
 159
 160#ifndef __ASSEMBLY__
 161
 162/**
 163 * atomic64_xchg - atomically exchange contents of memory with a new value
 164 * @v: pointer of type atomic64_t
 165 * @i: integer value to store in memory
 166 *
 167 * Atomically sets @v to @i and returns old @v
 168 */
 169static inline long long atomic64_xchg(atomic64_t *v, long long n)
 170{
 171        return xchg64(&v->counter, n);
 172}
 173
 174/**
 175 * atomic64_cmpxchg - atomically exchange contents of memory if it matches
 176 * @v: pointer of type atomic64_t
 177 * @o: old value that memory should have
 178 * @n: new value to write to memory if it matches
 179 *
 180 * Atomically checks if @v holds @o and replaces it with @n if so.
 181 * Returns the old value at @v.
 182 */
 183static inline long long atomic64_cmpxchg(atomic64_t *v, long long o,
 184                                        long long n)
 185{
 186        return cmpxchg64(&v->counter, o, n);
 187}
 188
 189static inline long long atomic64_dec_if_positive(atomic64_t *v)
 190{
 191        long long c, old, dec;
 192
 193        c = atomic64_read(v);
 194        for (;;) {
 195                dec = c - 1;
 196                if (unlikely(dec < 0))
 197                        break;
 198                old = atomic64_cmpxchg((v), c, dec);
 199                if (likely(old == c))
 200                        break;
 201                c = old;
 202        }
 203        return dec;
 204}
 205
 206#endif /* __ASSEMBLY__ */
 207
 208#endif /* _ASM_TILE_ATOMIC_H */
 209