| 31 | | * Dans kO6, les appels systèmes ne sont pas interruptibles. Cela signifie que, lorsque vous demandez au système de créer un objet (un thread par exemple) et qu'il utilise ses allocateurs de mémoire (`malloc_ustack()` et `kmalloc()`), il n'y a pas de risque de compétition avec d'autres threads sur le même core, parce que si le tick courant s'achève, l'IRQ du timer sera masquée et donc ne sera traitée que lorsque les allocations seront terminées. Mais il y a un risque s'il y a deux cores, parce qu'ils seront en vrai parallélisme. Pour le moment, il n'y a qu'un core parce qu'avec deux cores, il y a le problème de la cohérence des caches non traitée dans cette version du SoC. Il n'y a donc pas de risque pour les allocations du noyau, mais nous mettrons quand même les protections pour le futur. |
| | 31 | * Dans kO6, les appels système ne sont pas interruptibles. Cela signifie que, lorsque vous demandez au système de créer un objet (un thread par exemple) et qu'il utilise ses allocateurs de mémoire (`malloc_ustack()` et `kmalloc()`), il n'y a pas de risque de compétition avec d'autres threads sur le même core, parce que si le tick courant s'achève, l'IRQ du timer sera masquée et donc ne sera traitée que lorsque les allocations seront terminées. Mais il y a un risque s'il y a deux cores, parce qu'ils seront en vrai parallélisme. Pour le moment, il n'y a qu'un core parce qu'avec deux cores, il y a le problème de la cohérence des caches non traitée dans cette version du SoC. Il n'y a donc pas de risque pour les allocations du noyau, mais nous mettrons quand même les protections pour le futur. |
| 82 | | * L'effacement a lieu après le passage à l'état DEAD et un thread ne peut pas s'effacer lui-même. Pour effacer, il faut exécuter du code, or pour exécuter du code, il faut une pile, et on ne peut pas effacer la pile parce qu'elle est utilisée. C'est pour ça que c'est toujour un autre thread qui fait le ménage. |
| 83 | | * Dans le code de kO6, il n'y a pas encore de ménage, ça permet de voir les threads mort de l'affichage du contenu du scheduler. Mais, plus tard cela pourra être ajouté dans le scheduler. Quand un thread devient RUNNING, il peut regarder s'il y a eu un DEAD juste précédemment et l'effacer. On pourrait aussi, le faire au dernier moment quand le kernel n'a plus de place, alors il fait le ménage (un peu comme chez moi à certaines périodes :-) |
| 84 | | ''' |
| 85 | | }}} |
| 86 | | 1. Le contenu de la structure `struct thread_s` (c'est-à-dire les champs qui la compose) est définie dans le fichier `kernel/kthread.c`. En conséquence cette structure n'est utilisable que par les fonctions de ce même fichier `kernel/kthread.c`. A l'extérieur, les fonctions ne manipulent que des pointeurs sur la structure de type `thread_t` (défnis par un `typedef struct thread_s * thread_t`. Pourquoi ce choix, pourquoi n'avoir pas définie la structure `thread_s` dans le fichier `kernel/kthread.h` ? |
| 87 | | {{{#!protected ------------------------------------------------------------------ |
| 88 | | ''' |
| 89 | | * |
| | 82 | * L'effacement a lieu après le passage à l'état DEAD et un thread ne peut pas s'effacer lui-même. Pour effacer, il faut exécuter du code, or pour exécuter du code, il faut une pile, et on ne peut pas effacer la pile parce qu'elle est utilisée. C'est pour ça que c'est toujours un autre thread qui fait le ménage. |
| | 83 | * Dans le code de kO6, il n'y a pas encore de ménage, ça permet de voir les threads DEAD de l'affichage du contenu du scheduler. Mais, plus tard, cela devra être ajouté, par exemple, dans le scheduler. Quand un thread devient RUNNING, il peut regarder s'il y a eu un DEAD juste précédemment et l'effacer. On pourrait aussi, le faire au dernier moment quand le kernel n'a plus de place, alors il fait le ménage (un peu comme chez moi à certaines périodes :-) |
| | 84 | ''' |
| | 85 | }}} |
| | 86 | 1. Le contenu de la structure `struct thread_s` (c'est-à-dire les champs qui la composent) est définie dans le fichier `kernel/kthread.c`. En conséquence cette structure n'est utilisable que par les fonctions de ce même fichier `kernel/kthread.c`. A l'extérieur, les fonctions ne manipulent que des pointeurs sur la structure de type `thread_t` (définis par un `typedef struct thread_s * thread_t`. Pourquoi ce choix, pourquoi n'avoir pas défini la structure `thread_s` dans le fichier `kernel/kthread.h` ? |
| | 87 | {{{#!protected ------------------------------------------------------------------ |
| | 88 | ''' |
| | 89 | * Le fait de ne pas rendre visibles les champs de la structure thread_s en dehors du fichier thread permet d'éviter des erreurs de programmation. En effet, pour modifier cette structure partagée, il faut prendre un verrou et le fait d'avoir réduit le nombre de fonctions ayant la possibilité de le faire est plus sûr. |
| | 90 | * Dans la mesure du possible, on essaye de faire ça pour toutes les structures du kernel. Cela n'a rien d'obligatoire, c'est juste plus sûr. |
| 107 | | * |
| 108 | | ''' |
| 109 | | }}} |
| 110 | | 1. Le système définit `errno` de la façon suivante : `#define errno *__errno_location()`, que fait la fonction `errno_location()` ? Comment cela peut régler le problème ? |
| 111 | | {{{#!protected ------------------------------------------------------------------ |
| 112 | | ''' |
| 113 | | * |
| | 110 | * Le problème de errno, c'est qu'une application peut avoir plusieurs threads, c'est même le cas général, et chaque thread fait des appels système. Or lorsqu'un appel système sort, il doit mettre un code d'erreur dans la variable `errno`. Il soit y en avoir autant que de thread, mais toutes avec le même nom. |
| | 111 | * `errno` est une variable globale locale au thread. Elle est dans le Thread Local Storage. |
| | 112 | * Dans le cas de kO6, il n'y aura pas d'autres variables de cette catégorie pour le moment. |
| | 113 | ''' |
| | 114 | }}} |
| | 115 | 1. Le système définit `errno` de la façon suivante : `#define errno *__errno_location()`, que fait la fonction `__errno_location()` ? Comment cela peut régler le problème ? |
| | 116 | {{{#!protected ------------------------------------------------------------------ |
| | 117 | ''' |
| | 118 | * `__errno_location()` est une fonction qui rend l'adresse d'une case de mémoire. Si cette adresse est différente pour chaque thread, le problème est réglé/ |