Ce n' __asm__ __volatile__ faire en C?
J'ai regardé dans du code C à partir de
http://www.mcs.anl.gov/~kazutomo/rdtsc.html
Ils utilisent des trucs comme "inline", "asm" etc comme suit:
code1:
static __inline__ tick gettick (void) {
unsigned a, d;
__asm__ __volatile__("rdtsc": "=a" (a), "=d" (d) );
return (((tick)a) | (((tick)d) << 32));
}
code2:
volatile int __attribute__((noinline)) foo2 (int a0, int a1) {
__asm__ __volatile__ ("");
}
Je me demandais quel est le code1 code2 et faire?
- gcc.gnu.org/onlinedocs/gcc/Extended-Asm.html (sinon, ignorez le
__
partout,__inline__
est tout simplementinline
.
Vous devez vous connecter pour publier un commentaire.
La
__volatile__
modificateur sur un__asm__
empêcher les forces du compilateur optimiseur pour exécuter le code en tant que-est. Sans elle, l'optimiseur peut penser qu'il peut être supprimé purement et simplement, ou de sortir d'une boucle et mis en cache.C'est utile pour l'
rdtsc
instruction comme suit:Cela ne prend pas de dépendances, de sorte que le compilateur pourrait supposer que la valeur peut être mis en cache. Volatile est utilisé afin de le forcer à lire un frais d'horodatage.
Lorsqu'il est utilisé seul, comme ceci:
Il ne sera pas réellement exécuter quoi que ce soit. Vous pouvez étendre ce système, cependant, à obtenir au moment de la compilation barrière de mémoire qui ne permettent pas à la réorganisation de la mémoire de l'accès instructions:
La
rdtsc
instruction est un bon exemple pour les volatiles.rdtsc
est généralement utilisé lorsque vous avez besoin de temps combien de temps certaines instructions pour exécuter. Imaginez un code comme celui-ci, où vous voulez le tempsr1
etr2
s'exécution:Ici, le compilateur est effectivement permis de mettre en cache le timestamp, et valide la sortie pourrait montrer que chaque ligne a pris exactement 0 horloges à exécuter. Évidemment, ce n'est pas ce que vous voulez, donc vous présenter
__volatile__
à empêcher la mise en cache:Maintenant, vous obtiendrez un nouveau timestamp à chaque fois, mais il a encore un problème que le compilateur et le PROCESSEUR sont autorisés à réorganiser l'ensemble de ces déclarations. Il pourrait finir par l'exécution de l'asm blocs après r1 et r2 ont déjà été calculés. Pour contourner ce problème, vous devez ajouter quelques obstacles que la force de la sérialisation:
Note le
mfence
instruction ici, qui applique un PROCESSEUR côté de la barrière, et la "mémoire" spécificateur de la volatilité de l'édifice, qui applique au moment de la compilation de la barrière. Sur les Processeurs modernes, vous pouvez remplacermfence:rdtsc
avecrdtscp
pour quelque chose de plus efficace.rdtsc
cela peut éventuellement provoquer des erreurs.__rdtsc
intrinsèque.volatile
est inutile dansasm volatile("")
. Et votre explication de la volatilité n'est pas bon, avecasm("rdtsc":...
le compilateur peut même réorganiser l'asm blocs (ou de les supprimer si a0 et d0 sont inutilisés), alors qu'avecvolatile
il a de les garder dans cet ordre, mais il peut encore bouger les ajouts et les magasins à travers.rdtsc
devrait être évitée pour la surveillance de la performance depuis beaucoup de facteurs peuvent modifier le résultat.asm
est, y compris pour les natifs du code assembleur dans le code source C. E. g.Compilateurs ont différentes variantes de celui-ci.
__asm__
devrait être synonyme, peut-être avec quelques compilateur des différences spécifiques.volatile
signifie que la variable peut être modifiée à partir de l'extérieur (aka pas par le programme C). Par exemple, lors de la programmation d'un microcontrôleur où l'adresse de la mémoire0x0000x1234
est mappé à un périphérique spécifique de l'interface (c'est à dire lors du codage de la GameBoy, boutons/écran/etc sont accessibles de cette manière.)Cette désactivé les optimisations du compilateur qui s'appuient sur
*button1
ne pas changer, à moins d'être modifiée par le code.Il est également utilisé en multi-thread de programmation (pas plus nécessaire aujourd'hui?) lorsqu'une variable peut être modifiée par un autre thread.
inline
est une indication pour le compilateur "inline" appels à une fonction.Cela ne devrait pas être compilé dans un appel de fonction à
f
mais enint b = a + 1
. Comme sif
où une macro. La plupart des compilateurs faire cette optimisation automatiquement en fonction de la fonction d'usage/contenu.__inline__
dans cet exemple peut avoir un sens plus précis.De même
__attribute__((noinline))
(GCC-syntaxe spécifique) empêche une fonction inline.foo2
se traduit à un appel de fonction à un vide de fonction avec deux arguments entiers et renvoyant un entier, dans l'assemblée. Au lieu d'être optimisé à l'écart. Cette fonction peut être mise en œuvre dans le code assembleur généré.int
. Cela signifie que le code assembleur généré sera telle que l'appelant attend un int valeur de retour pour être sur certains inscrire (selon convention d'appel). Dans le code assembleur le corps de la fonction peut être modifiée pour faire que.La
__asm__
attribut spécifie le nom à utiliser dans le code assembleur de la fonction ou variable.La
__volatile__
qualificatif, généralement utilisé en Temps Réel-l'Informatique des systèmes embarqués, traite d'un problème avec le compilateur tests de lastatus register
pour laERROR
ouREADY
peu de causer des problèmes lors de l'optimisation.__volatile__
a été présenté comme une façon de dire au compilateur que l'objet est soumis à une évolution rapide et à force de chaque référence de l'objet à une véritable référence.volatile
type de qualificatif (par exemplevolatile int
), pas GNU Casm volatile
. Avec inline asm il n'y a pas "l'objet".volatile
désactive l'optimisation de la jeter asm états s'ils décident, il n'est pas nécessaire pour les variables de sortie, de toute façon:)
"memory"
tabasser pour en faire un compilateur de la barrière.