原子x86指令与MS的InterlockedCompareExchange文档的对齐要求?

问题描述 投票:37回答:4

Microsoft提供了InterlockedCompareExchange函数,用于执行原子比较和交换操作。还有一个InterlockedCompareExchange intrinsic

在x86上,这些是使用_InterlockedCompareExchange指令实现的。

但是,通读有关这三种方法的文档,他们似乎在对齐要求上并不一致。

Intel的_InterlockedCompareExchange没有对对齐进行任何说明(除了启用了[[if对齐检查并且进行了未对齐的内存引用,生成了异常)]

我也查询了lock cmpxchg前缀,它具体指出:>

LOCK前缀的完整性受内存字段的对齐方式影响。[>]

(我的重点)

所以Intel似乎说对齐是无关紧要的。无论如何,该操作都是原子操作。

reference manual内在文档也没有提到对齐,但是lock

function

指出

此功能的参数必须在32位边界上对齐;否则,该功能在多处理器x86系统和任何非x86系统上的行为将无法预测。

那有什么作用?_InterlockedCompareExchange的对齐要求仅仅是为了确保该功能即使在InterlockedCompareExchange指令不可用的486之前的CPU上也能正常工作吗?基于以上信息,这似乎很可能,但是我想在确定之前先确定一下。 :)

或者ISA是否需要对齐以保证原子性,而我只是在Intel参考手册中找错了位置?

Microsoft提供用于执行原子比较和交换操作的InterlockedCompareExchange函数。还有一个_InterlockedCompareExchange内部函数。在x86上,这些是使用...

InterlockedCompareExchange来自1999年,显然已经过时。
[cmpxchg,特别是PDF you are quoting from讲述了一个不同的故事。

例如,在Core-i7处理器上,您仍然必须确保数据不跨越高速缓存行,否则,不能保证操作是原子的。

关于卷3A,系统编程,对于x86 / x64英特尔明确指出:

8.1.1保证原子操作

Intel486处理器(以及更新的处理器)保证以下各项基本的内存操作将始终以原子方式执行:

读取或写入字节

    读取或写入在16位边界上对齐的单词
  • 读取或写入在32位边界上对齐的双字
  • 奔腾处理器(以及以后的较新处理器)保证以下各项其他内存操作将始终以原子方式执行:
  • 读取或写入在64位边界上对齐的四字

    • 16位访问适合32位数据总线的未缓存内存位置
  • P6系列处理器(以及以后的较新处理器)保证以下各项额外的内存操作将始终以原子方式进行:
  • 对适合缓存的缓存内存进行未对齐的16位,32位和64位访问行

    • 访问跨缓存行和页面边界划分的可缓存内存Intel Core 2 Duo,Intel®Atom™,Intel Core不保证是原子的Duo,Pentium M,Pentium 4,Intel Xeon,P6系列,Pentium和Intel486处理器。Intel Core 2 Duo,Intel Atom,Intel Core Duo,Pentium M,Pentium 4,Intel Xeon,和P6系列处理器提供总线控制信号,允许外部存储器使分裂访问成为原子的子系统;但是,未对齐的数据访问将严重影响处理器的性能,应避免]
  • x86会
    not要求对齐才能使up-to-date Intel documentation指令是原子的。但是,为了获得良好的性能,必须进行对齐。

    这并不奇怪,向后兼容意味着用14年前的手册编写的软件仍可以在当今的处理器上运行。现代CPU甚至有一个专门用于分割Volume-3A检测的性能计数器,因为它是如此昂贵。 (核心不能在操作期间仅保持对单个高速缓存行的独占访问;它的确必须执行类似传统总线锁定的操作)。

    为什么Microsoft确切说明对齐要求不清楚。支持RISC架构当然是必要的,但是多处理器x86上不可预测的行为的特定声明甚至可能无效。 (除非它们表示不可预测的性能,而不是正确性问题。)

    您猜测仅适用于没有lock cmpxchg的486之前的系统可能是正确的;那里需要一个不同的机制,这可能需要围绕纯负载或纯存储进行某种锁定。 (还请注意,486 locklock cmpxchg有所不同,cmpxchgcurrently-undocumented opcode)与586 Pentium是新的; Windows可能仅在P5 Pentium上使用了0f a7,但我不知道。)这也许可以解释某些x86上的怪异现象,但并不意味着现代x86上的怪异现象。

    [Intel®64和IA-32体系结构软件开发人员手册第3卷(3A):系统编程指南2013年1月

    8.1.2.2软件控制的总线锁定

    要显式强制使用LOCK语义,在用于修改内存位置时,软件可以将LOCK前缀与以下说明配合使用。 [...]

    •交换指令(XADD,CMPXCHG和CMPXCHG8B)。•XCHG指令自动假定为LOCK前缀。•[...]

    [...]总线锁的完整性不受总线对准的影响内存字段。在多个总线周期内都遵循LOCK语义根据需要更新整个操作数。但是,建议使锁定的访问在其自然边界上对齐以更好地进行系统性能:

    •8位访问的任何边界(锁定或其他)。•16位边界,用于锁定字访问。•用于锁定双字访问的32位边界。•用于锁定四字访问的64位边界。

    有趣的事实:modern cmpxchg (0f b1),因此可用于单核系统上的多线程。


    即使未对齐,它仍然是原子的。中断(完全在中断之前或之后),并且只有其他设备(例如DMA)读取的内存才会出现中断。但是,这样的访问也可能会看到加载和存储之间的分离,因此,即使旧的Windows确实将其用于单核系统上更有效的InterlockedCompareExchange,它仍然不需要为正确性而对齐,而仅需要性能。如果可以将其用于硬件访问,则Windows可能不会这样做。

    如果库函数需要执行与cmpxchg分开的纯加载,这可能是有道理的,但不需要这样做。 (如果未内联,则32位版本必须从堆栈中加载其args,但这是私有的,不能访问共享变量。)

    请参阅0f b1:自然对齐对于性能很重要,并且在x64体系结构上是必需的(因此,它不仅是PRE-x86系统,而且是POST-x86系统-x64仍然是一个小众市场,但毕竟它越来越受欢迎;-);这可能就是Microsoft按要求对其进行记录的原因(很难找到有关MS是否已决定通过启用对齐检查来强制对齐问题的文档-可能因Windows版本而异;通过在文档中声称需要对齐,MS保留了在某些版本的Windows中强制使用它的自由,即使他们没有在其他版本上强制使用它。]

    Microsoft的互锁API也适用于ia64(尽管它仍然存在)。 ia64上没有锁定前缀,只有cmpxchg.acq和cmpxchg.rel指令(或fetchadd和其他类似的野兽),如果我没记错的话,这些都需要对齐。
  • winapi x86 atomic memory-alignment interlocked
    4个回答
    9
    投票
    [cmpxchg,特别是PDF you are quoting from讲述了一个不同的故事。

    11
    投票
    not要求对齐才能使up-to-date Intel documentation指令是原子的。但是,为了获得良好的性能,必须进行对齐。

    这并不奇怪,向后兼容意味着用14年前的手册编写的软件仍可以在当今的处理器上运行。现代CPU甚至有一个专门用于分割Volume-3A检测的性能计数器,因为它是如此昂贵。 (核心不能在操作期间仅保持对单个高速缓存行的独占访问;它的确必须执行类似传统总线锁定的操作)。


    4
    投票

    3
    投票
    © www.soinside.com 2019 - 2024. All rights reserved.