Changes between Version 44 and Version 45 of AS6-TME-B5
- Timestamp:
- Feb 22, 2022, 6:55:46 PM (3 years ago)
Legend:
- Unmodified
- Added
- Removed
- Modified
-
AS6-TME-B5
v44 v45 382 382 383 383 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. 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. 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 388 Le 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. 385 389 386 390 **uapp/main.c** 387 391 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 TTY1392 * 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 391 395 392 396 {{{#!c … … 442 446 * 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`. 443 447 * `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 s apce` 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. 445 449 * Quand `fgets()` appelle `read()`, cela fait l'appel système `SYSCALL_READ`. 446 450 … … 534 538 }}} 535 539 540 == Le problème et une solution possible 536 541 537 542 Le schéma ci-dessous illustre le problème: … … 546 551 [[Image(htdocs:img/IRQTTY_2.png,nolink,width=600)]] 547 552 553 === Mise en place d'une FIFO entre l'isr du TTY et la fonction `tty_read()` 554 548 555 Le 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. 549 556 … … 552 559 Pour implémenter la FIFO, nous allons utiliser un tableau circulaire et des pointeurs. Il y a une structure et 2 fonctions d'accès. 553 560 {{{#!c 554 /**555 561 /** 556 562 * Simple fifo (1 writer - 1 reader) … … 572 578 * \param fifo structure of fifo to store data 573 579 * \param c char to write 574 * \return 1 on success, 0 on f ealure580 * \return 1 on success, 0 on failure 575 581 */ 576 582 static int tty_fifo_push (struct tty_fifo_s *fifo, int c) … … 582 588 * \param fifo structure of fifo to store data 583 589 * \param c pointer on char to put the read char 584 * \return 1 on success, 0 on f ealure590 * \return 1 on success, 0 on failure 585 591 */ 586 592 static int tty_fifo_pull (struct tty_fifo_s *fifo, int *c) … … 605 611 [[Image(htdocs:img/FIFO.png,nolink,width=600)]] 606 612 607 608 613 {{{#!protected 609 614 {{{#!c … … 621 626 }}} 622 627 628 === Utilisation de la FIFO 629 630 Pour 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 639 Pour 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 651 static 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 }}}