浏览代码

Added atomicTestAndInc/Dec.

Branimir Karadžić 11 年之前
父节点
当前提交
aa2d6a90b3
共有 1 个文件被更改,包括 64 次插入15 次删除
  1. 64 15
      include/bx/cpu.h

+ 64 - 15
include/bx/cpu.h

@@ -27,37 +27,43 @@ extern "C" void _ReadWriteBarrier();
 #	pragma intrinsic(_ReadWriteBarrier)
 #	pragma intrinsic(_ReadWriteBarrier)
 #	pragma intrinsic(_InterlockedIncrement)
 #	pragma intrinsic(_InterlockedIncrement)
 #	pragma intrinsic(_InterlockedDecrement)
 #	pragma intrinsic(_InterlockedDecrement)
+#	pragma intrinsic(_InterlockedCompareExchange)
+#	pragma intrinsic(_InterlockedExchangePointer)
 #endif // BX_COMPILER_MSVC
 #endif // BX_COMPILER_MSVC
 
 
 namespace bx
 namespace bx
 {
 {
+	///
 	inline void readBarrier()
 	inline void readBarrier()
 	{
 	{
 #if BX_COMPILER_MSVC
 #if BX_COMPILER_MSVC
 		_ReadBarrier();
 		_ReadBarrier();
-#elif BX_COMPILER_GCC || BX_COMPILER_CLANG
+#else
 		asm volatile("":::"memory");
 		asm volatile("":::"memory");
 #endif // BX_COMPILER
 #endif // BX_COMPILER
 	}
 	}
 
 
+	///
 	inline void writeBarrier()
 	inline void writeBarrier()
 	{
 	{
 #if BX_COMPILER_MSVC
 #if BX_COMPILER_MSVC
 		_WriteBarrier();
 		_WriteBarrier();
-#elif BX_COMPILER_GCC || BX_COMPILER_CLANG
+#else
 		asm volatile("":::"memory");
 		asm volatile("":::"memory");
 #endif // BX_COMPILER
 #endif // BX_COMPILER
 	}
 	}
 
 
+	///
 	inline void readWriteBarrier()
 	inline void readWriteBarrier()
 	{
 	{
 #if BX_COMPILER_MSVC
 #if BX_COMPILER_MSVC
 		_ReadWriteBarrier();
 		_ReadWriteBarrier();
-#elif BX_COMPILER_GCC || BX_COMPILER_CLANG
+#else
 		asm volatile("":::"memory");
 		asm volatile("":::"memory");
 #endif // BX_COMPILER
 #endif // BX_COMPILER
 	}
 	}
 
 
+	///
 	inline void memoryBarrier()
 	inline void memoryBarrier()
 	{
 	{
 #if BX_PLATFORM_XBOX360
 #if BX_PLATFORM_XBOX360
@@ -72,33 +78,76 @@ namespace bx
 #endif // BX_COMPILER
 #endif // BX_COMPILER
 	}
 	}
 
 
-	inline int32_t atomicIncr(volatile void* _var)
+	///
+	inline int32_t atomicInc(volatile void* _ptr)
 	{
 	{
 #if BX_COMPILER_MSVC
 #if BX_COMPILER_MSVC
-		return _InterlockedIncrement( (volatile LONG*)(_var) );
-#elif BX_COMPILER_GCC || BX_COMPILER_CLANG
-		return __sync_fetch_and_add( (volatile int32_t*)_var, 1);
+		return _InterlockedIncrement( (volatile LONG*)(_ptr) );
+#else
+		return __sync_fetch_and_add( (volatile int32_t*)_ptr, 1);
 #endif // BX_COMPILER
 #endif // BX_COMPILER
 	}
 	}
 
 
-	inline int32_t atomicDecr(volatile void* _var)
+	///
+	inline int32_t atomicDec(volatile void* _ptr)
 	{
 	{
 #if BX_COMPILER_MSVC
 #if BX_COMPILER_MSVC
-		return _InterlockedDecrement( (volatile LONG*)(_var) );
-#elif BX_COMPILER_GCC || BX_COMPILER_CLANG
-		return __sync_fetch_and_sub( (volatile int32_t*)_var, 1);
+		return _InterlockedDecrement( (volatile LONG*)(_ptr) );
+#else
+		return __sync_fetch_and_sub( (volatile int32_t*)_ptr, 1);
+#endif // BX_COMPILER
+	}
+
+	///
+	inline int32_t atomicCompareAndSwap(volatile void* _ptr, int32_t _old, int32_t _new)
+	{
+#if BX_COMPILER_MSVC
+		return _InterlockedCompareExchange( (volatile LONG*)(_ptr), _new, _old);
+#else
+		return __sync_val_compare_and_swap(_ptr, _old, _new);
 #endif // BX_COMPILER
 #endif // BX_COMPILER
 	}
 	}
 
 
-	inline void* atomicExchangePtr(void** _target, void* _ptr)
+	///
+	inline void* atomicExchangePtr(void** _ptr, void* _new)
 	{
 	{
 #if BX_COMPILER_MSVC
 #if BX_COMPILER_MSVC
-		return InterlockedExchangePointer(_target, _ptr);
-#elif BX_COMPILER_GCC || BX_COMPILER_CLANG
-		return __sync_lock_test_and_set(_target, _ptr);
+		return _InterlockedExchangePointer(_ptr, _new);
+#else
+		return __sync_lock_test_and_set(_ptr, _new);
 #endif // BX_COMPILER
 #endif // BX_COMPILER
 	}
 	}
 
 
+	///
+	inline int32_t atomicTestAndInc(volatile void* _ptr, int32_t _test)
+	{
+		int32_t oldVal;
+		int32_t newVal = *(int32_t volatile*)_ptr;
+		do
+		{
+			oldVal = newVal;
+			newVal = atomicCompareAndSwap(_ptr, oldVal, newVal >= _test ? _test : newVal+1);
+
+		} while (oldVal != newVal);
+
+		return oldVal;
+	}
+
+	///
+	inline int32_t atomicTestAndDec(volatile void* _ptr, int32_t _test)
+	{
+		int32_t oldVal;
+		int32_t newVal = *(int32_t volatile*)_ptr;
+		do
+		{
+			oldVal = newVal;
+			newVal = atomicCompareAndSwap(_ptr, oldVal, newVal <= _test ? _test : newVal+1);
+
+		} while (oldVal != newVal);
+
+		return oldVal;
+	}
+
 } // namespace bx
 } // namespace bx
 
 
 #endif // BX_CPU_H_HEADER_GUARD
 #endif // BX_CPU_H_HEADER_GUARD