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] "ir"(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
  73#define __HAVE_ARCH_CMPXCHG 1
  74
  75static inline unsigned long __cmpxchg(volatile void *ptr, unsigned long old,
  76                                      unsigned long new, int size)
  77{
  78        switch (size) {
  79        case 4:
  80                return __cmpxchg_u32(ptr, old, new);
  81        case 8:
  82                return __cmpxchg_u64(ptr, old, new);
  83        }
  84
  85        __cmpxchg_called_with_bad_pointer();
  86        return old;
  87}
  88
  89#define cmpxchg(ptr, old, new)                                  \
  90        ((typeof(*(ptr)))__cmpxchg((ptr), (unsigned long)(old), \
  91                                   (unsigned long)(new),        \
  92                                   sizeof(*(ptr))))
  93
  94#include <asm-generic/cmpxchg-local.h>
  95
  96static inline unsigned long __cmpxchg_local(volatile void *ptr,
  97                                      unsigned long old,
  98                                      unsigned long new, int size)
  99{
 100        switch (size) {
 101        case 4:
 102                return __cmpxchg_u32(ptr, old, new);
 103        default:
 104                return __cmpxchg_local_generic(ptr, old, new, size);
 105        }
 106
 107        return old;
 108}
 109
 110#define cmpxchg_local(ptr, old, new)                                    \
 111        ((typeof(*(ptr)))__cmpxchg_local((ptr), (unsigned long)(old),   \
 112                                   (unsigned long)(new),                \
 113                                   sizeof(*(ptr))))
 114
 115#define cmpxchg64_local(ptr, o, n) __cmpxchg64_local_generic((ptr), (o), (n))
 116
 117#endif /* __ASM_AVR32_CMPXCHG_H */
 118