diff --git a/include/bx/cpu.h b/include/bx/cpu.h index 483d935..d5ef1d3 100644 --- a/include/bx/cpu.h +++ b/include/bx/cpu.h @@ -27,37 +27,43 @@ extern "C" void _ReadWriteBarrier(); # pragma intrinsic(_ReadWriteBarrier) # pragma intrinsic(_InterlockedIncrement) # pragma intrinsic(_InterlockedDecrement) +# pragma intrinsic(_InterlockedCompareExchange) +# pragma intrinsic(_InterlockedExchangePointer) #endif // BX_COMPILER_MSVC namespace bx { + /// inline void readBarrier() { #if BX_COMPILER_MSVC _ReadBarrier(); -#elif BX_COMPILER_GCC || BX_COMPILER_CLANG +#else asm volatile("":::"memory"); #endif // BX_COMPILER } + /// inline void writeBarrier() { #if BX_COMPILER_MSVC _WriteBarrier(); -#elif BX_COMPILER_GCC || BX_COMPILER_CLANG +#else asm volatile("":::"memory"); #endif // BX_COMPILER } + /// inline void readWriteBarrier() { #if BX_COMPILER_MSVC _ReadWriteBarrier(); -#elif BX_COMPILER_GCC || BX_COMPILER_CLANG +#else asm volatile("":::"memory"); #endif // BX_COMPILER } + /// inline void memoryBarrier() { #if BX_PLATFORM_XBOX360 @@ -72,33 +78,76 @@ namespace bx #endif // BX_COMPILER } - inline int32_t atomicIncr(volatile void* _var) + /// + inline int32_t atomicInc(volatile void* _ptr) { #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 } - inline int32_t atomicDecr(volatile void* _var) + /// + inline int32_t atomicDec(volatile void* _ptr) { #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 void* atomicExchangePtr(void** _target, void* _ptr) + /// + inline int32_t atomicCompareAndSwap(volatile void* _ptr, int32_t _old, int32_t _new) { #if BX_COMPILER_MSVC - return InterlockedExchangePointer(_target, _ptr); -#elif BX_COMPILER_GCC || BX_COMPILER_CLANG - return __sync_lock_test_and_set(_target, _ptr); + return _InterlockedCompareExchange( (volatile LONG*)(_ptr), _new, _old); +#else + return __sync_val_compare_and_swap(_ptr, _old, _new); #endif // BX_COMPILER } + /// + inline void* atomicExchangePtr(void** _ptr, void* _new) + { +#if BX_COMPILER_MSVC + return _InterlockedExchangePointer(_ptr, _new); +#else + return __sync_lock_test_and_set(_ptr, _new); +#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 #endif // BX_CPU_H_HEADER_GUARD