J'essaie de construire une application qui utilise le type Pthreads et __M128 SSE. Selon le manuel GCC, l'alignement de la pile par défaut est de 16 octets. Pour utiliser __M128, l'exigence est l'alignement de 16 octets.
Mon CPU cible prend en charge SSE. J'utilise un compilateur GCC qui ne prend pas en charge le réalignement d'exécution de la pile d'exécution (par exemple, -Mstackrealign). Je ne peux pas utiliser d'autre version du compilateur GCC. P>
Mon application de test ressemble à: p> L'application génère une exception et des sorties. Après un simple débogage (printf "% p", & y), j'ai trouvé que la variable y n'est pas 16 octets alignée. P> Ma question est la suivante: Comment puis-je réaligner la pile correctement (16 octets) Sans utiliser aucun drapeau et attributs de GCC (ils n'aident pas)? Dois-je utiliser un assembleur en ligne GCC dans cette fonction de thread f ()? P> p>
5 Réponses :
Cela ne devrait pas se produire en premier lieu, mais pour contourner le problème, vous pouvez essayer:
void *f(void *x) { __m128 y __attribute__ ((aligned (16))); ... }
Non, ça n'aide pas. Le même problème.
Je suppose que vous faites cela sur Windows plutôt qu'un système d'exploitation approprié? Il y a quelques bonnes informations sur le travail autour de ce problème: Sourceware.org/ ML / Pthreads-Win32 / 2008 / msg00056.html
Il semble que ceci est un bug dans les anciennes versions de GCC - il semble avoir été fixé vers 2004 - existe-t-il une raison pour laquelle vous ne pouvez pas utiliser une boîte à outils plus à jour?
En fait, non, je ne peux pas utiliser une autre version GCC - nous avons un environnement matériel / logiciel spécifique.
J'essaie d'implémenter un ajustement explicite de la pile à l'aide de l'assembleur en ligne.
allouer sur la pile d'un tableau de 15 octets plus grand que Je ne me souviens pas si vous allociez un tableau code> non signé le tableau code> vous permet de protéger des optimisations d'aliasing strictes par le compilateur ou si cela ne fonctionne que l'inverse de l'inverse. p> Tailleof (__ M128) code> et utilisez la première adresse alignée dans ce tableau. Si vous en avez besoin de plusieurs, allouez-les dans une matrice avec une marge unique de 15 octets pour l'alignement.
Vous voudrez peut-être également examiner si la pile de threads globale est allouée à un alignement de 16 octets.
Merci, mais qu'est-ce que pTR_T et pourquoi utilisez-vous et ~ 15?
Malheureusement, cela oblige la variable à être sur la pile, quelles que soient les optimisations potentielles du compilateur (comme la garder dans un registre).
Je suppose que c'est censé être uintptr_t code>, mais de toute façon, il s'agit simplement d'un type d'entier suffisamment grand pour contenir un pointeur.
@Paul r droit, je cherchais le bon fichier d'en-tête et je ne pouvais pas le trouver parce que je me souviens mal du nom. @psihodelia & ~ 15 code> signifie "arrondir jusqu'au multiple de 16 immédiatement inférieur".
Cela ne fonctionne pas pour moi, car j'ai beaucoup de fonctions imbriquées et de variables locales.
J'ai résolu ce problème. Voici ma solution:
void another_function(){ __m128 y; ... } void *f(void *x){ asm("pushl %esp"); asm("subl $16,%esp"); asm("andl $-0x10,%esp"); another_function(); asm("popl %esp"); }
Sérieusement. Mettez à jour votre compilateur. Ne soyez pas fier de vous pour mettre des périphériques Rube Goldberg dans votre code.
Ce code semble sauvegarder ESP sur la pile, puis bouger ESP ailleurs, puis pop esp. Cela entraînera une valeur aléatoire dans l'ESP. Cela ne caque-t-il pas un crash? Ou utilisez-vous une convention appelante où ESP est sauvée ailleurs, peut-être dans EBP et restauré à la fin, ce qui rendait ce pop superflu?
1) Je ne peux pas mettre à jour GCC -> J'ai un environnement d'exécution spécifique et un processeur spécifique compatible X86. 2) Non, pourquoi peut-il causer un crash? Économisez ESP, puis la restaurée ne provoque aucun crash ni une valeur aléatoire. J'ai testé le code ci-dessus aussi sans push / POPL et c'est aussi ok. Aucune convention appelante et ESP n'est enregistrée ailleurs.
Comme User9876 a déclaré - Savez-vous ce qu'est-ce que "pushl% esp"? Conceptuellement, cela fonctionne comme ceci: mémoire [% ESP] =% ESP% ESP - = 4; // En fonction de la façon dont votre pile grandit, il peut s'agir de "+ = 4" alors, un "POPL% ESP" fait essentiellement:% ESP + = 4; % ESP = mémoire [% ESP] MAINTENANT, si entre le "PUSH" et "POP", vous avez modifié ESP - le deuxième accès à la mémoire (la "pop") lira à partir d'une mauvaise adresse. La seule explication raisonnable pour la raison pour laquelle cela fonctionne est que le compilateur sauve un% ESP ailleurs également (par exemple dans EBP?) Dans le prologue de la fonction F (), puis la restaure dans l'épilogue de F (). Ainsi, il cache votre erreur.
Une autre solution serait, d'utiliser une fonction de rembourrage, qui aligne d'abord la pile, puis appelle Le Le code ressemblerait à ceci: p> f code>. Donc au lieu d'appeler
f code> directement, vous appelez
pad code>, quels pads la pile d'abord, puis appelle
foo code> avec une pile alignée.
Désolé de ressusciter un vieux fil ... p>
Pour ceux avec un nouveau compilateur que OP, OP mentionne une option Article cool pour ceux qui voudront peut-être en savoir plus: http://wiki.osdev.org/system_v_abi < / a> p> -MStackrealign CODE>, qui me conduit à
__ attribut __ ((forcer_align_arg_pointer)) code>. Si votre fonction est optimisée pour utiliser SSE, mais
% ebp code> est mal aligné, cela fera les corrections d'exécution si nécessaire pour vous, de manière transparente. J'ai également découvert que ce n'est qu'un problème sur
i386 code>. Le
x86_64 code> abi garantit les arguments sont alignés sur 16 octets. P>
__ attribut __ ((forcer_align_arg_pointer))
void i_crash_when_not_aligned_to_16_bytes () {
...
}
code> p>
Merci pour cela. Il a aidé à résoudre un problème X86 32 bits avec Fabrication de fichiers .so code> en tant que binaires
. Il m'a également aidé à trouver le bogue qui discute de la confusion à ce sujet a>.
Si vous devez utiliser une version de GCC particulière, veuillez inclure la version GCC (par exemple GCC 4.3.2 I386) et OS hôte / cible (E.G. Debian 5.0 (Lenny) Linux 2.6.26 I686). Savoir s'il faut suggérer que les options GCC 4.3 par rapport à 3.4 peuvent faire une différence.