le volatile garantie que les données seront mise a nouveau en mémoire une fois qu'elles sont calculées.
Elle évite donc qu'elles reste dans des registres pour des optimisations.
Par exemple j'ai trois variables et 5 registres.
Je peux stocker toutes les variables dans les registres et faire toutes mes instructions dessus.
Si il y a un thread qui en a besoin au milieu (je libère un lock et je le reprend après) je n'ai aucune assurance que les variables qui sont des les registres sont bien pushé en mémoire.
Le volatile sert a ca.
D'ailleur le volatile nous protège tellement peu de ca qu'il y a un spinlock au début des lock ou unlock d'un mutex. Car le spinlock est fait lui sur une véritable instruction atomique (test and set).
exemple de code .
toto (){
int a;
lock();
++a;
a*=2;
unlock();
do_something();
lock();
a/=2;
unlock();
}
Sans le volatile, au premier unlock, on ne sait pas si a sera en mémoire (donc visible par les autres threads) ou alors encore dans les registres.
Si il est encore dans les registres, alors lors du second lock, on n'aura pas une bonne valeur de a car il a pu etre modifié pendant qu'on était dans do_something et qu'on aurait donc une valeur obsolète.
le volatile n'est permet pas de faire une fonction atomique.
Comme je sens déja l'attaque (pas forcément de lasher ou d'isnotgood, mais mieux vaut prevenir que guerir) du 'tu ne sais pas de quoi tu parle'
regardons donc ce que fait volatile :
int test1()
{
volatile int a;
++a;
a+=2;
return a;
}
int test2()
{
int a;
++a;
a+=2;
return a;
}
int main()
{
}
Un code relativement simple n'est il pas ?
Maintenant regardons l'asm qu'il nous génère pour ca : gcc -S test.c
test1:
pushl %ebp
movl %esp, %ebp
subl 16,ドル %esp
movl -4(%ebp), %eax ; on recupere a
addl 1,ドル %eax ; ++a
movl %eax, -4(%ebp) ; on le remet
movl -4(%ebp), %eax ; on le recupere a nouveau
addl 2,ドル %eax ; a+=2
movl %eax, -4(%ebp) ; on le remet
movl -4(%ebp), %eax ; return a
leave ; bye bye
ret
.size test1, .-test1
.globl test2
.type test2, @function
test2:
pushl %ebp
movl %esp, %ebp
subl 16,ドル %esp
addl 1,ドル -4(%ebp) ;++a
addl 2,ドル -4(%ebp) ;a+=2
movl -4(%ebp), %eax ;return a
leave
ret
.size test2, .-test2
je vois mal en quoi faire 3 instructions a la place d'une seule rend ces instructions 'atomiques'.
Ps désolé pour la liste en début de commentaire, je sais pas comment incoporer du code , mais pouvoir avoir des retour chariots 'normaux' dans le reste du commentaire.
[^] # Re: Multicoeur ?
Posté par briaeros007 . En réponse à la dépêche Intel libère TBB. Évalué à 4.
toto (){ int a; lock(); ++a; a*=2; unlock(); do_something(); lock(); a/=2; unlock(); }Sans le volatile, au premier unlock, on ne sait pas si a sera en mémoire (donc visible par les autres threads) ou alors encore dans les registres. Si il est encore dans les registres, alors lors du second lock, on n'aura pas une bonne valeur de a car il a pu etre modifié pendant qu'on était dans do_something et qu'on aurait donc une valeur obsolète. le volatile n'est permet pas de faire une fonction atomique. Comme je sens déja l'attaque (pas forcément de lasher ou d'isnotgood, mais mieux vaut prevenir que guerir) du 'tu ne sais pas de quoi tu parle' regardons donc ce que fait volatile :int test1() { volatile int a; ++a; a+=2; return a; } int test2() { int a; ++a; a+=2; return a; } int main() { }Un code relativement simple n'est il pas ? Maintenant regardons l'asm qu'il nous génère pour ca : gcc -S test.c je vois mal en quoi faire 3 instructions a la place d'une seule rend ces instructions 'atomiques'. Ps désolé pour la liste en début de commentaire, je sais pas comment incoporer du code , mais pouvoir avoir des retour chariots 'normaux' dans le reste du commentaire.