8
votes

COMPILER REORTERING autour des limites de mutex?

Supposons que j'ai mes propres fonctions non lignes Lockmutex et Déverrouillermutex, qui utilisent un mutex approprié, tel que Boost - Inside. Comment le compilateur saura-t-il de ne pas réorganiser d'autres opérations en ce qui concerne les appels vers le Lockmutex et Débloquermutex? Il ne peut pas éventuellement savoir comment puis-je implémenter ces fonctions dans une autre unité de compilation.

void SomeClass::store(int i)
{
  LockMutex(_m);
  _field = i;  // could the compiler move this around?
  UnlockMutex(_m);
}


1 commentaires

Je tiens à noter que malgré la réorganisation du compilateur, un processeur peut également réorganiser des instructions (voir la cohérence de la cache). Les implémentations mutex inséraient également des barrières de mémoire afin que cela soit définitivement en sécurité.


6 Réponses :


0
votes

Si le compilateur faisait, ce serait un mauvais compilateur. ; -)


0 commentaires

2
votes

En général, un compilateur ne déplacera pas le code autour de celui-ci sauf s'il ne le sait pas avec certitude que cela n'affectera pas le comportement du temps d'exécution.


2 commentaires

Correct. Un compilateur de code de code aura un modèle d'analyse statique de la manière dont votre programme fonctionne et ses dépendances de données / opérationnelles, et conservera ces dépendances.


Strictement parlant, il n'y a aucune dépendance entre la variable _field, par exemple, et l'appel à Lockmutex ou déverrouillermutex, de sorte que la préservation des dépendances n'aident pas ici.



0
votes

Si le compilateur ne peut pas garantir que les appels de fonction n'auront pas d'effets secondaires qui modifieront les variables entre les appels, il ne peut pas déplacer le code. Si la variable est une variable locale et que vous n'avez jamais pris de référence ni créer un pointeur, le compilateur peut supposer qu'il est prudent de bouger; Je ne sais pas.


3 commentaires

Si la variable est locale, n'est pas volatile et n'a pas eu de pointeur ou de référence prise, aucun autre thread ne peut y accéder. Donc, dans la mesure où prendre un mutex est concerné, peu importe que le magasin se produise auparavant, après ou entre les appels de fonction ou si cela ne se produit jamais.


@Michael Burr, n'est-ce pas ce que j'ai dit? Si le compilateur est suffisamment sophistiqué, il peut déterminer qu'une charge / magasin variable locale est sécuritaire de réorganiser; Que ce soit ou non probablement dépend des paramètres d'optimisation. Je cherchais au-delà des limites de la question où il est évident que la variable est pas local. Comme on l'a demandé, il tombe sous ma première phrase - le compilateur n'a aucun moyen de connaître les effets secondaires de Lockmutex ou de déverrouillage, de sorte qu'il ne peut donc pas réorganiser.


Je n'étais pas en désaccord; Je pensais que je clarifiais quelque chose qui semblait être incertain à la fin de la réponse. Je ne voulais pas dire que cela semble argumenté si c'est comme ça que cela se trouvait.



1
votes

Comme il est écrit, si les fonctions ne sont pas en ligne, le compilateur ne déplace pas l'attribution de la variable, car l'appel peut être sans rapport avec la variable _field, mais elle doit préserver l'ordre strict des appels. Si, toutefois, le compilateur décide de faire connaître les appels, je pense que cela les traitera comme des blocs de code indépendant, c'est-à-dire qu'il ne réalsera que des instructions dans la même unité de code (la fonction inlined elle-même) mais non avec le suivant ou précédent code (assignation à la variable _field).


1 commentaires

Merci. Avez-vous un lien vers la documentation indiquant que la réorganisation du compilateur s'arrête à des limites des fonctions même en ligne?



1
votes

Vous avez raison, ce code est correct et sûr. J'ai pensé à une "blague de code", cependant.

pthread_mutex_lock( &mx ) + foo() + pthread_mutex_unlock( &mx );


0 commentaires

3
votes

Il ne peut pas éventuellement savoir comment vais-je mettre en œuvre ces fonctions dans une autre unité de compilation.

Ceci est la clé - puisque le compilateur ne peut pas savoir (en général) sur la mise en œuvre des appels de fonction, il ne peut pas déplacer le magasin sur _field en dehors de ces appels de fonction.

Généralement, car _field est accessible en dehors de Someclass :: Store (Store () (Ce n'est pas un local), le compilateur ne peut pas savoir s'il est modifié ou non La fonction externe doit donc exécuter le magasin sur _field entre les points de séquence d'appel de fonction.

La plate-forme matérielle sous-jacente peut avoir besoin d'une attention particulière sous la forme de barrières de mémoire ou de cache des flushès pour faire face à la mise en cache ou à des opérations hors commandement qui se produisent dans le matériel. La mise en œuvre de la plate-forme des API mutex traitera ces problèmes si nécessaire.


0 commentaires