Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/delphi/9.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Assembly 英特尔64和IA-32 |原子操作,包括获取/发布语义_Assembly_Locking_X86_Intel_Memory Fences - Fatal编程技术网

Assembly 英特尔64和IA-32 |原子操作,包括获取/发布语义

Assembly 英特尔64和IA-32 |原子操作,包括获取/发布语义,assembly,locking,x86,intel,memory-fences,Assembly,Locking,X86,Intel,Memory Fences,根据《英特尔64和IA-32体系结构软件开发人员手册》,锁定信号前缀“确保处理器在断言信号时独占使用任何共享内存”。可以是总线或缓存锁形式的 但是——这就是我问这个问题的原因——我不清楚这个前缀是否也提供了记忆障碍 我正在多处理器环境中使用NASM进行开发,需要使用可选的获取和/或释放语义实现原子操作 那么,我是否需要使用MFENCE、SFENCE和LFENCE指令,或者这是多余的?否,不需要使用指令MFENCE、SFENCE和LFENCE来关联锁前缀 MFENCE、SFENCE和LFENCE指

根据《英特尔64和IA-32体系结构软件开发人员手册》,锁定信号前缀“确保处理器在断言信号时独占使用任何共享内存”。可以是总线或缓存锁形式的

但是——这就是我问这个问题的原因——我不清楚这个前缀是否也提供了记忆障碍

我正在多处理器环境中使用NASM进行开发,需要使用可选的获取和/或释放语义实现原子操作


那么,我是否需要使用MFENCE、SFENCE和LFENCE指令,或者这是多余的?

否,不需要使用指令
MFENCE、SFENCE和LFENCE
来关联
前缀

MFENCE、SFENCE和LFENCE指令保证所有CPU内核中内存的可见性。在实例中,
MOV
指令不能与
LOCK
前缀一起使用,因此为了确保所有CPU内核都能看到内存移动的结果,我们必须确保CPU缓存被刷新到RAM中,并且我们使用围栏指令到达

编辑:有关“英特尔手册”中锁定的原子操作的详细信息:

锁定的原子操作

32位 IA-32处理器支持锁定原子 系统中位置的操作 记忆。这些操作通常是 用于管理共享数据结构 (例如信号量、段) 描述符、系统段或页面 表)其中有两个或多个 处理器可能会同时尝试 修改相同的字段或标志。这个 处理器使用三个相互依赖的 执行锁定操作的机制 原子操作:

•有保障的原子能运作

•总线锁定,使用锁定信号和锁定指令前缀

•缓存一致性协议,确保可以在缓存数据结构上执行原子操作(缓存锁);这种机制存在于奔腾4、英特尔至强和P6系列处理器中

这些机制在许多方面是相互依存的 有以下几种方法。某些基本的 内存事务(如读取) 或在系统内存中写入一个字节) 始终保证能够处理这些问题 原子的。也就是说,一旦启动 处理器保证 手术将在术前完成 另一个处理器或总线代理正在运行 允许访问内存位置。 处理器还支持总线 用于执行选定内存的锁定 操作(例如 在中执行读修改写操作 共享内存区域),通常 需要原子化处理,但是 不会自动以这种方式处理。 因为经常使用内存 位置通常缓存在 处理器的L1或L2缓存,原子 通常可以执行操作 在处理器的缓存中,没有 断言总线锁。这是 处理器的缓存一致性协议 确保其他处理器 缓存相同的内存位置是必要的 在原子状态下正确管理 对缓存的对象执行操作 内存位置


编号摘自IA32手册(第3A卷,第8.2章:内存排序):

无法使用I/O指令对读取或写入进行重新排序,已锁定 指令,或序列化指令


因此,锁定指令不需要围栏指令。

编译intel_lock1.c(可从上面的URL获得)时仍然会出现问题 在带有GCC 5或7的linux上,不带参数“-D_with_CLFLUSH_”或 “-D_与_HLE_u”(这样既不使用CLFLUSH*也不使用HLE XACQUIRE)—— 互斥锁汇编器现在看起来像:

# 74 "intel_lock1.c" 1
    LFENCE
    lock subl   $1, lck(%rip)
    rep nop
    SFENCE
所以,我试着用MFENCE替换{L,S}围栏


我仍然不太明白为什么两个线程会得到相同的-1*lck值。

是的,我知道。但是我想使用(例如)一个互锁的增量来表示我正在获取一个资源。因此,这意味着我需要在增量之前使用“lfence”。为什么?因为我必须确保在发信号之前,所有之前的加载操作都已经完成。不,没有必要这样做,它应该是原子化的。检查我对锁定的原子操作的编辑。但是原子操作与前置或后续内存读写无关?!查看此博客:当然可以。缓存一致性机制只会自动防止已缓存同一内存区域的两个或多个处理器同时修改该区域中的数据。所以你不需要勇气。查看“英特尔参考资料”第8章:多处理器管理中的更多信息以更清楚地了解:如果使用锁定前缀,则不需要在增量之前使用lfence!我就是这么想的。但不管出于什么原因,今天我无法编写这个高度简单的互斥实现,只是作为一个测试,因为没有锁前缀或/{l,s}围栏的组合似乎可以阻止两个线程获得相同的-1值。完整源代码位于:[intel_lock1.c]:我想确实需要mfence,以及锁定的subl/xaddl。这应该是对您最近的问题的编辑吗?这肯定不是任何问题的答案,也肯定不是这个问题的答案。请参阅更新的[intel_lock1.c]:至少对我来说,这是一个答案。更新后的版本可以使用-D_NO_FENCE_编译,以完全不使用任何FENCE,或者使用-D_mfence_________________________________。我想问的具体问题是“为什么两个线程在都执行lock subl、$addr、1并且*addr的内容为0时得到相同的值?”“英特尔原子/锁定原语”是否有任何组合可以实现此递减/递增,从而使两个线程必须始终看到彼此的结果并获得不同的值?哎呀,对不起,我的浏览器更改了我的选项卡,我发布了这些对错误问题的回答-我只想更新: