Comment faire en sorte que `gcc` génère l’instruction` bts` pour x86-64 à partir du C standard?

Inspiré par une question récente , j’aimerais savoir si quelqu’un sait comment faire en sorte que gcc génère l’instruction x86-64 bts (bit test and set) sur les plates-formes Linux x86-64, sans recourir à un assemblage en ligne ou à un compilateur non standard. les insortingnsèques.

Questions connexes:

La portabilité est plus importante pour moi que bts , je n’utiliserai donc pas de directive asm , et s’il existe une autre solution, je préfère ne pas utiliser les instructions du compilateur.

EDIT : Le langage source C ne supporte pas les opérations atomiques, je ne suis donc pas particulièrement intéressé par le test-set atomique (même si c’est la raison originale pour laquelle test-and-set existait à l’origine). Si je veux quelque chose d’atomique, je sais que je n’ai aucune chance de le faire avec une source C standard: ce doit être une fonction insortingnsèque, une fonction de bibliothèque ou un assemblage en ligne. (J’ai implémenté des opérations atomiques dans des compilateurs prenant en charge plusieurs threads.)

C’est dans la première réponse pour le premier lien – combien cela compte dans le grand schéma des choses. La seule partie lorsque vous testez des bits sont:

  • Conducteurs de bas niveau. Toutefois, si vous en écrivez un, vous connaissez probablement ASM, il est suffisant pour le système et la plupart des retards concernent probablement les E / S.
  • Test de drapeaux. Il s’agit généralement d’une initialisation (une fois seulement au début) ou d’un calcul partagé (qui prend beaucoup plus de temps).

L’impact global sur les performances des applications et des macrobiosques sera probablement minime, même si les micro-indices montrent une amélioration.

Pour la partie Edit – utiliser uniquement bts ne garantit pas l’atome de l’opération. Tout ce que cela garantit, c’est qu’il sera atomique sur ce kernel (tel est le cas or est fait sur la mémoire). Sur les unités multiprocesseurs (inhabituelles) ou les unités multicœurs (très courantes), vous devez toujours vous synchroniser avec d’autres processeurs.

Comme la synchronisation coûte beaucoup plus cher, je crois que cette différence entre:

 asm("lock bts %0, %1" : "+m" (*array) : "r" (bit)); 

et

 asm("lock or %0, %1" : "+m" (*array) : "r" (1 << bit)); 

est minime. Et la deuxième forme:

  • Peut définir plusieurs drapeaux à la fois
  • Ayez une belle forme __sync_fetch_and_or (array, 1 << bit) (travaillant sur le compilateur gcc et intel pour autant que je m'en souvienne).

J’utilise les composants génériques atomiques de gcc tels que __sync_lock_test_and_set ( http://gcc.gnu.org/onlinedocs/gcc-4.1.2/gcc/Atomic-Builtins.html ). Changer le drapeau -march affectera directement ce qui est généré. Je l’utilise avec i686 ce moment, mais http://gcc.gnu.org/onlinedocs/gcc-4.1.2/gcc/i386-and-x86_002d64-Options.html#i386-and-x86_002d64-Options montre tout les possibilités.

Je me rends compte que ce n’est pas exactement ce que vous demandez, mais j’ai trouvé ces deux pages Web très utiles lorsque je cherchais de tels mécanismes.

Je crois (mais je ne suis pas certain) que ni les normes C ++ ni C n’ont encore de mécanismes pour ces types de mécanismes de synchronisation. La prise en charge des mécanismes de synchronisation de niveau supérieur est dans différents états de normalisation, mais je ne pense même pas que l’un de ceux-ci vous permettrait d’accéder au type de primitive que vous recherchez.

Programmez-vous des infrastructures de données sans locking dans lesquelles les verrous sont insuffisants?

Vous voudrez probablement simplement utiliser les extensions non standard et / ou les primitives de synchronisation fournies par le système d’exploitation ou la bibliothèque de gcc. Je parierais qu’il existe une bibliothèque qui pourrait fournir le type de portabilité que vous recherchez si vous êtes préoccupé par l’utilisation d’insortingnsèques du compilateur. (Bien que vraiment, je pense que la plupart des gens ne font que mordre la balle et utilisent un code spécifique à gcc quand ils en ont besoin. Pas idéal, mais les normes n’ont pas vraiment suivi.)