用于Sparc架构的GCC内联汇编

我在互联网上找到了__sync_val_compare_and_swap的实现:

#define LOCK_PREFIX "lock ; " struct __xchg_dummy { unsigned long a[100]; }; #define __xg(x) ((struct __xchg_dummy *)(x)) static inline unsigned long __cmpxchg(volatile void *ptr, unsigned long old, unsigned long new, int size) { unsigned long prev; switch (size) { case 1: __asm__ __volatile__(LOCK_PREFIX "cmpxchgb %b1,%2" : "=a"(prev) : "q"(new), "m"(*__xg(ptr)), "0"(old) : "memory"); return prev; case 2: __asm__ __volatile__(LOCK_PREFIX "cmpxchgw %w1,%2" : "=a"(prev) : "q"(new), "m"(*__xg(ptr)), "0"(old) : "memory"); return prev; case 4: __asm__ __volatile__(LOCK_PREFIX "cmpxchgl %1,%2" : "=a"(prev) : "q"(new), "m"(*__xg(ptr)), "0"(old) : "memory"); return prev; } return old; } #define cmpxchg(ptr,o,n)\ ((__typeof__(*(ptr)))__cmpxchg((ptr),(unsigned long)(o),\ (unsigned long)(n),sizeof(*(ptr)))) 

当我为i386架构编译和使用这个函数(cmpxchg)时 – 一切都很好! 但是,当我在Sparc架构下编译时,我有以下错误:

 error: impossible constraint in `asm' 

有什么问题?

在Solaris上,最好不要为此编写自己的代码(在SPARC和x86上都没有); 相反,使用atomic_cas(3C)函数用于此目的:

 static inline unsigned long __cmpxchg(volatile void *ptr, unsigned long old, unsigned long new, int size) { switch (size) { case 1: return atomic_cas_8(ptr, (unsigned char)old, (unsigned char)new); case 2: return atomic_cas_16(ptr, (unsigned short)old, (unsigned short)new); case 4: return atomic_cas_32(ptr, (unsigned int)old, (unsigned int)new); #ifdef _LP64 case 8: return atomic_cas_64(ptr, old, new); #endif default: break; } return old; } 

这对Solaris有用。

编辑:如果你绝对必须内联这种东西,SPARC(v8 +,又名UltraSPARC)使用的指令是“比较和交换”,即CAS 。 它总是primefaces的(sparc不知道锁前缀)。 它只有32位和64位( CASX )变体,因此8/16位库函数执行32位CAS屏蔽非目标字/字节。 我不会帮助重新实现 – 这不是一个好主意,使用库接口。

Edit2:通过阅读源代码可以帮助重新实现(如果无法与Solaris libc链接)。

cmpxchgb是一个i386指令,它不能在Sparc下工作。

您无法为sparc编译x86 asm。 这是我使用clang得到的:

 [~] main% ~/ellcc/bin/sparc-linux-ecc asm.c asm.c:13:20: error: invalid output constraint '=a' in asm : "=a"(prev) 

‘a’不是sparc寄存器,它特定于x86。

即使你要修复约束,当sparc汇编程序看到cmpxchgb操作码时,你会得到汇编时错误,这是x86特定的。