r600g: Use the actual Evergreen functions to query format support on Evergreen.
[mesa.git] / src / gallium / auxiliary / util / u_atomic.h
index 1c042c3ede94b7e7efd87cca193b0cece568bf08..8434491a42129534314174ec2b68ee1d7ce82492 100644 (file)
 #include "pipe/p_compiler.h"
 #include "pipe/p_defines.h"
 
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-
 /* Favor OS-provided implementations.
  *
  * Where no OS-provided implementation is available, fall back to
@@ -25,29 +20,81 @@ extern "C" {
  */
 #if (defined(PIPE_SUBSYSTEM_WINDOWS_DISPLAY) || \
      defined(PIPE_SUBSYSTEM_WINDOWS_MINIPORT))
-#define PIPE_ATOMIC_OS_UNLOCKED 
+#define PIPE_ATOMIC_OS_UNLOCKED
+#elif defined(PIPE_OS_SOLARIS)
+#define PIPE_ATOMIC_OS_SOLARIS
 #elif defined(PIPE_CC_MSVC)
 #define PIPE_ATOMIC_MSVC_INTRINSIC
 #elif (defined(PIPE_CC_MSVC) && defined(PIPE_ARCH_X86))
 #define PIPE_ATOMIC_ASM_MSVC_X86                
 #elif (defined(PIPE_CC_GCC) && defined(PIPE_ARCH_X86))
 #define PIPE_ATOMIC_ASM_GCC_X86
-#elif defined(PIPE_CC_GCC)
+#elif (defined(PIPE_CC_GCC) && defined(PIPE_ARCH_X86_64))
+#define PIPE_ATOMIC_ASM_GCC_X86_64
+#elif defined(PIPE_CC_GCC) && (PIPE_CC_GCC_VERSION >= 401)
 #define PIPE_ATOMIC_GCC_INTRINSIC
 #else
 #error "Unsupported platform"
 #endif
 
 
+#if defined(PIPE_ATOMIC_ASM_GCC_X86_64)
+#define PIPE_ATOMIC "GCC x86_64 assembly"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define p_atomic_set(_v, _i) (*(_v) = (_i))
+#define p_atomic_read(_v) (*(_v))
+
+static INLINE boolean
+p_atomic_dec_zero(int32_t *v)
+{
+   unsigned char c;
+
+   __asm__ __volatile__("lock; decl %0; sete %1":"+m"(*v), "=qm"(c)
+                       ::"memory");
+
+   return c != 0;
+}
+
+static INLINE void
+p_atomic_inc(int32_t *v)
+{
+   __asm__ __volatile__("lock; incl %0":"+m"(*v));
+}
+
+static INLINE void
+p_atomic_dec(int32_t *v)
+{
+   __asm__ __volatile__("lock; decl %0":"+m"(*v));
+}
+
+static INLINE int32_t
+p_atomic_cmpxchg(int32_t *v, int32_t old, int32_t _new)
+{
+   return __sync_val_compare_and_swap(v, old, _new);
+}
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* PIPE_ATOMIC_ASM_GCC_X86_64 */
+
 
 #if defined(PIPE_ATOMIC_ASM_GCC_X86)
 
 #define PIPE_ATOMIC "GCC x86 assembly"
 
+#ifdef __cplusplus
+extern "C" {
+#endif
+
 #define p_atomic_set(_v, _i) (*(_v) = (_i))
 #define p_atomic_read(_v) (*(_v))
 
-
 static INLINE boolean
 p_atomic_dec_zero(int32_t *v)
 {
@@ -76,6 +123,11 @@ p_atomic_cmpxchg(int32_t *v, int32_t old, int32_t _new)
 {
    return __sync_val_compare_and_swap(v, old, _new);
 }
+
+#ifdef __cplusplus
+}
+#endif
+
 #endif
 
 
@@ -86,10 +138,13 @@ p_atomic_cmpxchg(int32_t *v, int32_t old, int32_t _new)
 
 #define PIPE_ATOMIC "GCC Sync Intrinsics"
 
+#ifdef __cplusplus
+extern "C" {
+#endif
+
 #define p_atomic_set(_v, _i) (*(_v) = (_i))
 #define p_atomic_read(_v) (*(_v))
 
-
 static INLINE boolean
 p_atomic_dec_zero(int32_t *v)
 {
@@ -113,6 +168,11 @@ p_atomic_cmpxchg(int32_t *v, int32_t old, int32_t _new)
 {
    return __sync_val_compare_and_swap(v, old, _new);
 }
+
+#ifdef __cplusplus
+}
+#endif
+
 #endif
 
 
@@ -140,6 +200,10 @@ p_atomic_cmpxchg(int32_t *v, int32_t old, int32_t _new)
 
 #define PIPE_ATOMIC "MSVC x86 assembly"
 
+#ifdef __cplusplus
+extern "C" {
+#endif
+
 #define p_atomic_set(_v, _i) (*(_v) = (_i))
 #define p_atomic_read(_v) (*(_v))
 
@@ -190,6 +254,11 @@ p_atomic_cmpxchg(int32_t *v, int32_t old, int32_t _new)
 
    return orig;
 }
+
+#ifdef __cplusplus
+}
+#endif
+
 #endif
 
 
@@ -203,45 +272,81 @@ p_atomic_cmpxchg(int32_t *v, int32_t old, int32_t _new)
 #pragma intrinsic(_InterlockedDecrement)
 #pragma intrinsic(_InterlockedCompareExchange)
 
+#ifdef __cplusplus
+extern "C" {
+#endif
+
 #define p_atomic_set(_v, _i) (*(_v) = (_i))
 #define p_atomic_read(_v) (*(_v))
 
 static INLINE boolean
 p_atomic_dec_zero(int32_t *v)
 {
-   return _InterlockedDecrement(v) == 0;
+   return _InterlockedDecrement((long *)v) == 0;
 }
 
 static INLINE void
 p_atomic_inc(int32_t *v)
 {
-   _InterlockedIncrement(v);
+   _InterlockedIncrement((long *)v);
 }
 
 static INLINE void
 p_atomic_dec(int32_t *v)
 {
-   _InterlockedDecrement(v);
+   _InterlockedDecrement((long *)v);
 }
 
 static INLINE int32_t
 p_atomic_cmpxchg(int32_t *v, int32_t old, int32_t _new)
 {
-   return _InterlockedCompareExchange(v, _new, old);
+   return _InterlockedCompareExchange((long *)v, _new, old);
 }
 
+#ifdef __cplusplus
+}
 #endif
 
+#endif
 
+#if defined(PIPE_ATOMIC_OS_SOLARIS)
 
-#ifndef PIPE_ATOMIC
-#error "No pipe_atomic implementation selected"
+#define PIPE_ATOMIC "Solaris OS atomic functions"
+
+#include <atomic.h>
+
+#ifdef __cplusplus
+extern "C" {
 #endif
 
+#define p_atomic_set(_v, _i) (*(_v) = (_i))
+#define p_atomic_read(_v) (*(_v))
+
+static INLINE boolean
+p_atomic_dec_zero(int32_t *v)
+{
+   uint32_t n = atomic_dec_32_nv((uint32_t *) v);
+
+   return n != 0;
+}
+
+#define p_atomic_inc(_v) atomic_inc_32((uint32_t *) _v)
+#define p_atomic_dec(_v) atomic_dec_32((uint32_t *) _v)
 
+#define p_atomic_cmpxchg(_v, _old, _new) \
+       atomic_cas_32( (uint32_t *) _v, (uint32_t) _old, (uint32_t) _new)
 
 #ifdef __cplusplus
 }
 #endif
 
+#endif
+
+
+#ifndef PIPE_ATOMIC
+#error "No pipe_atomic implementation selected"
+#endif
+
+
+
 #endif /* U_ATOMIC_H */