linux/arch/avr32/include/asm/cmpxchg.h
<<
>>
Prefs
   1/*
   2 * Atomic operations that C can't guarantee us.  Useful for
   3 * resource counting etc.
   4 *
   5 * But use these as seldom as possible since they are slower than
   6 * regular operations.
   7 *
   8 * Copyright (C) 2004-2006 Atmel Corporation
   9 *
  10 * This program is free software; you can redistribute it and/or modify
  11 * it under the terms of the GNU General Public License version 2 as
  12 * published by the Free Software Foundation.
  13 */
  14#ifndef __ASM_AVR32_CMPXCHG_H
  15#define __ASM_AVR32_CMPXCHG_H
  16
  17#define xchg(ptr,x) \
  18        ((__typeof__(*(ptr)))__xchg((unsigned long)(x),(ptr),sizeof(*(ptr))))
  19
  20extern void __xchg_called_with_bad_pointer(void);
  21
  22static inline unsigned long xchg_u32(u32 val, volatile u32 *m)
  23{
  24        u32 ret;
  25
  26        asm volatile("xchg %[ret], %[m], %[val]"
  27                        : [ret] "=&r"(ret), "=m"(*m)
  28                        : "m"(*m), [m] "r"(m), [val] "r"(val)
  29                        : "memory");
  30        return ret;
  31}
  32
  33static inline unsigned long __xchg(unsigned long x,
  34                                       volatile void *ptr,
  35                                       int size)
  36{
  37        switch(size) {
  38        case 4:
  39                return xchg_u32(x, ptr);
  40        default:
  41                __xchg_called_with_bad_pointer();
  42                return x;
  43        }
  44}
  45
  46static inline unsigned long __cmpxchg_u32(volatile int *m, unsigned long old,
  47                                          unsigned long new)
  48{
  49        __u32 ret;
  50
  51        asm volatile(
  52                "1:     ssrf    5\n"
  53                "       ld.w    %[ret], %[m]\n"
  54                "       cp.w    %[ret], %[old]\n"
  55                "       brne    2f\n"
  56                "       stcond  %[m], %[new]\n"
  57                "       brne    1b\n"
  58                "2:\n"
  59                : [ret] "=&r"(ret), [m] "=m"(*m)
  60                : "m"(m), [old] "Ks21r"(old), [new] "r"(new)
  61                : "memory", "cc");
  62        return ret;
  63}
  64
  65extern unsigned long __cmpxchg_u64_unsupported_on_32bit_kernels(
  66        volatile int * m, unsigned long old, unsigned long new);
  67#define __cmpxchg_u64 __cmpxchg_u64_unsupported_on_32bit_kernels
  68
  69/* This function doesn't exist, so you'll get a linker error
  70   if something tries to do an invalid cmpxchg().  */
  71extern void __cmpxchg_called_with_bad_pointer(void);
  72
  73static inline unsigned long __cmpxchg(volatile void *ptr, unsigned long old,
  74                                      unsigned long new, int size)
  75{
  76        switch (size) {
  77        case 4:
  78                return __cmpxchg_u32(ptr, old, new);
  79        case 8:
  80                return __cmpxchg_u64(ptr, old, new);
  81        }
  82
  83        __cmpxchg_called_with_bad_pointer();
  84        return old;
  85}
  86
  87#define cmpxchg(ptr, old, new)                                  \
  88        ((typeof(*(ptr)))__cmpxchg((ptr), (unsigned long)(old), \
  89                                   (unsigned long)(new),        \
  90                                   sizeof(*(ptr))))
  91
  92#include <asm-generic/cmpxchg-local.h>
  93
  94static inline unsigned long __cmpxchg_local(volatile void *ptr,
  95                                      unsigned long old,
  96                                      unsigned long new, int size)
  97{
  98        switch (size) {
  99        case 4:
 100                return __cmpxchg_u32(ptr, old, new);
 101        default:
 102                return __cmpxchg_local_generic(ptr, old, new, size);
 103        }
 104
 105        return old;
 106}
 107
 108#define cmpxchg_local(ptr, old, new)                                    \
 109        ((typeof(*(ptr)))__cmpxchg_local((ptr), (unsigned long)(old),   \
 110                                   (unsigned long)(new),                \
 111                                   sizeof(*(ptr))))
 112
 113#define cmpxchg64_local(ptr, o, n) __cmpxchg64_local_generic((ptr), (o), (n))
 114
 115#endif /* __ASM_AVR32_CMPXCHG_H */
 116