Fonctions intégrées atomiques gcc

http://gcc.gnu.org/onlinedocs/gcc-4.4.2/gcc/Atomic-Builtins.html

Je crois que le code suivant augmente la valeur de var de manière atomique.

volatile int var = 0; __sync_fetch_and_add( &var, 1 ) 

J’ai compris les codes ci-dessus comme étant la logique suivante:

  1. Charger l’adresse de la variable var
  2. écrit le numéro 1 sur la variable var de manière atomique – via registre / cache, en quelque sorte

Cependant, je doute que la suite soit aussi atomique

 volatile int var = 0; volatile int num = 1; __sync_fetch_and_add( &var, num ) 

Puisqu’il peut être interprété comme

  1. Charger l’adresse de la variable var
  2. Charger la valeur de la variable num dans un registre
  3. écrire la valeur sur variable var.

Après l’exécution de # 2, mais avant # 3, la CPU / thread est interrompue et une autre CPU / thread met à jour la valeur de la variable num.

En d’autres termes, lorsque vous utilisez _ sync * () de gcc, puis-je utiliser une variable, pas une constante, comme second argument?

Cela ne brise-t-il pas l’atomicité?

L’opération est vraiment deux opérations.

 __sync_fetch_and_add( &var, num ) 

Le nombre de chargement est atomique. L’append à var est atomique. Mais deux opérations atomiques ne font pas une opération atomique lorsqu’elles sont mises ensemble. C’est pourquoi il est si difficile d’inventer de nouvelles structures de données sans locking. En général, deux opérations thread-safe ne créent pas nécessairement une opération thread-safe une fois composées. C’est la raison pour laquelle il est si difficile de créer des applications multithread correctes.

Vous voyez, __sync_fetch_and_add est en effet atomique, mais elle se comporte comme une fonction ordinaire – elle prend donc la valeur courante de “num” en tant que paramètre. Il n’est pas tout à fait correct de dire que l’atomicité de la fonction est brisée, car l’appelant est chargé de charger la valeur à partir de num et ne fait pas partie de l’interface de la fonction. Je pourrais également me plaindre à ce sujet:

 __sync_fetch_and_add(&var, some_really_long_function()); 

Ou pire,

 __sync_fetch_and_add(long_function_1(), long_function_2()); 

Vous dites que “peut être interprété comme”

  1. Charger l’adresse de la variable var
  2. Charger la valeur de la variable num
  3. Effectuer l’addition atomique

Mais selon la spécification C, ce n’est pas que cela puisse être interprété de cette façon, mais plutôt, cela doit être interprété de cette façon, sinon le compilateur ne serait pas conforme (en fait, il pourrait échanger les n ° 1 et n ° 2, mais ce n’est pas important. ici).