我感兴趣的是在静态汇编程序库中将事务xbegin和xend封装在XBEGIN()和XEND()函数中.但是我不清楚如何(或者如果)堆栈恢复到原始xbegin调用状态,给定xabort源自其他堆栈级别(更高或更低).换句话说,动态堆栈上下文(包括中断效果)是否作为事务的另一部分进行管理和回滚?
对于没有支持或可用的_xbegin()和_xend()内在函数的VC 2010构建,需要此汇编程序方法,并且x64构建不能使用_asm {}内联.
解决方法:
相关:有关它如何工作的一些理论以及软件如何从中受益,请参阅David Kanter’s TSX writeup;有关HSW的一些实验性能数据,请参见this blog post(在发现TSX错误并且微码更新在该硬件上禁用TSX之前).
英特尔insn参考手册entry for xbegin
非常清楚. (有关英特尔官方PDF和其他内容的链接,请参阅x86标签维基.)
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遇到无法回滚的任何事务时,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,因为doc提到了rax,看起来IACA’s header file使用了__asm _emit.
我想,把XEND放在自己的包装函数中会更安全.你只需要一个止损,直到你可以升级到带有内在函数的编译器,所以只要来自ret和call的额外读/写不会导致太多中止,它就不一定非常完美.