Changes between Version 1 and Version 2 of TME6-2014


Ignore:
Timestamp:
Mar 7, 2014, 8:42:12 AM (11 years ago)
Author:
franck
Comment:

--

Legend:

Unmodified
Added
Removed
Modified
  • TME6-2014

    v1 v2  
    33== Objectif de la séance
    44
    5 Nous avons vu en cours que la gestion des threads se fait en utilisant des structures de données abstraites c'est qui n'exposent pas leur contenu mais juste leur méthodes. L'accès aux attributs de ces structures se fait par des fonctions d'accès.
     5Nous avons vu en cours que la gestion des threads se fait en utilisant des structures de données abstraites c'est qui n'exposent pas leur contenu mais juste leur méthodes.
     6L'accès aux attributs de ces structures se fait par des fonctions d'accès.
    67Toutefois avant d'utiliser ces structures, nous allons faire une gestion "naïve" et simplifiée des threads.
     8Dans cette version:
     9 * les structures sont ouvertes,
     10 * il n'y a qu'une seule politique d'ordonnancement (FIFO),
     11 * les threads ne peuvent être joints (on ne peut pas récupérer leur valeur de retour)
    712
    813== Définitions
    914
    10 Un thread peut être dans 5 états
     15=== thread
    1116
    12 [[Image(sched.png)]]
     17* Un thread peut être dans 5 états (vous ferez une énumeration) :
     18  * CREATE : état de démarrage attribué au thread lorsqu'il n'a jamais été chargé sur un core.
     19  * READY : état dans lequel le thread est en attente du core.
     20  * RUN : état en cours d'exécution.
     21  * WAIT : état dans lequel le thread est en attente d'une ressource.
     22  * DEAD : état de sortie dans lequel le thread peut être détruit.
     23
     24* La structure thread_t est définie par:
     25  * spinlock_t  lock;  !//// protection contre les accès concurrents
     26  * state_t     state; !//// CREATE, READY, ...
     27  * unsigned    cpuid; !//// numéro du core affecté au thread
     28  * list_t      list;  !//// utilisé pour le chainage des threads dans les listes d'attente
     29  * list_t      rope;  !//// chaine tous les threads quelque soit leur état
     30  * unsigned    pws[CONTEXT_SIZE];  !//// context
     31
     32* Les fonctions de manipulation des threads sont:
     33  * typedef void * thread_fct_t (void *);  // Thread function type
     34  * extern thread_t *   thread_create    (unsigned cpuid, thread_fct_t *start, void *arg);
     35  * extern unsigned     thread_save      (thread_t *     thread);
     36  * extern void         thread_restore   (thread_t *     thread);
     37  * extern void         thread_exit      (void *         exit_value) __attribute__((noreturn));
     38  * extern void *       thread_idle      (void *         arg);
     39 
     40  La fonction thread_create utilise malloc pour créer la structure thread et la pile du thread.
     41
     42=== scheduler
     43
     44* La structure schedroot_t:
     45  * spinlock_t    lock;  !//// protection contre les accès concurrents
     46  * thread_t *    run;   !//// thread en cours d'exec
     47  * thread_t *    idle;  !//// thread idle
     48  * list_t        dead;  !//// liste des threads à détruire
     49  * list_t        ready; !//// liste des threads en attente du core
     50
     51* Les fonctions de manipulation du scheduler sont:
     52  * extern void sched_init      (void);                 !//// initialise un scheduler
     53  * extern void sched_create    (thread_t *thread);     !//// ajoute un nouveau thread
     54  * extern void sched_wakeup    (thread_t *thread);     !//// remet un thread dans l'état READY
     55  * extern void sched_yield     (void);                 !//// demande d'ordonnancement
     56  * extern void sched_sleep     (void);                 !//// place le thread dans une liste d'attente
     57  * extern void sched_exit      (void);                 !//// termine un thread (ici on ne récupère pas la valeur)
     58
     59* Le graphe ci-dessous illustre le comportement des fonction sur l'état des threads
     60
     61  [[Image(sched.png, 500px)]]
     62
     63
     64
     65=== mutex
     66
     67* Afin que tous les états de threads soient utilisés, il est nécessaire d'ajouter une ressource qui pourra être partagée par plusieurs threads.
     68  La plus simple est le mutex qui est une variable à deux états: 0 pour libre, 1 pour occupé.[[BR]]
     69  La structure mutex_t est définie par:
     70  * spinlock_t lock; !//// protection contre les accès concurrents
     71  * int state; !//// état du mutex
     72  * list_t wait; !//// liste d'attente des threads ayant demandé le mutex alors que celui-ci était occupé.
     73
     74* Les fonctions d'accès:
     75  * extern int mutex_init (mutex_t *mutex); !//// initialise un mutex dont on passe le pointeur (pas de malloc)
     76  * extern int mutex_lock (mutex_t *mutex); !//// prend le verrou s'il est libre ne met en attente sinon
     77  * extern int mutex_unlock (mutex_t *mutex); !//// rend le verrou et réveille un des threads en attente s'il y en a un.
     78
     79== Travail demandé
     80
     81Vous allez créer plusieurs fichiers:
     82* scheduler.h + scheduler.c : les prototypes et fonctions du scheduler
     83* thread.h + thread.c : les prototypes et fonctions des threads + thread_idle()
     84* mutex.h + mutex.c : les prototypes et fonctions des mutex
     85* app.c : les threads de votre application
     86
     87Je vous propose une application mais vous pouvez en imaginer une autre plus intelligente.
     88N threads identiques de type 1 qui se partagent un compteur commun protégé par un mutex.
     89Un thread de type 2 va recevoir les compteurs de chaque instance des threads de type 1 et vérifier qu'il ne reçoit pas deux valeurs identiques (vous faite comme vous voulez pour faire cette vérification mais vous pouvez profiter du fait que les valeurs envoyées par les threads de type 1 sont strictement croissantes...).
     90Le compteur est une variable globale initialisée à 0.
     91Chaque instance de thread de type 1 boucle sur la séquence suivante:
     92* prend le mutex
     93* prend la valeur du compteur
     94* rend le mutex
     95* attend un nombre aléatoire de cycles
     96* envoi de la valeur du compteur vers le thread de type 2
     97
     98Pour faire l'envoi des valeurs de compteur vous allez avoir besoin d'un moyen de communication N vers 1. Je vous laisse spécifier et implémenter ce moyen.