mirror of
https://github.com/RPCS3/rpcs3.git
synced 2025-02-11 06:40:39 +00: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
|
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
|
// Rotate helpers
|
||||||
#if defined(__GNUG__)
|
#if defined(__GNUG__)
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user