Changes between Version 44 and Version 45 of AS6-TME-B5


Ignore:
Timestamp:
Feb 22, 2022, 6:55:46 PM (3 years ago)
Author:
franck
Comment:

--

Legend:

Unmodified
Added
Removed
Modified
  • AS6-TME-B5

    v44 v45  
    382382
    383383
    384 Pour la partie pratique, je ne vous fait pas modifier, ou pire écrire, la gestion des threads, mais je vous invite à lire le code. Pour Vous vous forcer à ouvrir les fichiers, vous allez répondre à quelques questions sur le code. Puis vous allez changer la manière de lire les caractères du TTY pour la rendre plus efficace.
     384Pour la partie pratique, je ne vous fait pas modifier, ou pire écrire, la gestion des threads, mais je vous invite à lire le code. Vous allez changer la manière de lire les caractères du TTY pour la rendre plus efficace. Tous les changements seront faits dans le fichier `kernel/harch.c`.
     385
     386== Etat du code par une lecture directe
     387
     388Le code proposé fonctionne mais il a un problème que nous allons résoudre. Pour illustrer ce problème, nous allons partir d'un exemple.
    385389
    386390**uapp/main.c**
    387391
    388  * Le code ci-dessous contient l'application. Nous avons 3 threads : `main`, `t0` et `t1`.
    389  * `main` et `t1` se contente d'afficher des messages sur le TTY0 et d'attendre (une attente active pour ralentir l'affichage des messages).
    390  * `t0` lit le clavier de TTY1
     392 * Le code ci-dessous contient l'application donnée pour ce TP. Nous avons 3 threads : `main`, `TO` et `T1`.
     393 * `main` et `T1` se contente d'afficher des messages sur le TTY0 et d'attendre (une attente active pour ralentir l'affichage des messages).
     394 * `T0` lit le clavier de TTY1
    391395
    392396{{{#!c
     
    442446 * La fonction `fgets()` est dans la **libc**, c'est une fonction bloquante du point de vue de l'utilisateur. Il l'appelle pour lire `count` caractères sur le TTY n°`tty` et les enregistre dans `buf`.
    443447 * `fgets()` demande 1 caractère à la fois et elle le revoit sur l'écran (c'est un ''loopback'') pour que l'utilisateur sache que son caractère a été pris en compte.
    444  * Il y a quelques subtilités dues au fait que lorsque vous taper sur ''**enter''**, le clavier envoie deux caractères '\r' (`13` = ''carriage return'') et '\n' (`10` = ''line feed''), on jette `\r`. En outre, on gère le `back sapce` et le `delete` (à qui on donne le même comportement pour simplifier). Je vous laisse essayer de comprendre pour le plaisir.
     448 * Il y a quelques subtilités dues au fait que lorsque vous taper sur ''**enter''**, le clavier envoie deux caractères '\r' (`13` = ''carriage return'') et '\n' (`10` = ''line feed''), on jette `\r`. En outre, on gère le `back space` et le `delete` (à qui on donne le même comportement pour simplifier). Je vous laisse essayer de comprendre pour le plaisir.
    445449 * Quand `fgets()` appelle `read()`, cela fait l'appel système `SYSCALL_READ`.
    446450
     
    534538}}}
    535539
     540== Le problème et une solution possible
    536541
    537542Le schéma ci-dessous illustre le problème:
     
    546551 [[Image(htdocs:img/IRQTTY_2.png,nolink,width=600)]]
    547552
     553=== Mise en place d'une FIFO entre l'isr du TTY et la fonction `tty_read()`
     554
    548555Le caractère lu est mis dans une structure FIFO (First In First Out). Le schéma ci-dessous illustre le fonctionnement de la FIFO. Une fifo simple a un écrivain et un lecteur. L'écrivain écrit des données avec une commande `push()` tant que la FIFO n'est pas pleine. Si elle elle pleine, il y a deux comportements possibles : l'écrivain attend de la place ou l'écrivain jette la donnée, ça dépend ce qu'on veut. Ici, on jettera, parce qu'on n'a pas le moyen de ralentir le flux de données (les frappes du clavier). Le lecteur lit les données avec `pull()` tant que la FIFO n'est pas vide.
    549556
     
    552559Pour implémenter la FIFO, nous allons utiliser un tableau circulaire et des pointeurs. Il y a une structure et 2 fonctions d'accès.
    553560{{{#!c
    554 /**
    555561/**
    556562 * Simple fifo (1 writer - 1 reader)
     
    572578 * \param   fifo    structure of fifo to store data
    573579 * \param   c       char to write
    574  * \return  1 on success, 0 on fealure
     580 * \return  1 on success, 0 on failure
    575581 */
    576582static int tty_fifo_push (struct tty_fifo_s *fifo, int c)
     
    582588 * \param   fifo    structure of fifo to store data
    583589 * \param   c       pointer on char to put the read char
    584  * \return  1 on success, 0 on fealure
     590 * \return  1 on success, 0 on failure
    585591 */
    586592static int tty_fifo_pull (struct tty_fifo_s *fifo, int *c)
     
    605611 [[Image(htdocs:img/FIFO.png,nolink,width=600)]]
    606612
    607 
    608613{{{#!protected
    609614{{{#!c
     
    621626}}}
    622627
     628=== Utilisation de la FIFO
     629
     630Pour utiliser la FIFO, vous allez de devoir :
     631* créer une fifo par TTY, donc un tableau de `struct tty_fifo_s` de taille `NTTYS`.
     632* Vous allez devoir changer le code de `tty_read()` qui doit désormais lire la fifo.
     633* Créer une fonction `tty_isr(int tty)` qui lit le registre `READ` du `tty` en argument et écrit le caractère lu dans la FIFO du `tty`
     634* Faire le **''binding''** des lignes d'interruption des TTY. C'est-à-dire modifier `arch_init()` pour
     635  * démasquer les lignes IRQ 10, 11, 12 et 13 dans le masque de l'ICU, ce sont les entrées de l'ICU utilisées par les TTY0 à TTY3.
     636  * initialiser les cases 10, 11, 12 et 13 des deux tableaux du vecteur d'interruption : `irq_vector_isr[]` et `irq_vector_dev[]`
     637
     638{{{#!protected
     639Pour la correction, je vous met le code sans le ranger dans des fonctions, histoire de vous aider, mais pas trop...
     640
     641{{{#!c
     642    int pt_write_next = (fifo->pt_write + 1) % sizeof(fifo->data);
     643    if (pt_write_next != fifo->pt_read) {
     644        fifo->data [fifo->pt_write] = c;
     645        fifo->pt_write = pt_write_next;
     646        return 1;
     647    }
     648    return 0;
     649}}}
     650{{{#!c
     651static struct tty_fifo_s tty_fifo [NTTYS];
     652}}}
     653{{{#!c
     654{
     655    struct tty_fifo_s *fifo = &tty_fifo[ tty%NTTYS ];
     656    int c = __tty_regs_map[tty].read;
     657    tty_fifo_push (fifo, c);
     658}
     659}}}
     660{{{#!c
     661{
     662    int res = 0;                                     
     663    tty = tty % NTTYS;                                 
     664    int c;                                             
     665    struct tty_fifo_s *fifo = &tty_fifo[ tty%NTTYS ];
     666
     667    while (count--) {
     668        while (tty_fifo_pull (fifo, &c) == 0) {       
     669            thread_yield();                         
     670        }
     671        *buf++ = c;
     672        res++;
     673    }
     674    return res;   
     675}
     676}}}
     677{{{#!c
     678    for (int tty = 1; tty < NTTYS; tty++) {
     679        icu_set_mask (0, 10+tty);           
     680        irq_vector_isr [10+tty] = tty_isr;
     681        irq_vector_dev [10+tty] = tty;   
     682    }
     683}}}
     684{{{#!c
     685}}}