Cette fonction fait partie d'un bout d'OS que je passe en 64 bits.
En 32 bits, ça fonctionne parfaitement. Ce bout de code est appelé
depuis une fonction en C (équivalente à mutex_trylock() pour des
mutexes récursifs).
Mon problème est simple. Le 'cmpxchgq' ne semble pas faire ce qu'il
devrait (ou alors, je n'ai rien compris).
Je viens de lire et de relire la doc (origine AMD) et si j'ai bien
tout compris, CMPXCHGQ est censé comparer la valeur de %RAX à la
valeur (%RCX). Si ces deux valeurs sont égales, il copie la valeur
de %RDX dans %(RCX) et met le drapeau Z à 1.
Dans mon cas, le programme saute à ma routine de débug qui m'affiche
la pile. J'en déduis donc que ce drapeau est à 1 et que CMPXCHGQ
aurait dû copier %RDX dans (%RCX). Je vois bien que %RDX contient la
bonne valeur, mais (%RCX) reste nul comme le prouve la sortie :
Le Wed, 03 Nov 2010 06:44:00 +0100, Pierre Maurette écrivait :
JKB, le 11/2/2010 a écrit :
[...]
Il y a un truc bizarre lorsque je remplace 0 par une valeur non nulle. Je vais laisser tomber pour ce soir...
C'est également ce que j'ai fait hier soir. Mais je suis tombé du lit ce matin. J'ai fait quelques tests, et cmpxchg fonctionne comme vous et moi l'attendions:
Je vais m'y remettre. Ça doit être gros comme une maison et ça risque de me sauter aux yeux...
JKB
-- Si votre demande me parvient sur carte perforée, je titiouaillerai très volontiers une réponse... => http://grincheux.de-charybde-en-scylla.fr
Le Wed, 03 Nov 2010 06:44:00 +0100,
Pierre Maurette <maurettepierre@wanadoo.fr> écrivait :
JKB, le 11/2/2010 a écrit :
[...]
Il y a un truc bizarre lorsque je remplace 0 par une valeur non
nulle. Je vais laisser tomber pour ce soir...
C'est également ce que j'ai fait hier soir. Mais je suis tombé du lit
ce matin. J'ai fait quelques tests, et cmpxchg fonctionne comme vous et
moi l'attendions:
Je vais m'y remettre. Ça doit être gros comme une maison et ça
risque de me sauter aux yeux...
JKB
--
Si votre demande me parvient sur carte perforée, je titiouaillerai très
volontiers une réponse...
=> http://grincheux.de-charybde-en-scylla.fr
Le Wed, 03 Nov 2010 06:44:00 +0100, Pierre Maurette écrivait :
JKB, le 11/2/2010 a écrit :
[...]
Il y a un truc bizarre lorsque je remplace 0 par une valeur non nulle. Je vais laisser tomber pour ce soir...
C'est également ce que j'ai fait hier soir. Mais je suis tombé du lit ce matin. J'ai fait quelques tests, et cmpxchg fonctionne comme vous et moi l'attendions:
Je vais m'y remettre. Ça doit être gros comme une maison et ça risque de me sauter aux yeux...
JKB
-- Si votre demande me parvient sur carte perforée, je titiouaillerai très volontiers une réponse... => http://grincheux.de-charybde-en-scylla.fr
Antoine Leca
JKB écrivit :
Le Tue, 2 Nov 2010 15:51:04 +0000 (UTC),
cmpxchgq %rdx, (%rcx)
En 32 bits, ça fonctionne parfaitement.
En 32 bits, tu ne peux pas utiliser cmpxchg16b, donc je suppose que tu utilises cmpxchg8b à la place (ce ne sont pas les mêmes instructions.)
Mon problème est simple. Le 'cmpxchgq' ne semble pas faire ce qu'il devrait (ou alors, je n'ai rien compris).
As-tu vérifié préalablement que cette instruction était implémentée dans le processeur que tu utilises ? (bit CX16 du CPUID, bit 13 de ECX, cf. http://www.sandpile.org/ia32/cpuid.htm)
Antoine
JKB écrivit :
Le Tue, 2 Nov 2010 15:51:04 +0000 (UTC),
cmpxchgq %rdx, (%rcx)
En 32 bits, ça fonctionne parfaitement.
En 32 bits, tu ne peux pas utiliser cmpxchg16b, donc je suppose que tu
utilises cmpxchg8b à la place (ce ne sont pas les mêmes instructions.)
Mon problème est simple. Le 'cmpxchgq' ne semble pas faire ce qu'il
devrait (ou alors, je n'ai rien compris).
As-tu vérifié préalablement que cette instruction était implémentée dans
le processeur que tu utilises ? (bit CX16 du CPUID, bit 13 de ECX, cf.
http://www.sandpile.org/ia32/cpuid.htm)
En 32 bits, tu ne peux pas utiliser cmpxchg16b, donc je suppose que tu utilises cmpxchg8b à la place (ce ne sont pas les mêmes instructions.)
Mon problème est simple. Le 'cmpxchgq' ne semble pas faire ce qu'il devrait (ou alors, je n'ai rien compris).
As-tu vérifié préalablement que cette instruction était implémentée dans le processeur que tu utilises ? (bit CX16 du CPUID, bit 13 de ECX, cf. http://www.sandpile.org/ia32/cpuid.htm)
Antoine
JKB
Le Tue, 2 Nov 2010 13:13:54 -0700 (PDT), Jean-Christophe écrivait :
On Nov 2, 5:48 pm, JKB
Gnî !
Bon, je me lance :
1. As-tu essayé de changer cmpxchgq par une suite de codes équivalents pour comparer le résultat ? Un truc de ce genre ( si j'ai bien tout suivi ) cmp eax,edx bne skip mov edx,ecx skip ...
Objection. Je cherche à écrire un mutex récursif en _64_ bits (en 32, ça fonctionne). Tout le code est _64_ bits. Et le mutex impose une opération _atomique_.
2. Il me semble que cmpxchgq compare le RESTE d'un modulo 8, 16 ou 32 selon le cas. Sachant que ton code tourne en 32 bits mais pas en 64, y a t'il une chance que ce soit du à ce remainder ?
"CMPXCHG r/m8, r8 Compare AL with r/m8. If equal, ZF is set and r8 is loaded into r/m8. Else, clear ZF and load r/m8 into AL." "CMPXCHG r/m16, r16 Compare AX with r/m16. If equal, ZF is set and r16 is loaded into r/m16. Else, clear ZF and load r/m16 into AL" "CMPXCHG r/m32, r32 Compare EAX with r/m32. If equal, ZF is set and r32 is loaded into r/m32. Else, clear ZF and load r/m32 into AL"
CMPXCHG fonctionne aussi en 64 bits comme une extension du mode 32 bits.
JKB
-- Si votre demande me parvient sur carte perforée, je titiouaillerai très volontiers une réponse... => http://grincheux.de-charybde-en-scylla.fr
Le Tue, 2 Nov 2010 13:13:54 -0700 (PDT),
Jean-Christophe <5.d@free.fr> écrivait :
On Nov 2, 5:48 pm, JKB
Gnî !
Bon, je me lance :
1. As-tu essayé de changer cmpxchgq par une suite
de codes équivalents pour comparer le résultat ?
Un truc de ce genre ( si j'ai bien tout suivi )
cmp eax,edx
bne skip
mov edx,ecx
skip ...
Objection. Je cherche à écrire un mutex récursif en _64_ bits (en
32, ça fonctionne). Tout le code est _64_ bits. Et le mutex impose
une opération _atomique_.
2. Il me semble que cmpxchgq compare le
RESTE d'un modulo 8, 16 ou 32 selon le cas.
Sachant que ton code tourne en 32 bits mais pas en 64,
y a t'il une chance que ce soit du à ce remainder ?
"CMPXCHG r/m8, r8 Compare AL with r/m8. If equal, ZF is set and r8
is loaded into r/m8. Else, clear ZF and load r/m8 into AL."
"CMPXCHG r/m16, r16 Compare AX with r/m16. If equal, ZF is set and
r16 is loaded into r/m16. Else, clear ZF and load r/m16 into AL"
"CMPXCHG r/m32, r32 Compare EAX with r/m32. If equal, ZF is set and
r32 is loaded into r/m32. Else, clear ZF and load r/m32 into AL"
CMPXCHG fonctionne aussi en 64 bits comme une extension du mode 32
bits.
JKB
--
Si votre demande me parvient sur carte perforée, je titiouaillerai très
volontiers une réponse...
=> http://grincheux.de-charybde-en-scylla.fr
Le Tue, 2 Nov 2010 13:13:54 -0700 (PDT), Jean-Christophe écrivait :
On Nov 2, 5:48 pm, JKB
Gnî !
Bon, je me lance :
1. As-tu essayé de changer cmpxchgq par une suite de codes équivalents pour comparer le résultat ? Un truc de ce genre ( si j'ai bien tout suivi ) cmp eax,edx bne skip mov edx,ecx skip ...
Objection. Je cherche à écrire un mutex récursif en _64_ bits (en 32, ça fonctionne). Tout le code est _64_ bits. Et le mutex impose une opération _atomique_.
2. Il me semble que cmpxchgq compare le RESTE d'un modulo 8, 16 ou 32 selon le cas. Sachant que ton code tourne en 32 bits mais pas en 64, y a t'il une chance que ce soit du à ce remainder ?
"CMPXCHG r/m8, r8 Compare AL with r/m8. If equal, ZF is set and r8 is loaded into r/m8. Else, clear ZF and load r/m8 into AL." "CMPXCHG r/m16, r16 Compare AX with r/m16. If equal, ZF is set and r16 is loaded into r/m16. Else, clear ZF and load r/m16 into AL" "CMPXCHG r/m32, r32 Compare EAX with r/m32. If equal, ZF is set and r32 is loaded into r/m32. Else, clear ZF and load r/m32 into AL"
CMPXCHG fonctionne aussi en 64 bits comme une extension du mode 32 bits.
JKB
-- Si votre demande me parvient sur carte perforée, je titiouaillerai très volontiers une réponse... => http://grincheux.de-charybde-en-scylla.fr
JKB
Le Wed, 03 Nov 2010 09:50:56 +0100, Antoine Leca écrivait :
JKB écrivit :
Le Tue, 2 Nov 2010 15:51:04 +0000 (UTC),
cmpxchgq %rdx, (%rcx)
En 32 bits, ça fonctionne parfaitement.
En 32 bits, tu ne peux pas utiliser cmpxchg16b, donc je suppose que tu utilises cmpxchg8b à la place (ce ne sont pas les mêmes instructions.)
J'ai trouvé et j'ai honte. Je ne sais pas pourquoi, mais j'ai mélangé les deux arguments de ma fonction... En les remettant dans l'ordre ça fonctionne tout de suite beaucoup mieux. On devrait toujours laisser reposer ses problèmes une bonne nuit...
Mon problème est simple. Le 'cmpxchgq' ne semble pas faire ce qu'il devrait (ou alors, je n'ai rien compris).
As-tu vérifié préalablement que cette instruction était implémentée dans le processeur que tu utilises ? (bit CX16 du CPUID, bit 13 de ECX, cf. http://www.sandpile.org/ia32/cpuid.htm)
try_lock_amd64: // Setup the local variables pushq %rbp movq %rsp, %rbp movq 24(%rbp), %rcx /* %rcx = &m->holder */ movq 16(%rbp), %rdx /* %rdx = me */
// Test the lock : // if (%rcx) == $0, write %rdx into (%rcx) // if not, write (%rcx) into %rax. movq $0, %rax lock cmpxchgq %rdx, (%rcx)
// What is the result movq (%rcx), %rcx /* %rcx = m->holder */ cmpq 16(%rbp), %rcx /* m->holder == me */ sete %al andq $0xff, %rax
popq %rbp ret #endif
Cordialement,
JKB
-- Si votre demande me parvient sur carte perforée, je titiouaillerai très volontiers une réponse... => http://grincheux.de-charybde-en-scylla.fr
Le Wed, 03 Nov 2010 09:50:56 +0100,
Antoine Leca <root@localhost.invalid> écrivait :
JKB écrivit :
Le Tue, 2 Nov 2010 15:51:04 +0000 (UTC),
cmpxchgq %rdx, (%rcx)
En 32 bits, ça fonctionne parfaitement.
En 32 bits, tu ne peux pas utiliser cmpxchg16b, donc je suppose que tu
utilises cmpxchg8b à la place (ce ne sont pas les mêmes instructions.)
J'ai trouvé et j'ai honte. Je ne sais pas pourquoi, mais j'ai
mélangé les deux arguments de ma fonction... En les remettant dans
l'ordre ça fonctionne tout de suite beaucoup mieux. On devrait
toujours laisser reposer ses problèmes une bonne nuit...
Mon problème est simple. Le 'cmpxchgq' ne semble pas faire ce qu'il
devrait (ou alors, je n'ai rien compris).
As-tu vérifié préalablement que cette instruction était implémentée dans
le processeur que tu utilises ? (bit CX16 du CPUID, bit 13 de ECX, cf.
http://www.sandpile.org/ia32/cpuid.htm)
Le Wed, 03 Nov 2010 09:50:56 +0100, Antoine Leca écrivait :
JKB écrivit :
Le Tue, 2 Nov 2010 15:51:04 +0000 (UTC),
cmpxchgq %rdx, (%rcx)
En 32 bits, ça fonctionne parfaitement.
En 32 bits, tu ne peux pas utiliser cmpxchg16b, donc je suppose que tu utilises cmpxchg8b à la place (ce ne sont pas les mêmes instructions.)
J'ai trouvé et j'ai honte. Je ne sais pas pourquoi, mais j'ai mélangé les deux arguments de ma fonction... En les remettant dans l'ordre ça fonctionne tout de suite beaucoup mieux. On devrait toujours laisser reposer ses problèmes une bonne nuit...
Mon problème est simple. Le 'cmpxchgq' ne semble pas faire ce qu'il devrait (ou alors, je n'ai rien compris).
As-tu vérifié préalablement que cette instruction était implémentée dans le processeur que tu utilises ? (bit CX16 du CPUID, bit 13 de ECX, cf. http://www.sandpile.org/ia32/cpuid.htm)
try_lock_amd64: // Setup the local variables pushq %rbp movq %rsp, %rbp movq 24(%rbp), %rcx /* %rcx =&m->holder */ movq 16(%rbp), %rdx /* %rdx = me */
// Test the lock : // if (%rcx) == $0, write %rdx into (%rcx) // if not, write (%rcx) into %rax. movq $0, %rax lock cmpxchgq %rdx, (%rcx)
// What is the result movq (%rcx), %rcx /* %rcx = m->holder */ cmpq 16(%rbp), %rcx /* m->holder == me */ sete %al andq $0xff, %rax
popq %rbp ret #endif
Bon, c'est pas bientôt fini, vos grossièretés ? allez donc faire ça ailleurs !
Michel__D
JKB a écrit :
Je viens de lire et de relire la doc (origine AMD) et si j'ai bien tout compris, CMPXCHGQ est censé comparer la valeur de %RAX à la valeur (%RCX). Si ces deux valeurs sont égales, il copie la valeur de %RDX dans %(RCX) et met le drapeau Z à 1.
Avec ma doc, CMPXCHG en 32 bit donne ceci :
CMPXCHG Operande1, Operande2
CMPXCHG compare *Operande1* à AL, AX, EAX et s'il y a égalité *Operande2* est copié dans *Operande1* sinon *Operande1* est copié dans AL, AX, EAX.
JKB a écrit :
Je viens de lire et de relire la doc (origine AMD) et si j'ai bien
tout compris, CMPXCHGQ est censé comparer la valeur de %RAX à la
valeur (%RCX). Si ces deux valeurs sont égales, il copie la valeur
de %RDX dans %(RCX) et met le drapeau Z à 1.
Avec ma doc, CMPXCHG en 32 bit donne ceci :
CMPXCHG Operande1, Operande2
CMPXCHG compare *Operande1* à AL, AX, EAX et
s'il y a égalité *Operande2* est copié dans *Operande1*
sinon *Operande1* est copié dans AL, AX, EAX.
Je viens de lire et de relire la doc (origine AMD) et si j'ai bien tout compris, CMPXCHGQ est censé comparer la valeur de %RAX à la valeur (%RCX). Si ces deux valeurs sont égales, il copie la valeur de %RDX dans %(RCX) et met le drapeau Z à 1.
Avec ma doc, CMPXCHG en 32 bit donne ceci :
CMPXCHG Operande1, Operande2
CMPXCHG compare *Operande1* à AL, AX, EAX et s'il y a égalité *Operande2* est copié dans *Operande1* sinon *Operande1* est copié dans AL, AX, EAX.
JKB
Le Wed, 03 Nov 2010 19:05:42 +0100, Michel__D écrivait :
JKB a écrit :
Je viens de lire et de relire la doc (origine AMD) et si j'ai bien tout compris, CMPXCHGQ est censé comparer la valeur de %RAX à la valeur (%RCX). Si ces deux valeurs sont égales, il copie la valeur de %RDX dans %(RCX) et met le drapeau Z à 1.
Avec ma doc, CMPXCHG en 32 bit donne ceci :
CMPXCHG Operande1, Operande2
CMPXCHG compare *Operande1* à AL, AX, EAX et s'il y a égalité *Operande2* est copié dans *Operande1* sinon *Operande1* est copié dans AL, AX, EAX.
Certes, mais je suis en _64_ bits et en notation AT&T et non Intel. Mon esprit est formaté AT&T et Motorola et j'ai toujours eu un peu de mal avec la notation Intel.
JKB
-- Si votre demande me parvient sur carte perforée, je titiouaillerai très volontiers une réponse... => http://grincheux.de-charybde-en-scylla.fr
Le Wed, 03 Nov 2010 19:05:42 +0100,
Michel__D <Michel.NOSPAM@orange-ft.com.invalid> écrivait :
JKB a écrit :
Je viens de lire et de relire la doc (origine AMD) et si j'ai bien
tout compris, CMPXCHGQ est censé comparer la valeur de %RAX à la
valeur (%RCX). Si ces deux valeurs sont égales, il copie la valeur
de %RDX dans %(RCX) et met le drapeau Z à 1.
Avec ma doc, CMPXCHG en 32 bit donne ceci :
CMPXCHG Operande1, Operande2
CMPXCHG compare *Operande1* à AL, AX, EAX et
s'il y a égalité *Operande2* est copié dans *Operande1*
sinon *Operande1* est copié dans AL, AX, EAX.
Certes, mais je suis en _64_ bits et en notation AT&T et non Intel.
Mon esprit est formaté AT&T et Motorola et j'ai toujours eu un peu
de mal avec la notation Intel.
JKB
--
Si votre demande me parvient sur carte perforée, je titiouaillerai très
volontiers une réponse...
=> http://grincheux.de-charybde-en-scylla.fr
Le Wed, 03 Nov 2010 19:05:42 +0100, Michel__D écrivait :
JKB a écrit :
Je viens de lire et de relire la doc (origine AMD) et si j'ai bien tout compris, CMPXCHGQ est censé comparer la valeur de %RAX à la valeur (%RCX). Si ces deux valeurs sont égales, il copie la valeur de %RDX dans %(RCX) et met le drapeau Z à 1.
Avec ma doc, CMPXCHG en 32 bit donne ceci :
CMPXCHG Operande1, Operande2
CMPXCHG compare *Operande1* à AL, AX, EAX et s'il y a égalité *Operande2* est copié dans *Operande1* sinon *Operande1* est copié dans AL, AX, EAX.
Certes, mais je suis en _64_ bits et en notation AT&T et non Intel. Mon esprit est formaté AT&T et Motorola et j'ai toujours eu un peu de mal avec la notation Intel.
JKB
-- Si votre demande me parvient sur carte perforée, je titiouaillerai très volontiers une réponse... => http://grincheux.de-charybde-en-scylla.fr
jj
Le 02/11/2010 21:13, Jean-Christophe a écrit :
On Nov 2, 5:48 pm, JKB
Gnî !
Bon, je me lance :
1. As-tu essayé de changer cmpxchgq par une suite de codes équivalents pour comparer le résultat ? Un truc de ce genre ( si j'ai bien tout suivi ) cmp eax,edx bne skip mov edx,ecx skip ...
2. Il me semble que cmpxchgq compare le RESTE d'un modulo 8, 16 ou 32 selon le cas. Sachant que ton code tourne en 32 bits mais pas en 64, y a t'il une chance que ce soit du à ce remainder ?
"CMPXCHG r/m8, r8 Compare AL with r/m8. If equal, ZF is set and r8 is loaded into r/m8. Else, clear ZF and load r/m8 into AL." "CMPXCHG r/m16, r16 Compare AX with r/m16. If equal, ZF is set and r16 is loaded into r/m16. Else, clear ZF and load r/m16 into AL" "CMPXCHG r/m32, r32 Compare EAX with r/m32. If equal, ZF is set and r32 is loaded into r/m32. Else, clear ZF and load r/m32 into AL"
HTH ...
Le Tue, 2 Nov 2010 15:51:04 +0000 (UTC), JKB écrivait :
Bonjour à tous,
Attention, Xpost et Fu2. Le Xpost se fait sur des groupes où je suis totalement hors charte mais où risquent de se trouver des personnes pouvant m'aider à trouver une solution. Merci de me pardonner cette pollution.
Quelques précisions : - j'utilise qemu pour tester (émulation d'un processeur core2 mono coeur). - la machine hôte est une machine avec un core2duo et un système Linux/debian. - la fonctio en question fait partie de la root task d'un OS tournant au-dessus d'un micronoyau L4 (64 bits). - l'assembleur utilisé est GNU as. J'ai naturellement vérifié le code objet en le désassemblant.
Pardonnez-moi cette question à la limite de la charte, mais j'ai un petit problème avec un bout d'assembleur amd64 trivial (en notation AT&T) :
Cette fonction fait partie d'un bout d'OS que je passe en 64 bits. En 32 bits, ça fonctionne parfaitement. Ce bout de code est appelé depuis une fonction en C (équivalente à mutex_trylock() pour des mutexes récursifs). Mon problème est simple. Le 'cmpxchgq' ne semble pas faire ce qu'il devrait (ou alors, je n'ai rien compris). Je viens de lire et de relire la doc (origine AMD) et si j'ai bien tout compris, CMPXCHGQ est censé comparer la valeur de %RAX à la valeur (%RCX). Si ces deux valeurs sont égales, il copie la valeur de %RDX dans %(RCX) et met le drapeau Z à 1. Dans mon cas, le programme saute à ma routine de débug qui m'affiche la pile. J'en déduis donc que ce drapeau est à 1 et que CMPXCHGQ aurait dû copier %RDX dans (%RCX). Je vois bien que %RDX contient la bonne valeur, mais (%RCX) reste nul comme le prouve la sortie :
Je suppose que j'ai raté quelque chose, mais je ne vois pas quoi. Merci de toute lumière, JKB
-- Si votre demande me parvient sur carte perforée, je titiouaillerai très volontiers une réponse... =>http://grincheux.de-charybde-en-scylla.fr
Moais, l'emploi d'instruction miraculeuses qui font tout en un opcode sont souvent très difficiles à manipuler...
On passe des heures à mettre au point parceque l'on ne connait pas bien tous les détails et finalement on passe 80% de son énergie sur 2 octets !
le RISC est moins risqué !!
JJ
Le 02/11/2010 21:13, Jean-Christophe a écrit :
On Nov 2, 5:48 pm, JKB
Gnî !
Bon, je me lance :
1. As-tu essayé de changer cmpxchgq par une suite
de codes équivalents pour comparer le résultat ?
Un truc de ce genre ( si j'ai bien tout suivi )
cmp eax,edx
bne skip
mov edx,ecx
skip ...
2. Il me semble que cmpxchgq compare le
RESTE d'un modulo 8, 16 ou 32 selon le cas.
Sachant que ton code tourne en 32 bits mais pas en 64,
y a t'il une chance que ce soit du à ce remainder ?
"CMPXCHG r/m8, r8 Compare AL with r/m8. If equal, ZF is set and r8
is loaded into r/m8. Else, clear ZF and load r/m8 into AL."
"CMPXCHG r/m16, r16 Compare AX with r/m16. If equal, ZF is set and
r16 is loaded into r/m16. Else, clear ZF and load r/m16 into AL"
"CMPXCHG r/m32, r32 Compare EAX with r/m32. If equal, ZF is set and
r32 is loaded into r/m32. Else, clear ZF and load r/m32 into AL"
HTH ...
Le Tue, 2 Nov 2010 15:51:04 +0000 (UTC),
JKB<j...@koenigsberg.invalid> écrivait :
Bonjour à tous,
Attention, Xpost et Fu2. Le Xpost se fait sur des groupes où je suis
totalement hors charte mais où risquent de se trouver des personnes
pouvant m'aider à trouver une solution. Merci de me pardonner cette
pollution.
Quelques précisions :
- j'utilise qemu pour tester (émulation d'un processeur core2 mono
coeur).
- la machine hôte est une machine avec un core2duo et un système
Linux/debian.
- la fonctio en question fait partie de la root task d'un OS
tournant au-dessus d'un micronoyau L4 (64 bits).
- l'assembleur utilisé est GNU as. J'ai naturellement vérifié le
code objet en le désassemblant.
Pardonnez-moi cette question à la limite de la charte, mais j'ai un
petit problème avec un bout d'assembleur amd64 trivial (en notation
AT&T) :
Cette fonction fait partie d'un bout d'OS que je passe en 64 bits.
En 32 bits, ça fonctionne parfaitement. Ce bout de code est appelé
depuis une fonction en C (équivalente à mutex_trylock() pour des
mutexes récursifs).
Mon problème est simple. Le 'cmpxchgq' ne semble pas faire ce qu'il
devrait (ou alors, je n'ai rien compris).
Je viens de lire et de relire la doc (origine AMD) et si j'ai bien
tout compris, CMPXCHGQ est censé comparer la valeur de %RAX à la
valeur (%RCX). Si ces deux valeurs sont égales, il copie la valeur
de %RDX dans %(RCX) et met le drapeau Z à 1.
Dans mon cas, le programme saute à ma routine de débug qui m'affiche
la pile. J'en déduis donc que ce drapeau est à 1 et que CMPXCHGQ
aurait dû copier %RDX dans (%RCX). Je vois bien que %RDX contient la
bonne valeur, mais (%RCX) reste nul comme le prouve la sortie :
1. As-tu essayé de changer cmpxchgq par une suite de codes équivalents pour comparer le résultat ? Un truc de ce genre ( si j'ai bien tout suivi ) cmp eax,edx bne skip mov edx,ecx skip ...
2. Il me semble que cmpxchgq compare le RESTE d'un modulo 8, 16 ou 32 selon le cas. Sachant que ton code tourne en 32 bits mais pas en 64, y a t'il une chance que ce soit du à ce remainder ?
"CMPXCHG r/m8, r8 Compare AL with r/m8. If equal, ZF is set and r8 is loaded into r/m8. Else, clear ZF and load r/m8 into AL." "CMPXCHG r/m16, r16 Compare AX with r/m16. If equal, ZF is set and r16 is loaded into r/m16. Else, clear ZF and load r/m16 into AL" "CMPXCHG r/m32, r32 Compare EAX with r/m32. If equal, ZF is set and r32 is loaded into r/m32. Else, clear ZF and load r/m32 into AL"
HTH ...
Le Tue, 2 Nov 2010 15:51:04 +0000 (UTC), JKB écrivait :
Bonjour à tous,
Attention, Xpost et Fu2. Le Xpost se fait sur des groupes où je suis totalement hors charte mais où risquent de se trouver des personnes pouvant m'aider à trouver une solution. Merci de me pardonner cette pollution.
Quelques précisions : - j'utilise qemu pour tester (émulation d'un processeur core2 mono coeur). - la machine hôte est une machine avec un core2duo et un système Linux/debian. - la fonctio en question fait partie de la root task d'un OS tournant au-dessus d'un micronoyau L4 (64 bits). - l'assembleur utilisé est GNU as. J'ai naturellement vérifié le code objet en le désassemblant.
Pardonnez-moi cette question à la limite de la charte, mais j'ai un petit problème avec un bout d'assembleur amd64 trivial (en notation AT&T) :
Cette fonction fait partie d'un bout d'OS que je passe en 64 bits. En 32 bits, ça fonctionne parfaitement. Ce bout de code est appelé depuis une fonction en C (équivalente à mutex_trylock() pour des mutexes récursifs). Mon problème est simple. Le 'cmpxchgq' ne semble pas faire ce qu'il devrait (ou alors, je n'ai rien compris). Je viens de lire et de relire la doc (origine AMD) et si j'ai bien tout compris, CMPXCHGQ est censé comparer la valeur de %RAX à la valeur (%RCX). Si ces deux valeurs sont égales, il copie la valeur de %RDX dans %(RCX) et met le drapeau Z à 1. Dans mon cas, le programme saute à ma routine de débug qui m'affiche la pile. J'en déduis donc que ce drapeau est à 1 et que CMPXCHGQ aurait dû copier %RDX dans (%RCX). Je vois bien que %RDX contient la bonne valeur, mais (%RCX) reste nul comme le prouve la sortie :
Moais, l'emploi d'instruction miraculeuses qui font tout en un opcode sont souvent très difficiles à manipuler...
Je suis d'accord. Mais explique moi comment tu fais la même chose (c'est-à-dire une opération _atomique_ pour un mutex) autrement.
On passe des heures à mettre au point parceque l'on ne connait pas bien tous les détails et finalement on passe 80% de son énergie sur 2 octets !
le RISC est moins risqué !!
Pour ce même problème ? Non. Et personnellement, je cause sparc v8 et v9 dans le texte et le sparc v9 peut être assez rapidement rigolo.
JKB
-- Si votre demande me parvient sur carte perforée, je titiouaillerai très volontiers une réponse... => http://grincheux.de-charybde-en-scylla.fr
Pierre Maurette
(supersedes )
JKB, le 11/2/2010 a écrit :
[...]
Il y a un truc bizarre lorsque je remplace 0 par une valeur non nulle. Je vais laisser tomber pour ce soir...
C'est également ce que j'ai fait hier soir. Mais je suis tombé du lit ce matin. J'ai fait quelques tests, et cmpxchg fonctionne comme vous et moi l'attendions:
Ubuntu Maverick64 VirtualBox, gcc 4.4.5, as 2.20.51 On peut entrer des valeurs > 0xFFFF, mais l'affichage est tronqué. [supersedes: j'ai relu et mis au propre ce petit bout avant de l'archiver, j'ai corrigé quelques erreurs et maladresses, même s'il en reste encore très certainement] <testcmpxchg.c> /* * cmpxchg rdx, (var) * compare (var) et rax * si égal (ZF == 1): rdx -> (var) * sinon (ZF == 0): (var) -> rax */
Il y a un truc bizarre lorsque je remplace 0 par une valeur non
nulle. Je vais laisser tomber pour ce soir...
C'est également ce que j'ai fait hier soir. Mais je suis tombé du lit
ce matin. J'ai fait quelques tests, et cmpxchg fonctionne comme vous et
moi l'attendions:
Ubuntu Maverick64 VirtualBox, gcc 4.4.5, as 2.20.51
On peut entrer des valeurs > 0xFFFF, mais l'affichage est tronqué.
[supersedes: j'ai relu et mis au propre ce petit bout avant de
l'archiver, j'ai corrigé quelques erreurs et maladresses, même s'il en
reste encore très certainement]
<testcmpxchg.c>
/*
* cmpxchg rdx, (var)
* compare (var) et rax
* si égal (ZF == 1): rdx -> (var)
* sinon (ZF == 0): (var) -> rax
*/
Il y a un truc bizarre lorsque je remplace 0 par une valeur non nulle. Je vais laisser tomber pour ce soir...
C'est également ce que j'ai fait hier soir. Mais je suis tombé du lit ce matin. J'ai fait quelques tests, et cmpxchg fonctionne comme vous et moi l'attendions:
Ubuntu Maverick64 VirtualBox, gcc 4.4.5, as 2.20.51 On peut entrer des valeurs > 0xFFFF, mais l'affichage est tronqué. [supersedes: j'ai relu et mis au propre ce petit bout avant de l'archiver, j'ai corrigé quelques erreurs et maladresses, même s'il en reste encore très certainement] <testcmpxchg.c> /* * cmpxchg rdx, (var) * compare (var) et rax * si égal (ZF == 1): rdx -> (var) * sinon (ZF == 0): (var) -> rax */