x64 CPU上的原子16字节读取
Atomic 16 byte read on x64 CPUs
我需要以原子方式读/写16个字节。我只使用cmpxchg16进行编写,它在所有x64处理器上都可用,除了一个不知名的AMD处理器。
现在的问题是,对于对齐的16字节值,只有使用cmpxchg16(它的作用就像一个完整的内存屏障)进行修改,才有可能读取一半是旧数据一半是新数据的16字节位置吗?
只要我使用SSE指令进行读取(因此线程不能在读取过程中中断),我认为读取不可能(即使在多处理器numa系统中)看到不一致的数据。我认为它一定是原子的。
我假设,当cmpxchg16被执行时,它会原子性地修改16个字节,而不是通过写两个8字节的块,让其他线程在这两个块之间进行读取(老实说,如果它不是原子性的,我不知道它怎么能工作。)
我说得对吗?如果我错了,有没有一种方法可以在不使用锁定的情况下进行16字节的原子读取?
注意:这里有几个类似的问题,但它们不涉及只使用cmpxchg16进行写入的情况,所以我觉得这是一个单独的、未回答的问题。
编辑:事实上,我认为我的推理是错误的。SSE加载指令可以作为两个64位读取执行,并且cmpxchg16可以由另一个处理器在两个读取之间执行。
typedef struct
{
unsigned __int128 value;
} __attribute__ ((aligned (16))) atomic_uint128;
unsigned __int128
atomic_read_uint128 (atomic_uint128 *src)
{
unsigned __int128 result;
asm volatile ("xor %%rax, %%rax;"
"xor %%rbx, %%rbx;"
"xor %%rcx, %%rcx;"
"xor %%rdx, %%rdx;"
"lock cmpxchg16b %1" : "=A"(result) : "m"(*src) : "rbx", "rcx");
return result;
}
这就行了。typedef可确保正确对齐。cmpxchg16b需要在16字节的边界上对齐数据。
cmpxchg16b将测试*src
是否包含零,如果是则写入零(nop)。在任何一种情况下,正确的值都将在RAX:RDX中显示。
上面的代码评估为这样简单的东西
push %rbx
xor %rax,%rax
xor %rbx,%rbx
xor %rcx,%rcx
xor %rdx,%rdx
lock cmpxchg16b (%rdi)
pop %rbx
retq
根据参考http://siyobik.info/main/reference/instruction/CMPXCHG8B%2FCMPXCHG16BCCD_ 2在默认情况下不是原子的,但可以通过使用CCD_http://siyobik.info/main/reference/instruction/LOCK
这意味着默认情况下,数据可以在读取和写入阶段进行更改。锁定使读和写都成为原子。
- 从文件中读取多个字节,并将它们存储在C++中进行比较
- 在java中读取c++字节的位字段
- 读取文件中所有可能的十六进制 16 字节序列并打印每个序列
- std::ifstream::read 不会读取所有 512 字节,并设置 EOF 和失败位
- QDataStream 读取和写入的字节数比 QFile::length() 报告要多
- 如何从保存在 Java 中C++的字节数组中读取数字?
- Async_read_until限制读取的字节大小(Boost::asio)
- 如果由不同的线程写入 8 字节,那么现代英特尔 x86 上的 8 字节读取是否保证理智?
- C++ - 将任何文件的字节读取到无符号字符数组中
- InternetReadFile 填充缓冲区,但返回零字节读取
- ReadFromFile C++具有未知字节读取大小
- 从字节 [] 读取字符串
- C 如何将字节读取为整数enderness独立
- x64 CPU上的原子16字节读取
- 具有重叠I/O的FILE_FLAG_NO_BUFFERING-字节读取为零
- std::数组和字节读取
- 如何发现字节读取是日语还是英语
- 内存的字节读取:"signed char *" vs "unsigned char *"
- TCP Recv使用select()返回1字节读取
- c++字节读取问题