linux/arch/tile/include/asm/cmpxchg.h
<<
>>
Prefs
   1/*
   2 * cmpxchg.h -- forked from asm/atomic.h with this copyright:
   3 *
   4 * Copyright 2010 Tilera Corporation. All Rights Reserved.
   5 *
   6 *   This program is free software; you can redistribute it and/or
   7 *   modify it under the terms of the GNU General Public License
   8 *   as published by the Free Software Foundation, version 2.
   9 *
  10 *   This program is distributed in the hope that it will be useful, but
  11 *   WITHOUT ANY WARRANTY; without even the implied warranty of
  12 *   MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
  13 *   NON INFRINGEMENT.  See the GNU General Public License for
  14 *   more details.
  15 *
  16 */
  17
  18#ifndef _ASM_TILE_CMPXCHG_H
  19#define _ASM_TILE_CMPXCHG_H
  20
  21#ifndef __ASSEMBLY__
  22
  23#include <asm/barrier.h>
  24
  25/* Nonexistent functions intended to cause compile errors. */
  26extern void __xchg_called_with_bad_pointer(void)
  27        __compiletime_error("Bad argument size for xchg");
  28extern void __cmpxchg_called_with_bad_pointer(void)
  29        __compiletime_error("Bad argument size for cmpxchg");
  30
  31#ifndef __tilegx__
  32
  33/* Note the _atomic_xxx() routines include a final mb(). */
  34int _atomic_xchg(int *ptr, int n);
  35int _atomic_xchg_add(int *v, int i);
  36int _atomic_xchg_add_unless(int *v, int a, int u);
  37int _atomic_cmpxchg(int *ptr, int o, int n);
  38long long _atomic64_xchg(long long *v, long long n);
  39long long _atomic64_xchg_add(long long *v, long long i);
  40long long _atomic64_xchg_add_unless(long long *v, long long a, long long u);
  41long long _atomic64_cmpxchg(long long *v, long long o, long long n);
  42
  43#define xchg(ptr, n)                                                    \
  44        ({                                                              \
  45                if (sizeof(*(ptr)) != 4)                                \
  46                        __xchg_called_with_bad_pointer();               \
  47                smp_mb();                                               \
  48                (typeof(*(ptr)))_atomic_xchg((int *)(ptr), (int)(n));   \
  49        })
  50
  51#define cmpxchg(ptr, o, n)                                              \
  52        ({                                                              \
  53                if (sizeof(*(ptr)) != 4)                                \
  54                        __cmpxchg_called_with_bad_pointer();            \
  55                smp_mb();                                               \
  56                (typeof(*(ptr)))_atomic_cmpxchg((int *)ptr, (int)o,     \
  57                                                (int)n);                \
  58        })
  59
  60#define xchg64(ptr, n)                                                  \
  61        ({                                                              \
  62                if (sizeof(*(ptr)) != 8)                                \
  63                        __xchg_called_with_bad_pointer();               \
  64                smp_mb();                                               \
  65                (typeof(*(ptr)))_atomic64_xchg((long long *)(ptr),      \
  66                                                (long long)(n));        \
  67        })
  68
  69#define cmpxchg64(ptr, o, n)                                            \
  70        ({                                                              \
  71                if (sizeof(*(ptr)) != 8)                                \
  72                        __cmpxchg_called_with_bad_pointer();            \
  73                smp_mb();                                               \
  74                (typeof(*(ptr)))_atomic64_cmpxchg((long long *)ptr,     \
  75                                        (long long)o, (long long)n);    \
  76        })
  77
  78#else
  79
  80#define xchg(ptr, n)                                                    \
  81        ({                                                              \
  82                typeof(*(ptr)) __x;                                     \
  83                smp_mb();                                               \
  84                switch (sizeof(*(ptr))) {                               \
  85                case 4:                                                 \
  86                        __x = (typeof(__x))(unsigned long)              \
  87                                __insn_exch4((ptr),                     \
  88                                        (u32)(unsigned long)(n));       \
  89                        break;                                          \
  90                case 8:                                                 \
  91                        __x = (typeof(__x))                             \
  92                                __insn_exch((ptr), (unsigned long)(n)); \
  93                        break;                                          \
  94                default:                                                \
  95                        __xchg_called_with_bad_pointer();               \
  96                        break;                                          \
  97                }                                                       \
  98                smp_mb();                                               \
  99                __x;                                                    \
 100        })
 101
 102#define cmpxchg(ptr, o, n)                                              \
 103        ({                                                              \
 104                typeof(*(ptr)) __x;                                     \
 105                __insn_mtspr(SPR_CMPEXCH_VALUE, (unsigned long)(o));    \
 106                smp_mb();                                               \
 107                switch (sizeof(*(ptr))) {                               \
 108                case 4:                                                 \
 109                        __x = (typeof(__x))(unsigned long)              \
 110                                __insn_cmpexch4((ptr),                  \
 111                                        (u32)(unsigned long)(n));       \
 112                        break;                                          \
 113                case 8:                                                 \
 114                        __x = (typeof(__x))__insn_cmpexch((ptr),        \
 115                                                (long long)(n));        \
 116                        break;                                          \
 117                default:                                                \
 118                        __cmpxchg_called_with_bad_pointer();            \
 119                        break;                                          \
 120                }                                                       \
 121                smp_mb();                                               \
 122                __x;                                                    \
 123        })
 124
 125#define xchg64 xchg
 126#define cmpxchg64 cmpxchg
 127
 128#endif
 129
 130#endif /* __ASSEMBLY__ */
 131
 132#endif /* _ASM_TILE_CMPXCHG_H */
 133