来自atomic.h的操作似乎是非原子的

时间:2022-01-31 21:01:43

The following code produces random values for both n and v. It's not surprising that n is random without being properly protected. But it is supposed that v should finally be 0. Is there anything wrong in my code? Or could anyone explain this for me? Thanks.

下面的代码为n和v生成随机值。在没有得到适当保护的情况下,n是随机的并不奇怪。但是假设v应该最终为0.我的代码中有什么问题吗?或者有人能为我解释一下吗?谢谢。

I'm working on a 4-core server of x86 architecture. The uname is as follows.

我正在研究x86架构的4核服务器。 uname如下。

Linux 2.6.9-22.ELsmp #1 SMP Mon Sep 19 18:00:54 EDT 2005 x86_64 x86_64 x86_64 GNU/Linux

Linux 2.6.9-22.ELsmp#1 SMP Mon Sep 19 18:00:54 EDT 2005 x86_64 x86_64 x86_64 GNU / Linux

#include <stdio.h>
#include <pthread.h>
#include <asm-x86_64/atomic.h>

int n = 0;
atomic_t v;
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;

#define LOOP 10000

void* foo(void *p)
{
    int i = 0;
    for(i = 0; i < LOOP; i++) {
//        pthread_mutex_lock(&mutex);
        ++n;
        --n;
        atomic_inc(&v);
        atomic_dec(&v);
//        pthread_mutex_unlock(&mutex);
    }

    return NULL;
}

#define COUNT 50

int main(int argc, char **argv)
{
    int i;
    pthread_t pids[COUNT];
    pthread_attr_t attr;
    pthread_attr_init(&attr);
    atomic_set(&v, 0);

    for(i = 0; i < COUNT; i++) {
        pthread_create(&pids[i], &attr, foo, NULL);
    }

    for(i = 0; i < COUNT; i++) {
        pthread_join(pids[i], NULL);
    }

    printf("%d\n", n);
    printf("%d\n", v);
    return 0;
}

4 个解决方案

#1


3  

Can we get a look at the assembler output of the code (gcc -E, I think). Even thought the uname indicates it's SMP-aware, that doesn't necessarily mean it was compiled with CONFIG_SMP.

我们可以看一下代码的汇编输出(gcc -E,我想)。即使认为uname表明它是SMP感知的,这并不一定意味着它是用CONFIG_SMP编译的。

Without that, the assembler code output does not have the lock prefix and you can find your cores interfering with one another.

没有它,汇编代码输出没有锁定前缀,你可以发现你的内核相互干扰。

But I would be using the pthread functions anyway since they're portable across more platforms.

但是我会使用pthread函数,因为它们可以在更多平台上移植。

#2


6  

You should use gcc built-ins instead (see. this) This works fine, and also works with icc.

你应该使用gcc内置函数(参见.this)这很好用,也适用于icc。

int a; 
__sync_fetch_and_add(&a, 1); // atomic a++

Note that you should be aware of the cache consistency issues when you modify variables without locking.

请注意,在未锁定的情况下修改变量时,应注意缓存一致性问题。

#3


4  

This old post implies that

这个老帖子意味着

  • It's not obvious that you're supposed to include this kernel header in userspace programs
  • 您应该在用户空间程序中包含此内核标头并不明显
  • It's been known to fail to provide atomicity for userspace programs.
  • 众所周知,它无法为用户空间程序提供原子性。

So ... Perhaps that's the reason for the problems you're seeing?

那么......也许这就是你遇到的问题的原因?

#4


0  

Linux kernel atomic.h is not usable from userland and never was. On x86, some of it might work, because x86 is rather synchronization-friendly architecture, but on some platforms it relies heavily on being able to do privileged operations (older arm) or at least on being able to disable preemption (older arm and sparc at least), which is not the case in userland!

Linux内核atomic.h在userland中不可用,从来没有。在x86上,其中一些可能会起作用,因为x86是相当友好的体系结构,但在某些平台上,它很大程度上依赖于能够执行特权操作(较旧的臂)或至少能够禁用抢占(较旧的arm和sparc)至少),用户地区的情况并非如此!

#1


3  

Can we get a look at the assembler output of the code (gcc -E, I think). Even thought the uname indicates it's SMP-aware, that doesn't necessarily mean it was compiled with CONFIG_SMP.

我们可以看一下代码的汇编输出(gcc -E,我想)。即使认为uname表明它是SMP感知的,这并不一定意味着它是用CONFIG_SMP编译的。

Without that, the assembler code output does not have the lock prefix and you can find your cores interfering with one another.

没有它,汇编代码输出没有锁定前缀,你可以发现你的内核相互干扰。

But I would be using the pthread functions anyway since they're portable across more platforms.

但是我会使用pthread函数,因为它们可以在更多平台上移植。

#2


6  

You should use gcc built-ins instead (see. this) This works fine, and also works with icc.

你应该使用gcc内置函数(参见.this)这很好用,也适用于icc。

int a; 
__sync_fetch_and_add(&a, 1); // atomic a++

Note that you should be aware of the cache consistency issues when you modify variables without locking.

请注意,在未锁定的情况下修改变量时,应注意缓存一致性问题。

#3


4  

This old post implies that

这个老帖子意味着

  • It's not obvious that you're supposed to include this kernel header in userspace programs
  • 您应该在用户空间程序中包含此内核标头并不明显
  • It's been known to fail to provide atomicity for userspace programs.
  • 众所周知,它无法为用户空间程序提供原子性。

So ... Perhaps that's the reason for the problems you're seeing?

那么......也许这就是你遇到的问题的原因?

#4


0  

Linux kernel atomic.h is not usable from userland and never was. On x86, some of it might work, because x86 is rather synchronization-friendly architecture, but on some platforms it relies heavily on being able to do privileged operations (older arm) or at least on being able to disable preemption (older arm and sparc at least), which is not the case in userland!

Linux内核atomic.h在userland中不可用,从来没有。在x86上,其中一些可能会起作用,因为x86是相当友好的体系结构,但在某些平台上,它很大程度上依赖于能够执行特权操作(较旧的臂)或至少能够禁用抢占(较旧的arm和sparc)至少),用户地区的情况并非如此!