7
votes

Verrouiller le préfixe d'instruction Intel. Dans quel but?

J'ai lu le manuel Intel et trouvé qu'il existe un préfixe de verrouillage pour les instructions, ce qui peut empêcher les processeurs d'écrire dans le même emplacement de mémoire simultanément. Je suis assez excité à ce sujet. Je suppose que cela pourrait être utilisé comme mutex matériel. J'ai donc écrit un morceau de code pour avoir un coup. Le résultat est assez frustrant. La serrure ne prend pas en charge les instructions MOV ou LEA. Le manuel indique que Verrouiller ne prend en charge que Ajouter, ADC et, BTC, BTR, BTS, CMPXCHG, CMPXCH8B, Dec, Inc, Neg, non ou, SBB, SUB, XOR, XAD et XCHG. Quoi de plus, si le préfixe de verrouillage est utilisé avec l'une de ces instructions et que l'opérande de la source est un opérande de mémoire, une exception d'opcode non définie (#ud) peut être générée.

Je me demande pourquoi tant de limitations, de nombreuses restrictions font La serrure semble inutile. Je ne peux pas l'utiliser pour garantir une opération d'écriture générale ne pas avoir de données sales ou d'autres problèmes causés par le parallélisme.

E.g. J'ai écrit le code ++ (* p) dans C. P est pointeur à une mémoire partagée. L'assemblage correspondant est comme: xxx

J'ai ajouté "verrouillage" avant "MOVL" et "LEAL", mais le processeur se plaint "Instruction non valide". :-( Je suppose que le seul moyen de rendre les opérations d'écriture Serialized est d'utiliser le logiciel mutex, non?


11 commentaires

en.wikipedia.org/wiki/fetch-and-add


EN.Wikipedia.org/wiki/compara-and-swap


Un MOVL à une adresse alignée est toujours atomique, alors la serrure ne ferait aucune différence du tout.


Si ces "restrictions" n'existaient pas, les utilisations supplémentaires seraient toutes inutiles de toute façon.


BTW, il y a un problème avec votre code: même si chaque instruction a été effectuée avec une serrure de bus, le code ne serait toujours pas en sécurité, car il pouvait être interrompu entre toutes les instructions. Vous voulez que tout le bloc d'instructions soit exécuté au maximum un fil un temps. Vous avez besoin d'une approche complètement différente de celle-ci - un mutex ou similaire. Pour ce faire, vous devez fondamentalement entourer le code avec le code de verrouillage / déverrouillage - qui implique des instructions telles que "verrouiller CMPXCHG" et al


@drhirsch - Je ne pense pas que les mouvements alignés sont garantis atomique. Ce n'est certainement pas atomique sur les opérations 8088 (pour 16 bits) ou 386SX (pour 32 bits).


@Brianknoblauch: Ils sont garantis atomiques sur tous les transformateurs depuis 486, pour être plus précis. Je viens de supposer que nous parlions de processeurs de moins de 20 ans. Voir le Guide de programmation du système Intel Chapitre 8.1.1 "Le processeur Intel486 (et les processeurs plus récents depuis) ​​garantit que les opérations de mémoire de base suivantes seront toujours effectuées atomiquement: • lire ou écrire un octet • lire ou écrire un mot aligné sur un 16 -Bit limite • lire ou écrire un double mot d'alignement sur une limite de 32 bits "etc.


Si vous souhaitez utiliser une instruction ED, une barrière de mémoire (sur un CPU qui ne prend pas en charge mfence ou où mfence est plus lent qu'une instruction verrouillée), vous pouvez simplement LOCK Ajouter 0 $,% (ESP) , qui est sinon un NO-OP (à l'exception des drapeaux de clapering) et son cycle verrouillé en lecture-modification en mémoire C'est très probablement chaud dans le cache L1 et non sur un autre noyau. Autre que cela, cette question semble manquer entièrement le point du préfixe verrouillage . C'est pour les écrits en lecture atomique. La barrière de mémoire complète n'est qu'un effet secondaire, mais X86 n'avait pas de barrière séparée insn jusqu'à Mfence .


Dupliqué possible de est x86 CMPXCHG atomique?


@Petercordes devrait-il être dupphed martelé, semble que nous en avons aussi beaucoup ici ici Stackoverflow.com/Questtions/17020128/...


@EventRancarroll: Ce n'est pas un duplicata: il semble demander à quel point le point de verrouillage est s'il ne peut pas être utilisé pour créer un MOV atomique. (Mais il est totalement mélangé à propos de la fabrication de l'ensemble de la RMW Atomic par rapport à la fabrication d'un MOV atomique.) Il ne pose pas de questions sur CMPXCHG; Si quelque chose l'instruction souhaité est verroue Ajouter ou verrouiller xadd . Mais oui, j'ai démonté votre 2e lien, comme si j'essayais d'il y a des années avant d'avoir eu le représentant de le faire seul.


5 Réponses :


12
votes

Je n'appelerais certainement pas verrouillage inutile. verrouiller cmPxchg est le moyen standard d'effectuer comparer-and-swap , lequel est le bloc de base de nombreux algorithmes de synchronisation.

Aussi, voir Fetch-and-Ajouter .


0 commentaires

5
votes

Le but de verrouillage est de faire des opérations atomiques , non sérialisées. De cette manière, la CPU ne peut pas être préemptée avant l'entrée de l'opération.


2 commentaires

Merci pour votre réponse. Je ne suis pas très sûr de ces terminologies. Je suppose que atomique signifie que l'opération sera effectuée dans un ensemble, aucune interruption, sinon annulée. Dans ce problème, même si "Serrure Ajouter" est effectué de manière atomique, si cela ne signifie pas que d'autres processeurs ne peuvent pas accéder à cet emplacement de mémoire furtivement en même temps. Donc, ce que «verrouillage» fait est d'empêcher l'accès parallèle à la même position de mémoire. Je suppose que cela s'appelle sérialiséisé, ce qui rend chaque thread accédant à la mémoire un par un.


Les opérations atomiques sont des primitives utilisées pour la sérialisation , mais elles ne sont pas sérialisées elles-mêmes; La sérialisation fait référence à plusieurs entités exécutant la même opération une à la fois, alors que les opérations atomiques préforment une opération arbitraire dans une motion discrète, non perturbée par d'autres.



2
votes

Il est utile lorsque, sur une machine multiprocesseur, deux processus concurrents utilisent les mêmes données, mais ils ne peuvent pas la modifier simultanément.

Lorsque l'un des processus modifie les données, il utilise une serrure sur l'instruction de modification de sorte que, lorsque le second processus tente de le modifier, il faut attendre le premier à terminer son travail avant de pouvoir faire son travail avant de pouvoir faire son propre à son tour.

J'espère que cela aidera un peu.


0 commentaires

3
votes

Les processeurs X86 sont connus pour un design velu avec de nombreuses caractéristiques, de nombreuses règles et encore plus d'exceptions à toutes ces règles. Ceci est lié à la longue histoire de la famille.

Lorsque les compilateurs ou les personnes utilisent verrouillent , ils l'utilisent toujours avec toutes ses limitations, souvent sur des données spécialement introduites pour effectuer la synchronisation entre les threads, par opposition aux données d'application que les algorithmes éventuellement manipulent. On adapte ensuite les protocoles de synchronisation de fil à ce que verrouillage peut faire pour eux plutôt que inversement.

Le type d'instruction générale que vous semblez rechercher est appelé barrières de mémoire . En effet, X86 a plusieurs instructions "modernes" de cette famille (Mfence, Lfence, Sfence). Ils sont pleines de clôture, de clôture de chargement et de clôture de stockage respectivement. Cependant, leur importance dans le jeu d'instructions est limitée à SSE , car Intel garantit la sérialisation des écritures La partie traditionnelle de l'instruction set, et c'est à peu près la raison pour laquelle cette architecture vieillie est une cible assez facile pour la programmation multithread.

Voir aussi Cette réponse Pour plus d'informations.


0 commentaires

1
votes

Dans l'exemple que vous fournissez, vous pouvez utiliser un préfixe verrouillage avec un instruction inc tel que ceci (en supposant p est situé dans % EAX ): xxx

Dans des cas plus généraux, vous devez utiliser des serrures.


0 commentaires