Вы находитесь на странице: 1из 20

Threads

• Qu’est ce qu’un thread?

• Usage des threads

• Implémentation des threads


– Au niveau utilisateur (Java)
– Au niveau noyau (Linux)
– Hybride (Solaris et Windows)

• Threads POSIX
– Création d’un thread
– Attente de la fin d’un thread
– Terminaison d’un thread
– Nettoyage à la terminaison

Systèmes d’exploitation Génie Informatique Chapitre 3. 1


École Polytechnique de Montréal

Qu’est ce qu’un thread ?


• Le modèle processus décrit précédemment est un programme qui s’exécute selon un chemin
unique (compteur ordinal). On dit qu’il a un flot de contrôle unique (un seul thread).

• De nombreux systèmes d’exploitation modernes offrent la possibilité d’associer à un même


processus plusieurs chemins d’exécution (multithreading, multiflot d’exécution).

Processus et threads

Systèmes d’exploitation Génie Informatique Chapitre 3. 2


École Polytechnique de Montréal

1
Qu’est ce qu’un thread? (2)
• Un thread est une unité d’exécution rattachée à un processus, chargée
d’exécuter une partie du processus.

• Un processus est vu comme étant un ensemble de ressources (espace


d’adressage, fichiers, périphériques…) que ses threads (flots de contrôle ou
processus légers) partagent.

• Lorsqu’un processus est créé, un seul flot d’exécution (thread) est associé
au processus. Ce thread peut en créer d’autres.

• Chaque thread a :
– un identificateur unique
– une pile d'exécution
– des registres (un compteur ordinal)
– un état…

Systèmes d’exploitation Génie Informatique Chapitre 3. 3


École Polytechnique de Montréal

Qu’est ce qu’un thread? (3)

• Le multithreading permet l’exécution simultanée ou en pseudo-parallèle de


plusieurs parties d’un même processus.

Systèmes d’exploitation Génie Informatique Chapitre 3. 4


École Polytechnique de Montréal

2
Qu’est ce qu’un thread? (4)
Avantages des threads / processus

• Réactivité (le processus peut continuer à s’exécuter même si certaines de


ses parties sont bloquées),

• Partage de ressources (facilite la coopération, améliore la performance),

• Économie d’espace mémoire et de temps. Il faut moins de temps pour :

– créer, terminer un thread (sous Solaris, la création d’un processus est


30 fois plus lente que celle d’un thread),

– “switcher” entre deux threads d’un même processus.

Systèmes d’exploitation Génie Informatique Chapitre 3. 5


École Polytechnique de Montréal

Usage des threads (1)


Word processor

• Un thread pour interagir avec l’utilisateur,


• Un thread pour reformater en arrière plan,
• Un thread pour sauvegarder périodiquement le document

Systèmes d’exploitation Génie Informatique Chapitre 3. 6


École Polytechnique de Montréal

3
Usage des threads (2)
Serveur Web

• Le Dispatcher thread se charge de


réceptionner les requêtes.

• Il choisit, pour chaque requête


reçue, un thread libre (en attente
d’une requête). Ce thread va se
charger d’interpréter la requête.

Systèmes d’exploitation Génie Informatique Chapitre 3. 7


École Polytechnique de Montréal

Implémentation des threads

• L’implémentation du multiflot (multithreading) varie considérablement


d’une plateforme à une autre (threads Linux, threads de Win32, threads
de Solaris et threads de POSIX).

• Le multiflot peut être implémenté :

– au niveau utilisateur (threads utilisateur) -> modèle plusieurs-à- un,

– au niveau noyau (threads noyau) -> modèle un-à-un, ou

– aux deux niveaux (threads hybrides) -> modèle plusieurs-à-plusieurs.

Systèmes d’exploitation Génie Informatique Chapitre 3. 8


École Polytechnique de Montréal

4
Threads utilisateur
(java threads, anciennes versions d’UNIX)

• Les threads utilisateur sont implantés


dans une bibliothèque (niveau
utilisateur) qui fournit un support pour
les gérer.

• Ils ne sont pas gérés par le noyau.

• Le noyau gère les processus (table


des processus) et ne se préoccupe
pas de l’existence des threads
(modèle plusieurs-à-un).

• Lorsque le noyau alloue le


processeur à un processus, le temps
d’allocation du processeur est réparti
entre les différents threads du
processus (cette répartition n’est pas
gérée par le noyau).

Systèmes d’exploitation Génie Informatique Chapitre 3. 9


École Polytechnique de Montréal

Threads utilisateur (2)

• Les threads utilisateur sont généralement créés, et gérés rapidement.

• Ils facilitent la portabilité (comparativement aux autres implémentations)

• Inconvénients :

– À tout instant, au plus un thread par processus est en cours d’exécution.


Cette implémentation n’est pas intéressante pour des systèmes
multiprocesseurs.

– Si un thread d’un processus se bloque, tout le processus est bloqué. Pour


pallier cet inconvénient, certaines librairies transforment les appels système
bloquants en appels système non bloquants.

Systèmes d’exploitation Génie Informatique Chapitre 3. 10


École Polytechnique de Montréal

5
Threads utilisateur (3)
Threads Java

• Les threads Java peuvent être créés en :

– en dérivant la class Thread ou


– implémentant l’interface Runnable

• Plusieurs API pour contrôler les threads:

suspend() , sleep() , resume() , stop() , etc.

• Les threads Java sont gérés par la machine virtuelle Java (JVM).

Systèmes d’exploitation Génie Informatique Chapitre 3. 11


École Polytechnique de Montréal

Threads utilisateur (4)


Threads Java
import java. awt.*;
class Travailleur extends Thread
{ public void run()
{ System. out. println(" Je suis le thread Travailleur");
try { Thread. sleep( 1000); }
catch (InterruptedException e){}
System. out. println(" Je suis le thread Travailleur");
}
}

public class Principal


{ public static void main( String args[])
{ Travailleur t = new Travailleur();
t. start();
System. out. println(" Je suis le thread principal");
try { Thread. sleep( 1000); }
catch (InterruptedException e){}
System. out. println(" Je suis le thread principal");
}
}

Systèmes d’exploitation Génie Informatique Chapitre 3. 12


École Polytechnique de Montréal

6
Threads noyau
• Les threads noyau sont directement
supportés par le système d’exploitation.

• Le système d’exploitation se charge de leur


gestion. Un temps CPU est alloué à chaque
thread. (modèle un-à-un)

• Si un thread d’un processus est bloqué, un


autre thread du processus peut être élu par
le noyau

• Cette implémentation est plus intéressante


pour les systèmes multiprocesseurs.

• Un processus peux ajuster les niveaux de


priorité de ses threads. Par exemple, un
processus peut améliorer son interactivité en
assignant :
– une forte priorité à un thread qui traite les
requêtes des utilisateurs et
– une plus faible priorité aux autres.

Systèmes d’exploitation Génie Informatique Chapitre 3. 13


École Polytechnique de Montréal

Threads noyau (2)

Inconvénients :

• Performance (gestion plus coûteuse)

• Les programmes utilisant les threads


noyau sont moins portables que
ceux qui utilisent des threads
utilisateur.

Systèmes d’exploitation Génie Informatique Chapitre 3. 14


École Polytechnique de Montréal

7
Threads noyau (3)
Linux
• Linux ne fait pas de distinction entre les processus et les threads qui sont
communément appelés tâches.

• Il implémente le modèle multiflot un-à-un.

• La création de tâches est réalisée au moyen de l’appel système clone().

• Clone() permet de spécifier les ressources à partager (espace d’adressage, fichiers,


signaux..) entre les tâches créatrice et créée.

Systèmes d’exploitation Génie Informatique Chapitre 3. 15


École Polytechnique de Montréal

Threads hybrides
(Solaris 2)

• Un ensemble de threads d’un même processus peuvent être associés à un


thread noyau (pooling thread).

Inconvénient : mise en œuvre plus complexe

Systèmes d’exploitation Génie Informatique Chapitre 3. 16


École Polytechnique de Montréal

8
Threads hybrides (2)
Solaris 2
• Solaris 2 implémente le multiflot selon le modèle plusieurs-à-plusieurs.

• Il distingue 3 niveaux de threads :


– threads utilisateur,
– processus poids léger (LWP) et
– threads noyau.

• Il fournit une bibliothèque contenant des API pour la création et la gestion de threads
utilisateur et des LWP. La bibliothèque se charge de :
– assigner un ou plusieurs LWP à un processus,
– multiplexer les threads utilisateur avec les LWP disponibles pour le processus.
– ajuster dynamiquement le nombre de LWP fournis au processus :
• Si tous les LWP sont bloqués et un thread est prêt à l’exécution, un autre LWP sera
fourni au processus pour exécuter ce thread.
• Les LWP inutilisés pendant un certain temps sont éliminés

• Chaque LWP supporte un ou plusieurs threads utilisateur et correspond à un thread noyau.

• Le noyau ordonnance les threads noyau.

• Le modèle plusieurs-à-plusieurs a été abandonné, dans Solaris 8, au profit du modèle un-à-


un.

Systèmes d’exploitation Génie Informatique Chapitre 3. 17


École Polytechnique de Montréal

Threads hybrides (3)


Solaris 2

Systèmes d’exploitation Génie Informatique Chapitre 3. 18


École Polytechnique de Montréal

9
Threads hybrides (4)
Windows
• Une application Win32 est composée d'
un ou plusieurs processus.

• Un ou plusieurs threads fonctionnent dans le contexte du processus.

• Un thread est l'


unité de base à laquelle le système d'
exploitation assigne du
temps de processeur.

• Un thread peut exécuter n'importe quelle partie du code de processus, y


compris celles actuellement exécuté par un autre thread.

• Une fibre est une unité d'exécution ordonnancée au niveau utilisateur. Les
fibres s’exécutent dans le contexte des threads qui les ordonnancent
(chaque thread peut avoir plusieurs fibres).

• Un job permet à des groupes de processus d' être considérés comme une
unité. Les opérations exécutées sur un job affectent tous les processus du
job.

Systèmes d’exploitation Génie Informatique Chapitre 3. 19


École Polytechnique de Montréal

Threads hybrides (5)


Windows XP (exemple)
#include <windows.h>
#define MAX_THREADS 3

typedef struct _MyData {


int val1;
int val2;
} MYDATA, *PMYDATA;

DWORD WINAPI ThreadProc( LPVOID lpParam )


{ PMYDATA pData;
// Un simple cast.
pData = (PMYDATA)lpParam;

// Imprimer sur la console les valeurs des variables.


printf("Parameters = %d, %d\n", pData->val1, pData->val2);
printf("global var is: %d\n", globalVar);

// Libérer la mémoire.
HeapFree(GetProcessHeap(), 0, pData);
return 0;
}
Systèmes d’exploitation Génie Informatique Chapitre 3. 20
École Polytechnique de Montréal

10
Threads hybrides (6)
Windows XP
void main()
{ PMYDATA pData;
DWORD dwThreadId[MAX_THREADS];
HANDLE hThread[MAX_THREADS];
for( int i=0; i<MAX_THREADS; i++ ) // Créer MAX_THREADS threads.
{ // Allocation dynamique de mémoire
pData = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(MYDATA));
if( pData == NULL ) ExitProcess(2);
pData->val1 = i;
pData->val2 = i+100;
hThread[i] = CreateThread( NULL, // attributs de sécurité par défaut
0, // taille du stack par défaut
ThreadProc, // pointeur vers la fonction thread
pData, // argument de la fonction thread
0, // création de flags par défaut
&dwThreadId[i]); // retourne l’identificateur du thread
if (hThread[i] == NULL) ExitProcess(i); // Vérifier si l’identificateur est valide.
}
// Attendre la fin de l’exécution de tous les threads.
WaitForMultipleObjects(MAX_THREADS, hThread, TRUE, INFINITE);
for(i=0; i<MAX_THREADS; i++) CloseHandle(hThread[i]); // Fermer tous les handles.
}
Systèmes d’exploitation Génie Informatique Chapitre 3. 21
École Polytechnique de Montréal

Threads POSIX

• L’objectif premier des Pthreads est la portabilité (disponibles


sous Solaris, Linux, Windows XP… ).
#include <pthread.h>

Systèmes d’exploitation Génie Informatique Chapitre 3. 22


École Polytechnique de Montréal

11
Threads POSIX (2)
Fonction pthread_create()
• int pthread_create(

pthread_t *tid,
// sert à récupérer le TID du thread créé

const pthread_attr_t *attr,


// sert à préciser les attributs du thread `(taille de la pile, priorité….)
//attr = NULL pour les attributs par défaut

void * (*func) (void*),


// est la fonction à exécuter par le thread

void *arg);
//le paramètre de la fonction.

• L'appel renvoie 0 s'il réussit, sinon il renvoie une valeur non nulle identifiant
l'
erreur qui s'
est produite

Systèmes d’exploitation Génie Informatique Chapitre 3. 23


École Polytechnique de Montréal

Threads POSIX (3)


Fonctions pthread_join() et pthread_self

void pthread_join( pthread_t tid, void * *status);

• Attend la fin d’un thread. L’équivalent de waitpid des processus sauf qu’on
doit spécifier le tid du thread à attendre.

• status sert à récupérer la valeur de retour et l’état de terminaison.

pthread_t pthread_self(void);

• Retourne le TID du thread.

Systèmes d’exploitation Génie Informatique Chapitre 3. 24


École Polytechnique de Montréal

12
Threads POSIX (4)
Fonction pthread_exit()
void pthread_exit( void * status);
• Termine l' exécution du thread

• Si le thread n’est pas détaché, le TID du thread et l’état de terminaison sont


sauvegardés pour les communiquer au thread qui effectuera pthread_join.

• Un thread détaché (par la fonction pthread_detach(pthread_t tid)) a pour


effet de le rendre indépendant de celui qui l'
a créé (plus de valeur de retour
attendue).

• Un thread peut annuler ou terminer l’exécution d’un autre thread


(pthread_cancel). Cependant, les ressources utilisées (fichiers, allocations
dynamiques, verrous, etc) ne sont pas libérées.

• Il est possible de spécifier une ou plusieurs fonctions de nettoyage à


exécuter à la terminaison du thread (pthread_cleanup_push() et
pthread_cleanup_pop()).

Systèmes d’exploitation Génie Informatique Chapitre 3. 25


École Polytechnique de Montréal

Threads POSIX (5)


Exemple 1
// exemple_threads.c
#define _REENTRANT
#include <pthread.h>
#include <unistd.h>
#include <stdio.h>
void afficher(int n, char lettre)
{ int i,j;
for (j=1; j<n; j++)
{ for (i=1; i < 10000000; i++);
printf("%c",lettre);
fflush(stdout);
}
}

void *threadA(void *inutilise)


{ afficher(100,' A');
printf("\n Fin du thread A\n");
fflush(stdout);
pthread_exit(NULL);
}

Systèmes d’exploitation Génie Informatique Chapitre 3. 26


École Polytechnique de Montréal

13
Threads POSIX (6)
Exemple 1 (suite)
void *threadC(void *inutilise)
{
afficher(150,' C');
printf("\n Fin du thread C\n");
fflush(stdout);
pthread_exit(NULL);
}

void *threadB(void *inutilise)


{
pthread_t thC;
pthread_create(&thC, NULL, threadC, NULL);
afficher(100,' B');
printf("\n Le thread B attend la fin du thread C\n");
pthread_join(thC,NULL);
printf("\n Fin du thread B\n");
fflush(stdout);
pthread_exit(NULL);
}

Systèmes d’exploitation Génie Informatique Chapitre 3. 27


École Polytechnique de Montréal

Threads POSIX (7)


Exemple 1 (suite)

int main()
{
int i;

pthread_t thA, thB;

printf("Creation du thread A");

pthread_create(&thA, NULL, threadA, NULL);


pthread_create(&thB, NULL, threadB, NULL);

sleep(1);
//attendre que les threads aient termine
printf("Le thread principal attend que les autres se terminent\n");

pthread_join(thA,NULL);
pthread_join(thB,NULL);

exit(0);
}
Systèmes d’exploitation Génie Informatique Chapitre 3. 28
École Polytechnique de Montréal

14
Threads POSIX (8) Thread
Exemple 1 (suite) principal

pthread_create pthread_create pthread_create

Thread B Thread C
Thread A

pthread_join
pthread_exit
pthread_exit

pthread_exit
pthread_join
Systèmes d’exploitation Génie Informatique Chapitre 3. 29
École Polytechnique de Montréal

Threads POSIX (9)


Exemple 1 (suite)
bash-2.05b$ gcc -o ex_th -lpthread exemple_threads.c
bash-2.05b$ ./ex_th
Creation du thread
AAAAAAAAAABBBBBBBBBCCCCCCCCCAAAAAAAAABBBBBBBBBCCCC
CC Le thread principal attend que les autres se terminent
CCAAAAAAAAABBBBBBBBBCCCCCCCCCAAAAAAAAAABBBBBBBBBCC
CCCCCCCAAAAAAAABBBBBBBBBCCCCCCCCCCAAAAAAAAABBBBBBB
BBCCCCCCCCAAAAAAAAABBBBBBBBBCCCCCCCCCCAAAAAAAAABBB
BBBBBBCCCCCCCCCAAAAAAAAABBBBBBBBCCCCCCCCAAAAAAAAAB
BBBBBBBBCCCCCCCCCAAAAAAAAA
Fin du thread A
BBBBBBBBBCCCCCCCCCCB
Le thread B attend la fin du thread C
CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC
Fin du thread C
Fin du thread B

Systèmes d’exploitation Génie Informatique Chapitre 3. 30


École Polytechnique de Montréal

15
Threads POSIX (10)
Exemple 2 : Partage de variables
// programme threads.c
#include <unistd.h> //pour sleep
#include <pthread.h>
#include <stdio.h>
int glob=0;
void* decrement(void * x)
{
int dec=1;
sleep(1);
glob = glob - dec ;
printf("ici decrement[%d], glob = %d\n",pthread_self(),glob);
pthread_exit(NULL);
}

void* increment (void * x)


{
int inc=2;
sleep(10);
glob = glob + inc;
printf("ici increment[%d], glob = %d\n",pthread_self(), glob);
pthread_exit(NULL);
} Systèmes d’exploitation Génie Informatique Chapitre 3. 31
École Polytechnique de Montréal

Threads POSIX (11)


Exemple 2 : Partage de variables (suite)
int main( )
{
pthread_t tid1, tid2;
printf("ici main[%d], glob = %d\n", getpid(),glob);
//creation d' un thread pour increment
if ( pthread_create(&tid1, NULL, increment, NULL) != 0)
return -1;
printf("ici main: creation du thread[%d] avec succes\n",tid1);
// creation d'un thread pour decrement
if ( pthread_create(&tid2, NULL, decrement, NULL) != 0)
return -1;
printf("ici main: creation du thread [%d] avec succes\n",tid2);
// attendre la fin des threads
pthread_join(tid1,NULL);
pthread_join(tid2,NULL);
printf("ici main : fin des threads, glob = %d \n",glob);
return 0;
}

Systèmes d’exploitation Génie Informatique Chapitre 3. 32


École Polytechnique de Montréal

16
Threads POSIX (12)
Exemple 3 : Passage de paramètres à un thread

// Programme p11.1.cpp
#define _REENTRANT
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <pthread.h>
#include <sys/types.h>
#include <sys/time.h>
#include <unistd.h>
using namespace std;

int MAX=5;
inline int gen_alea( int, int );
void *afficher( void * );

Systèmes d’exploitation Génie Informatique Chapitre 3. 33


École Polytechnique de Montréal

Thread POSIX (13)


Exemple 3 : Passage de paramètres à un thread (suite)

int main(int argc, char *argv[])


{
pthread_t thread_id[MAX];
int retour;
setvbuf(stdout, (char *) NULL, _IONBF, 0);
if ( argc > MAX+1 ){ // verifier la liste d'
arguments
cerr << *argv << " arg1, arg2, ... arg" << MAX << endl;
return 1;
}
cout << "Affichage" << endl;
for (int i = 0; i < argc-1; ++i)
{ // creation des threads
if( pthread_create(&thread_id[i],NULL,afficher, (void *)argv[i+1]) > 0) {
cerr << "Echec a la creation des threads" << endl;
return 2;
}
}

Systèmes d’exploitation Génie Informatique Chapitre 3. 34


École Polytechnique de Montréal

17
Thread POSIX (14)
Exemple 3 : Passage de paramètres à un thread (suite)

for (int i=0; i < argc-1; ++i)


{ // attendre les threads
if ( pthread_join(thread_id[i], (void **) retour) > 0){
cerr << "Echec a l'
attente des threads" << endl;
return 3;
}
cout << endl << "Thread " << thread_id[i] << " retourne " << retour;
}
cout << endl << "Termine" << endl;
return 0;
// fin de main()
}

Systèmes d’exploitation Génie Informatique Chapitre 3. 35


École Polytechnique de Montréal

Threads POSIX (15)


Exemple 3 : Passage de paramètres à un thread (suite)

// Afficher, un nombre aléatoire de fois, un mot


void * afficher(void *mot)
{
int nombre = gen_alea(2,6);
cout << (char *)mot << "\t sera affiche " << nombre << " fois." << endl;
for (int i=0; i < nombre; ++i){
sleep(1);
cout << (char *) mot << " ";
}
return (void *) nombre;
}

Systèmes d’exploitation Génie Informatique Chapitre 3. 36


École Polytechnique de Montréal

18
Thread POSIX (16)
// cancel1.c
#define _REENTRANT Exemple 4 : Annulation d’un thread
#include <pthread.h>
int main()
#include <unistd.h>
{
#include <stdio.h>
pthread_t th;
void _fclose (void *arg)
if (pthread_create(&th,NULL,mon_thread, NULL) )
{ printf("\n fclose\n"); fclose((FILE *)arg);}
perror("Erreur dans la création du thread");
void _unlink(void * arg)
sleep(3);
{ printf("unlink\n"); unlink((char*)arg);}
pthread_cancel(th); // annulation
}
void *mon_thread(void *inutilise)
{ FILE* un_fichier;
int i; d5333-09> cancel1
setvbuf(stdout, (char *) NULL, _IONBF, 0); 0123456789
if ((un_fichier = fopen("sortie.txt","w")) == NULL) fclose
perror("Erreur dans l'ouverture du fichier"); unlink
else { // pour une terminaison propre fin du programme
pthread_cleanup_push(_unlink, (void *) "sortie.txt");
pthread_cleanup_push(_fclose, (void *) un_fichier);
for (i=0; i<10; i++){
fprintf(un_fichier,"%d",i); fprintf(stdout,"%d",i); } pthread_cleanup_push et
pthread_cleanup_pop(1); // exécute fclose pthread_cleanup_pop indiquent les
pthread_cleanup_pop(1); // exécute unlink fonctions à appeler ainsi que l’ordre
} d’appels (en cas d’annulation)
} Terminaison propre
Systèmes d’exploitation Génie Informatique Chapitre 3. 37
École Polytechnique de Montréal

Thread POSIX (17)


Exemple 5 : Annulation d’un thread
//cancel2.c // la fonction des threads
#define _REENTRANT void *mon_thread(void *allocate)
#include <pthread.h> {
int* block;
#include <unistd.h> if (*((int*)allocate))
#include <stdio.h> { block = new int; // allocation dynamique
// à appeler pour libérer l'espace alloué *block = 123;
void free (void *arg){ pthread_cleanup_push(free, (void *) block);
int * a = (int*)arg; printf( "push free\n");
printf("ici free %d \n", *a); pthread_cleanup_pop(1);
} else
delete a;
{ block = NULL; // pas d' allocation
} pthread_cleanup_push(notfree, (void *) block);
printf("push notfree\n");
//à appeler si pas de libération pthread_cleanup_pop(1);
void notfree (void * arg) }
{ sleep(3);
if (arg ==NULL) printf("ici notfree \n"); printf("fin du thread\n");
pthread_exit(0);
}
}

Systèmes d’exploitation Génie Informatique Chapitre 3. 38


École Polytechnique de Montréal

19
Thread POSIX (18)
Exemple 5 : Annulation d’un thread (suite)
int main()
{ int allocate = 1;
d5333-09> cancel2
pthread_t th; push free
// création d' un thread qui effectuera le bloc du if ici free 123
if (pthread_create(&th,NULL,mon_thread,(void*)&allocate)) fin du thread
perror("Erreur dans la creation du thread"); push notfree
sleep(1); ici notfree
pthread_cancel(th); fin du thread
allocate = 0;
fin du main
//création d' un thread qui exécutera le else du if
if (pthread_create(&th,NULL,mon_thread,(void*)&allocate) != 0)
perror("Erreur dans la creation du thread");
sleep(1);
pthread_cancel(th);
printf("fin du main\n");
}

//Dans un bloc, il doit y avoir autant pthread_cleanup_pop qu’il y a de pthread_cleanup_push.


//En cas d’annulation, les push/pop des blocs en cours sont considérées.
// Le fonctionnement est similaire aux destructeurs des classes de C++.

Systèmes d’exploitation Génie Informatique Chapitre 3. 39


École Polytechnique de Montréal

20

Вам также может понравиться