微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

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
> movq

原文地址:https://www.jb51.cc/c/114781.html

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐