c – 用GCC进行原子64位写入
我已经陷入了一个混乱的混乱的多线程编程,并希望有人可以来和我的一些理解.
在做了相当多的阅读之后,我已经明白,我应该能够在64位系统1上设置64位int原子值的值. 我发现很多阅读困难,所以以为我会尝试做一个测试来验证这一点.所以我用一个线程写了一个简单的程序,它将一个变量设置为两个值之一: bool switcher = false; while(true) { if (switcher) foo = a; else foo = b; switcher = !switcher; } 另一个线程会检查foo的值: while (true) { __uint64_t blah = foo; if ((blah != a) && (blah != b)) { cout << "Not atomic! " << blah << endl; } } 我设一个= 1844674407370955161;和b = 1144644202170355111 ;.我运行这个程序,没有输出警告我,blah不是a或b. 好的,看起来可能是一个原子写…但是,我改变了第一个线程直接设置a和b,像这样: bool switcher = false; while(true) { if (switcher) foo = 1844674407370955161; else foo = 1144644202170355111; switcher = !switcher; } 我重新跑了,突然间: Not atomic! 1144644203261303193 Not atomic! 1844674406280007079 Not atomic! 1144644203261303193 Not atomic! 1844674406280007079 有什么变化无论哪种方式,我分配大量的foo – 编译器是否处理不同的数字,或者我误解了一切? 谢谢! 1:Intel CPU documentation,section 8.1,Guaranteed Atomic Operations 2:GCC Development list discussing that GCC doesn’t guarantee it in the documentation,but the kernel and other programs rely on it 解决方法
反汇编循环,我得到以下代码与gcc:
.globl _switcher _switcher: LFB2: pushq %rbp LCFI0: movq %rsp,%rbp LCFI1: movl $0,-4(%rbp) L2: cmpl $0,-4(%rbp) je L3 movq _foo@GOTPCREL(%rip),%rax movl $-1717986919,(%rax) movl $429496729,4(%rax) jmp L5 L3: movq _foo@GOTPCREL(%rip),%rax movl $1486032295,(%rax) movl $266508246,4(%rax) L5: cmpl $0,-4(%rbp) sete %al movzbl %al,%eax movl %eax,-4(%rbp) jmp L2 LFE2: 所以看起来,gcc会使用32位的具有32位立即数值的movl指令.有一个指令movq可以将64位寄存器移动到存储器(或存储器到64位寄存器),但是似乎无法设置将立即值移动到存储器地址,因此编译器被强制要么使用临时寄存器,然后将值移动到内存,或者用于movl.您可以尝试强制使用一个临时变量使用寄存器,但是这可能无法正常工作. 参考文献: > mov (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |