2016-04-27 150 views
0

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

对于没有支持或可用的_xbegin()和_xend()内部函数的VC++ 2010构建,x64构建不能使用_asm {}内联,需要此汇编程序方法。

回答

2

相关:又见David Kanter's TSX writeup了一定的理论它是如何工作的引擎盖下和软件如何从中受益,并this blog post对HSW一些实验性的性能数据(之前被发现的TSX缺陷和微码上更新禁用TSX硬件)。


英特尔insn ref手册entry for xbegin很清楚。 (见链接标签维基英特尔的官方PDF,以及其他的东西。)

上的RTM中止,逻辑处理器放弃RTM执行和 恢复期间执行所有建筑 寄存器和存储器更新体系结构状态到对应于最外层的XBEGIN指令的最初的 。中止后的回退地址是从最外面的XBEGIN指令计算出来的。

所以指令就像一个条件分支,在该分支条件“并中止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确实有一个你可能想要使用的逻辑类型的真实例子,使用intrinsics。看起来他们只是测试eax而不是使用xbegin作为if的跳转,除非编译器优化了这个检查。最有效的方法。)

你是什么意思“中断效应”?在当前的实现中,任何改变特权级别的东西(如系统调用或中断)都会导致事务中止。所以戒指级别的变化永远不需要回滚。 当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,因为文档提到rax,它看起来像IACA's header file使用__asm _emit

我猜,将XEND放在自己的包装函数中会更安全。您只需要一个阻挡间隙,直到可以升级到具有内在函数的编译器,因此只要来自retcall的额外读取/写入不会导致过多的中止,它就不一定非常完美。

相关问题