相关疑难解决方法(0)

为什么(或不是?)SFENCE + LFENCE相当于MFENCE?

正如我们从之前的回答中所知道的,它是否在处理器x86/x86_64中指示LFENCE?我们不能使用SFENCE而不是MFENCE顺序一致性.

这里的答案表明MFENCE= SFENCE+ LFENCE,即LFENCE没有我们不能提供顺序一致性的东西.

LFENCE 无法重新排序:

SFENCE
LFENCE
MOV reg, [addr]
Run Code Online (Sandbox Code Playgroud)

- 到 - >

MOV reg, [addr]
SFENCE
LFENCE
Run Code Online (Sandbox Code Playgroud)

例如重新排序MOV [addr], reg LFENCE- > LFENCE MOV [addr], reg由机制提供- 存储缓冲区,它重新排序存储 - 负载以提高性能,并且因为LFENCE它不会阻止它.并SFENCE 禁用此机制.

什么机制禁用LFENCE无法重新排序(x86没有机制 - Invalidate-Queue)?

并且只是在理论上或者在现实中重新排序SFENCE MOV reg, [addr]- > MOV reg, [addr] SFENCE可能吗?如果可能,实际上,什么机制,它是如何工作的?

x86 assembly x86-64 memory-fences memory-barriers

5
推荐指数
3
解决办法
1091
查看次数

内存防护会阻止多核 CPU 中的线程吗?

我正在阅读英特尔指令集指南 64-ia-32指南 以了解内存栅栏。我的问题是,以 SFENCE 为例,为了确保所有存储操作都是全局可见的,多核 CPU 是否会停放所有线程甚至在其他内核上运行,直到实现缓存一致性?

x86 multithreading multicore cpu-architecture memory-barriers

5
推荐指数
1
解决办法
845
查看次数

如何通过微体系结构实现障碍/栅栏以及获取,释放语义?

因此还有很多问题,例如https://mirrors.edge.kernel.org/pub/linux/kernel/people/paulmck/perfbook/perfbook.2018.12.08a.pdf和Preshing的文章如https:/ /preshing.com/20120710/memory-barriers-are-like-source-control-operations/及其整个系列文章就不同的障碍类型提供的排序和可见性保证方面抽象地讨论了内存排序。我的问题是,如何在x86和ARM微体系结构上实现这些障碍和内存排序语义?

对于商店-商店壁垒,好像在x86上,商店缓冲区保持商店的程序顺序并将它们提交到L1D(因此使它们以相同的顺序在全局可见)。如果存储缓冲区未排序,即未按程序顺序维护它们,那么如何实现存储障碍?它只是以这样的方式“标记”存储缓冲区,即在屏障提交之前将存储提交到缓存一致性域,然后在屏障之后提交?还是存储屏障实际上刷新了存储缓冲区并暂停了所有指令,直到刷新完成?可以同时实现吗?

对于负载障碍,如何防止负载重新排序?很难相信x86将按顺序执行所有加载!我假设加载可以乱序执行,但是可以按顺序提交/退出。如果是这样,如果一个cpu在2个不同的位置执行2次加载,那么一个加载如何确保它从T100中得到一个值,而下一个加载在T100上或之后得到它?如果第一个负载未命中高速缓存并正在等待数据,而第二个负载命中并获取其值,该怎么办。当负载1获得其值时,如何确保它获得的值不是来自该负载2的值的较新商店?如果负载可以无序执行,如何检测到违反内存排序的情况?

类似地,如何实现负载存储屏障(在x86的所有负载中都是隐含的)以及如何实现存储负载屏障(例如mfence)?即dmb ld / st和dmb指令在ARM上是如何微体系结构的?每个负载和每个存储区以及mfence指令在x86上如何进行微体系结构,以确保内存排序?

x86 x86-64 cpu-architecture memory-barriers micro-architecture

5
推荐指数
1
解决办法
72
查看次数

Linux 内核 flush_write_buffers() 如何在 x86 上工作?

以下代码来自include/asm-i386/io.h,并且是从调用的dma_map_single()。我的理解是flush_write_buffers()应该在为 DMA 映射内存之前刷新 CPU 内存缓存。但是这个汇编代码是如何刷新 CPU 缓存的呢?

static inline void flush_write_buffers(void)
{
    __asm__ __volatile__ ("lock; addl $0,0(%%esp)": : :"memory");
}
Run Code Online (Sandbox Code Playgroud)

c x86 assembly linux-kernel dma

5
推荐指数
2
解决办法
276
查看次数

为什么这个“std::atomic_thread_fence”起作用

首先我想谈一下我对此的一些理解,如有错误请指正。

  1. aMFENCE在x86中可以保证全屏障
  2. 顺序一致性可防止 STORE-STORE、STORE-LOAD、LOAD-STORE 和 LOAD-LOAD 重新排序

    这是根据维基百科的说法。

  3. std::memory_order_seq_cst不保证防止 STORE-LOAD 重新排序。

    这是根据Alex 的回答,“负载可能会通过早期存储重新排序到不同位置”(对于 x86),并且 mfence 不会总是被添加。

    a是否std::memory_order_seq_cst表示顺序一致性?根据第2/3点,我认为这似乎不正确。std::memory_order_seq_cst仅当以下情况时才表示顺序一致性

    1. 至少一个显式MFENCE添加到任一LOAD或STORE
    2. LOAD(无栅栏)和 LOCK XCHG
    3. LOCK XADD ( 0 ) 和 STORE (无栅栏)

    否则仍有可能重新订购。

    根据@LWimsey的评论,我在这里犯了一个错误,如果 和LOAD都是STORE,memory_order_seq_cst则没有重新排序。Alex 可能指出使用非原子或非 SC 的情况。

  4. std::atomic_thread_fence(memory_order_seq_cst)总是产生一个完整的屏障

    这是根据Alex的回答。所以我总是可以替换asm volatile("mfence" ::: "memory")为std::atomic_thread_fence(memory_order_seq_cst)

    这对我来说很奇怪,因为memory_order_seq_cst原子函数和栅栏函数之间的用法似乎有很大不同。

现在我在MSVC 2015的标准库的头文件中找到这段代码,它实现了std::atomic_thread_fence

inline void _Atomic_thread_fence(memory_order _Order)
    {   /* …
Run Code Online (Sandbox Code Playgroud)

c++ x86 memory-barriers stdatomic

4
推荐指数
1
解决办法
2212
查看次数

从 x86 CPU 生成 64 字节读取 PCIe TLP

将数据写入 PCIe 设备时,可以使用写入组合映射来提示 CPU 应该向设备生成 64 字节的 TLP。

是否可以为读取做类似的事情?以某种方式提示 CPU 读取整个缓存行或更大的缓冲区,而不是一次读取一个字?

x86 pci-e

4
推荐指数
1
解决办法
1397
查看次数

x86 CPU有多少个内存屏障指令?

我已经发现,在x86 CPU有以下内存屏障指令:mfence,lfence,和sfence。

x86 CPU是否仅具有这三个内存屏障指令,或者还有更多指令?

x86 assembly multithreading memory-barriers

2
推荐指数
2
解决办法
728
查看次数

为什么我们需要读和写屏障?

为什么我们需要定义两种具有相同实现的障碍?

例如,io_uringLinux 中的这段代码:

#if defined(__x86_64) || defined(__i386__)
#define read_barrier()  __asm__ __volatile__("":::"memory")
#define write_barrier() __asm__ __volatile__("":::"memory")
#else
Run Code Online (Sandbox Code Playgroud)

c x86 gcc linux-kernel memory-barriers

2
推荐指数
1
解决办法
661
查看次数