143e40f25SDavid Howells #ifndef _ASM_IA64_CMPXCHG_H 243e40f25SDavid Howells #define _ASM_IA64_CMPXCHG_H 343e40f25SDavid Howells 443e40f25SDavid Howells /* 543e40f25SDavid Howells * Compare/Exchange, forked from asm/intrinsics.h 643e40f25SDavid Howells * which was: 743e40f25SDavid Howells * 843e40f25SDavid Howells * Copyright (C) 2002-2003 Hewlett-Packard Co 943e40f25SDavid Howells * David Mosberger-Tang <davidm@hpl.hp.com> 1043e40f25SDavid Howells */ 1143e40f25SDavid Howells 1243e40f25SDavid Howells #ifndef __ASSEMBLY__ 1343e40f25SDavid Howells 1443e40f25SDavid Howells #include <linux/types.h> 1543e40f25SDavid Howells /* include compiler specific intrinsics */ 1643e40f25SDavid Howells #include <asm/ia64regs.h> 1743e40f25SDavid Howells #ifdef __INTEL_COMPILER 1843e40f25SDavid Howells # include <asm/intel_intrin.h> 1943e40f25SDavid Howells #else 2043e40f25SDavid Howells # include <asm/gcc_intrin.h> 2143e40f25SDavid Howells #endif 2243e40f25SDavid Howells 2343e40f25SDavid Howells /* 2443e40f25SDavid Howells * This function doesn't exist, so you'll get a linker error if 2543e40f25SDavid Howells * something tries to do an invalid xchg(). 2643e40f25SDavid Howells */ 2743e40f25SDavid Howells extern void ia64_xchg_called_with_bad_pointer(void); 2843e40f25SDavid Howells 2943e40f25SDavid Howells #define __xchg(x, ptr, size) \ 3043e40f25SDavid Howells ({ \ 3143e40f25SDavid Howells unsigned long __xchg_result; \ 3243e40f25SDavid Howells \ 3343e40f25SDavid Howells switch (size) { \ 3443e40f25SDavid Howells case 1: \ 3543e40f25SDavid Howells __xchg_result = ia64_xchg1((__u8 *)ptr, x); \ 3643e40f25SDavid Howells break; \ 3743e40f25SDavid Howells \ 3843e40f25SDavid Howells case 2: \ 3943e40f25SDavid Howells __xchg_result = ia64_xchg2((__u16 *)ptr, x); \ 4043e40f25SDavid Howells break; \ 4143e40f25SDavid Howells \ 4243e40f25SDavid Howells case 4: \ 4343e40f25SDavid Howells __xchg_result = ia64_xchg4((__u32 *)ptr, x); \ 4443e40f25SDavid Howells break; \ 4543e40f25SDavid Howells \ 4643e40f25SDavid Howells case 8: \ 4743e40f25SDavid Howells __xchg_result = ia64_xchg8((__u64 *)ptr, x); \ 4843e40f25SDavid Howells break; \ 4943e40f25SDavid Howells default: \ 5043e40f25SDavid Howells ia64_xchg_called_with_bad_pointer(); \ 5143e40f25SDavid Howells } \ 5243e40f25SDavid Howells __xchg_result; \ 5343e40f25SDavid Howells }) 5443e40f25SDavid Howells 5543e40f25SDavid Howells #define xchg(ptr, x) \ 5643e40f25SDavid Howells ((__typeof__(*(ptr))) __xchg((unsigned long) (x), (ptr), sizeof(*(ptr)))) 5743e40f25SDavid Howells 5843e40f25SDavid Howells /* 5943e40f25SDavid Howells * Atomic compare and exchange. Compare OLD with MEM, if identical, 6043e40f25SDavid Howells * store NEW in MEM. Return the initial value in MEM. Success is 6143e40f25SDavid Howells * indicated by comparing RETURN with OLD. 6243e40f25SDavid Howells */ 6343e40f25SDavid Howells 6443e40f25SDavid Howells #define __HAVE_ARCH_CMPXCHG 1 6543e40f25SDavid Howells 6643e40f25SDavid Howells /* 6743e40f25SDavid Howells * This function doesn't exist, so you'll get a linker error 6843e40f25SDavid Howells * if something tries to do an invalid cmpxchg(). 6943e40f25SDavid Howells */ 7043e40f25SDavid Howells extern long ia64_cmpxchg_called_with_bad_pointer(void); 7143e40f25SDavid Howells 7243e40f25SDavid Howells #define ia64_cmpxchg(sem, ptr, old, new, size) \ 7343e40f25SDavid Howells ({ \ 7443e40f25SDavid Howells __u64 _o_, _r_; \ 7543e40f25SDavid Howells \ 7643e40f25SDavid Howells switch (size) { \ 7743e40f25SDavid Howells case 1: \ 7843e40f25SDavid Howells _o_ = (__u8) (long) (old); \ 7943e40f25SDavid Howells break; \ 8043e40f25SDavid Howells case 2: \ 8143e40f25SDavid Howells _o_ = (__u16) (long) (old); \ 8243e40f25SDavid Howells break; \ 8343e40f25SDavid Howells case 4: \ 8443e40f25SDavid Howells _o_ = (__u32) (long) (old); \ 8543e40f25SDavid Howells break; \ 8643e40f25SDavid Howells case 8: \ 8743e40f25SDavid Howells _o_ = (__u64) (long) (old); \ 8843e40f25SDavid Howells break; \ 8943e40f25SDavid Howells default: \ 9043e40f25SDavid Howells break; \ 9143e40f25SDavid Howells } \ 9243e40f25SDavid Howells switch (size) { \ 9343e40f25SDavid Howells case 1: \ 9443e40f25SDavid Howells _r_ = ia64_cmpxchg1_##sem((__u8 *) ptr, new, _o_); \ 9543e40f25SDavid Howells break; \ 9643e40f25SDavid Howells \ 9743e40f25SDavid Howells case 2: \ 9843e40f25SDavid Howells _r_ = ia64_cmpxchg2_##sem((__u16 *) ptr, new, _o_); \ 9943e40f25SDavid Howells break; \ 10043e40f25SDavid Howells \ 10143e40f25SDavid Howells case 4: \ 10243e40f25SDavid Howells _r_ = ia64_cmpxchg4_##sem((__u32 *) ptr, new, _o_); \ 10343e40f25SDavid Howells break; \ 10443e40f25SDavid Howells \ 10543e40f25SDavid Howells case 8: \ 10643e40f25SDavid Howells _r_ = ia64_cmpxchg8_##sem((__u64 *) ptr, new, _o_); \ 10743e40f25SDavid Howells break; \ 10843e40f25SDavid Howells \ 10943e40f25SDavid Howells default: \ 11043e40f25SDavid Howells _r_ = ia64_cmpxchg_called_with_bad_pointer(); \ 11143e40f25SDavid Howells break; \ 11243e40f25SDavid Howells } \ 11343e40f25SDavid Howells (__typeof__(old)) _r_; \ 11443e40f25SDavid Howells }) 11543e40f25SDavid Howells 11643e40f25SDavid Howells #define cmpxchg_acq(ptr, o, n) \ 11743e40f25SDavid Howells ia64_cmpxchg(acq, (ptr), (o), (n), sizeof(*(ptr))) 11843e40f25SDavid Howells #define cmpxchg_rel(ptr, o, n) \ 11943e40f25SDavid Howells ia64_cmpxchg(rel, (ptr), (o), (n), sizeof(*(ptr))) 12043e40f25SDavid Howells 12143e40f25SDavid Howells /* for compatibility with other platforms: */ 12243e40f25SDavid Howells #define cmpxchg(ptr, o, n) cmpxchg_acq((ptr), (o), (n)) 12343e40f25SDavid Howells #define cmpxchg64(ptr, o, n) cmpxchg_acq((ptr), (o), (n)) 12443e40f25SDavid Howells 12543e40f25SDavid Howells #define cmpxchg_local cmpxchg 12643e40f25SDavid Howells #define cmpxchg64_local cmpxchg64 12743e40f25SDavid Howells 12843e40f25SDavid Howells #ifdef CONFIG_IA64_DEBUG_CMPXCHG 12943e40f25SDavid Howells # define CMPXCHG_BUGCHECK_DECL int _cmpxchg_bugcheck_count = 128; 13043e40f25SDavid Howells # define CMPXCHG_BUGCHECK(v) \ 13143e40f25SDavid Howells do { \ 13243e40f25SDavid Howells if (_cmpxchg_bugcheck_count-- <= 0) { \ 13343e40f25SDavid Howells void *ip; \ 13443e40f25SDavid Howells extern int printk(const char *fmt, ...); \ 13543e40f25SDavid Howells ip = (void *) ia64_getreg(_IA64_REG_IP); \ 13643e40f25SDavid Howells printk("CMPXCHG_BUGCHECK: stuck at %p on word %p\n", ip, (v));\ 13743e40f25SDavid Howells break; \ 13843e40f25SDavid Howells } \ 13943e40f25SDavid Howells } while (0) 14043e40f25SDavid Howells #else /* !CONFIG_IA64_DEBUG_CMPXCHG */ 14143e40f25SDavid Howells # define CMPXCHG_BUGCHECK_DECL 14243e40f25SDavid Howells # define CMPXCHG_BUGCHECK(v) 14343e40f25SDavid Howells #endif /* !CONFIG_IA64_DEBUG_CMPXCHG */ 14443e40f25SDavid Howells 14543e40f25SDavid Howells #endif /* !__ASSEMBLY__ */ 14643e40f25SDavid Howells 14743e40f25SDavid Howells #endif /* _ASM_IA64_CMPXCHG_H */ 148