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)))                                           \
  84                __xchg((unsigned long)(x), (ptr), sizeof(*(ptr))));     \
  85})
  86
  87#endif /* xchg */
  88
  89/*
  90 * Atomic compare and exchange.
  91 */
  92#include <asm-generic/cmpxchg-local.h>
  93
  94#ifndef cmpxchg_local
  95#define cmpxchg_local(ptr, o, n) ({                                            \
  96        ((__typeof__(*(ptr)))__cmpxchg_local_generic((ptr), (unsigned long)(o),\
  97                        (unsigned long)(n), sizeof(*(ptr))));                  \
  98})
  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