6

根据 Intel 64 和 IA-32 架构软件开发人员手册,LOCK 信号前缀“确保处理器在信号被断言时独占使用任何共享内存”。这可以是总线或缓存锁的形式。

但是 - 这就是我问这个问题的原因 - 我不清楚这个前缀是否也提供了任何内存屏障。

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

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

4

3 回答 3

7

不,不需要使用MFENCE, SFENCE and LFENCELOCK前缀相关的指令。

MFENCE, SFENCE and LFENCE指令保证所有 CPU 内核中内存的可见性。例如,该MOV指令不能与LOCK前缀一起使用,因此为了确保所有 CPU 内核都能看到内存移动的结果,我们必须确保 CPU 缓存已刷新到 RAM 并且我们使用栅栏指令进行访问。

编辑:有关英特尔手册中锁定原子操作的更多信息:

锁定原子操作

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

• 保证原子操作

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

• 缓存一致性协议确保原子操作可以在缓存的数据结构上执行(缓存锁);这种机制存在于 Pentium 4、Intel Xeon 和 P6 系列处理器中

这些机制以下列方式相互依赖。某些基本的内存事务(例如在系统内存中读取或写入字节)始终保证以原子方式处理。也就是说,一旦启动,处理器保证操作将在另一个处理器或总线代理被允许访问内存位置之前完成。处理器还支持总线锁定以执行选定的内存操作(例如内存共享区域中的读-修改-写操作),这些操作通常需要以原子方式处理,但不会以这种方式自动处理。由于经常使用的内存位置通常缓存在处理器的 L1 或 L2 缓存中,因此原子操作通常可以在处理器的缓存内执行,而无需声明总线锁。

于 2011-01-27T10:08:35.983 回答
5

否。来自 IA32 手册(第 3A 卷,第 8.2 章:内存排序):

无法使用 I/O 指令、锁定指令或序列化指令重新排序读取或写入。

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

于 2013-05-31T04:25:00.900 回答
-2

当 intel_lock1.c(可在上面的 URL 获得)在 linux 上使用 GCC 5 或 7 编译而没有 args '-D_WITH_CLFLUSH_' 或 '-D_WITH_HLE_' 时仍然会出现问题(因此既不使用 CLFLUSH* 也不使用 HLE XACQUIRE) - mutex_lock 汇编器现在看起来像:

# 74 "intel_lock1.c" 1
    LFENCE
    lock subl   $1, lck(%rip)
    rep nop
    SFENCE

所以,我正在尝试用 MFENCE 替换 {L,S}FENCE 。

我仍然不太明白两个线程如何以相同的 -1 *lck 值结束。

于 2018-06-02T15:33:11.883 回答