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 */
 256#define atomic_add_unless(v, a, u)                              \
 257({                                                              \
 258        int c, old;                                             \
 259        c = atomic_read(v);                                     \
 260        while (c != (u) && (old = atomic_cmpxchg((v), c, c + (a))) != c) \
 261                c = old;                                        \
 262        c != (u);                                               \
 263})
 264#define atomic_inc_not_zero(v) atomic_add_unless((v), 1, 0)
 265
 266static __inline__ void atomic_clear_mask(unsigned long  mask, atomic_t *addr)
 267{
 268        unsigned long flags;
 269        unsigned long tmp;
 270
 271        local_irq_save(flags);
 272        __asm__ __volatile__ (
 273                "# atomic_clear_mask            \n\t"
 274                DCACHE_CLEAR("%0", "r5", "%1")
 275                M32R_LOCK" %0, @%1;             \n\t"
 276                "and    %0, %2;                 \n\t"
 277                M32R_UNLOCK" %0, @%1;           \n\t"
 278                : "=&r" (tmp)
 279                : "r" (addr), "r" (~mask)
 280                : "memory"
 281#ifdef CONFIG_CHIP_M32700_TS1
 282                , "r5"
 283#endif  /* CONFIG_CHIP_M32700_TS1 */
 284        );
 285        local_irq_restore(flags);
 286}
 287
 288static __inline__ void atomic_set_mask(unsigned long  mask, atomic_t *addr)
 289{
 290        unsigned long flags;
 291        unsigned long tmp;
 292
 293        local_irq_save(flags);
 294        __asm__ __volatile__ (
 295                "# atomic_set_mask              \n\t"
 296                DCACHE_CLEAR("%0", "r5", "%1")
 297                M32R_LOCK" %0, @%1;             \n\t"
 298                "or     %0, %2;                 \n\t"
 299                M32R_UNLOCK" %0, @%1;           \n\t"
 300                : "=&r" (tmp)
 301                : "r" (addr), "r" (mask)
 302                : "memory"
 303#ifdef CONFIG_CHIP_M32700_TS1
 304                , "r5"
 305#endif  /* CONFIG_CHIP_M32700_TS1 */
 306        );
 307        local_irq_restore(flags);
 308}
 309
 310/* Atomic operations are already serializing on m32r */
 311#define smp_mb__before_atomic_dec()     barrier()
 312#define smp_mb__after_atomic_dec()      barrier()
 313#define smp_mb__before_atomic_inc()     barrier()
 314#define smp_mb__after_atomic_inc()      barrier()
 315
 316#include <asm-generic/atomic.h>
 317#endif  /* _ASM_M32R_ATOMIC_H */
 318
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.