/* * cmpxchg.h -- forked from asm/atomic.h with this copyright: * * Copyright 2010 Tilera Corporation. All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation, version 2. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or * NON INFRINGEMENT. See the GNU General Public License for * more details. * */ #ifndef _ASM_TILE_CMPXCHG_H #define _ASM_TILE_CMPXCHG_H #ifndef __ASSEMBLY__ #include <asm/barrier.h> /* Nonexistent functions intended to cause compile errors. */ extern void __xchg_called_with_bad_pointer(void) __compiletime_error("Bad argument size for xchg"); extern void __cmpxchg_called_with_bad_pointer(void) __compiletime_error("Bad argument size for cmpxchg"); #ifndef __tilegx__ /* Note the _atomic_xxx() routines include a final mb(). */ int _atomic_xchg(int *ptr, int n); int _atomic_xchg_add(int *v, int i); int _atomic_xchg_add_unless(int *v, int a, int u); int _atomic_cmpxchg(int *ptr, int o, int n); long long _atomic64_xchg(long long *v, long long n); long long _atomic64_xchg_add(long long *v, long long i); long long _atomic64_xchg_add_unless(long long *v, long long a, long long u); long long _atomic64_cmpxchg(long long *v, long long o, long long n); #define xchg(ptr, n) \ ({ \ if (sizeof(*(ptr)) != 4) \ __xchg_called_with_bad_pointer(); \ smp_mb(); \ (typeof(*(ptr)))_atomic_xchg((int *)(ptr), (int)(n)); \ }) #define cmpxchg(ptr, o, n) \ ({ \ if (sizeof(*(ptr)) != 4) \ __cmpxchg_called_with_bad_pointer(); \ smp_mb(); \ (typeof(*(ptr)))_atomic_cmpxchg((int *)ptr, (int)o, \ (int)n); \ }) #define xchg64(ptr, n) \ ({ \ if (sizeof(*(ptr)) != 8) \ __xchg_called_with_bad_pointer(); \ smp_mb(); \ (typeof(*(ptr)))_atomic64_xchg((long long *)(ptr), \ (long long)(n)); \ }) #define cmpxchg64(ptr, o, n) \ ({ \ if (sizeof(*(ptr)) != 8) \ __cmpxchg_called_with_bad_pointer(); \ smp_mb(); \ (typeof(*(ptr)))_atomic64_cmpxchg((long long *)ptr, \ (long long)o, (long long)n); \ }) #else #define xchg(ptr, n) \ ({ \ typeof(*(ptr)) __x; \ smp_mb(); \ switch (sizeof(*(ptr))) { \ case 4: \ __x = (typeof(__x))(unsigned long) \ __insn_exch4((ptr), \ (u32)(unsigned long)(n)); \ break; \ case 8: \ __x = (typeof(__x)) \ __insn_exch((ptr), (unsigned long)(n)); \ break; \ default: \ __xchg_called_with_bad_pointer(); \ break; \ } \ smp_mb(); \ __x; \ }) #define cmpxchg(ptr, o, n) \ ({ \ typeof(*(ptr)) __x; \ __insn_mtspr(SPR_CMPEXCH_VALUE, (unsigned long)(o)); \ smp_mb(); \ switch (sizeof(*(ptr))) { \ case 4: \ __x = (typeof(__x))(unsigned long) \ __insn_cmpexch4((ptr), \ (u32)(unsigned long)(n)); \ break; \ case 8: \ __x = (typeof(__x))__insn_cmpexch((ptr), \ (long long)(n)); \ break; \ default: \ __cmpxchg_called_with_bad_pointer(); \ break; \ } \ smp_mb(); \ __x; \ }) #define xchg64 xchg #define cmpxchg64 cmpxchg #endif #define tas(ptr) xchg((ptr), 1) #endif /* __ASSEMBLY__ */ #endif /* _ASM_TILE_CMPXCHG_H */