2012-02-14 135 views
1

我在网上找到的__sync_val_compare_and_swap实现:GCC内联汇编的SPARC架构

#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)))) 

当我编译和使用此功能(CMPXCHG)为i386架构 - 所有的好!但是,当我在SPARC架构编译,我以下错误:

error: impossible constraint in `asm' 

什么问题?

回答

3

在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。它总是原子的(sparc不知道锁前缀)。它只包含32位和64位(CASX)变体,以便8/16位库函数执行掩盖非目标字/字节的32位CAS。我不会帮助重新实现 - 这不是一个好主意,请使用库接口。

编辑2:一些帮助重新实现你得到reading the sourcecode(如果你不能链接到Solaris libc)。

+0

test_cas.c :(.text + 0x70):undefined指向'atomic_cas_8' – 2012-02-20 14:20:37

1

您无法编译sparc的x86 asm。这是我得到的使用叮铛声:

[~] 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汇编程序看到x86特定的cmpxchgb操作码时,也会出现汇编时错误。

+0

当我可以找到sparc的__sync_val_compare_and_swap实现,如果我不知道汇编程序,或者我必须开始学习asm?:( – 2012-02-14 12:47:46

5

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