mirror of
https://github.com/RPCS3/rpcs3.git
synced 2024-11-22 02:32:36 +01:00
Implement utils::tx_start (for TSX)
Implement utils::tx_abort helper.
This commit is contained in:
parent
95c1443e30
commit
b57a9c31f0
@ -4,6 +4,80 @@
|
||||
|
||||
namespace utils
|
||||
{
|
||||
// Transaction helper (Max = max attempts) (result = pair of success and op result, which is only meaningful on success)
|
||||
template <uint Max = 10, typename F, typename R = std::invoke_result_t<F>>
|
||||
inline auto tx_start(F op)
|
||||
{
|
||||
uint status = -1;
|
||||
|
||||
for (uint i = 0; i < Max; i++)
|
||||
{
|
||||
#ifndef _MSC_VER
|
||||
__asm__ goto ("xbegin %l[retry];" ::: "memory" : retry);
|
||||
#else
|
||||
status = _xbegin();
|
||||
|
||||
if (status != _XBEGIN_STARTED) [[unlikely]]
|
||||
{
|
||||
goto retry;
|
||||
}
|
||||
#endif
|
||||
|
||||
if constexpr (std::is_void_v<R>)
|
||||
{
|
||||
std::invoke(op);
|
||||
#ifndef _MSC_VER
|
||||
__asm__ volatile ("xend;" ::: "memory");
|
||||
#else
|
||||
_xend();
|
||||
#endif
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
auto result = std::invoke(op);
|
||||
#ifndef _MSC_VER
|
||||
__asm__ volatile ("xend;" ::: "memory");
|
||||
#else
|
||||
_xend();
|
||||
#endif
|
||||
return std::make_pair(true, std::move(result));
|
||||
}
|
||||
|
||||
retry:
|
||||
#ifndef _MSC_VER
|
||||
__asm__ volatile ("movl %%eax, %0;" : "=r" (status) :: "memory");
|
||||
#endif
|
||||
if (!(status & _XABORT_RETRY)) [[unlikely]]
|
||||
{
|
||||
// In order to abort transaction, tx_abort() can be used, so there is no need for "special" return value
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if constexpr (std::is_void_v<R>)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
return std::make_pair(false, R());
|
||||
}
|
||||
};
|
||||
|
||||
// Special function to abort transaction
|
||||
[[noreturn]] FORCE_INLINE void tx_abort()
|
||||
{
|
||||
#ifndef _MSC_VER
|
||||
__asm__ volatile ("xabort $0;" ::: "memory");
|
||||
__builtin_unreachable();
|
||||
#else
|
||||
_xabort(0);
|
||||
__assume(0);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
// Rotate helpers
|
||||
#if defined(__GNUG__)
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user