Skip to content
Extraits de code Groupes Projets
Valider 05752db8 rédigé par CharlyBVO's avatar CharlyBVO
Parcourir les fichiers

Modification de la section sur les threads pour simplifier/retirer les notions d'assembleur

parent f7273f0b
Aucune branche associée trouvée
Aucune étiquette associée trouvée
Aucune requête de fusion associée trouvée
...@@ -205,23 +205,23 @@ De nombreux programmes découpés en threads fonctionnent avec un ensemble de pr ...@@ -205,23 +205,23 @@ De nombreux programmes découpés en threads fonctionnent avec un ensemble de pr
Compléments sur les threads POSIX Compléments sur les threads POSIX
================================= =================================
.. todo: look if it is useful
Il existe différentes implémentations des threads POSIX. Les mécanismes de coordination utilisables varient parfois d'une implémentation à l'autre. Dans les sections précédentes, nous nous sommes focalisés sur les fonctions principales qui sont en général bien implémentées. Une discussion plus détaillée des fonctions implémentées sous Linux peut se trouver dans [Kerrisk2010]_. [Gove2011]_ présente de façon détaillée les mécanismes de coordination utilisables sous Linux, Windows et Oracle Solaris. [StevensRago2008]_ comprend également une description des threads POSIX mais présente des exemples sur des versions plus anciennes de Linux, FreeBSD, Solaris et MacOS. Il existe différentes implémentations des threads POSIX. Les mécanismes de coordination utilisables varient parfois d'une implémentation à l'autre. Dans les sections précédentes, nous nous sommes focalisés sur les fonctions principales qui sont en général bien implémentées. Une discussion plus détaillée des fonctions implémentées sous Linux peut se trouver dans [Kerrisk2010]_. [Gove2011]_ présente de façon détaillée les mécanismes de coordination utilisables sous Linux, Windows et Oracle Solaris. [StevensRago2008]_ comprend également une description des threads POSIX mais présente des exemples sur des versions plus anciennes de Linux, FreeBSD, Solaris et MacOS.
Il reste cependant quelques concepts qu'il est utile de connaître lorsque l'on développe des programmes découpés en threads en langage C. Il reste cependant quelques concepts qu'il est utile de connaître lorsque l'on développe des programmes découpés en threads en langage C.
Variables ``volatile``
----------------------
Normalement, dans un programme C, lorsqu'une variable est définie, ses accès sont contrôlés entièrement par le compilateur. Si la variable est utilisée dans plusieurs calculs successifs, il peut être utile d'un point de vue des performances de stocker la valeur de cette variable dans un registre pendant au moins le temps correspondant à l'exécution de quelques instructions [#fregister]_. Cette optimisation peut éventuellement poser des difficultés dans certains programmes utilisant des threads puisqu'une variable peut être potentiellement modifiée ou lue par plusieurs threads simultanément. .. Variables ``volatile``
.. ----------------------
Les premiers compilateurs C avaient pris en compte un problème similaire. Lorsqu'un programme ou un système d'exploitation interagit avec des dispositifs d'entrée-sortie, cela se fait parfois en permettant au dispositif d'écrire directement en mémoire à une adresse connue par le système d'exploitation. La valeur présente à cette adresse peut donc être modifiée par le dispositif d'entrée-sortie sans que le programme ne soit responsable de cette modification. Face à ce problème, les inventeurs du langage C ont introduit le qualificatif ``volatile``. Lorsqu'une variable est ``volatile``, cela indique au compilateur qu'il doit recharger la variable de la mémoire chaque fois qu'elle est utilisée. .. Normalement, dans un programme C, lorsqu'une variable est définie, ses accès sont contrôlés entièrement par le compilateur. Si la variable est utilisée dans plusieurs calculs successifs, il peut être utile d'un point de vue des performances de stocker la valeur de cette variable dans un registre pendant au moins le temps correspondant à l'exécution de quelques instructions [#fregister]_. Cette optimisation peut éventuellement poser des difficultés dans certains programmes utilisant des threads puisqu'une variable peut être potentiellement modifiée ou lue par plusieurs threads simultanément.
Pour bien comprendre l'impact de ce qualificatif, il est intéressant d'analyser le code assembleur généré par un compilateur C dans l'exemple suivant. .. Les premiers compilateurs C avaient pris en compte un problème similaire. Lorsqu'un programme ou un système d'exploitation interagit avec des dispositifs d'entrée-sortie, cela se fait parfois en permettant au dispositif d'écrire directement en mémoire à une adresse connue par le système d'exploitation. La valeur présente à cette adresse peut donc être modifiée par le dispositif d'entrée-sortie sans que le programme ne soit responsable de cette modification. Face à ce problème, les inventeurs du langage C ont introduit le qualificatif ``volatile``. Lorsqu'une variable est ``volatile``, cela indique au compilateur qu'il doit recharger la variable de la mémoire chaque fois qu'elle est utilisée.
.. code-block:: c .. Pour bien comprendre l'impact de ce qualificatif, il est intéressant d'analyser le code assembleur généré par un compilateur C dans l'exemple suivant.
... code-block:: c
int x=1; int x=1;
int v[2]; int v[2];
...@@ -231,29 +231,29 @@ Pour bien comprendre l'impact de ce qualificatif, il est intéressant d'analyser ...@@ -231,29 +231,29 @@ Pour bien comprendre l'impact de ce qualificatif, il est intéressant d'analyser
v[1]=x; v[1]=x;
} }
Dans ce cas, la fonction ``f`` est traduite en la séquence d'instructions suivante : .. Dans ce cas, la fonction ``f`` est traduite en la séquence d'instructions suivante :
.. code-block:: nasm ... code-block:: nasm
f: f:
movl x, %eax ..
movl x, %eax
movl %eax, v movl %eax, v
movl %eax, v+4 movl %eax, v+4
ret ret
.. Si par contre la variable ``x`` est déclarée comme étant ``volatile``, le compilateur ajoute une instruction ``movl x, %eax`` qui permet de recharger la valeur de ``x`` dans un registre avant la seconde utilisation.
Si par contre la variable ``x`` est déclarée comme étant ``volatile``, le compilateur ajoute une instruction ``movl x, %eax`` qui permet de recharger la valeur de ``x`` dans un registre avant la seconde utilisation. ... code-block:: nasm
.. code-block:: nasm
f: f:
..
movl x, %eax movl x, %eax
movl %eax, v movl %eax, v
movl x, %eax movl x, %eax
movl %eax, v+4 movl %eax, v+4
ret ret
Le qualificatif ``volatile`` force le compilateur à recharger la variable depuis la mémoire avant chaque utilisation. Ce qualificatif est utile lorsque le contenu stocké à une adresse mémoire peut être modifié par une autre source que le programme lui-même. C'est le cas dans les threads, mais marquer les variables partagées par des threads comme ``volatile`` ne suffit pas. Si ces variables sont modifiées par certains threads, il est nécessaire d'utiliser des :term:`mutex` ou d'autres techniques de coordination pour réguler l'accès en ces variables partagées. En pratique, la documentation du programme devra spécifier quelles variables sont partagées entre les threads et la technique de coordination éventuelle qui est utilisée pour en réguler les accès. L'utilisation du qualificatif ``volatile`` permet de forcer le compilateur à recharger le contenu de la variable depuis la mémoire avant toute utilisation. C'est une règle de bonne pratique qu'il est utile de suivre. Il faut cependant noter que dans l'exemple ci-dessus, l'utilisation du qualificatif ``volatile`` augmente le nombre d'accès à la mémoire et peut donc dans certains cas réduire les performances. .. Le qualificatif ``volatile`` force le compilateur à recharger la variable depuis la mémoire avant chaque utilisation. Ce qualificatif est utile lorsque le contenu stocké à une adresse mémoire peut être modifié par une autre source que le programme lui-même. C'est le cas dans les threads, mais marquer les variables partagées par des threads comme ``volatile`` ne suffit pas. Si ces variables sont modifiées par certains threads, il est nécessaire d'utiliser des :term:`mutex` ou d'autres techniques de coordination pour réguler l'accès en ces variables partagées. En pratique, la documentation du programme devra spécifier quelles variables sont partagées entre les threads et la technique de coordination éventuelle qui est utilisée pour en réguler les accès. L'utilisation du qualificatif ``volatile`` permet de forcer le compilateur à recharger le contenu de la variable depuis la mémoire avant toute utilisation. C'est une règle de bonne pratique qu'il est utile de suivre. Il faut cependant noter que dans l'exemple ci-dessus, l'utilisation du qualificatif ``volatile`` augmente le nombre d'accès à la mémoire et peut donc dans certains cas réduire les performances.
Variables spécifiques à un thread Variables spécifiques à un thread
--------------------------------- ---------------------------------
......
...@@ -66,7 +66,9 @@ Cette progression continue des performances en MIPS a été possible grâce à l ...@@ -66,7 +66,9 @@ Cette progression continue des performances en MIPS a été possible grâce à l
La notion de thread d'exécution est très importante dans un système informatique. Elle permet non seulement de comprendre comme un ordinateur équipé d'un seul microprocesseur peut exécuter plusieurs programmes simultanément, mais aussi comment des programmes peuvent profiter des nouveaux processeurs capables d'exécuter plusieurs threads simultanément. Pour comprendre cette notion, il est intéressant de revenir à nouveau sur l'exécution d'une fonction en langage assembleur. Considérons la fonction ``f`` : La notion de thread d'exécution est très importante dans un système informatique. Elle permet non seulement de comprendre comme un ordinateur équipé d'un seul microprocesseur peut exécuter plusieurs programmes simultanément, mais aussi comment des programmes peuvent profiter des nouveaux processeurs capables d'exécuter plusieurs threads simultanément.
.. Pour comprendre cette notion, il est intéressant de revenir à nouveau sur l'exécution d'une fonction en langage assembleur.
Considérons la fonction ``f`` :
.. code-block:: c .. code-block:: c
...@@ -80,12 +82,12 @@ La notion de thread d'exécution est très importante dans un système informati ...@@ -80,12 +82,12 @@ La notion de thread d'exécution est très importante dans un système informati
return m; return m;
} }
En assembleur, cette fonction se traduit en : .. En assembleur, cette fonction se traduit en :
..
.. code-block:: nasm .. code-block:: nasm
f:
f:
subl $16, %esp subl $16, %esp
movl 24(%esp), %eax movl 24(%esp), %eax
movl 20(%esp), %ecx movl 20(%esp), %ecx
...@@ -93,11 +95,11 @@ En assembleur, cette fonction se traduit en : ...@@ -93,11 +95,11 @@ En assembleur, cette fonction se traduit en :
movl %eax, 8(%esp) movl %eax, 8(%esp)
movl $0, 4(%esp) movl $0, 4(%esp)
movl $0, (%esp) movl $0, (%esp)
.LBB0_1: .LBB0_1:
movl (%esp), %eax movl (%esp), %eax
cmpl 8(%esp), %eax cmpl 8(%esp), %eax
jge .LBB0_3 jge .LBB0_3
..
movl 12(%esp), %eax movl 12(%esp), %eax
movl 4(%esp), %ecx movl 4(%esp), %ecx
addl %eax, %ecx addl %eax, %ecx
...@@ -106,23 +108,26 @@ En assembleur, cette fonction se traduit en : ...@@ -106,23 +108,26 @@ En assembleur, cette fonction se traduit en :
addl $1, %eax addl $1, %eax
movl %eax, (%esp) movl %eax, (%esp)
jmp .LBB0_1 jmp .LBB0_1
.LBB0_3: .LBB0_3:
movl 4(%esp), %eax movl 4(%esp), %eax
addl $16, %esp addl $16, %esp
ret ret
Pour qu'un processeur puisse exécuter cette séquence d'instructions, il faut non seulement qu'il implémente chacune de ces instructions, mais également qu'il puisse accéder : Pour qu'un processeur puisse exécuter cette séquence d'instructions, il faut qu'il puisse accéder :
.. il faut non seulement qu'il implémente chacune de ces instructions, mais également qu'il puisse accéder :
- à la mémoire contenant les instructions à exécuter - à la mémoire contenant les instructions à exécuter
- à la mémoire contenant les données manipulées par cette séquence d'instruction. Pour rappel, cette mémoire est divisée en plusieurs parties : - à la mémoire contenant les données manipulées par cette séquence d'instruction. Pour rappel, cette mémoire est divisée en plusieurs parties :
- la zone contenant les variables globales - la zone contenant les variables globales
- le tas - le tas
- la pile - la pile
- aux registres et plus particulièrement, il doit accéder :
- aux registres, des zone de mémoire très rapide (mais peu nombreuses par soucis technique) se trouvant sur le processeur qui permettent de stocker entre autre : l'addresse de l'instruction à exécuter, des résultats intermédaires obtenus durant l'exécution d'un instruction ou encore des informations sur la pile.
.. et plus particulièrement, il doit accéder :
..
- aux registres de données pour stocker les résultats de chacune des instructions - aux registres de données pour stocker les résultats de chacune des instructions
- au registre ``%esp`` directement ou indirectement via les instructions ``push`` et ``pop`` qui permettent de manipuler la pile - au registre ``%esp`` directement ou indirectement via les instructions ``push`` et ``pop`` qui permettent de manipuler la pile
- au registre ``%eip`` qui contient l'adresse de l'instruction en cours d'exécution - au registre ``%eip`` qui contient l'adresse de l'instruction en cours d'exécution
......
...@@ -51,7 +51,7 @@ Systèmes Multiprocesseurs ...@@ -51,7 +51,7 @@ Systèmes Multiprocesseurs
Theorie/Threads/threads Theorie/Threads/threads
Theorie/Threads/threads2 Theorie/Threads/threads2
Theorie/Threads/coordination Theorie/Threads/coordination
.. Theorie/Threads/processus .. Theorie/Threads/processus
Fichiers Fichiers
******** ********
...@@ -60,7 +60,7 @@ Fichiers ...@@ -60,7 +60,7 @@ Fichiers
:maxdepth: 2 :maxdepth: 2
Theorie/Fichiers/fichiers Theorie/Fichiers/fichiers
Theorie/Fichiers/fichiers-signaux .. Theorie/Fichiers/fichiers-signaux
****** ******
......
0% Chargement en cours ou .
You are about to add 0 people to the discussion. Proceed with caution.
Terminez d'abord l'édition de ce message.
Veuillez vous inscrire ou vous pour commenter