linux/include/asm-m32r/atomic.h
<<
>>
Prefs
   1#ifndef _ASM_M32R_ATOMIC_H
   2#define _ASM_M32R_ATOMIC_H
   3
   4/*
   5 *  linux/include/asm-m32r/atomic.h
   6 *
   7 *  M32R version:
   8 *    Copyright (C) 2001, 2002  Hitoshi Yamamoto
   9 *    Copyright (C) 2004  Hirokazu Takata <takata at linux-m32r.org>
  10 */
  11
  12#include <asm/assembler.h>
  13#include <asm/system.h>
  14
  15/*
  16 * Atomic operations that C can't guarantee us.  Useful for
  17 * resource counting etc..
  18 */
  19
  20/*
  21 * Make sure gcc doesn't try to be clever and move things around
  22 * on us. We need to use _exactly_ the address the user gave us,
  23 * not some alias that contains the same information.
  24 */
  25typedef struct { volatile int counter; } atomic_t;
  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 */
  35#define atomic_read(v)  ((v)->counter)
  36
  37/**
  38 * atomic_set - set atomic variable
  39 * @v: pointer of type atomic_t
  40 * @i: required value
  41 *
  42 * Atomically sets the value of @v to @i.
  43 */
  44#define atomic_set(v,i) (((v)->counter) = (i))
  45
  46/**
  47 * atomic_add_return - add integer to atomic variable and return it
  48 * @i: integer value to add
  49 * @v: pointer of type atomic_t
  50 *
  51 * Atomically adds @i to @v and return (@i + @v).
  52 */
  53static __inline__ int atomic_add_return(int i, atomic_t *v)
  54{
  55        unsigned long flags;
  56        int result;
  57
  58        local_irq_save(flags);
  59        __asm__ __volatile__ (
  60                "# atomic_add_return            \n\t"
  61                DCACHE_CLEAR("%0", "r4", "%1")
  62                M32R_LOCK" %0, @%1;             \n\t"
  63                "add    %0, %2;                 \n\t"
  64                M32R_UNLOCK" %0, @%1;           \n\t"
  65                : "=&r" (result)
  66                : "r" (&v->counter), "r" (i)
  67                : "memory"
  68#ifdef CONFIG_CHIP_M32700_TS1
  69                , "r4"
  70#endif  /* CONFIG_CHIP_M32700_TS1 */
  71        );
  72        local_irq_restore(flags);
  73
  74        return result;
  75}
  76
  77/**
  78 * atomic_sub_return - subtract integer from atomic variable and return it
  79 * @i: integer value to subtract
  80 * @v: pointer of type atomic_t
  81 *
  82 * Atomically subtracts @i from @v and return (@v - @i).
  83 */
  84static __inline__ int atomic_sub_return(int i, atomic_t *v)
  85{
  86        unsigned long flags;
  87        int result;
  88
  89        local_irq_save(flags);
  90        __asm__ __volatile__ (
  91                "# atomic_sub_return            \n\t"
  92                DCACHE_CLEAR("%0", "r4", "%1")
  93                M32R_LOCK" %0, @%1;             \n\t"
  94                "sub    %0, %2;                 \n\t"
  95                M32R_UNLOCK" %0, @%1;           \n\t"
  96                : "=&r" (result)
  97                : "r" (&v->counter), "r" (i)
  98                : "memory"
  99#ifdef CONFIG_CHIP_M32700_TS1
 100                , "r4"
 101#endif  /* CONFIG_CHIP_M32700_TS1 */
 102        );
 103        local_irq_restore(flags);
 104
 105        return result;
 106}
 107
 108/**
 109 * atomic_add - add integer to atomic variable
 110 * @i: integer value to add
 111 * @v: pointer of type atomic_t
 112 *
 113 * Atomically adds @i to @v.
 114 */
 115#define atomic_add(i,v) ((void) atomic_add_return((i), (v)))
 116
 117/**
 118 * atomic_sub - subtract the atomic variable
 119 * @i: integer value to subtract
 120 * @v: pointer of type atomic_t
 121 *
 122 * Atomically subtracts @i from @v.
 123 */
 124#define atomic_sub(i,v) ((void) atomic_sub_return((i), (v)))
 125
 126/**
 127 * atomic_sub_and_test - subtract value from variable and test result
 128 * @i: integer value to subtract
 129 * @v: pointer of type atomic_t
 130 *
 131 * Atomically subtracts @i from @v and returns
 132 * true if the result is zero, or false for all
 133 * other cases.
 134 */
 135#define atomic_sub_and_test(i,v) (atomic_sub_return((i), (v)) == 0)
 136
 137/**
 138 * atomic_inc_return - increment atomic variable and return it
 139 * @v: pointer of type atomic_t
 140 *
 141 * Atomically increments @v by 1 and returns the result.
 142 */
 143static __inline__ int atomic_inc_return(atomic_t *v)
 144{
 145        unsigned long flags;
 146        int result;
 147
 148        local_irq_save(flags);
 149        __asm__ __volatile__ (
 150                "# atomic_inc_return            \n\t"
 151                DCACHE_CLEAR("%0", "r4", "%1")
 152                M32R_LOCK" %0, @%1;             \n\t"
 153                "addi   %0, #1;                 \n\t"
 154                M32R_UNLOCK" %0, @%1;           \n\t"
 155                : "=&r" (result)
 156                : "r" (&v->counter)
 157                : "memory"
 158#ifdef CONFIG_CHIP_M32700_TS1
 159                , "r4"
 160#endif  /* CONFIG_CHIP_M32700_TS1 */
 161        );
 162        local_irq_restore(flags);
 163
 164        return result;
 165}
 166
 167/**
 168 * atomic_dec_return - decrement atomic variable and return it
 169 * @v: pointer of type atomic_t
 170 *
 171 * Atomically decrements @v by 1 and returns the result.
 172 */
 173static __inline__ int atomic_dec_return(atomic_t *v)
 174{
 175        unsigned long flags;
 176        int result;
 177
 178        local_irq_save(flags);
 179        __asm__ __volatile__ (
 180                "# atomic_dec_return            \n\t"
 181                DCACHE_CLEAR("%0", "r4", "%1")
 182                M32R_LOCK" %0, @%1;             \n\t"
 183                "addi   %0, #-1;                \n\t"
 184                M32R_UNLOCK" %0, @%1;           \n\t"
 185                : "=&r" (result)
 186                : "r" (&v->counter)
 187                : "memory"
 188#ifdef CONFIG_CHIP_M32700_TS1
 189                , "r4"
 190#endif  /* CONFIG_CHIP_M32700_TS1 */
 191        );
 192        local_irq_restore(flags);
 193
 194        return result;
 195}
 196
 197/**
 198 * atomic_inc - increment atomic variable
 199 * @v: pointer of type atomic_t
 200 *
 201 * Atomically increments @v by 1.
 202 */
 203#define atomic_inc(v) ((void)atomic_inc_return(v))
 204
 205/**
 206 * atomic_dec - decrement atomic variable
 207 * @v: pointer of type atomic_t
 208 *
 209 * Atomically decrements @v by 1.
 210 */
 211#define atomic_dec(v) ((void)atomic_dec_return(v))
 212
 213/**
 214 * atomic_inc_and_test - increment and test
 215 * @v: pointer of type atomic_t
 216 *
 217 * Atomically increments @v by 1
 218 * and returns true if the result is zero, or false for all
 219 * other cases.
 220 */
 221#define atomic_inc_and_test(v) (atomic_inc_return(v) == 0)
 222
 223/**
 224 * atomic_dec_and_test - decrement and test
 225 * @v: pointer of type atomic_t
 226 *
 227 * Atomically decrements @v by 1 and
 228 * returns true if the result is 0, or false for all
 229 * other cases.
 230 */
 231#define atomic_dec_and_test(v) (atomic_dec_return(v) == 0)
 232
 233/**
 234 * atomic_add_negative - add and test if negative
 235 * @v: pointer of type atomic_t
 236 * @i: integer value to add
 237 *
 238 * Atomically adds @i to @v and returns true
 239 * if the result is negative, or false when
 240 * result is greater than or equal to zero.
 241 */
 242#define atomic_add_negative(i,v) (atomic_add_return((i), (v)) < 0)
 243
 244#define atomic_cmpxchg(v, o, n) ((int)cmpxchg(&((v)->counter), (o), (n)))
 245#define atomic_xchg(v, new) (xchg(&((v)->counter), new))
 246
 247/**
 248 * atomic_add_unless - add unless the number is a given value
 249 * @v: pointer of type atomic_t
 250 * @a: the amount to add to v...
 251 * @u: ...unless v is equal to u.
 252 *
 253 * Atomically adds @a to @v, so long as it was not @u.
 254 * Returns non-zero if @v was not @u, and zero otherwise.
 255 */
 256static __inline__ int atomic_add_unless(atomic_t *v, int a, int u)
 257{
 258        int c, old;
 259        c = atomic_read(v);
 260        for (;;) {
 261                if (unlikely(c == (u)))
 262                        break;
 263                old = atomic_cmpxchg((v), c, c + (a));
 264                if (likely(old == c))
 265                        break;
 266                c = old;
 267        }
 268        return c != (u);
 269}
 270
 271#define atomic_inc_not_zero(v) atomic_add_unless((v), 1, 0)
 272
 273static __inline__ void atomic_clear_mask(unsigned long  mask, atomic_t *addr)
 274{
 275        unsigned long flags;
 276        unsigned long tmp;
 277
 278        local_irq_save(flags);
 279        __asm__ __volatile__ (
 280                "# atomic_clear_mask            \n\t"
 281                DCACHE_CLEAR("%0", "r5", "%1")
 282                M32R_LOCK" %0, @%1;             \n\t"
 283                "and    %0, %2;                 \n\t"
 284                M32R_UNLOCK" %0, @%1;           \n\t"
 285                : "=&r" (tmp)
 286                : "r" (addr), "r" (~mask)
 287                : "memory"
 288#ifdef CONFIG_CHIP_M32700_TS1
 289                , "r5"
 290#endif  /* CONFIG_CHIP_M32700_TS1 */
 291        );
 292        local_irq_restore(flags);
 293}
 294
 295static __inline__ void atomic_set_mask(unsigned long  mask, atomic_t *addr)
 296{
 297        unsigned long flags;
 298        unsigned long tmp;
 299
 300        local_irq_save(flags);
 301        __asm__ __volatile__ (
 302                "# atomic_set_mask              \n\t"
 303                DCACHE_CLEAR("%0", "r5", "%1")
 304                M32R_LOCK" %0, @%1;             \n\t"
 305                "or     %0, %2;                 \n\t"
 306                M32R_UNLOCK" %0, @%1;           \n\t"
 307                : "=&r" (tmp)
 308                : "r" (addr), "r" (mask)
 309                : "memory"
 310#ifdef CONFIG_CHIP_M32700_TS1
 311                , "r5"
 312#endif  /* CONFIG_CHIP_M32700_TS1 */
 313        );
 314        local_irq_restore(flags);
 315}
 316
 317/* Atomic operations are already serializing on m32r */
 318#define smp_mb__before_atomic_dec()     barrier()
 319#define smp_mb__after_atomic_dec()      barrier()
 320#define smp_mb__before_atomic_inc()     barrier()
 321#define smp_mb__after_atomic_inc()      barrier()
 322
 323#include <asm-generic/atomic.h>
 324#endif  /* _ASM_M32R_ATOMIC_H */
 325
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.