Add TD2 Report

.
This commit is contained in:
Yorick Barbanneau 2021-11-19 23:00:14 +01:00
parent f277111e1c
commit dbc10545f3

View file

@ -0,0 +1,152 @@
---
title: systèmes d'exploitation, TD2
documentclass: scrartcl
author:
- Juliette Lenoir
- Yorick Barbanneau
fontsize: 13pt
mainfont: DejaVu Serif
geometry: [top=1.5cm, bottom=3cm, left=3cm, right=3cm]
header-includes:
- \definecolor{liens}{HTML}{de6a66}
urlcolor: liens
linkstyle: bold
...
## Bilan
Après le premier niveau de TD effectué, alors que nous pensions pouvoir vaincre
le boss NachOS facilement (tel ceux des jeux *Ubisoft*), nous nous sommes en
fait retrouvé dans un *Dark Souls* like. Vous savez ce genre de jeux qui nous
donnent on a envie de casser manettes, clavier, écran, traiter le chat comme
dans les pubs des *Nuls* mais sur lequel on revient forcément.
L'objectif de ce TD a été de permettre l'exécution de programme dans Nachos
avec plusieurs threads.
Il s'est déroulé en 2 parties:
* La première a été consacrée au multi-threading dans les programmes
utilisateurs. Nous avons permis aux programmes utilisateurs de manipuler d
es threads NachOS.
* La seconde a eu pour but d'implémenter la plusieurs threads par processus.
Pour réaliser ces deux parties, nous avons utilisé deux appels système :
* un pour créer des threads (`ThreadCreate`)
* un autre pour les détruire (`ThreadExit`)
Les fonctions de base de la gestions de nos threads sont présente dans le
fichier `userthread.cc`, dans leurs définitions se font dans `usertread.h`,
comme demandé dans le sujet du TD.
### Passage des paramètres depuis l'appel système
L'appel système `ThreadCreate` prends deux paramètres: l'adresse de la fonction
à exécuter et l'adresse des paramètres de cette fonction. Cependant nous ne
pouvons passer qu'une seule valeur lors de du démarrage de notre Thread:
```c
Thread->Start(void * funtion, void * arguments)
```
Nous avons choisi d'encapsuler l'adresse mémoire de la fonction et l'adresse
mémoire de ses arguments dans une structre `ThreadArgs_t`:
```c
typedef struct {
int f;
int arg;
int stackAddr;
} ThreadArgs_t;
```
Celle-ci est effectuée dans le fichier d'entête `userthread.h`, nous parlerons
de `int stackAddr` un peu plus loin dans ce chapitre.
La fonction `StartUserThread`, servant à initialiser les différents registres,
reçoit cette structure sous la forme d'un `(void*)`. Nos ne pouvons l'utiliser
tel quel, il nous faut donc la caster dans une variable de type `ThreadArgs_t`.
Afin de ne pas perdre cette structure lors de la fin de notre fonction
`Do_ThreadCreate`, nous la positionnons sur le tas avec un `malloc`
(`userspace.cc` ligne 50). Afin de ne pas froisser *LealSanitizer* nous n'avons
pas oublié de libérer cette zone mémoire une fois devenueNouveau dossier inutile dans la
fonction `StartUserThread` (ligne 38-39).
### Le comptage des thread.
Comme nous l'avons compris, la classe `AddrSpace` représente un processus -- un
espace d'adressage. Côté noyau, tout n'est que Thread, dont certains partagent
un même espace d'adressage. Il nous a donc **semblé légitime d'implémenter le
comptage des Threads dans `AddrSpace`** via la variable publique `int thread`
(définie dans `addrspace.h` ligne 50). Celle-ci est initialisée à 1 lors de
l'instanciation: le `main` de notre programme compte lui aussi pour un thread.
Une fois que nous savons combien de threads sont encore "en vie", il nous est
possible de terminer notre programme quand tous ses threads sont finis dans la
fonction `Do_ThreadExit` (fichier `usersthread.cc` ligne 88).
### Gestion de la pile
Comme l'a démontré notre programme de test (`/test/threadtest.c`), la première
version de notre gestion de threads était plus qu'imparfaite: elle les
conjuguait tous avec la même pile. Nous avons alors utilisé la classe `Bitmap`
afin de gérer les espaces de pile de nos différents threads. Sachant que nous
réservons 256 octets de pile par thread et que notre pile gérée par `AddrSpace`
a une taille de `UserStackSize`, nous pouvons en déduire le nombre de *"slots"*
disponibles. Il ne faut pas oublier que notre `main` a déjà une pile et done la
réserver a l'instanciation de notre `AddrSpace` (fichier `addrspace.cc` ligne
145).
L'affectation d'un espace de pile se fait par la fonction `AllocateUserStack`
(fichier `addrspace.h` ligne 320). Elle est appelée par `Do_ThreadCreate`
**avant la création d'un nouveau thread** car si l'allocation echoue il faut
tout arrêter et retourner une erreur: la célèbre *Stack Overflow*. L'adresse
de pile de notre nouveau thread est encapsulée dans notre structure
`ThreadArgs_t` afin de la passer à `StartUserThread`.
Nous avions au départ imaginé un autre mécanisme: faire attendre les threads
jusqu'à la libération d'une place. Petit problème cependant: que se
passera-t-il lorsqu'un programme fera une barrière?
### Les points bonus
Nous n'avons pas eu le temps d'aborder les points complémentaires.
## Points délicats
Plusieurs points ont été délicats lors de la réalisation de ce TD2.
Tout comme le premier TD, Il nous a fallu tout d'abord comprendre comment les
éléments s'articulent entre eux. Cette étape nous a pris beaucoup de temps,
nous avons obtenu **un premier thread réellement fonctionnel il y a tout juste
deux semaines** -- après avoir tout repris de zéro. Nous avons passé une grosse
partie de notre temps à lire, comprendre et expérimenter le code avant de
pouvoir le modifier et le compléter.
La création de notre premier thread a été pour nous le plus compliqué. En
effet, lors de cette implémentation, nous avons rencontré plusieurs erreurs de
segmentation car notre thread n'était pas à la bonne place dans la mémoire. Une
fois cette étape passée les choses ont été un peu plus simple.
## Limitations
Nous avons passé beaucoup de temps à comprendre comment tout les éléments
s'articule ente eux; nous avons perdu du temps au début de la partie 1. Par
manque de temps, nous n'avons pas pu réaliser la partie 3 Bonus.
La terminaison de notre processus une fois tous les threads finis ne nous
convient pas (`Do_ThreadExit`), nous la trouvons bancale, une version plus
élégante devrait être possible (sûrement plus simple une fois le TD3 plus
avancé).
## Tests
Tous nos test se sont fait avec `test/threadtest.c`, nous avon adapté son code
en fonction de ce que nous voulions tester:
* tester le fonctionnement d'un seul thread (Action I.7)
* tester le fonctionnement de plusieurs threads (Action II.1)
* tester la pile (Action II.3)
* l'utilisation de la classe `Bitmap` (Action II.4)