并发非原子写入从不读取内存安全吗?

问题描述 投票:0回答:1

注意:不是这个问题的重复。

假设某个内存区域永远不会被读取,那么并发非原子写入什么时候对它来说是安全的?这与语言无关,主要与 CPU 架构限制有关。

这个想法是为了在多线程应用程序中删除不可查找的对象(例如 TCP 套接字)中的字节,但在 BPF 删除过滤器不可行的情况下。

  • 这样的写入在字节分辨率下可以吗?我目前确实在野外有非关键任务代码(通过对其进行并发
    read
    系统调用以完全接收所有接收到的数据)并且还没有遇到问题到目前为止
  • 写入是否必须仅限于自己的缓存行?一个核心可以写入,另一个核心可以读取,它们可能会遇到共识问题。但是,我认为这只会影响(从不读取)内存区域? 写入是否必须仅限于其自己的(通常为 4 KiB)页面?如果假设不同步的指令意味着根本不需要 TLB,那么在某些情况下我可能会看到 TLB 问题,尽管这确实“非常”不太可能(大多数相同的同步只是为了正确处理具有不同地址的并发请求)。
  • 一般来说根本不安全吗?
  • 主流CPU ISA都没有做硬件竞态检测,所以在asm中是安全的。
原子存储(不是像 CAS 或
language-agnostic atomic
1个回答
1
投票
那样的

RMWs
)使用与普通存储相同的 asm 指令。

缓存在所有 CPU ISA
(不一定是 GPU)上是一致的,至少在我们运行线程的核心之间是一致的,这就是为什么 C / C++

volatile

atomic<T>

memory_order_relaxed
的工作原理类似,在普通编译器上将
volatile
访问视为需要在 asm 中加载或存储。 (
何时在多线程中使用 易失性?
 - 永远不会,除了在 Linux 内核代码中,它使用内联 asm 滚动自己的原子进行排序,以及 volatile 的 GNU C 语义,其中包括使用单个指令进行加载或存储如果可能的话。)
因此,对于 CPU 内核要将其私有存储缓冲区中的存储提交到一致的 L1d 缓存中,它需要在提交之前获得其存储到的缓存行的 MESI 独占所有权。用 C++ 术语来说,这就是为什么所有 
atomic
变量都存在“修改顺序”的原因。在 asm 中,每个缓存行都存在这样的顺序。

如果您的 ARM 板带有微控制器 + DSP 和非一致性共享内存,您仍然可以将两个内核存储到同一地址,而不会出现任何问题,除非您读取该共享内存区域,否则可能会获得令人惊讶的值。例如带有缓存的核心可能会看到它最后存储的值,即使另一个核心已经完成了稍后的存储。

在高级语言

中,通常不安全地假设使用非原子赋值的代码编译为与

atomic


relaxed

等效的 asm,除非您在处理的主流编译器上使用类似 C volatile 的东西正如您所期望的那样。

在像
clang -fsanitize=thread
这样的C实现上,当两个线程同时写入相同的非原子
stderr
时,它可能会中止或打印额外的内容到

int *

我不知道你在说什么
write
系统调用;这似乎与 asm 存储关系很远,并且内核需要实现 POSIX 语义以实现
write
原子性(文件位置和 I/O 的原子更新,以防多个进程或线程共享相同的打开文件描述符.)请参阅

https://man7.org/linux/man-pages/man2/write.2.html#BUGS

了解一些相关内容,例如Linux 3.14 及更高版本正确实现了这一点。

TLB 在这里不相关。
    
© www.soinside.com 2019 - 2024. All rights reserved.