View difference between Paste ID: 4BU9gwWE and eNZMWf15
SHOW: | | - or go back to the newest paste.
1-
/* Q4 HUE HUE (ノ ゜Д゜)ノ ︵ ┻━┻ 
1+
2-
   Francois "Rondoudou" Lebeau et Gabriel "Jesus Freak" Tessier */
2+
3
   Cette fonction est utilisée pour pour initialiser la librairie. Elle doit être
4-
/**************************************************************************
4+
5-
    Travail pratique No 2 : Thread utilisateurs
5+
6-
    
6+
7-
    Ce fichier est l'implémentation de la librarie des threads utilisateurs.
7+
8-
         
8+
9-
	Systemes d'explotation GLO-2001
9+
10-
	Universite Laval, Quebec, Qc, Canada.
10+
11-
	(c) 2015 Philippe Giguere
11+
12-
 **************************************************************************/
12+
13-
#include <stdio.h>
13+
14-
#include <stdlib.h>
14+
15-
#include <unistd.h>
15+
16-
#include <string.h>
16+
17-
#include <ucontext.h>
17+
18-
#include <time.h>
18+
19-
#include "ThreadUtilisateur.h"
19+
20
  gNTCB++;
21-
/* Définitions privées, donc pas dans le .h, car l'utilisateur n'a pas besoin de
21+
22-
   savoir ces détails d'implémentation. OBLIGATOIRE. */
22+
23-
typedef enum { 
23+
24-
	THREAD_EXECUTE=0,
24+
25-
	THREAD_PRET,
25+
26-
	THREAD_BLOQUE,
26+
27-
	THREAD_TERMINE
27+
28-
} EtatThread;
28+
29
    return 1;
30-
#define TAILLE_PILE 4096   // Taille de la pile utilisée pour les threads
30+
31
    return -1;
32-
/* Structure de données pour créer une liste chaînée simple sur les threads qui ont fait un join.
32+
33-
   Facultatif */
33+
34-
typedef struct WaitList {
34+
35-
	struct TCB *pThreadWaiting;
35+
36-
	struct WaitList *pNext;
36+
37-
} WaitList;
37+
38
   	  void (*fn)(void *) : une fonction fn qui sera le code exécuté par un thread.
39-
/* TCB : Thread Control Block. Cette structure de données est utilisée pour stocker l'information
39+
40-
   pour un thread. Elle permet aussi d'implémenter une liste doublement chaînée de TCB, ce qui
40+
41-
   facilite la gestion et permet de faire un ordonnanceur tourniquet sans grand effort. 
41+
42-
   Facultatif. */
42+
43-
typedef struct TCB {  // Important d'avoir le nom TCB ici, sinon le compilateur se plaint.
43+
44-
	tid                 id;        // Numero du thread
44+
45-
	EtatThread			etat;      // Etat du thread
45+
46-
	ucontext_t          ctx;       // Endroit où stocker le contexte du thread
46+
47-
	struct TCB         *pSuivant;   // Liste doublement chaînée
47+
48-
	struct TCB         *pPrecedant; // Liste doublement chaînée
48+
49-
	struct WaitList	   *pWaitListJoinedThreads; // Liste chaînée simple des threads en attente.
49+
50-
  	int					waitingCount;
50+
51-
} TCB;
51+
52
  thread->pWaitListJoinedThreads = malloc(sizeof(WaitList));
53
54
  thread->id = gNextTID;
55
56
  gNextTID++;
57-
// Pour que les variables soient cachées à l'utilisateur, on va les déclarer static. Facultatif.
57+
58-
static TCB *gpThreadCourant;	    //Thread en cours d'execution
58+
59-
static int gNTCB = 0;
59+
60-
static int gNextTID = 100;
60+
61
  getcontext(&thread->ctx);
62
  thread->ctx.uc_stack.ss_sp = malloc(TAILLE_PILE);
63-
/* Cette fonction insère le TCB pToInsert dans la liste doublement chaînée, juste après
63+
64-
   pActual. */
64+
65-
int InsertTCBAfter(TCB *pActual, TCB *pToInsert) {
65+
66-
    // Mettre à jour le TCB précédent
66+
67-
	TCB *pNext = pActual->pSuivant; // pNext == thread 100
67+
68-
 	pActual->pSuivant = pToInsert;
68+
69
  else
70-
	// Mettre à jour le TCB inséré
70+
71-
	pToInsert->pSuivant   = pNext; // pToInsert->pSuivant == 101
71+
72-
	pToInsert->pPrecedant = pActual;
72+
73-
	
73+
74-
	// Et aussi celui après
74+
75-
	pNext->pPrecedant = pToInsert;
75+
76
   d'ordonnacement) qui est prêt à être exécuté. L'ordonnancement se fait selon
77-
	// On incrémente le nombre de TCB
77+
78-
	return ++gNTCB;
78+
79
   états THREAD_BLOQUE ou THREAD_TERMINE. */
80
void ThreadCeder(void){
81-
/* Cette fonction retire le TCB pActual de la liste doublement chaînée. */
81+
82-
int RemoveTCB(TCB *pActual) {
82+
83-
    // Mettre à jour le TCB inséré
83+
84-
 	pActual->pSuivant->pPrecedant = pActual->pPrecedant;
84+
85-
	pActual->pPrecedant->pSuivant = pActual->pSuivant;
85+
86-
	// Mettre à jour le TCB inséré
86+
87-
	pActual->pSuivant   = NULL;
87+
88-
	pActual->pPrecedant = NULL;
88+
89-
	
89+
90-
	// On décrémente le nombre de TCB
90+
91-
	return --gNTCB;
91+
92
  {
93
    gpThreadCourant = gpThreadCourant->pSuivant;
94-
/* Cette fonction retourne le TCB correspondant au ThreadID fourni. */
94+
95-
TCB *GetPointerFromTid(tid ThreadID) {
95+
96-
	/* On inspecte la liste circulaire pour la traduction. Pas super rapide. */
96+
97-
	int i;
97+
98
  swapcontext(&threadCourant->ctx, &gpThreadCourant->ctx);
99-
	TCB *pTCB = gpThreadCourant;
99+
100-
	for (i=0; i< gNTCB; i++) {
100+
101-
		if (pTCB->id == ThreadID) { return pTCB;}
101+
102-
		
102+
103-
		pTCB = pTCB->pSuivant;
103+
104-
		
104+
105-
	}
105+
106-
	return NULL;
106+
107
   		 -1 si ThreadAJoindre n'existe pas
108
   		 -2 si ThreadAJoindre a déjà terminé (i.e. est dans l'état THREAD_TERMINE).
109-
char ThreadEtat(const EtatThread etat) {
109+
110-
  switch(etat){
110+
111-
    case 0:
111+
112-
    	return 'E';
112+
113-
    case 1:
113+
114-
    	return 'P';
114+
115-
    case 2:
115+
116-
    	return 'B';
116+
117-
    case 3:
117+
118-
    	return 'T';
118+
119
  {
120
    gpThreadCourant = gpThreadCourant->pSuivant;
121-
/*********************** CA C'EST LE POINT H CA LÀ LÀ ************************/
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
}