linux/include/asm-generic/cmpxchg.h
<<
>>
Prefs
   1/*
   2 * Generic UP xchg and cmpxchg using interrupt disablement.  Does not
   3 * support SMP.
   4 */
   5
   6#ifndef __ASM_GENERIC_CMPXCHG_H
   7#define __ASM_GENERIC_CMPXCHG_H
   8
   9#ifdef CONFIG_SMP
  10#error "Cannot use generic cmpxchg on SMP"
  11#endif
  12
  13#include <linux/types.h>
  14#include <linux/irqflags.h>
  15
  16#ifndef xchg
  17
  18/*
  19 * This function doesn't exist, so you'll get a linker error if
  20 * something tries to do an invalidly-sized xchg().
  21 */
  22extern void __xchg_called_with_bad_pointer(void);
  23
  24static inline
  25unsigned long __xchg(unsigned long x, volatile void *ptr, int size)
  26{
  27        unsigned long ret, flags;
  28
  29        switch (size) {
  30        case 1:
  31#ifdef __xchg_u8
  32                return __xchg_u8(x, ptr);
  33#else
  34                local_irq_save(flags);
  35                ret = *(volatile u8 *)ptr;
  36                *(volatile u8 *)ptr = x;
  37                local_irq_restore(flags);
  38                return ret;
  39#endif /* __xchg_u8 */
  40
  41        case 2:
  42#ifdef __xchg_u16
  43                return __xchg_u16(x, ptr);
  44#else
  45                local_irq_save(flags);
  46                ret = *(volatile u16 *)ptr;
  47                *(volatile u16 *)ptr = x;
  48                local_irq_restore(flags);
  49                return ret;
  50#endif /* __xchg_u16 */
  51
  52        case 4:
  53#ifdef __xchg_u32
  54                return __xchg_u32(x, ptr);
  55#else
  56                local_irq_save(flags);
  57                ret = *(volatile u32 *)ptr;
  58                *(volatile u32 *)ptr = x;
  59                local_irq_restore(flags);
  60                return ret;
  61#endif /* __xchg_u32 */
  62
  63#ifdef CONFIG_64BIT
  64        case 8:
  65#ifdef __xchg_u64
  66                return __xchg_u64(x, ptr);
  67#else
  68                local_irq_save(flags);
  69                ret = *(volatile u64 *)ptr;
  70                *(volatile u64 *)ptr = x;
  71                local_irq_restore(flags);
  72                return ret;
  73#endif /* __xchg_u64 */
  74#endif /* CONFIG_64BIT */
  75
  76        default:
  77                __xchg_called_with_bad_pointer();
  78                return x;
  79        }
  80}
  81
  82#define xchg(ptr, x) \
  83        ((__typeof__(*(ptr))) __xchg((unsigned long)(x), (ptr), sizeof(*(ptr))))
  84
  85#endif /* xchg */
  86
  87/*
  88 * Atomic compare and exchange.
  89 *
  90 * Do not define __HAVE_ARCH_CMPXCHG because we want to use it to check whether
  91 * a cmpxchg primitive faster than repeated local irq save/restore exists.
  92 */
  93#include <asm-generic/cmpxchg-local.h>
  94
  95#ifndef cmpxchg_local
  96#define cmpxchg_local(ptr, o, n)                                               \
  97        ((__typeof__(*(ptr)))__cmpxchg_local_generic((ptr), (unsigned long)(o),\
  98                        (unsigned long)(n), sizeof(*(ptr))))
  99#endif
 100
 101#ifndef cmpxchg64_local
 102#define cmpxchg64_local(ptr, o, n) __cmpxchg64_local_generic((ptr), (o), (n))
 103#endif
 104
 105#define cmpxchg(ptr, o, n)      cmpxchg_local((ptr), (o), (n))
 106#define cmpxchg64(ptr, o, n)    cmpxchg64_local((ptr), (o), (n))
 107
 108#endif /* __ASM_GENERIC_CMPXCHG_H */
 109