linux/arch/m68k/include/asm/atomic_mm.h
<<
>>
Prefs
   1#ifndef __ARCH_M68K_ATOMIC__
   2#define __ARCH_M68K_ATOMIC__
   3
   4#include <linux/types.h>
   5#include <asm/system.h>
   6
   7/*
   8 * Atomic operations that C can't guarantee us.  Useful for
   9 * resource counting etc..
  10 */
  11
  12/*
  13 * We do not have SMP m68k systems, so we don't have to deal with that.
  14 */
  15
  16#define ATOMIC_INIT(i)  { (i) }
  17
  18#define atomic_read(v)          ((v)->counter)
  19#define atomic_set(v, i)        (((v)->counter) = i)
  20
  21static inline void atomic_add(int i, atomic_t *v)
  22{
  23        __asm__ __volatile__("addl %1,%0" : "+m" (*v) : "id" (i));
  24}
  25
  26static inline void atomic_sub(int i, atomic_t *v)
  27{
  28        __asm__ __volatile__("subl %1,%0" : "+m" (*v) : "id" (i));
  29}
  30
  31static inline void atomic_inc(atomic_t *v)
  32{
  33        __asm__ __volatile__("addql #1,%0" : "+m" (*v));
  34}
  35
  36static inline void atomic_dec(atomic_t *v)
  37{
  38        __asm__ __volatile__("subql #1,%0" : "+m" (*v));
  39}
  40
  41static inline int atomic_dec_and_test(atomic_t *v)
  42{
  43        char c;
  44        __asm__ __volatile__("subql #1,%1; seq %0" : "=d" (c), "+m" (*v));
  45        return c != 0;
  46}
  47
  48static inline int atomic_inc_and_test(atomic_t *v)
  49{
  50        char c;
  51        __asm__ __volatile__("addql #1,%1; seq %0" : "=d" (c), "+m" (*v));
  52        return c != 0;
  53}
  54
  55#ifdef CONFIG_RMW_INSNS
  56
  57static inline int atomic_add_return(int i, atomic_t *v)
  58{
  59        int t, tmp;
  60
  61        __asm__ __volatile__(
  62                        "1:     movel %2,%1\n"
  63                        "       addl %3,%1\n"
  64                        "       casl %2,%1,%0\n"
  65                        "       jne 1b"
  66                        : "+m" (*v), "=&d" (t), "=&d" (tmp)
  67                        : "g" (i), "2" (atomic_read(v)));
  68        return t;
  69}
  70
  71static inline int atomic_sub_return(int i, atomic_t *v)
  72{
  73        int t, tmp;
  74
  75        __asm__ __volatile__(
  76                        "1:     movel %2,%1\n"
  77                        "       subl %3,%1\n"
  78                        "       casl %2,%1,%0\n"
  79                        "       jne 1b"
  80                        : "+m" (*v), "=&d" (t), "=&d" (tmp)
  81                        : "g" (i), "2" (atomic_read(v)));
  82        return t;
  83}
  84
  85#define atomic_cmpxchg(v, o, n) ((int)cmpxchg(&((v)->counter), (o), (n)))
  86#define atomic_xchg(v, new) (xchg(&((v)->counter), new))
  87
  88#else /* !CONFIG_RMW_INSNS */
  89
  90static inline int atomic_add_return(int i, atomic_t * v)
  91{
  92        unsigned long flags;
  93        int t;
  94
  95        local_irq_save(flags);
  96        t = atomic_read(v);
  97        t += i;
  98        atomic_set(v, t);
  99        local_irq_restore(flags);
 100
 101        return t;
 102}
 103
 104static inline int atomic_sub_return(int i, atomic_t * v)
 105{
 106        unsigned long flags;
 107        int t;
 108
 109        local_irq_save(flags);
 110        t = atomic_read(v);
 111        t -= i;
 112        atomic_set(v, t);
 113        local_irq_restore(flags);
 114
 115        return t;
 116}
 117
 118static inline int atomic_cmpxchg(atomic_t *v, int old, int new)
 119{
 120        unsigned long flags;
 121        int prev;
 122
 123        local_irq_save(flags);
 124        prev = atomic_read(v);
 125        if (prev == old)
 126                atomic_set(v, new);
 127        local_irq_restore(flags);
 128        return prev;
 129}
 130
 131static inline int atomic_xchg(atomic_t *v, int new)
 132{
 133        unsigned long flags;
 134        int prev;
 135
 136        local_irq_save(flags);
 137        prev = atomic_read(v);
 138        atomic_set(v, new);
 139        local_irq_restore(flags);
 140        return prev;
 141}
 142
 143#endif /* !CONFIG_RMW_INSNS */
 144
 145#define atomic_dec_return(v)    atomic_sub_return(1, (v))
 146#define atomic_inc_return(v)    atomic_add_return(1, (v))
 147
 148static inline int atomic_sub_and_test(int i, atomic_t *v)
 149{
 150        char c;
 151        __asm__ __volatile__("subl %2,%1; seq %0" : "=d" (c), "+m" (*v): "g" (i));
 152        return c != 0;
 153}
 154
 155static inline int atomic_add_negative(int i, atomic_t *v)
 156{
 157        char c;
 158        __asm__ __volatile__("addl %2,%1; smi %0" : "=d" (c), "+m" (*v): "g" (i));
 159        return c != 0;
 160}
 161
 162static inline void atomic_clear_mask(unsigned long mask, unsigned long *v)
 163{
 164        __asm__ __volatile__("andl %1,%0" : "+m" (*v) : "id" (~(mask)));
 165}
 166
 167static inline void atomic_set_mask(unsigned long mask, unsigned long *v)
 168{
 169        __asm__ __volatile__("orl %1,%0" : "+m" (*v) : "id" (mask));
 170}
 171
 172static __inline__ int atomic_add_unless(atomic_t *v, int a, int u)
 173{
 174        int c, old;
 175        c = atomic_read(v);
 176        for (;;) {
 177                if (unlikely(c == (u)))
 178                        break;
 179                old = atomic_cmpxchg((v), c, c + (a));
 180                if (likely(old == c))
 181                        break;
 182                c = old;
 183        }
 184        return c != (u);
 185}
 186
 187#define atomic_inc_not_zero(v) atomic_add_unless((v), 1, 0)
 188
 189/* Atomic operations are already serializing */
 190#define smp_mb__before_atomic_dec()     barrier()
 191#define smp_mb__after_atomic_dec()      barrier()
 192#define smp_mb__before_atomic_inc()     barrier()
 193#define smp_mb__after_atomic_inc()      barrier()
 194
 195#include <asm-generic/atomic.h>
 196#endif /* __ARCH_M68K_ATOMIC __ */
 197
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.