2012-02-14 5 views
1

내가 인터넷에서 __sync_val_compare_and_swap의 구현을 발견했습니다GCC 인라인 어셈블리 스팍 아키텍처

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

문제점 :

답변

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 +, 일명 울트라 스팍)를 사용하는 명령은, "비교 및 스왑"일명 CAS입니다. 항상 원자 적입니다 (sparc은 잠금 접두사를 모릅니다). 32 비트 및 64 비트 (CASX) 변형이 제공되므로 8/16 비트 라이브러리 함수는 32 비트 CAS을 대상으로하지 않는 단어/바이트를 마스킹합니다. 다시 구현하는 것을 도와주지는 않을 것입니다. 라이브러리 인터페이스를 사용하는 것은 좋지 않습니다.

편집 2 :reading the sourcecode (Solaris libc와 연결할 수없는 경우)을 다시 작성하는 데 도움이됩니다.

+0

test_cas.c :(. 텍스트 + 0x70) : 'atomic_cas_8'에 대한 정의되지 않은 참조 –

1

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 어셈블러에서 x86 전용 cmpxchgb opcode를 볼 때 어셈블리 시간 오류가 발생합니다.

+0

sparc에 대한 __sync_val_compare_and_swap 구현을 찾을 수있을 때 어셈블러에 대해 모르거나 ASM 학습을 시작해야합니까? :( –

5

cmpxchgb은 i386 명령어이므로 Sparc에서는 작동하지 않습니다.

관련 문제