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 | } |