c++ - 中止的 xbegin 事务是否会恢复 xbegin 启动时存在的堆栈上下文?

标签 c++ x86 intrinsics intel-tsx

我有兴趣将事务性 xbegin 和 xend 封装在静态汇编器库中的 XBEGIN( ) 和 XEND( ) 函数中。但是,如果 xabort 源自其他堆栈级别(更高或更低),我不清楚堆栈如何(或是否)恢复到原始 xbegin 调用状态。换句话说,动态堆栈上下文(包括中断效果)是否作为事务的另一部分进行管理和回滚?

对于不支持或不支持 _xbegin( ) 和 _xend( ) 内在函数的 VC++ 2010 构建,需要此汇编器方法,并且 x64 构建无法使用 _asm { } 内联。

最佳答案

相关:另请参阅David Kanter's TSX writeup有关它如何在幕后工作以及软件如何从中受益的一些理论,以及 this blog post有关 HSW 上的一些实验性能数据(在发现 TSX 错误并且微代码更新禁用该硬件上的 TSX 之前。)


英特尔 insn 引用手册 entry for xbegin很清楚。 (请参阅 标签 wiki,获取英特尔官方 PDF 和其他内容的链接。)

On an RTM abort, the logical processor discards all architectural register and memory updates performed during the RTM execution and restores architectural state to that corresponding to the outermost XBEGIN instruction. The fallback address following an abort is computed from the outermost XBEGIN instruction.

因此该指令的工作方式类似于条件分支,其中分支条件是“在 XEND 之前发生中止吗?”例如:

; NASM syntax, I assume MASM is similar
ALIGN 16
retry:
    ; eax holds abort info, all other architectural state + memory is unchanged
    inc     [retry_count]      ; or whatever other debug instrumentation you want to add

global xbegin_wrapper_with_retry
xbegin_wrapper_with_retry:
    xbegin  retry
    ret

如果发生中止,就好像 xbegin 之后运行的所有代码根本没有运行,只是使用 跳转到回退地址eax 已修改。

当然,除了无限重试中止之外,您可能还想做一些其他事情。这并不是一个真实的例子。 ( This article 确实有一个您可能想要使用的逻辑类型的真实示例,使用内部函数。看起来他们只是测试 eax 而不是使用 xbegin 作为if 中的跳转,除非编译器优化该检查。IDK 如果这是最有效的方法。)

“中断效果”是什么意思?在当前的实现中,任何更改特权级别的行为(例如系统调用或中断)都会导致事务中止。因此环级更改永远不需要回滚。 当CPU遇到无法回滚的事情时,它只会中止事务。这意味着可能的错误包括在事务中放置一些总是导致中止的内容,但并不是您执行了无法回滚的操作。


您可能希望尝试让编译器在不调用函数的情况下发出三字节 XEND 指令,因此将返回地址压入堆栈不是事务的一部分。例如

// no idea if this is safe, or if it might get reordered by the optimizer
#define xend_MSVC  __asm _emit 0x0F  __asm _emit   0x01 __asm _emit 0xD5

I think this does still work in 64bit mode ,因为文档提到了 rax,它看起来像 IACA's header file使用__asm _emit

我想,将 XEND 放入其自己的包装函数中也会更安全。您只需要一个权宜之计,直到可以升级到具有内在函数的编译器,因此只要从 retcall< 进行额外的读/写操作,它就不必是完美的 不要导致太多中止。

关于c++ - 中止的 xbegin 事务是否会恢复 xbegin 启动时存在的堆栈上下文?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36898325/

相关文章:

c++ - set<string> 像数字一样排序

c++ - 采访: Maximum path sum in a 2-D matrix using recursion.路径恢复

.net-core - SSE 和 AVX 的 MoveMask 的目的是什么

linux - 强制 GNU 链接器生成 32 位 ELF 可执行文件

c - 加速牛顿法求 n 次根的速度

c++ - 如何为 QTreeWidgetItem 的每个*类型*创建不同的弹出(上下文)菜单

c++ - 在 C++ 中使用组合时如何确定类属性应该是指针还是值?

function - as8088中的变量初始化

c++ - Constexpr 和 SSE 内在函数

c++ - 在哪里可以找到将 VC++ 内联汇编程序转换为内在函数的脚本?