From b57a9c31f049a612c73fe321edb1988cf5293d1b Mon Sep 17 00:00:00 2001 From: Nekotekina Date: Mon, 12 Oct 2020 15:09:39 +0300 Subject: [PATCH] Implement utils::tx_start (for TSX) Implement utils::tx_abort helper. --- Utilities/asm.h | 74 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 74 insertions(+) diff --git a/Utilities/asm.h b/Utilities/asm.h index 951dd2fd2a..6f972040fa 100644 --- a/Utilities/asm.h +++ b/Utilities/asm.h @@ -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 > + 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) + { + 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) + { + 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__)