diff --git a/Utilities/Atomic.h b/Utilities/Atomic.h index 42e786a660..4204267b86 100644 --- a/Utilities/Atomic.h +++ b/Utilities/Atomic.h @@ -174,7 +174,7 @@ struct atomic_storage } }; -/* The rest: ugly MSVC intrinsics + possibly __asm__ implementations (TODO) */ +/* The rest: ugly MSVC intrinsics + inline asm implementations */ template struct atomic_storage : atomic_storage @@ -297,6 +297,27 @@ struct atomic_storage : atomic_storage short r = _InterlockedDecrement16((volatile short*)&dest); return (T&)r; } +#else + static inline bool bts(T& dest, uint bit) + { + bool result; + __asm__("lock btsw %2, %0\n" "setc %1" : "+m" (dest), "=r" (result) : "Ir" (bit) : "cc"); + return result; + } + + static inline bool btr(T& dest, uint bit) + { + bool result; + __asm__("lock btrw %2, %0\n" "setc %1" : "+m" (dest), "=r" (result) : "Ir" (bit) : "cc"); + return result; + } + + static inline bool btc(T& dest, uint bit) + { + bool result; + __asm__("lock btcw %2, %0\n" "setc %1" : "+m" (dest), "=r" (result) : "Ir" (bit) : "cc"); + return result; + } #endif }; @@ -375,6 +396,27 @@ struct atomic_storage : atomic_storage { return _interlockedbittestandreset((volatile long*)&dest, bit) != 0; } +#else + static inline bool bts(T& dest, uint bit) + { + bool result; + __asm__("lock btsl %2, %0\n" "setc %1" : "+m" (dest), "=r" (result) : "Ir" (bit) : "cc"); + return result; + } + + static inline bool btr(T& dest, uint bit) + { + bool result; + __asm__("lock btrl %2, %0\n" "setc %1" : "+m" (dest), "=r" (result) : "Ir" (bit) : "cc"); + return result; + } + + static inline bool btc(T& dest, uint bit) + { + bool result; + __asm__("lock btcl %2, %0\n" "setc %1" : "+m" (dest), "=r" (result) : "Ir" (bit) : "cc"); + return result; + } #endif }; @@ -453,6 +495,27 @@ struct atomic_storage : atomic_storage { return _interlockedbittestandreset64((volatile llong*)&dest, bit) != 0; } +#else + static inline bool bts(T& dest, uint bit) + { + bool result; + __asm__("lock btsq %2, %0\n" "setc %1" : "+m" (dest), "=r" (result) : "Ir" (bit) : "cc"); + return result; + } + + static inline bool btr(T& dest, uint bit) + { + bool result; + __asm__("lock btrq %2, %0\n" "setc %1" : "+m" (dest), "=r" (result) : "Ir" (bit) : "cc"); + return result; + } + + static inline bool btc(T& dest, uint bit) + { + bool result; + __asm__("lock btcq %2, %0\n" "setc %1" : "+m" (dest), "=r" (result) : "Ir" (bit) : "cc"); + return result; + } #endif }; @@ -490,6 +553,8 @@ struct atomic_storage : atomic_storage return *(T*)+cmp; } #endif + + // TODO }; template @@ -642,7 +707,7 @@ struct atomic_test_and_set { bool operator()(T1& lhs, const T2& rhs) const { - return lhs.test_and_set(rhs); + return test_and_set(lhs, rhs); } }; @@ -659,7 +724,7 @@ struct atomic_test_and_reset { bool operator()(T1& lhs, const T2& rhs) const { - return lhs.test_and_reset(rhs); + return test_and_reset(lhs, rhs); } }; @@ -676,7 +741,7 @@ struct atomic_test_and_complement { bool operator()(T1& lhs, const T2& rhs) const { - return lhs.test_and_complement(rhs); + return test_and_complement(lhs, rhs); } }; diff --git a/Utilities/bit_set.h b/Utilities/bit_set.h index 9d81c94cf1..fda36f5ec8 100644 --- a/Utilities/bit_set.h +++ b/Utilities/bit_set.h @@ -199,32 +199,32 @@ struct bs_base return (shift(lhs) & static_cast(rhs)) != 0; } - friend constexpr bool test_and_set(type& lhs, type rhs) + friend bool test_and_set(type& lhs, type rhs) { return test_and_set(reinterpret_cast(lhs), static_cast(rhs)); } - friend constexpr bool test_and_set(type& lhs, T rhs) + friend bool test_and_set(type& lhs, T rhs) { return test_and_set(reinterpret_cast(lhs), shift(rhs)); } - friend constexpr bool test_and_reset(type& lhs, type rhs) + friend bool test_and_reset(type& lhs, type rhs) { return test_and_reset(reinterpret_cast(lhs), static_cast(rhs)); } - friend constexpr bool test_and_reset(type& lhs, T rhs) + friend bool test_and_reset(type& lhs, T rhs) { return test_and_reset(reinterpret_cast(lhs), shift(rhs)); } - friend constexpr bool test_and_complement(type& lhs, type rhs) + friend bool test_and_complement(type& lhs, type rhs) { return test_and_complement(reinterpret_cast(lhs), static_cast(rhs)); } - friend constexpr bool test_and_complement(type& lhs, T rhs) + friend bool test_and_complement(type& lhs, T rhs) { return test_and_complement(reinterpret_cast(lhs), shift(rhs)); } @@ -461,6 +461,8 @@ struct atomic_test_and_set::bts(reinterpret_cast(left), static_cast(static_cast(value))); } + static constexpr auto fetch_op = &_op; + static constexpr auto op_fetch = &_op; static constexpr auto atomic_op = &_op; }; @@ -474,6 +476,8 @@ struct atomic_test_and_reset::btr(reinterpret_cast(left), static_cast(static_cast(value))); } + static constexpr auto fetch_op = &_op; + static constexpr auto op_fetch = &_op; static constexpr auto atomic_op = &_op; }; @@ -487,6 +491,53 @@ struct atomic_test_and_complement::btc(reinterpret_cast(left), static_cast(static_cast(value))); } + static constexpr auto fetch_op = &_op; + static constexpr auto op_fetch = &_op; + static constexpr auto atomic_op = &_op; +}; + +template +struct atomic_test_and_set> +{ + using under = std::underlying_type_t; + + static inline bool _op(T& left, T value) + { + return atomic_storage::test_and_set(reinterpret_cast(left), static_cast(value)); + } + + static constexpr auto fetch_op = &_op; + static constexpr auto op_fetch = &_op; + static constexpr auto atomic_op = &_op; +}; + +template +struct atomic_test_and_reset> +{ + using under = std::underlying_type_t; + + static inline bool _op(T& left, T value) + { + return atomic_storage::test_and_reset(reinterpret_cast(left), static_cast(value)); + } + + static constexpr auto fetch_op = &_op; + static constexpr auto op_fetch = &_op; + static constexpr auto atomic_op = &_op; +}; + +template +struct atomic_test_and_complement> +{ + using under = std::underlying_type_t; + + static inline bool _op(T& left, T value) + { + return atomic_storage::test_and_complement(reinterpret_cast(left), static_cast(value)); + } + + static constexpr auto fetch_op = &_op; + static constexpr auto op_fetch = &_op; static constexpr auto atomic_op = &_op; }; @@ -634,3 +685,48 @@ struct atomic_xor +struct atomic_test_and_set::value>>> +{ + using under = std::underlying_type_t; + + static inline bool _op(T& left, T value) + { + return atomic_storage::test_and_set(reinterpret_cast(left), static_cast(value)); + } + + static constexpr auto fetch_op = &_op; + static constexpr auto op_fetch = &_op; + static constexpr auto atomic_op = &_op; +}; + +template +struct atomic_test_and_reset::value>>> +{ + using under = std::underlying_type_t; + + static inline bool _op(T& left, T value) + { + return atomic_storage::test_and_reset(reinterpret_cast(left), static_cast(value)); + } + + static constexpr auto fetch_op = &_op; + static constexpr auto op_fetch = &_op; + static constexpr auto atomic_op = &_op; +}; + +template +struct atomic_test_and_complement::value>>> +{ + using under = std::underlying_type_t; + + static inline bool _op(T& left, T value) + { + return atomic_storage::test_and_complement(reinterpret_cast(left), static_cast(value)); + } + + static constexpr auto fetch_op = &_op; + static constexpr auto op_fetch = &_op; + static constexpr auto atomic_op = &_op; +};