xref: /openbmc/linux/arch/ia64/include/uapi/asm/cmpxchg.h (revision 43e40f25)
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