root/include/asm-generic/atomic.h

/* [<][>][^][v][top][bottom][index][help] */

INCLUDED FROM


DEFINITIONS

This source file includes following definitions.
  1. atomic_add
  2. atomic_sub

   1 /* SPDX-License-Identifier: GPL-2.0-or-later */
   2 /*
   3  * Generic C implementation of atomic counter operations. Usable on
   4  * UP systems only. Do not include in machine independent code.
   5  *
   6  * Copyright (C) 2007 Red Hat, Inc. All Rights Reserved.
   7  * Written by David Howells (dhowells@redhat.com)
   8  */
   9 #ifndef __ASM_GENERIC_ATOMIC_H
  10 #define __ASM_GENERIC_ATOMIC_H
  11 
  12 #include <asm/cmpxchg.h>
  13 #include <asm/barrier.h>
  14 
  15 /*
  16  * atomic_$op() - $op integer to atomic variable
  17  * @i: integer value to $op
  18  * @v: pointer to the atomic variable
  19  *
  20  * Atomically $ops @i to @v. Does not strictly guarantee a memory-barrier, use
  21  * smp_mb__{before,after}_atomic().
  22  */
  23 
  24 /*
  25  * atomic_$op_return() - $op interer to atomic variable and returns the result
  26  * @i: integer value to $op
  27  * @v: pointer to the atomic variable
  28  *
  29  * Atomically $ops @i to @v. Does imply a full memory barrier.
  30  */
  31 
  32 #ifdef CONFIG_SMP
  33 
  34 /* we can build all atomic primitives from cmpxchg */
  35 
  36 #define ATOMIC_OP(op, c_op)                                             \
  37 static inline void atomic_##op(int i, atomic_t *v)                      \
  38 {                                                                       \
  39         int c, old;                                                     \
  40                                                                         \
  41         c = v->counter;                                                 \
  42         while ((old = cmpxchg(&v->counter, c, c c_op i)) != c)          \
  43                 c = old;                                                \
  44 }
  45 
  46 #define ATOMIC_OP_RETURN(op, c_op)                                      \
  47 static inline int atomic_##op##_return(int i, atomic_t *v)              \
  48 {                                                                       \
  49         int c, old;                                                     \
  50                                                                         \
  51         c = v->counter;                                                 \
  52         while ((old = cmpxchg(&v->counter, c, c c_op i)) != c)          \
  53                 c = old;                                                \
  54                                                                         \
  55         return c c_op i;                                                \
  56 }
  57 
  58 #define ATOMIC_FETCH_OP(op, c_op)                                       \
  59 static inline int atomic_fetch_##op(int i, atomic_t *v)                 \
  60 {                                                                       \
  61         int c, old;                                                     \
  62                                                                         \
  63         c = v->counter;                                                 \
  64         while ((old = cmpxchg(&v->counter, c, c c_op i)) != c)          \
  65                 c = old;                                                \
  66                                                                         \
  67         return c;                                                       \
  68 }
  69 
  70 #else
  71 
  72 #include <linux/irqflags.h>
  73 
  74 #define ATOMIC_OP(op, c_op)                                             \
  75 static inline void atomic_##op(int i, atomic_t *v)                      \
  76 {                                                                       \
  77         unsigned long flags;                                            \
  78                                                                         \
  79         raw_local_irq_save(flags);                                      \
  80         v->counter = v->counter c_op i;                                 \
  81         raw_local_irq_restore(flags);                                   \
  82 }
  83 
  84 #define ATOMIC_OP_RETURN(op, c_op)                                      \
  85 static inline int atomic_##op##_return(int i, atomic_t *v)              \
  86 {                                                                       \
  87         unsigned long flags;                                            \
  88         int ret;                                                        \
  89                                                                         \
  90         raw_local_irq_save(flags);                                      \
  91         ret = (v->counter = v->counter c_op i);                         \
  92         raw_local_irq_restore(flags);                                   \
  93                                                                         \
  94         return ret;                                                     \
  95 }
  96 
  97 #define ATOMIC_FETCH_OP(op, c_op)                                       \
  98 static inline int atomic_fetch_##op(int i, atomic_t *v)                 \
  99 {                                                                       \
 100         unsigned long flags;                                            \
 101         int ret;                                                        \
 102                                                                         \
 103         raw_local_irq_save(flags);                                      \
 104         ret = v->counter;                                               \
 105         v->counter = v->counter c_op i;                                 \
 106         raw_local_irq_restore(flags);                                   \
 107                                                                         \
 108         return ret;                                                     \
 109 }
 110 
 111 #endif /* CONFIG_SMP */
 112 
 113 #ifndef atomic_add_return
 114 ATOMIC_OP_RETURN(add, +)
 115 #endif
 116 
 117 #ifndef atomic_sub_return
 118 ATOMIC_OP_RETURN(sub, -)
 119 #endif
 120 
 121 #ifndef atomic_fetch_add
 122 ATOMIC_FETCH_OP(add, +)
 123 #endif
 124 
 125 #ifndef atomic_fetch_sub
 126 ATOMIC_FETCH_OP(sub, -)
 127 #endif
 128 
 129 #ifndef atomic_fetch_and
 130 ATOMIC_FETCH_OP(and, &)
 131 #endif
 132 
 133 #ifndef atomic_fetch_or
 134 ATOMIC_FETCH_OP(or, |)
 135 #endif
 136 
 137 #ifndef atomic_fetch_xor
 138 ATOMIC_FETCH_OP(xor, ^)
 139 #endif
 140 
 141 #ifndef atomic_and
 142 ATOMIC_OP(and, &)
 143 #endif
 144 
 145 #ifndef atomic_or
 146 ATOMIC_OP(or, |)
 147 #endif
 148 
 149 #ifndef atomic_xor
 150 ATOMIC_OP(xor, ^)
 151 #endif
 152 
 153 #undef ATOMIC_FETCH_OP
 154 #undef ATOMIC_OP_RETURN
 155 #undef ATOMIC_OP
 156 
 157 /*
 158  * Atomic operations that C can't guarantee us.  Useful for
 159  * resource counting etc..
 160  */
 161 
 162 #define ATOMIC_INIT(i)  { (i) }
 163 
 164 /**
 165  * atomic_read - read atomic variable
 166  * @v: pointer of type atomic_t
 167  *
 168  * Atomically reads the value of @v.
 169  */
 170 #ifndef atomic_read
 171 #define atomic_read(v)  READ_ONCE((v)->counter)
 172 #endif
 173 
 174 /**
 175  * atomic_set - set atomic variable
 176  * @v: pointer of type atomic_t
 177  * @i: required value
 178  *
 179  * Atomically sets the value of @v to @i.
 180  */
 181 #define atomic_set(v, i) WRITE_ONCE(((v)->counter), (i))
 182 
 183 #include <linux/irqflags.h>
 184 
 185 static inline void atomic_add(int i, atomic_t *v)
 186 {
 187         atomic_add_return(i, v);
 188 }
 189 
 190 static inline void atomic_sub(int i, atomic_t *v)
 191 {
 192         atomic_sub_return(i, v);
 193 }
 194 
 195 #define atomic_xchg(ptr, v)             (xchg(&(ptr)->counter, (v)))
 196 #define atomic_cmpxchg(v, old, new)     (cmpxchg(&((v)->counter), (old), (new)))
 197 
 198 #endif /* __ASM_GENERIC_ATOMIC_H */

/* [<][>][^][v][top][bottom][index][help] */