View difference between Paste ID: L5VJTqcr and wfzW5eXq
SHOW: | | - or go back to the newest paste.
1
/* ----------------------------------------------------------------------------
2
   Fonction int ThreadInit(void) 
3
   Cette fonction est utilisée pour pour initialiser la librairie. Elle doit être
4
   appelée avant la toute première utilisation de vos threads.
5
   La fonction retourne:
6
	    1 si tout s'est bien passé
7
	   -1 si vous avez une erreur lors de l'initialisation. */
8
int ThreadInit(void){
9
	// Allocation
10
	TCB *mainThread = malloc (sizeof (struct TCB));
11
	mainThread = malloc (sizeof(tid));
12
	mainThread = malloc(sizeof(EtatThread));
13
	mainThread = malloc(sizeof(ucontext_t));
14
	mainThread->pSuivant = malloc(sizeof(struct TCB));
15
	mainThread->pPrecedant = malloc(sizeof(struct TCB));
16
	mainThread = malloc(sizeof(int));
17
	mainThread->pWaitListJoinedThreads = malloc(sizeof(WaitList));
18
	// Initialisation
19
	mainThread->id = gNextTID;
20
	mainThread->etat = THREAD_EXECUTE;
21
 	gNextTID++;
22
  	gNTCB++;
23
  	getcontext(&mainThread->ctx);
24
  	mainThread->ctx.uc_stack.ss_sp = malloc(TAILLE_PILE);
25
  	mainThread->ctx.uc_stack.ss_size = TAILLE_PILE;
26
  	mainThread->pSuivant = mainThread;
27
  	mainThread->pPrecedant = mainThread;
28
  	gpThreadCourant = mainThread;
29
  	if(GetPointerFromTid(100) == mainThread) 
30
  	  return 1;
31
  	else
32
  	  return -1;
33
}
34
35
/* ----------------------------------------------------------------------------
36
   Fonction tid ThreadCreer(void (*fn)(void *), void *arg)
37
   Cette fonction va créer un thread et le placer dans la file d'ordonnancement.
38
   Les entrées sont :
39
   	  void (*fn)(void *) : une fonction fn qui sera le code exécuté par un thread.
40
   	  void *arg          : un pointeur sur les données passées au thread lors du démarrage.
41
   La fonction retourne :
42
	    le tid du thread si tout s'est bien passé
43
	   -1 si il y a une erreur. */
44
tid ThreadCreer(void (*fn)(void *), void *arg){
45
	//Allocation
46
 	TCB *thread = malloc (sizeof (struct TCB));
47
  	thread = malloc (sizeof(tid));
48
  	thread = malloc(sizeof(EtatThread));
49
  	thread = malloc(sizeof(ucontext_t));
50
  	thread->pSuivant = malloc(sizeof(struct TCB));
51
  	thread->pPrecedant = malloc(sizeof(struct TCB));
52
  	thread = malloc(sizeof(int));
53
  	thread->pWaitListJoinedThreads = malloc(sizeof(WaitList));
54
	// Initialisation
55
  	thread->id = gNextTID;
56
 	gNextTID++;
57
  	thread->waitingCount = 0;
58
  	thread->etat = THREAD_PRET;
59
	thread->pSuivant = thread;
60
	thread->pPrecedant = thread;
61
  	getcontext(&thread->ctx);
62
  	thread->ctx.uc_stack.ss_sp = malloc(TAILLE_PILE);
63
  	thread->ctx.uc_stack.ss_size = TAILLE_PILE;
64
  	makecontext(&thread->ctx, (void *)&fn, 1, arg);
65
  	InsertTCBAfter(gpThreadCourant, thread);
66
  	gpThreadCourant = thread;
67
  	if(GetPointerFromTid(thread->id) == thread) 
68
  	  return thread->id;
69
  	else
70
  	  return -1;
71
} 
72
73
/* ----------------------------------------------------------------------------
74
   Fonction void ThreadCeder(void)
75
   Cette fonction va faire passer le fil d'exécution au prochain thread (dans la file
76
   d'ordonnacement) qui est prêt à être exécuté. L'ordonnancement se fait selon
77
   l'algorithme du tourniquet. Il faut que le prochain thread à exécuter soit dans 
78
   l'état THREAD_PRET. Il faut donc sauter tous les threads qui sont dans les 
79
   états THREAD_BLOQUE ou THREAD_TERMINE. */
80
void ThreadCeder(void){
81
  TCB *threadCourant = gpThreadCourant;
82
  printf("ThreadCeder():\n");
83
  while(gpThreadCourant->pSuivant != threadCourant)
84
  {
85
    printf("ThreadID:%d\tÉtat:%c\n", ThreadId(), ThreadEtat(gpThreadCourant->etat) );
86
    gpThreadCourant = gpThreadCourant->pSuivant;   
87
  }
88
  printf("ThreadID:%d\tÉtat:%c\n", ThreadId(), ThreadEtat(gpThreadCourant->etat) );
89
  gpThreadCourant = gpThreadCourant->pSuivant;
90
  threadCourant = gpThreadCourant;
91
  while(gpThreadCourant->pSuivant->etat == THREAD_BLOQUE || gpThreadCourant->pSuivant->etat == THREAD_TERMINE)
92
  {
93
    gpThreadCourant = gpThreadCourant->pSuivant;
94
  }    
95
  gpThreadCourant->pSuivant->etat = THREAD_EXECUTE;
96-
  gpThreadCourant->etat = THREAD_EXECUTE;
96+
97
98
  swapcontext(&threadCourant->ctx, &gpThreadCourant->ctx);
99
}
100
/* ----------------------------------------------------------------------------
101
   Fonction int ThreadJoindre(tid ThreadAJoindre)
102
   Cette fonction va joindre le thread en cours à l'exécution du thread ThreadAJoindre.
103
   Cela signifie que a) le thread qui appelle cette fonction bloquera en passant à
104
   l'état THREAD_BLOQUE b) lorsque le thread ThreadAJoindre quitte, il devra "réveiller"
105
   le thread appelant. Cette fonction devra invoquer ultimement la fonction ThreadCeder()
106
   pour faire exécuter un autre thread. La fonction retourne :
107
   		 -1 si ThreadAJoindre n'existe pas
108
   		 -2 si ThreadAJoindre a déjà terminé (i.e. est dans l'état THREAD_TERMINE).
109
   		  1 si tout se passe bien. */
110
int ThreadJoindre(tid ThreadAJoindre){
111
  
112
  TCB *TCBThreadAJoindre = GetPointerFromTid(ThreadAJoindre);
113
114
  if(TCBThreadAJoindre == NULL)
115
    return -1;
116
  else if(TCBThreadAJoindre->etat == THREAD_TERMINE)
117
    return -2;
118
  while(gpThreadCourant->etat != THREAD_EXECUTE)
119
  {
120
    gpThreadCourant = gpThreadCourant->pSuivant;
121
  }
122
  gpThreadCourant->etat = THREAD_BLOQUE;
123
  int i;
124
  for(i = 0; i < gpThreadCourant->waitingCount; i++)
125
  {
126
  TCBThreadAJoindre->pWaitListJoinedThreads->pThreadWaiting = TCBThreadAJoindre->pWaitListJoinedThreads->pNext->pThreadWaiting;	// On trouve un espace libre pour ajouter un thread qui attend dans la waiting list
127
  }  
128
  TCBThreadAJoindre->pWaitListJoinedThreads->pThreadWaiting = gpThreadCourant;	// On dit que le thread main attend après ce thread (ThreadAJoindre)
129
  gpThreadCourant->waitingCount++;
130
  ThreadCeder();
131
  return 1;
132
}