Les opérations de atomic.h semblent être non atomiques

Le code suivant produit des valeurs aléatoires pour n et v. Il n’est pas surprenant que n soit aléatoire sans être correctement protégé. Mais il est supposé que v devrait finalement être 0. Y at-il quelque chose de mal dans mon code? Ou quelqu’un pourrait-il m’expliquer cela? Merci.

Je travaille sur un serveur 4-core d’architecture x86. L’uname est comme suit.

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  #include  #include  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; } 

Peut-on avoir un aperçu de la sortie de l’assembleur du code (gcc -E, je pense). Même si le uname indique qu’il est compatible SMP, cela ne signifie pas nécessairement qu’il a été compilé avec CONFIG_SMP.

Sans cela, la sortie du code de l’assembleur n’a pas le préfixe de lock et vous pouvez trouver que vos cœurs interfèrent les uns avec les autres.

Mais j’utiliserais les fonctions pthread de toute façon car elles sont portables sur plus de plates-formes.

Vous devriez plutôt utiliser les fonctions intégrées de gcc (voir ceci ). Cela fonctionne bien et fonctionne également avec icc.

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

Notez que vous devez connaître les problèmes de cohérence du cache lorsque vous modifiez des variables sans les verrouiller.

Cet ancien post implique que

  • Il n’est pas évident que vous soyez censé inclure cet en-tête du kernel dans les programmes de l’espace utilisateur
  • Il est connu pour ne pas fournir d’atomicité pour les programmes de l’espace utilisateur.

Alors … Peut-être que c’est la raison des problèmes que vous voyez?

Le kernel Linux atomic.h n’est pas utilisable depuis l’utilisateur et ne l’a jamais été. Sur x86, une partie pourrait fonctionner, car x86 est plutôt une architecture compatible avec la synchronisation, mais sur certaines plates-formes, elle repose en grande partie sur la possibilité de faire des opérations privilégiées (armes plus anciennes). au moins), ce qui n’est pas le cas en pays utilisateur!