中止的 xbegin 事务是否会恢复 xbegin 开始时存在的堆栈上下文?

Does an aborted xbegin transaction restore the stack context that existed at the xbegin start?

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

VC++ 2010 版本需要这种汇编程序方法,它不支持或不提供 _xbegin( ) 和 _xend( ) 内在函数,并且 x64 版本不能使用 _asm { } 内联。

相关:另请参阅 David Kanter's TSX writeup for some theory on how it works under the hood and how software can benefit from it, and this blog post 了解 HSW 上的一些实验性性能数据(在发现 TSX 错误和微代码更新在该硬件上禁用 TSX 之前。)


英特尔 insn 参考手册 entry for xbegin is pretty clear. (See the 标记 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.

因此该指令的工作方式类似于条件 b运行ch,其中 b运行ch 条件为 "did an abort happen before 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 如果它是最有效的方法。)

你是什么意思"interrupts effects"?在当前的实现中,任何更改特权级别(如系统调用或中断)都会导致 t运行saction 中止。因此,环级更改永远不需要回滚。 当 CPU 遇到无法回滚的任何事情时,CPU 将中止 t运行saction。这意味着可能的错误包括在 t运行saction 中放置一些总是导致中止的内容,而不是你做了一些无法回滚的事情。


您可能希望编译器在不调用函数的情况下发出三字节 XEND 指令,因此将 return 地址压入堆栈不是 t 的一部分运行行动。例如

// 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, since the doc mentions rax, and it looks like IACA's header file 使用 __asm _emit.

我想,将 XEND 也放在它自己的包装函数中会更安全。在可以升级到具有内在函数的编译器之前,您只需要一个权宜之计,因此只要 retcall 中的额外 reads/writes 不存在,它就不必是完美的导致中止次数过多。