Page principale   Liste par ordre alphabétique   Liste des composants   Liste des fichiers   Composants   Déclarations  

interpreteur.c

Aller à la documentation de ce fichier.
00001 /**
00002  * @file interpreteur.c
00003  * Source definissant toutes les fonctions utiles pour interpreter une instruction
00004  * et par extention toutes les fonctions pour manipuler les processus et la mémoire.
00005  */
00006 
00007 #include "interpreteur.h"
00008 #include "commandes.h"
00009 
00010 /**************************************************************************************
00011  Entierement fait par Martin Ludovic
00012 **************************************************************************************/
00013 
00014 /**
00015  * Fonction qui permet de changer l'etat d'un processus
00016  * L'information est stockee sur les bits 2, 3 et 4 par ordre de poids croissant
00017  * (00001110) du 2eme octet de poids faible (ie le 3eme en partant de la droite) 
00018  * du mot
00019  * \param etat : le nouvel etat
00020  * \param mot : l'entree correspondante au processus ds la table des processus
00021  * \return l'ancien etat 
00022  */
00023 int changer_etat(int etat, mot_t mot) {
00024   int old_etat;
00025 
00026   old_etat = mot[2] >> 1;
00027   mot[2] = (mot[2] & 0xF1) | (etat * 2);
00028   return old_etat;
00029 }
00030 
00031 /**
00032  * Fonction qui permet de lire l'etat d'un processus
00033  * L'information est stockee sur les bits 2, 3 et 4 par ordre de poids croissant
00034  * (00001110) du 2eme octet de poids faible (ie le 3eme en partant de la droite) 
00035  * du mot
00036  * \param mot : l'entree correspondante au processus ds la table des processus
00037  * \return l'etat courant
00038  */
00039 int lire_etat(mot_t mot) {
00040   return ((mot[2] & 0x0E) >> 1);
00041 }
00042 
00043 /**
00044  * Fonction qui permet de changer le type de la page physique ou est stockee la 
00045  * table des pages d'un processus.
00046  * L'information est stockee ds le bit de poids faible du 2eme octet de poids 
00047  * faible (ie le 3eme en partant de la droite) du mot
00048  * \param type : le nouveau type
00049  * \param mot : l'entree correspondante au processus ds la table des processus
00050  * \return l'ancien type
00051  */
00052 int changer_type_pp(int type, mot_t mot) {
00053   int old_type;
00054 
00055   old_type = (mot[2] & 0x01) + 1;
00056   mot[2] = (mot[2] & 0xFE) | ((type+1) % 2);
00057   return old_type;
00058 }
00059 
00060 /**
00061  * Fonction qui permet de lire le type de la page physique ou est stockee la 
00062  * table des pages d'un processus.
00063  * L'information est stockee ds le bit de poids faible du 2eme octet de poids 
00064  * faible (ie le 3eme en partant de la droite) du mot
00065  * \param mot : l'entree correspondante au processus ds la table des processus
00066  * \return Le type de la page (PP_SWAP ou PP_RAM)
00067  */
00068 int lire_type_pp(mot_t mot) {
00069   return (mot[2] & 0x01) + 1;
00070 }
00071 
00072 /**
00073  * Fonction retournant un numero de processus libre
00074  * \return 
00075  * - -1 en cas d'erreur
00076  * - -2 S'il n'y a plus de pid libre
00077  * - un num de processus libre
00078  */
00079 int pid_libre ( ) {
00080   mot_t mot,mot2;
00081   int pid_libre;
00082   int i;
00083 
00084   // Lit le mot ou est stocke le plus petit pid libre
00085   if (lire_mot_mem(0, NUM_PAGE_META, mot) == -1)
00086     return -1;
00087   // Verifie qu'il reste au moins un pid libre
00088   if ((pid_libre=(int)mot[3]) == NO_MORE_PID) {
00089     fprintf(stderr,"Il n'y a plus de pid libre\n");
00090     return -2;
00091   }
00092   // Ajoute ce pid a la liste des processus eligibles
00093   liste_add_pid(liste_proc,pid_libre);
00094   // Recherche le prochain pid libre
00095   for (i=pid_libre+1 ; i<N_MAX_PROC+1 ; i++) {
00096     if (lire_mot_mem(i, NUM_PAGE_META, mot2) == -1) {
00097       liste_supp_pid(liste_proc,pid_libre);
00098       return -1;
00099     }
00100     if (lire_etat(mot2) == E_MORT) {
00101       // Met a jour le mot ou est stocke le plus petit pid libre 
00102       mot[3] = (octet_t)i;
00103       if (ecrire_mot_mem(0, NUM_PAGE_META, mot) == -1) {
00104         liste_supp_pid(liste_proc,pid_libre);
00105         return -1;
00106       }
00107       // Renvoie un pid libre
00108       return pid_libre;
00109     }
00110   }
00111   // il n'y a pas d'autre pid libre
00112   // Met a jour le mot ou est stocke le plus petit pid libre 
00113   mot[3] = (octet_t)NO_MORE_PID;
00114   if (ecrire_mot_mem(0, NUM_PAGE_META, mot) == -1) {
00115     liste_supp_pid(liste_proc,pid_libre);
00116     return -1;
00117   }
00118   // Renvoie un pid libre
00119   return pid_libre;
00120 }
00121 
00122 /**
00123  * Fonction permettant de liberer un num de processus apres sa mort
00124  * \param pid : Numero du processus mort qu'il faut donc declare comme libre
00125  * \return 
00126  * - -1 erreur : le numero de processus n'a pas ete libere
00127  * - -2 erreur : le numero de processus a ete libere mais le numero de le plus petit pid
00128  *               n'est peut-etre plus exact
00129  * - 0  succes
00130  */
00131 int liberer_pid (int pid) {
00132   mot_t mot,mot2;
00133 
00134   // Libere le num de pid
00135   changer_etat(E_MORT,mot);
00136   if (ecrire_mot_mem(pid,NUM_PAGE_META, mot2) == -1)
00137     return -1;
00138   // Modifie eventuellement le num du plus petit pid libre
00139   if (lire_mot_mem(0, NUM_PAGE_META, mot) == -1)
00140     return -2;
00141   if (pid < (int)mot[3]) {
00142     mot[3] = (octet_t)pid;
00143     if (ecrire_mot_mem(0,NUM_PAGE_META, mot) == -1)
00144       return -2;
00145   }
00146   return 0;
00147 }
00148 
00149 /**
00150  * Fonction retournant un num de page physique libre ds la memoire afin
00151  * de l'attacher a un processus.
00152  * \param pid : Numero du processus auquel on veut attacher cette page
00153  * \return 
00154  * - -1 en cas d'erreur
00155  * - -2 S'il n'y a plus de page libre en memoire principale
00156  * - un num de page libre
00157  */
00158 int page_libre (int pid) {
00159   int page_libre;
00160   int i,j;
00161   int num_mot, num_octet;
00162   mot_t mot, mot2;
00163 
00164   // Lit le mot ou est stocke le plus petit pid libre
00165   if (lire_mot_mem(DEBUT_T_PAGES, NUM_PAGE_META, mot) == -1)
00166     return -1;
00167   // Verifie qu'il reste au moins une page libre
00168   if ((page_libre=(int)mot[0]) == NO_MORE_PAGE) {
00169     fprintf(stdout,"Rem : Il n'y a plus de page libre en memoire RAM\n");
00170     return -2;
00171   }
00172   // Recherche la prochaine page libre
00173   num_mot = (page_libre + 1) / T_MOT + DEBUT_T_PAGES;
00174   num_octet = (page_libre + 1) % T_MOT;
00175   for (i=num_mot ; i<NMPPP ; i++) {
00176     if (lire_mot_mem(i, NUM_PAGE_META, mot2) == -1)
00177       return -1;
00178     for (j=num_octet ; j<T_MOT ; j++) {
00179       if (mot2[j] == PAGE_VIDE) {
00180         // Met a jour le mot ou est stocke le plus petit pid libre 
00181         mot[0] = (octet_t)(i - DEBUT_T_PAGES) * T_MOT + j;
00182         if (ecrire_mot_mem(DEBUT_T_PAGES, NUM_PAGE_META, mot) == -1)
00183           return -1;
00184         // Ajoute la page retournee a la liste des pages memoire utilisees
00185         liste_add_page(liste_pages,page_libre);
00186         // Attache la page au processus passe en parametre
00187         num_mot = page_libre / T_MOT + DEBUT_T_PAGES;
00188         num_octet = page_libre % T_MOT;
00189         if (lire_mot_mem(num_mot, NUM_PAGE_META, mot2) == -1) {
00190           liberer_page(page_libre);
00191           return -1;
00192         }
00193         mot2[num_octet] = (octet_t)pid;
00194         if (ecrire_mot_mem(num_mot, NUM_PAGE_META, mot2) == -1) {
00195           liberer_page(page_libre);
00196           return -1;
00197         }
00198         return page_libre;
00199       }
00200     }
00201     num_octet = 0;
00202   }
00203   // il n'y a pas d'autre page libre
00204   // Met a jour le mot ou est stocke le plus petit pid libre 
00205   mot[0] = (octet_t)NO_MORE_PAGE;
00206   if (ecrire_mot_mem(DEBUT_T_PAGES, NUM_PAGE_META, mot) == -1)
00207     return -1;
00208   // Ajoute la page retournee a la liste des pages memoire utilisees
00209   liste_add_page(liste_pages,page_libre);
00210   // Attache la page au processus passe en parametre
00211   num_mot = page_libre / T_MOT + DEBUT_T_PAGES;
00212   num_octet = page_libre % T_MOT;
00213   if (lire_mot_mem(num_mot, NUM_PAGE_META, mot2) == -1) {
00214     liberer_page(page_libre);
00215     return -1;
00216   }
00217   mot2[num_octet] = (octet_t)pid;
00218   if (ecrire_mot_mem(num_mot, NUM_PAGE_META, mot2) == -1) {
00219     liberer_page(page_libre);
00220     return -1;
00221   }
00222   return page_libre;
00223 }
00224 
00225 /**
00226  * Fonction retournant un num de page physique de la memoire principale.
00227  * La page retournee est 
00228  * - soit une page libre s'il reste des pages en memoire principale
00229  * - soit une page utilisee dont on a copier le contenu ds le swap
00230  *   apres modification de la table des pages du processus auquel elle appartenait.
00231  *   Dans ce cas, il s'agit de la page utilisee le moins recemment.
00232  * \param pid : Numero du processus auquel on veut attacher cette page
00233  * \return 
00234  * - -1 en cas d'erreur
00235  * - -2 S'il n'y a plus de page libre en memoire principale et secondaire
00236  * - un num de page libre
00237  */
00238 int page_forcee (int pid) {
00239   int num_page_mem,num_page_swap,num_table_pages;
00240   int num_mot_modif,num_mot;
00241   int old_pid;
00242   int find_page=0;
00243   mot_t mot_tab_page,mot_proc;
00244   int i,j;
00245 
00246   // Regarde s'il y a des pages libres en mem
00247   num_page_mem = page_libre(pid);
00248   if (num_page_mem > 0) { // Il reste au moins une page libre en mem 
00249     return num_page_mem;
00250   }
00251   else if (num_page_mem != -2) { // Erreur inconnue
00252     return -1;
00253   }
00254   else { // Il n'y a plus de page libre en mem
00255     // On cherche la page la moins recemment utilisee
00256     if ((num_page_mem=liste_old_page(liste_pages)) == -1)
00257       return -1;
00258     // On met cette page en swap
00259     num_page_swap = page_swap_libre();
00260     if (num_page_swap == -1) // Erreur inconnue
00261       return -1;
00262     else if (num_page_swap == -2) // Il n'y a plus de page swap libre
00263       return -2;
00264     if (page_mem2swap(num_page_mem,num_page_swap) == -1)
00265       return -1;
00266     // On cherche le num du processus auquel appartient la page
00267     if (lire_mot_mem(DEBUT_T_PAGES+num_page_mem/T_MOT,NUM_PAGE_META,mot_tab_page) == -1) {
00268       // Libere la page swap allouee
00269       liberer_page_swap(num_page_swap);
00270       return -1;
00271     }
00272     old_pid =(int) mot_tab_page[num_page_mem%T_MOT];
00273     // On modifie la table des pages du processus associe a cette page
00274     if (lire_mot_mem(old_pid,NUM_PAGE_META,mot_proc) == -1) {
00275       // Libere la page swap allouee
00276       liberer_page_swap(num_page_swap);
00277       return -1;
00278     }
00279     num_table_pages = (int)mot_proc[3];
00280     if (num_table_pages == num_page_mem) {
00281       // La page mise en swap correspond a la table des pages du processus
00282       mot_proc[3] = (octet_t)num_page_swap;
00283       changer_type_pp(PP_SWAP,mot_proc);
00284       if (ecrire_mot_mem(old_pid,NUM_PAGE_META,mot_proc) == -1) {
00285         // Libere la page swap allouee
00286         liberer_page_swap(num_page_swap);
00287         return -1;
00288       }
00289       // Change le num du processus proprietaire de la page
00290       mot_tab_page[num_page_mem%T_MOT] = (octet_t)pid;
00291       if (ecrire_mot_mem(DEBUT_T_PAGES+num_page_mem/T_MOT,NUM_PAGE_META,mot_tab_page) == -1) {
00292         // Reviens a l'ancien etat de la table des processus
00293         mot_proc[3] = (octet_t)num_page_mem;
00294         changer_type_pp(PP_RAM,mot_proc);
00295         ecrire_mot_mem(old_pid,NUM_PAGE_META,mot_proc);
00296         // Libere la page swap allouee
00297         liberer_page_swap(num_page_swap);
00298         return -1;
00299       }
00300     }
00301     else {
00302       // La page est une page de code, de donnees, de pile ou de tampon
00303       for (i=0 ; (i<3) && (find_page==0) ; i++) {
00304         for (j=0 ; j<T_MAX_ZONES ; j++) {
00305           if (lire_mot_mem(i*8+j,num_table_pages,mot_proc) == -1) {
00306             // Libere la page swap allouee
00307             liberer_page_swap(num_page_swap);
00308             return -1;
00309           }
00310           if ((int)mot_proc[2] == PP_NULL)
00311             // On passe a la zone suivante
00312             break;
00313           if (mot_proc[3] == num_page_mem) {
00314             // On a trouve ds la table des pages du processus, l'entree correspondant a 
00315             // la page mise en swap. Il faut la modifier en consequence
00316             mot_proc[2] = (octet_t)PP_SWAP;
00317             mot_proc[3] = (octet_t)num_page_swap;
00318             if (ecrire_mot_mem(i*8+j,num_table_pages,mot_proc) == -1) {
00319               // Libere la page swap allouee
00320               liberer_page_swap(num_page_swap);
00321               return -1;
00322             }
00323             find_page = 1;
00324             num_mot_modif = i*8+j;
00325             break;
00326           }
00327         }
00328       }
00329       if (find_page == 0) {
00330         // La page est peut etre une page de tampon
00331         num_mot = NUM_MOT_IN;
00332         if (lire_mot_mem(num_mot,num_table_pages,mot_proc) == -1) {
00333           liberer_page_swap(num_page_swap);
00334           return -1;
00335         }
00336         if (((int)mot_proc[3] != num_page_mem) || ((int)mot_proc[2] != PP_SWAP)) {
00337           num_mot = NUM_MOT_OUT;
00338           if (lire_mot_mem(num_mot,num_table_pages,mot_proc) == -1) {
00339             liberer_page_swap(num_page_swap);
00340             return -1;
00341           }
00342           if (((int)mot_proc[3] != num_page_mem) || ((int)mot_proc[2] != PP_SWAP)) {
00343             // La page rapatriee n'appartient pas au processus 'pid'
00344             fprintf(stderr,"La table des pages du processus %d n'est pas coherente avec la ",old_pid);
00345             fprintf(stderr,"table des pages de la memoire principale.\n");
00346             liberer_page_swap(num_page_swap);
00347             return -1;
00348           }
00349         }
00350         mot_proc[2] = (octet_t)PP_SWAP;
00351         mot_proc[3] = (octet_t)num_page_swap;
00352         num_mot_modif = num_mot;
00353         if (ecrire_mot_mem(num_mot,num_table_pages,mot_proc) == -1) {
00354           liberer_page_swap(num_page_swap);
00355           return -1;
00356         }
00357       }
00358       // Change le num du processus proprietaire de la page
00359       mot_tab_page[num_page_mem%T_MOT] = (octet_t)pid;
00360       if (ecrire_mot_mem(DEBUT_T_PAGES+num_page_mem/T_MOT,NUM_PAGE_META,mot_tab_page) == -1) {
00361         // Reviens a l'ancien etat de la table des pages du processus
00362         mot_proc[3] = (octet_t)num_page_mem;
00363         mot_proc[2] = (octet_t)PP_RAM;
00364         ecrire_mot_mem(num_mot_modif,num_table_pages,mot_proc);
00365         // Libere la page swap allouee
00366         liberer_page_swap(num_page_swap);
00367         return -1;
00368       }
00369     }
00370   }
00371   liste_acces_page(liste_pages,num_page_mem);
00372   return num_page_mem;
00373 }
00374 
00375 /**
00376  * Fonction permettant de liberer un numero de page physique ds la memoire
00377  * \param page : Numero de la page non utilisee (a liberer)
00378  * \return 
00379  * - -1 erreur : le numero de page n'a pas ete libere
00380  * - -2 erreur : le numero de page a ete libere mais le numero de la plus petite page
00381  *               n'est peut-etre plus exact
00382  * - 0  succes
00383  */
00384 int liberer_page(int page) {
00385   mot_t mot;
00386   int num_mot,num_octet;
00387 
00388   // Libere le num de la page
00389   num_mot = page/T_MOT + DEBUT_T_PAGES;
00390   num_octet = page % T_MOT;
00391   if (lire_mot_mem(num_mot, NUM_PAGE_META, mot) == -1)
00392     return -1;
00393   mot[num_octet] = PAGE_VIDE;
00394   if (ecrire_mot_mem(num_mot,NUM_PAGE_META, mot) == -1)
00395     return -1;
00396   // Modifie eventuellement le num de la plus petite page libre
00397   if (lire_mot_mem(DEBUT_T_PAGES, NUM_PAGE_META, mot) == -1)
00398   return -2;
00399   if (page < (int)mot[0]) {
00400     mot[0] = (octet_t)page;
00401     if (ecrire_mot_mem(DEBUT_T_PAGES,NUM_PAGE_META, mot) == -1)
00402       return -2;
00403   }
00404   // Supprime cette page de la liste des pages memoire
00405   // Mise a jour de la liste des pages memoire
00406   if (liste_supp_page(liste_pages,page) != 0) {
00407     fprintf(stderr,"La table des pages memoire utilisees n'etait pas coherente.\n");
00408     // On continue tout de meme car elle est peut-etre de nouveau coherente
00409   }
00410   return 0;
00411 }
00412 
00413 /**
00414  * Fonction retournant un numero de page physique du swap libre 
00415  * \return 
00416  * - -1  En cas d'erreur
00417  * - -2 S'il n'y a plus de page libre en memoire principale
00418  * - un num de page libre
00419  */
00420 int page_swap_libre () {
00421   mot_t mot,mot2;
00422   int pc,num_mot,num_page_libre;
00423 
00424   // Lecture de la position courante ds la table des pages swap libres
00425   if (lire_mot_mem(DEBUT_T_PAGES, NUM_PAGE_META, mot) == -1)
00426     return -1;
00427   pc = (int)mot[1];
00428   // Lecture du num de la page swap libre
00429   num_mot = pc / T_MOT;
00430   if (lire_mot_mem(num_mot, NUM_PAGE_SWAP, mot2) == -1) 
00431     return -1;
00432   num_page_libre = (int)mot2[pc%T_MOT];
00433   if (num_page_libre == NO_MORE_SWAP) {
00434     fprintf(stderr,"Il n'y a plus de page libre dans le swap\n");
00435     return -2;
00436   }
00437   // Deplacement du pointeur courant
00438   pc ++;
00439   // Rechargement du debut de la liste des pages swap libres si necessaire
00440   if (pc >= NMPPP*T_MOT) {
00441     if (page_swap2mem(num_page_libre, NUM_PAGE_SWAP) == -1)
00442       return -1;
00443     mot[1] = (octet_t)0;
00444     if (ecrire_mot_mem(DEBUT_T_PAGES, NUM_PAGE_META, mot) == -1) {
00445       fprintf(stderr,"Position courante de la table des pages swap libres incoherente\n");
00446       return -1;
00447     }
00448   }
00449   else {
00450     // Modification de la position courante
00451     mot[1] = (octet_t)pc;
00452     if (ecrire_mot_mem(DEBUT_T_PAGES, NUM_PAGE_META, mot) == -1)
00453       return -1;
00454   }
00455   return num_page_libre;
00456 }
00457 
00458 /**
00459  * Fonction permettant de liberer un numero de page physique ds le swap
00460  * \param page : Numero de la page non utilisee (a liberer)
00461  * \return 
00462  * - -1 erreur : le numero de page n'a pas ete libere
00463  * - -2 erreur : le numero de page a ete libere mais le pointeur courant n'a pas ete mis a jour
00464  * - 0  succes
00465  */
00466 int liberer_page_swap (int page) {
00467   mot_t mot,mot2;
00468   int pc,num_mot;
00469 
00470   // Lecture de la position courante ds la table des pages swap libres
00471   if (lire_mot_mem(DEBUT_T_PAGES, NUM_PAGE_META, mot) == -1)
00472     return -1;
00473   pc = (int)mot[1];
00474   if (pc > 0) {
00475     pc --;
00476     num_mot = pc / T_MOT;
00477     if (lire_mot_mem(num_mot, NUM_PAGE_SWAP, mot2) == -1) 
00478       return -1;
00479     mot2[pc%T_MOT] = (octet_t)page;
00480     // Libere le num de la page
00481     if (ecrire_mot_mem(num_mot,NUM_PAGE_SWAP, mot2) == -1)
00482       return -1;
00483     // Modifie le pointeur courant
00484     mot[1] = (octet_t)pc;
00485     if (ecrire_mot_mem(DEBUT_T_PAGES,NUM_PAGE_META, mot) == -1)
00486       return -2;
00487   }
00488   else {
00489     // Sauvegarde dans le swap de cette page de la liste des pages swap libres
00490     if (page_mem2swap(NUM_PAGE_SWAP,page) == -1)
00491       return -1;
00492     // Creation de la nouvelle page de la liste des pages swap libres
00493     mot2[3] = (octet_t)page;
00494     if (ecrire_mot_mem(NMPPP-1,NUM_PAGE_SWAP,mot2) == -1)
00495       return -1;
00496     pc = NMPPP*T_MOT-1;
00497     mot[1] = (octet_t)pc;
00498     if (ecrire_mot_mem(DEBUT_T_PAGES,NUM_PAGE_META, mot) == -1)
00499       return -2;
00500   }
00501   return 0;
00502 }
00503 
00504 /**
00505  * Fonction permettant de mettre en memoire principale une page du processus 'pid'
00506  * se trouvant dans le swap.
00507  * Fait toutes les modifications necessaires dans la table des pages RAM et la table
00508  * des processus ou la table des pages du processus 'pid'.
00509  * \param page : Numero de la page swap qu'on veut mettre en memoire principale
00510  * \return 
00511  * - -1 en cas d'erreur
00512  * - -2 erreur : plus assez de memoire pour realiser l'operation (minimum : 1  page swap libre)
00513  * - le numero de la page memoire dans laquelle a ete copiee la page swap
00514  */
00515 int rapatrier_page_swap (int pid, int page) {
00516   int num_page_mem,num_tab_pages;
00517   int num_mot;
00518   int i,j;
00519   int find_page = 0;
00520   mot_t mot_proc,mot_tab;
00521 
00522   if (lire_mot_mem(pid,NUM_PAGE_META,mot_proc) == -1) {
00523     return -1;
00524   }
00525   if (lire_etat(mot_proc) == E_MORT) {
00526     fprintf(stderr,"Impossible de rapatrier une page d'un processus mort (%d)\n",pid);
00527     return -1;
00528   }
00529   // Regarde s'il y a des pages libres en mem
00530   num_page_mem = page_forcee(pid);
00531   if (num_page_mem > 0) {
00532     // Rapatrie la page swap ds cette page libre
00533     if (page_swap2mem(page, num_page_mem) == -1) {
00534       liberer_page(num_page_mem);
00535       return -1;
00536     }
00537   }
00538   else if (num_page_mem != -2) {
00539     return -1;
00540   }
00541   else {
00542     // Il n'y a plus de page physique libre
00543     fprintf(stderr,"Memoire insuffisante\n");
00544     return -2;
00545   }
00546   // Modifie le mot qui pointait sur 'page'
00547   // Regarde a quel type de page correspond la page rapatriee
00548   if ((mot_proc[3] == page) && (lire_type_pp(mot_proc) == PP_SWAP)) {
00549     // La page rapatriee correspond a la table des pages du proc
00550     mot_proc[3] = (octet_t)num_page_mem;
00551     changer_type_pp(PP_RAM,mot_proc);
00552     if (ecrire_mot_mem(pid,NUM_PAGE_META,mot_proc) == -1) {
00553       liberer_page(num_page_mem);
00554       return -1;
00555     }
00556   }
00557   else { 
00558     // La page rapatriee est une page de code, pile, donnees ou tampon
00559     switch (lire_type_pp(mot_proc)) {
00560     case PP_SWAP:
00561       switch (num_tab_pages=rapatrier_page_swap(pid,(int)mot_proc[3])) {
00562       case -1:
00563         liberer_page(num_page_mem);
00564         return -1;
00565       case -2:
00566         liberer_page(num_page_mem);
00567         return -2;
00568       }
00569       break;
00570     case PP_RAM:
00571       num_tab_pages = (int)mot_proc[3];
00572       break;
00573     }
00574     // Parcours la table des pages a la recherche de la page rapatriee
00575     for (i=0 ; (i<3) && (find_page==0) ; i++) {
00576       for (j=i*T_MAX_ZONES ; (j<(i+1)*T_MAX_ZONES) && (find_page==0) ; j++) {
00577         if (lire_mot_mem(j,num_tab_pages,mot_tab) == -1) {
00578           liberer_page(num_page_mem);
00579           return -1;
00580         }
00581         if (((int)mot_tab[3] == page) && ((int)mot_tab[2] == PP_SWAP)) {
00582           // On a trouve le mot qui pointe sur la page rapatriee
00583           find_page = 1;
00584           mot_tab[3] = (octet_t)num_page_mem;
00585           mot_tab[2] = (octet_t)PP_RAM;
00586           if (ecrire_mot_mem(j,num_tab_pages,mot_tab) == -1) {
00587             liberer_page(num_page_mem);
00588             return -1;
00589           }
00590         }
00591         else if ((int)mot_tab[2] == PP_NULL)
00592           break;
00593       }
00594     }
00595     if (find_page == 0) {
00596       // La page rapatriee est une page de tampon
00597       num_mot = NUM_MOT_IN;
00598       if (lire_mot_mem(num_mot,num_tab_pages,mot_tab) == -1) {
00599         liberer_page(num_page_mem);
00600         return -1;
00601       }
00602       if (((int)mot_tab[3] != page) || ((int)mot_tab[2] != PP_SWAP)) {
00603         num_mot = NUM_MOT_OUT;
00604         if (lire_mot_mem(num_mot,num_tab_pages,mot_tab) == -1) {
00605           liberer_page(num_page_mem);
00606           return -1;
00607         }
00608         if (((int)mot_tab[3] != page) || ((int)mot_tab[2] != PP_SWAP)) {
00609           // La page rapatriee n'appartient pas au processus 'pid'
00610           fprintf(stderr,"La page %d en swap n'appartient pas au proc %d\n",page,pid);
00611           liberer_page(num_page_mem);
00612           return -1;
00613         }
00614       }
00615       mot_tab[3] = (octet_t)num_page_mem;
00616       mot_tab[2] = (octet_t)PP_RAM;
00617       if (ecrire_mot_mem(num_mot,num_tab_pages,mot_tab) == -1) {
00618         liberer_page(num_page_mem);
00619         return -1;
00620       }
00621     }
00622   }
00623   // Libere la page swap ramenee en memoire principale
00624   if (liberer_page_swap(page) == -1) 
00625     return -1;
00626   return num_page_mem;
00627 }
00628 
00629 /**
00630  * Fonction permettant de lire un mot se trouvant ds la mem principale
00631  * \param num_pp : Numero de la page physique en memoire ds laquelle on veut lire un mot
00632  * \param num_mot : Numero du mot qu'on veut lire ds cette page
00633  * \param mot : Structure qui sera remplie apres lecture
00634  * \return 
00635  * - -1 en cas d'erreur
00636  * -  0 sinon
00637  */
00638 int lire_mot_mem(int num_mot, int num_pp, mot_t mot) {
00639   unsigned char *p_mot;
00640 
00641   // Verifie que les coordonnees du mot sont valides
00642   if (num_pp < 0 || num_pp > NPP-1) {
00643     fprintf(stderr,"%d n'est pas un numero de page physique en memoire correct\n",num_pp);
00644     return -1;
00645   }
00646   if (num_mot < 0 || num_mot > NMPPP-1) {
00647     fprintf(stderr,"%d n'est pas un numero de mot correct\n",num_mot);
00648     return -1;
00649   }
00650   // Lecture du mot
00651   p_mot = mem[num_pp][num_mot];
00652   // Remplissage de la structure mot_t
00653   memcpy(mot,p_mot,sizeof(mot_t));
00654   // Mise a jour de la liste des pages memoire
00655   if ((num_pp != NUM_PAGE_META) && (num_pp != NUM_PAGE_SWAP)) {
00656     if (liste_acces_page(liste_pages,num_pp) != 0) {
00657       fprintf(stderr,"Tentative de lecture ds une page non reservee (%d)\n",num_pp);
00658       return -1;
00659     }
00660   }
00661   return 0;
00662 }
00663 
00664 /**
00665  * Fonction permettant d'ecrire un mot dans la mem principale
00666  * \param num_pp : Numero de la page physique en memoire ds laquelle on veut ecrire un mot
00667  * \param num_mot : Emplacement ds cette page ou on veut ecrire le mot
00668  * \param mot : Le mot a ecrire
00669  * \return 
00670  * - -1 en cas d'erreur
00671  * -  0 sinon
00672  */
00673 int ecrire_mot_mem(int num_mot, int num_pp, mot_t mot) {
00674   unsigned char *p_mot;
00675 
00676   // Verifie que les coordonnees du mot sont valides
00677   if (num_pp < 0 || num_pp > NPP-1) {
00678     fprintf(stderr,"%d n'est pas un numero de page physique en memoire correct\n",num_pp);
00679     return -1;
00680   }
00681   if (num_mot < 0 || num_mot > NMPPP-1) {
00682     fprintf(stderr,"%d n'est pas un numero de mot correct\n",num_mot);
00683     return -1;
00684   }
00685   // Ecriture du mot
00686   p_mot = mem[num_pp][num_mot];
00687   memcpy(p_mot,mot,sizeof(mot_t));
00688   // Mise a jour de la liste des pages memoire
00689   if ((num_pp != NUM_PAGE_META) && (num_pp != NUM_PAGE_SWAP)) {
00690     if (liste_acces_page(liste_pages,num_pp) != 0) {
00691       fprintf(stderr,"Tentative d'ecriture ds une page non reservee (%d)\n",num_pp);
00692       return -1;
00693     }
00694   }
00695   return 0;
00696 }
00697 
00698 /**
00699  *  Fonction retournant a partir d'une adresse virtuelle :
00700  * - le numero de la page physique a laquelle elle correspond
00701  * - le type (memoire principale ou secondaire) de cette page
00702  * \param pid : num du processus auquel appartient l'adresse virtuelle
00703  * \param ad_v : adresse virtuelle dont on veut connaitre l'adresse physique correspondante
00704  * \param info : structure qui sera remplie par l'adresse physique, son type et ses droits
00705  * \return 
00706  * - -1 en cas d'erreur
00707  * - -2 recherche en dehors de la pile
00708  * - 0  sinon
00709  */
00710 int adresse_phys (int pid, vad_t ad_v, info_mot_t *info) {
00711   int num_page, num_mot;
00712   mot_t mot;
00713   int taille;
00714 
00715   // Verifie la coherence de l'adresses virtuelle
00716   if ((ad_v.zone!=Z_CODE) && (ad_v.zone!=Z_PILE) && (ad_v.zone!=Z_DONNEES)) {
00717     fprintf(stderr,"Adresse virtuelle incoherente: zone inconnue\n");
00718     return -1;
00719   }
00720   if ((ad_v.num < 0) || (ad_v.num > T_MAX_ZONES*NMPPP)) {
00721     fprintf(stderr,"Adresse virtuelle incoherente: depassement de zone\n");
00722     return -1;
00723   }
00724   // Lecture de la table des pages du processus pid
00725   if (lire_mot_mem(pid,NUM_PAGE_META,mot) == -1)
00726     return -1;
00727   if (lire_etat(mot) == E_MORT) {
00728     // Ce num de processus ne correspond a aucune page physique
00729     fprintf(stderr,"Tentative de lecture d'une page d'un proc mort (%d)\n",pid);
00730     return -1;
00731   }
00732   switch (lire_type_pp(mot)) {
00733   case PP_SWAP:
00734     // La table des pages du processus pid se trouve ds le swap
00735     // On la ramene en mem principale
00736     if ((num_page=rapatrier_page_swap(pid,(int)mot[3])) == -1)
00737       return -1;
00738     else if (num_page == -2)
00739       // Il n'y a plus assez de mem pour lire la table des pages du processus
00740       // Impossible de continuer
00741       return -1;
00742     break;
00743   case PP_RAM:
00744     num_page = (int)mot[3];
00745     break;
00746   }
00747   // Regarde dans quelle zone se trouve l'adresse car le traitement des adresses de la pile 
00748   // ne se fait pas de la meme facon que pour celles de code ou de donnees
00749   if (ad_v.zone != Z_PILE) {
00750     num_mot = ad_v.zone*T_MAX_ZONES+ad_v.num/NMPPP;
00751     if (lire_mot_mem(num_mot, num_page, mot) == -1)
00752       return -1;
00753     // Remplissage de la structure info_mot_t
00754     info->type = (int)mot[2];
00755     info->page = (int)mot[3];
00756     info->mot = ad_v.num % NMPPP;
00757     return 0;
00758   }
00759   else {
00760     // Dans la pile les adresses se lisent a l'envers (P0 = haut de la pile)
00761     // Cherche le haut de la pile
00762     if ((taille=lire_esp(pid)) == -1)
00763       return -1;
00764     if (taille == 0) {
00765       // L'adresse virtuelle est incorrecte: il n'y a aucune donnees ds la pile
00766       fprintf(stderr,"Recherche de donnees ds une pile vide!\n");
00767       return -2;
00768     }
00769     if ((taille-ad_v.num) < 1) {
00770       // L'adresse virtuelle est incorrecte: reference un donnee hors de la pile
00771       fprintf(stderr,"Recherche de donnees en dehors de la pile\n");
00772       return -2;
00773     }
00774     num_mot = ad_v.zone*T_MAX_ZONES + ((taille-1) - ad_v.num)/NMPPP;
00775     if (lire_mot_mem(num_mot, num_page, mot) == -1)
00776       return -1;
00777     // Remplissage de la structure info_mot_t
00778     info->type = (int)mot[2];
00779     info->page = (int)mot[3];
00780     info->mot = ((taille-1) - ad_v.num) % NMPPP;
00781     return 0;
00782   }
00783 }
00784 
00785 /**
00786  * Fonction permettant d'ecrire une page dans la memoire swap
00787  * \param page : page a ecrire
00788  * \param num_page : numero de la page swap ou il faut ecrire
00789  * \return 
00790  * - -1 en cas d'erreur
00791  * - 0  sinon
00792  */
00793 int ecrire_page_swap (page_t page, int num_page) {
00794   if (lseek(swap_d,num_page*sizeof(page_t),SEEK_SET) == -1)
00795     return -1;
00796   if (write(swap_d,page,sizeof(page_t)) != sizeof(page_t))
00797     return -1;
00798   return 0;
00799 }
00800 
00801 /**
00802  * Fonction permettant de copier une page du swap dans la memoire princale
00803  * \param num_page_swap : numero de la page a copier
00804  * \param num_page_mem : numero de la page memoire dans laquelle on veut faire la copie
00805  * \return 
00806  * - -1 en cas d'erreur
00807  * - 0  sinon
00808  */
00809 int page_swap2mem (int num_page_swap, int num_page_mem) {
00810   if (lseek(swap_d,num_page_swap*T_PAGE,SEEK_SET) == (off_t)-1)
00811     return -1;
00812   if (read(swap_d,mem[num_page_mem],T_PAGE) != T_PAGE)
00813     return -1;
00814   return 0;
00815 }
00816 
00817 /**
00818  * Fonction permettant de copier une page de la mem princale ds le swap
00819  * \param num_page_mem : numero de la page a copier
00820  * \param num_page_swap : numero de la page swap dans laquelle on veut faire la copie
00821  * \return 
00822  * - -1 en cas d'erreur
00823  * - 0  sinon
00824  */
00825 int page_mem2swap (int num_page_mem, int num_page_swap) {
00826   if (lseek(swap_d,num_page_swap*T_PAGE,SEEK_SET) == -1)
00827     return -1;
00828   if (write(swap_d,mem[num_page_mem],T_PAGE) != T_PAGE)
00829     return -1;
00830   return 0;
00831 }
00832 
00833 /**
00834  * Fonction permettant d'ajouter une page a la table des pages d'un processus.
00835  * Cette page est ajoutee a la suite des pages deja presentes.
00836  * \param pid : numero du processus auquel on veut ajouter une page
00837  * \param zone : zone memoire du processus ou la page doit etre ajoutee
00838  * \param page : numero de la page en memoire principale a ajouter
00839  * \return 
00840  * - -1 en cas d'erreur
00841  * - -2 plus de place pour rajouter une page ds la zone voulue
00842  * - 0  en cas de succes
00843  */
00844 int page_add2proc (int pid, int zone, int page) {
00845   int num_page, num_mot;
00846   mot_t mot;
00847   int i;
00848 
00849   // Cherche le num de la table des pages du processus pid
00850   if (lire_mot_mem(pid,NUM_PAGE_META,mot) == -1)
00851     return -1;
00852   if (lire_etat(mot) == E_MORT) {
00853     // Ce num de processus ne correspond a aucune page physique
00854     fprintf(stderr,"Tentative de lecture d'une page d'un proc mort (%d)\n",pid);
00855     return -1;
00856   }
00857   switch (lire_type_pp(mot)) {
00858   case PP_SWAP:
00859     // La table des pages du processus pid se trouve ds le swap
00860     // On la ramene en mem principale
00861     if ((num_page=rapatrier_page_swap(pid,(int)mot[3])) < 0)
00862       return -1;
00863     break;
00864   case PP_RAM:
00865     num_page = (int)mot[3];
00866     break;
00867   }
00868   // Lecture de la table des pages
00869   num_mot = zone*T_MAX_ZONES;
00870   for (i=0 ; i<T_MAX_ZONES ; i++) {
00871     if (lire_mot_mem(num_mot, num_page, mot) == -1)
00872       return -1;
00873     if ((int)mot[2] == PP_NULL) {
00874       // 1er entree non attribuee ds cette table des pages du processus
00875       // On y met la page a ajouter
00876       mot[2] = (octet_t) PP_RAM;
00877       mot[3] = (octet_t) page;
00878       if (ecrire_mot_mem(num_mot, num_page, mot) == -1)
00879         return -1;
00880       return 0;
00881     }
00882     num_mot++;
00883   }
00884   // Il n'y a plus de place ds cette zone de la memoire du processus
00885   fprintf(stderr,"Il n'y a plus de place ds zone %d de memoire du processus %d\n",zone,pid);
00886   return -2;
00887 }
00888 
00889 /**
00890  * Fonction permettant de supprimer la derniere page d'une des zones memoire 
00891  * d'un processus. Cela consiste a:
00892  * - supprimer le mot qui lui correspond dans la table des pages du processus
00893  * - liberer cette page
00894  * \param pid : numero du processus auquel on veut supprimer une page
00895  * \param zone : zone memoire du processus ou la derniere page doit etre suprimer
00896  * \return 
00897  * - -1 en cas d'erreur
00898  * - -2 il n'y a pas de page a supprimer dans cette zone
00899  * - 0  en cas de succes
00900  */
00901 int page_supp2proc (int pid, int zone) {
00902   int num_page, num_mot;
00903   mot_t mot,mot_precedent;
00904 
00905   // Lecture de la table des pages du processus pid
00906   if (lire_mot_mem(pid,NUM_PAGE_META,mot) == -1)
00907     return -1;
00908   if (lire_etat(mot) == E_MORT) {
00909     // Ce num de processus ne correspond a aucune page physique
00910     fprintf(stderr,"Le processus %d n'est pas utilise\n",pid);
00911     return -1;
00912   }
00913   switch (lire_type_pp(mot)) {
00914   case PP_SWAP:
00915     // La table des pages du processus pid se trouve ds le swap
00916     // On la ramene en mem principale
00917     if ((num_page=rapatrier_page_swap(pid,(int)mot[3])) < 0)
00918       return -1;
00919     break;
00920   case PP_RAM:
00921     num_page = (int)mot[3];
00922     break;
00923   }
00924   // Suppression de la derniere page
00925   for (num_mot=zone*T_MAX_ZONES ; num_mot<(zone+1)*T_MAX_ZONES ; num_mot++) {
00926     if (lire_mot_mem(num_mot, num_page, mot) == -1)
00927       return -1;
00928     if ((int)mot[2] == PP_NULL) {
00929       // 1er entree non attribuee ds cette table des pages du processus
00930       if (num_mot%T_MAX_ZONES == 0) {
00931         // La zone dans laquelle on veut retirer une page n'en contient aucune
00932         fprintf(stderr,"Il n'y a pas de page a supprimer ds zone %d de memoire du processus %d\n",zone,pid);
00933         return -2;
00934       }
00935       // Si cette entree est vide, alors il faut supprimer l'entree precedente
00936       mot[2] = (octet_t) PP_NULL;
00937       if (ecrire_mot_mem(num_mot-1, num_page, mot) == -1)
00938         return -1;
00939       // Sort du for pour liberer la page
00940       break;
00941     }
00942     else {
00943       // Ce mot correspond a une page utilisee. Il s'agit peut etre de la derniere page
00944       // de la zone. Alors on memorise ses coordonnees.
00945       memcpy(mot_precedent,mot,sizeof(mot_t));
00946     }
00947   }
00948   if (num_mot == (zone+1)*T_MAX_ZONES) {
00949     // Le mot a supprimer est le dernier
00950     mot[2] = (octet_t) PP_NULL;
00951     if (ecrire_mot_mem(num_mot-1, num_page, mot) == -1)
00952       return -1;
00953   }
00954   // Liberation de la page
00955   switch ((int)mot_precedent[2]) {
00956   case PP_RAM:
00957     if (liberer_page((int)mot_precedent[3]) != 0) {
00958       // Remet la table des pages ds son etat premier
00959       ecrire_mot_mem(num_mot-1, num_page, mot_precedent);
00960       return -1;
00961     }
00962     return 0;
00963   case PP_SWAP:
00964     if (liberer_page_swap((int)mot_precedent[3]) != 0) {
00965       // Remet la table des pages ds son etat premier
00966       ecrire_mot_mem(num_mot-1, num_page, mot_precedent);
00967       return -1;
00968     }
00969     return 0;
00970   default:
00971     fprintf(stderr,"Table des pages du processus %d incoherente\n",pid);
00972     return -1;
00973   }
00974 }
00975 
00976 /**
00977  * Fonction permettant de lire un mot a partir d'une adresse virtuelle (si elle correspond a
00978  * une page physique existante).
00979  * \param pid : numero du processus auquel appartient la page dont on veut lire un mot
00980  * \param ad_v : adresse virtuelle du mot a lire
00981  * \param mot : structure dans laquelle on stocke le mot lu
00982  * \return 
00983  * - -1 en cas d'erreur
00984  * - -2 le mot ne fait pas parti de l'espace mem du processus (cependant il a qd meme ete lu
00985  *      si il fait parti de la zone de code ou de donnees)
00986  * - 0  sinon
00987  */
00988 int lire_mot (int pid, vad_t ad_v, mot_t mot) {
00989   info_mot_t info;
00990   int num_page;
00991 
00992   // Recherche l'adresse physique du mot
00993   switch (adresse_phys (pid, ad_v, &info)) {
00994   case -1:
00995     return -1;
00996   case -2:
00997     return -2;
00998   }
00999   // Rapatrie eventuellement le mot en memoire principale
01000   switch (info.type) {
01001   case PP_SWAP:
01002     if ((num_page=rapatrier_page_swap(pid,info.page)) < 0)
01003       return -1;
01004     break;
01005   case PP_RAM:
01006     num_page = info.page;
01007     break;
01008   case PP_NULL:
01009     fprintf(stderr,"Tentative de lecture d'une page inexistante\n");
01010     return -1;
01011   default:
01012     fprintf(stderr,"Table des pages du processus %d incoherente\n",pid);
01013     return -1;
01014   }
01015   if (lire_mot_mem(info.mot,num_page,mot) == -1)
01016     return -1;
01017   // Verifie que le mot fait bien parti de l'espace mem du processus
01018   if ((int)mot[0] == M_NU)
01019     return -2;
01020   return 0;
01021 }
01022 
01023 /**
01024  * Fonction qui ecrit un mot a partir d'une adresse virtuelle. Il faut que cette adresse virtuelle
01025  * reference une adresse physique existante car elle ne cree pas de page automatiquement.
01026  * Le mot ecrit est systematiquement marque comme utilise car la fonction ne sert pas a diminuer 
01027  * l'espace memoire du processus.
01028  * \param pid : Numero du processus auquel appartient la page dans laquelle on veut ecrire un mot
01029  * \param ad_v : Adresse virtuelle du mot a ecrire
01030  * \param mot : Le mot a ecrire
01031  * \return 
01032  * - -1 en cas d'erreur
01033  * - -2 en cas d'ecriture en dehors de l'espace mem
01034  * - 0  sinon
01035  */
01036 int ecrire_mot (int pid, vad_t ad_v, mot_t mot) {
01037   info_mot_t info;
01038   int num_page;
01039   mot_t mot_lu;
01040 
01041   // Verifie qu'on a les droits en ecriture
01042   if (ad_v.zone == Z_CODE) {
01043     fprintf(stderr,"Impossible de modifier la zone de code\n");
01044     return -1;
01045   }
01046   // Recherche l'adresse physique du mot
01047   switch (adresse_phys (pid, ad_v,&info)) {
01048   case -1:
01049     return -1;
01050   case -2:
01051     return -2;
01052   }
01053   // Rapatrie eventuellement la page contenant le mot en memoire principale
01054   switch (info.type) {
01055   case PP_SWAP:
01056     if ((num_page=rapatrier_page_swap(pid,info.page)) < 0)
01057       return -1;
01058     break;
01059   case PP_RAM:
01060     num_page = info.page;
01061     break;
01062   case PP_NULL:
01063     fprintf(stderr,"Tentative d'ecriture dans une page inexistante\n");
01064     return -1;
01065   default:
01066     fprintf(stderr,"Table des pages du processus %d incoherente\n",pid);
01067     return -1;
01068   }
01069   // Verifie que le mot est ds l'espave mem du proc
01070   if (lire_mot_mem(info.mot,num_page,mot_lu) == -1)
01071     return -1;
01072   if ((int)mot_lu[0] == M_NU)
01073     return -2;
01074   // Verifie que le mot a ecrire n'est pas marque comme inutilise
01075   if ((int)mot[0] ==  M_NU)
01076     mot[0] = M_UT;
01077   // Ecrit le mot
01078   if (ecrire_mot_mem(info.mot,num_page,mot) == -1)
01079     return -1;
01080   return 0;
01081 }
01082 
01083 /**
01084  * Fonction permettant de modifier le pid du processus pere.
01085  * Le ppid devrait se trouver dans la table des processus. Cependant, faute de place, il
01086  * est stockee dans un mot inutilise (le NUM_MOT_PPID+1 eme) de la table des pages de chaque
01087  * processus.
01088  * \param pid : num du processus
01089  * \param ppid : le nouveau num du processus pere
01090  * \return 
01091  * - -1 en cas d'erreur
01092  * - 0  sinon
01093  */
01094 int changer_ppid (int pid, int ppid) {
01095   mot_t mot;
01096   int num_tab_pages;
01097 
01098   // Cherche la table des pages du processus
01099   if (lire_mot_mem(pid,NUM_PAGE_META,mot) == -1)
01100     return -1;
01101   if (lire_etat(mot) == E_MORT) {
01102     fprintf(stderr,"Acces a un processus mort (%d)\n",pid);
01103     return -1;
01104   }
01105   switch (lire_type_pp(mot)) {
01106   case PP_RAM:
01107     num_tab_pages = mot[3];
01108     break;
01109   case PP_SWAP:
01110     // Ramene la table des pages du proc en mem RAM
01111     if ((num_tab_pages=rapatrier_page_swap(pid,(int)mot[3])) < 0)
01112       return -1;
01113     break;
01114   }
01115   // Ecrit le nouveau num du processus pere
01116   mot[3] = (octet_t)ppid;
01117   if (ecrire_mot_mem(NUM_MOT_PPID,num_tab_pages,mot) == -1)
01118     return -1;
01119   return 0;
01120 }
01121 
01122 /**
01123  * Fonction permettant de lire le pid du processus pere.
01124  * Le ppid devrait se trouver dans la table des processus. Cependant, faute de place, il
01125  * est stockee dans un mot inutilise (le NUM_MOT_PPID+1 eme) de la table des pages de chaque
01126  * processus.
01127  * \param pid : num du processus
01128  * \return 
01129  * - -1 en cas d'erreur
01130  * - le ppid  sinon
01131  */
01132 int lire_ppid (int pid) {
01133   mot_t mot;
01134   int num_tab_pages;
01135 
01136   // Cherche la table des pages du processus
01137   if (lire_mot_mem(pid,NUM_PAGE_META,mot) == -1)
01138     return -1;
01139   if (lire_etat(mot) == E_MORT) {
01140     return -1;
01141   }
01142   switch (lire_type_pp(mot)) {
01143   case PP_RAM:
01144     num_tab_pages = mot[3];
01145     break;
01146   case PP_SWAP:
01147     // Ramene la table des pages du proc en mem RAM
01148     if ((num_tab_pages=rapatrier_page_swap(pid,(int)mot[3])) < 0)
01149       return -1;
01150     break;
01151   }
01152   // Lit le num du processus pere
01153   if (lire_mot_mem(NUM_MOT_PPID,num_tab_pages,mot) == -1)
01154     return -1;
01155   return (int)mot[3];
01156 }
01157 
01158 /**
01159  * Modifie la hauteur de la pile.\n
01160  * Cette hauteur devrait se trouver dans la table des processus. Cependant, faute de place,
01161  * elle est stockee dans un mot inutilise (le NUM_MOT_ESP+1 eme) de la table des pages de 
01162  * chaque processus.\n
01163  * En plus de modifier la taille, la fonction met aussi a jour la pile en:
01164  * - marquant le dernier mot de la pile comme non utilise en cas de decrementattion \n
01165  *   supprime eventuellement une page physique.
01166  * - marquant le 1er mot au-dela de la pile comme utilise en cas d'incrementation \n
01167  *   rajoute eventuellement une page physique.
01168  * \param pid : numero du processus dont on veut connaitre la hauteur de pile
01169  * \param op : operation (incremente / decremente) a realiser sur la pile
01170  * \return 
01171  * - -1 en cas d'erreur
01172  * - 0 sinon
01173  */
01174 int changer_esp (int pid, int op) {
01175   mot_t mot, mot_pile, mot_reg;
01176   int num_tab_pages;
01177   int taille,modif;
01178   int num_p_pile;
01179   int i;
01180 
01181   // Verifie que l'operation est correcte
01182   if ((op != 1) && (op != -1)) {
01183     fprintf(stderr,"Operation sur la pile du processus %d illegale\n",pid);
01184     return -1;
01185   }
01186   // Cherche la table des pages du processus
01187   if (lire_mot_mem(pid,NUM_PAGE_META,mot) == -1)
01188     return -1;
01189   if (lire_etat(mot) == E_MORT) {
01190     fprintf(stderr,"Acces a un processus mort (%d)\n",pid);
01191     return -1;
01192   }
01193   switch (lire_type_pp(mot)) {
01194   case PP_RAM:
01195     num_tab_pages = mot[3];
01196     break;
01197   case PP_SWAP:
01198     // Ramene la table des pages du proc en mem RAM
01199     if ((num_tab_pages=rapatrier_page_swap(pid,(int)mot[3])) < 0)
01200       return -1;
01201     break;
01202   }
01203   // Lit la taille de la pile
01204   if (lire_mot_mem(NUM_MOT_ESP,num_tab_pages,mot_reg) == -1)
01205     return -1;
01206   // Verifie qu'il est possible de realisre l'operation voulue
01207   taille = (int)mot_reg[3];
01208   if ((op == 1) && (taille == SP_MAX)) {
01209     fprintf(stderr,"Impossible d'incrementer la pile du proc %d: pile pleine\n",pid);
01210     return -1;
01211   }
01212   else if ((op == -1) && (taille == 0)) {
01213     fprintf(stderr,"Impossible de decrementer la pile du proc %d: pile vide\n",pid);
01214     return -1;
01215   }
01216   // Modifie la taille de la pile
01217   taille += op;
01218   mot_reg[3] = (octet_t)taille;
01219   if (ecrire_mot_mem(NUM_MOT_ESP,num_tab_pages,mot_reg) == -1)
01220     return -1;
01221   // MAJ de la pile
01222   if (op == -1) { // Operation de decrementation
01223     modif = taille;
01224     // Lit la derniere page de la pile
01225     if (lire_mot_mem(modif/NMPPP+2*T_MAX_ZONES,num_tab_pages,mot_pile) == -1) {
01226       mot_reg[3] = (octet_t)taille - op;
01227       ecrire_mot_mem(NUM_MOT_ESP,num_tab_pages,mot_reg);
01228       return -1;
01229     }
01230     if ((modif % NMPPP) == 0) {
01231       // On supprime la derniere page de la pile
01232       switch ((int)mot_pile[2]) {
01233       case PP_RAM:
01234         // Modifie la table des pages
01235         mot_pile[2] = (octet_t)PP_NULL;
01236         if (ecrire_mot_mem(modif/NMPPP+2*T_MAX_ZONES,num_tab_pages,mot_pile) == -1) {
01237           mot_reg[3] = (octet_t)taille - op;
01238           ecrire_mot_mem(NUM_MOT_ESP,num_tab_pages,mot_reg);
01239           return -1;
01240         }
01241         // Libere la page
01242         if (liberer_page((int)mot_pile[3]) == -1) {
01243           mot_reg[3] = (octet_t)taille - op;
01244           ecrire_mot_mem(NUM_MOT_ESP,num_tab_pages,mot_reg);
01245           mot_pile[2] = (octet_t)PP_RAM;
01246           ecrire_mot_mem(modif/NMPPP+2*T_MAX_ZONES,num_tab_pages,mot_pile);
01247           return -1;
01248         }
01249         return 0;
01250       case PP_SWAP:
01251         // Modifie la table des pages
01252         mot_pile[2] = (octet_t)PP_NULL;
01253         if (ecrire_mot_mem(modif/NMPPP+2*T_MAX_ZONES,num_tab_pages,mot_pile) == -1) {
01254           mot_reg[3] = (octet_t)taille - op;
01255           ecrire_mot_mem(NUM_MOT_ESP,num_tab_pages,mot_reg);
01256           return -1;
01257         }
01258         // Libere la page
01259         if (liberer_page_swap((int)mot_pile[3]) == -1) {
01260           mot_reg[3] = (octet_t)taille - op;
01261           ecrire_mot_mem(NUM_MOT_ESP,num_tab_pages,mot_reg);
01262           mot_pile[2] = (octet_t)PP_SWAP;
01263           ecrire_mot_mem(modif/NMPPP+2*T_MAX_ZONES,num_tab_pages,mot_pile);
01264           return -1;
01265         }
01266         return 0;
01267       default:
01268         fprintf(stderr,"Table des pages du proc %d incoherente\n",pid);
01269         mot_reg[3] = (octet_t)taille - op;
01270         ecrire_mot_mem(NUM_MOT_ESP,num_tab_pages,mot_reg);
01271         return -1;
01272       }
01273     }
01274     else {
01275       // On marque le dernier mot de la pile comme inutilise
01276       switch ((int)mot_pile[2]) {
01277       case PP_RAM:
01278         num_p_pile = (int)mot_pile[3];
01279         break;
01280       case PP_SWAP:
01281         if ((num_p_pile=rapatrier_page_swap(pid,(int)mot_pile[3])) < 0) {
01282           mot_reg[3] = (octet_t)taille - op;
01283           ecrire_mot_mem(NUM_MOT_ESP,num_tab_pages,mot_reg);
01284           return -1;
01285         }
01286         break;
01287       default:
01288         fprintf(stderr,"Table des pages du proc %d incoherente\n",pid);
01289         mot_reg[3] = (octet_t)taille - op;
01290         ecrire_mot_mem(NUM_MOT_ESP,num_tab_pages,mot_reg);
01291         return -1;
01292       }
01293       mot_pile[0]  = (octet_t)M_NU;
01294       if (ecrire_mot_mem(modif%NMPPP,num_p_pile,mot_pile) == -1) {
01295         mot_reg[3] = (octet_t)taille - op;
01296         ecrire_mot_mem(NUM_MOT_ESP,num_tab_pages,mot_reg);
01297         return -1;
01298       }
01299     }
01300   }
01301   if (op == 1) { // Operation d'incrementation
01302     modif = taille-1;
01303     if ((modif % NMPPP) == 0) {
01304       // On rajoute une nouvelle page a la pile
01305       if ((num_p_pile = page_forcee(pid)) < 0) {
01306         mot_reg[3] = (octet_t)taille - op;
01307         ecrire_mot_mem(NUM_MOT_ESP,num_tab_pages,mot_reg);
01308         return -1;
01309       }
01310       mot_pile[3] = (octet_t)num_p_pile;
01311       mot_pile[2] = (octet_t)PP_RAM;
01312       if (ecrire_mot_mem(modif/NMPPP+2*T_MAX_ZONES, num_tab_pages, mot_pile) == -1) {
01313         mot_reg[3] = (octet_t)taille - op;
01314         ecrire_mot_mem(NUM_MOT_ESP,num_tab_pages,mot_reg);
01315         liberer_page(num_p_pile);
01316         return -1;
01317       }
01318       // Initialise cette nouvelle page de pile
01319       mot_pile[3] = (octet_t)0;
01320       mot_pile[2] = (octet_t)0;
01321       for (i=0 ; i<NMPPP ; i++) {
01322         if (i == 0)
01323           mot_pile[0] = (octet_t)M_UT;
01324         else
01325           mot_pile[0] = (octet_t)M_NU;
01326         if (ecrire_mot_mem(i, num_p_pile, mot_pile) == -1) {
01327           // Annule l'operation sur la taille de la pile
01328           mot_reg[3] = (octet_t)taille - op;
01329           ecrire_mot_mem(NUM_MOT_ESP,num_tab_pages,mot_reg);
01330           // Libere la page allouee
01331           liberer_page(num_p_pile);
01332           // Supprime cette page de la table des pages du proc
01333           mot_pile[2] = (octet_t)PP_NULL;
01334           ecrire_mot_mem(modif/NMPPP+2*T_MAX_ZONES, num_tab_pages, mot_pile);
01335           return -1;
01336         }
01337       }
01338       return 0;
01339     }
01340     else {
01341       // Lit la derniere page de la pile pour la modifier
01342       if (lire_mot_mem(modif/NMPPP+2*T_MAX_ZONES,num_tab_pages,mot_pile) == -1) {
01343         mot_reg[3] = (octet_t)taille - op;
01344         ecrire_mot_mem(NUM_MOT_ESP,num_tab_pages,mot_reg);
01345         return -1;
01346       }
01347       // On marque le dernier mot de la pile agrandie comme utilise
01348       switch ((int)mot_pile[2]) {
01349       case PP_RAM:
01350         num_p_pile = (int)mot_pile[3];
01351         break;
01352       case PP_SWAP:
01353         if ((num_p_pile=rapatrier_page_swap(pid,(int)mot_pile[3])) < 0) {
01354           mot_reg[3] = (octet_t)taille - op;
01355           ecrire_mot_mem(NUM_MOT_ESP,num_tab_pages,mot_reg);
01356           return -1;
01357         }
01358         break;
01359       default:
01360         fprintf(stderr,"Table des pages du proc %d incoherente\n",pid);
01361         mot_reg[3] = (octet_t)taille - op;
01362         ecrire_mot_mem(NUM_MOT_ESP,num_tab_pages,mot_reg);
01363         return -1;
01364       }
01365       mot_pile[0]  = (octet_t)M_UT;
01366       mot_pile[3] = (octet_t)0;
01367       mot_pile[2] = (octet_t)0;
01368       if (ecrire_mot_mem(modif%NMPPP,num_p_pile,mot_pile) == -1) {
01369         mot_reg[3] = (octet_t)taille - op;
01370         ecrire_mot_mem(NUM_MOT_ESP,num_tab_pages,mot_reg);
01371         return -1;
01372       }
01373     }
01374   }
01375   return 0;
01376 }
01377 
01378 /**
01379  * Retourne la hauteur de la pile.
01380  * Cette hauteur devrait se trouver dans la table des processus. Cependant, faute de place,
01381  * elle est stockee dans un mot inutilise (le NUM_MOT_ESP+1 eme) de la table des pages de 
01382  * chaque processus.\n
01383  * \param pid : numero du processus dont on veut connaitre la hauteur de pile
01384  * \return 
01385  * - -1 en cas d'erreur
01386  * - la hauteur sinon
01387  */
01388 int lire_esp (int pid) {
01389   mot_t mot;
01390   int num_tab_pages;
01391 
01392   // Cherche la table des pages du processus
01393   if (lire_mot_mem(pid,NUM_PAGE_META,mot) == -1)
01394     return -1;
01395   if (lire_etat(mot) == E_MORT) {
01396     fprintf(stderr,"Acces a un processus mort (%d)\n",pid);
01397     return -1;
01398   }
01399   switch (lire_type_pp(mot)) {
01400   case PP_RAM:
01401     num_tab_pages = mot[3];
01402     break;
01403   case PP_SWAP:
01404     // Ramene la table des pages du proc en mem RAM
01405     if ((num_tab_pages=rapatrier_page_swap(pid,(int)mot[3])) < 0)
01406       return -1;
01407     break;
01408   }
01409   // Lit la taille de la pile
01410   if (lire_mot_mem(NUM_MOT_ESP,num_tab_pages,mot) == -1)
01411     return -1;
01412   return (int)mot[3];
01413 }
01414 
01415 /**
01416  * Verrouille un tampon:
01417  * - Verifie que le tampmon n'est pas deja verrouille
01418  * - Vourrouille le tampon
01419  * \param pid : num du processus
01420  * \param num_p_tampon : num du mot ds la table des pages du processus correspondant au tampon
01421  * \return 
01422  * - -1 en cas d'erreur
01423  * - -3 le tampon est deja verrouille
01424  * - 0  sinon
01425  */
01426 int verrouiller_tampon (int pid, int num_tampon) {
01427   mot_t mot;
01428   int num_tab_pages;
01429 
01430   if ((num_tampon != NUM_MOT_IN) && (num_tampon != NUM_MOT_OUT)) {
01431     return -1;
01432   }
01433   // Cherche la table des pages du processus
01434   if (lire_mot_mem(pid,NUM_PAGE_META,mot) == -1)
01435     return -1;
01436   if (lire_etat(mot) == E_MORT) {
01437     fprintf(stderr,"Acces a un processus mort (%d)\n",pid);
01438     return -1;
01439   }
01440   switch (lire_type_pp(mot)) {
01441   case PP_RAM:
01442     num_tab_pages = mot[3];
01443     break;
01444   case PP_SWAP:
01445     // Ramene la table des pages du proc en mem RAM
01446     if ((num_tab_pages=rapatrier_page_swap(pid,(int)mot[3])) < 0)
01447       return -1;
01448     break;
01449   }
01450   // Verifie que le tampon n'est pas deja verrouille
01451   if (lire_mot_mem(num_tampon+1,num_tab_pages,mot) == -1)
01452     return -1;
01453   if ((int)mot[3] == F_LOCK) 
01454     return -3;
01455   // Verrouille le tampon
01456   mot[3] = (octet_t)F_LOCK;
01457   if (ecrire_mot_mem(num_tampon+1,num_tab_pages,mot) == -1)
01458     return -1;
01459   return 0;
01460 }
01461 
01462 /**
01463  * Deverrouille un tampon:
01464  * - Deverrouille le tampon
01465  * - Reveille un processus ds l'etat E_ATT_LECT ou E_ATT_ECRIT
01466  * \param pid : num du processus
01467  * \param num_p_tampon : num du mot ds la table des pages du processus correspondant au tampon
01468  * \return 
01469  * - -1 en cas d'erreur
01470  * - 0  sinon
01471  */
01472 int deverrouiller_tampon (int pid, int num_tampon) {
01473   mot_t mot;
01474   int num_tab_pages;
01475   int i;
01476   int etat;
01477 
01478   if ((num_tampon != NUM_MOT_IN) && (num_tampon != NUM_MOT_OUT)) {
01479     return -1;
01480   }
01481   // Cherche la table des pages du processus
01482   if (lire_mot_mem(pid,NUM_PAGE_META,mot) == -1)
01483     return -1;
01484   if (lire_etat(mot) == E_MORT) {
01485     fprintf(stderr,"Acces a un processus mort (%d)\n",pid);
01486     return -1;
01487   }
01488   switch (lire_type_pp(mot)) {
01489   case PP_RAM:
01490     num_tab_pages = mot[3];
01491     break;
01492   case PP_SWAP:
01493     // Ramene la table des pages du proc en mem RAM
01494     if ((num_tab_pages=rapatrier_page_swap(pid,(int)mot[3])) < 0)
01495       return -1;
01496     break;
01497   }
01498   // Deverrouille le tampon
01499   mot[3] = (octet_t)F_UNLOCK;
01500   if (ecrire_mot_mem(num_tampon+1,num_tab_pages,mot) == -1)
01501     return -1;
01502   // Reveille le processus pid s'il etait en attente de lecture / ecriture
01503   switch (num_tampon) {
01504   case NUM_MOT_IN:
01505     etat = E_ATT_LECT;
01506     break;
01507   case NUM_MOT_OUT:
01508     etat = E_ATT_ECRIT;
01509     break;
01510   }
01511   if (lire_mot_mem(pid,NUM_PAGE_META,mot) != -1) {
01512     if (lire_etat(mot) == etat) {
01513       // Reveille le processus i
01514       liste_add_pid(liste_proc,pid);
01515       // MAJ la table des processus
01516       changer_etat(E_ELIGIBLE,mot);
01517       if (ecrire_mot_mem(i,NUM_PAGE_META,mot) != -1)
01518         return 0;
01519       liste_supp_pid(liste_proc,i);
01520     }
01521   }
01522   return 0;
01523 }
01524 
01525 /**
01526  * Fonction qui ecrit un caractere dans le tampon d'entree d'un processus.\n
01527  * Elle est non bloquante.\n
01528  * A la fin, reveille le proc pid s'il etait en E_ATT_LECT.
01529  * \param pid : num du processus
01530  * \param c : le caractere a ecrire
01531  * \return 
01532  * - -1 en cas d'erreur inconnue
01533  * - -2 plus de place dans le tampon
01534  * - -3 tampon verrouille
01535  * - 0  sinon
01536  */
01537 int ecrire_stdin (int pid, char c) {
01538   mot_t mot,mot_tampon;
01539   int num_tab_pages,num_p_tampon;
01540   int deb, longueur,fin;
01541 
01542   // Cherche la table des pages du processus
01543   if (lire_mot_mem(pid,NUM_PAGE_META,mot) == -1)
01544     return -1;
01545   if (lire_etat(mot) == E_MORT) {
01546     fprintf(stderr,"Tentative d'ecriture dans une page d'un processus mort (%d)\n",pid);
01547     return -1;
01548   }
01549   switch (lire_type_pp(mot)) {
01550   case PP_RAM:
01551     num_tab_pages = mot[3];
01552     break;
01553   case PP_SWAP:
01554     // Ramene la table des pages du proc en mem RAM
01555     if ((num_tab_pages=rapatrier_page_swap(pid,(int)mot[3])) < 0)
01556       return -1;
01557     break;
01558   }
01559   // Verrouille le tampon
01560   switch (verrouiller_tampon(pid,NUM_MOT_IN)) {
01561   case -1:
01562     return -1;
01563   case -3:
01564     return -3;
01565   }
01566   // Cherche la page contenant le tampon d'entree
01567   if (lire_mot_mem(NUM_MOT_IN,num_tab_pages,mot) == -1) {
01568     deverrouiller_tampon(pid,NUM_MOT_IN);
01569     return -1;
01570   }
01571   switch ((int)mot[2]) {
01572   case PP_NULL:
01573     // On n'a encore jamais rien ecrit ds le tampon
01574     if ((num_p_tampon=page_forcee(pid)) < 0) {
01575       deverrouiller_tampon(pid,NUM_MOT_IN);
01576       return -1;
01577     }
01578     // Met a jour la table des pages
01579     mot[0] = 0;
01580     mot[1] = 0;
01581     mot[2] = PP_RAM;
01582     mot[3] = num_p_tampon;
01583     if (ecrire_mot_mem(NUM_MOT_IN,num_tab_pages,mot) == -1) {
01584       deverrouiller_tampon(pid,NUM_MOT_IN);
01585       liberer_page(num_p_tampon);
01586       return -1;
01587     }
01588     break;
01589   case PP_SWAP:
01590     //On rapatrie le tampon en mem RAM
01591     if ((num_p_tampon=rapatrier_page_swap(pid,(int)mot[3])) < 0) {
01592       deverrouiller_tampon(pid,NUM_MOT_IN);
01593       return -1;
01594     }
01595     break;
01596   case PP_RAM:
01597     num_p_tampon = (int)mot[3];
01598     break;
01599   default:
01600     fprintf(stderr,"Table des pages %d du processus %d incoherente\n",num_tab_pages,pid);
01601     deverrouiller_tampon(pid,NUM_MOT_IN);
01602     return -1;
01603   }
01604   deb = (int)mot[0];
01605   longueur = (int)mot[1];
01606   // Teste s'il reste de la place
01607   if (longueur == T_MAX_TAMPON) {
01608     deverrouiller_tampon(pid,NUM_MOT_IN);
01609     return -2;
01610   }
01611   fin = (deb + longueur) % T_MAX_TAMPON;
01612   // On ecrit le caractere
01613   if (lire_mot_mem(fin/T_MOT,num_p_tampon,mot_tampon) == -1) {
01614     deverrouiller_tampon(pid,NUM_MOT_IN);
01615     return -1;
01616   }
01617   mot_tampon[fin%T_MOT] = (octet_t)c;
01618   if (ecrire_mot_mem(fin/T_MOT,num_p_tampon,mot_tampon) == -1) {
01619     deverrouiller_tampon(pid,NUM_MOT_IN);
01620     return -1;
01621   }
01622   // MAJ de la table des pages
01623   mot[1] = (octet_t)longueur+1;
01624   if (ecrire_mot_mem(NUM_MOT_IN,num_tab_pages,mot) == -1) {
01625     deverrouiller_tampon(pid,NUM_MOT_IN);
01626     return -1;
01627   }
01628   // Deverrouille le tampon
01629   if (deverrouiller_tampon(pid,NUM_MOT_IN) == -1)
01630     return -1;
01631   // Reveille le proc pid s'il etait en E_ATT_LECT.
01632   if (lire_mot_mem(pid,NUM_PAGE_META,mot) != -1) {
01633     if (lire_etat(mot) == E_ATT_LECT) {
01634       // Reveille le processus i
01635       liste_add_pid(liste_proc,pid);
01636       // MAJ la table des processus
01637       changer_etat(E_ELIGIBLE,mot);
01638       if (ecrire_mot_mem(pid,NUM_PAGE_META,mot) != -1)
01639         return 0;
01640       liste_supp_pid(liste_proc,pid);
01641     }
01642   }
01643   return 0;
01644 }
01645 
01646 /**
01647  * Fonction qui lit un caractere dans le tampon d'entree d'un processus.\n
01648  * La fonction n'est pas bloquante mais elle retourne un code d'erreur qui permet
01649  * a la fonction appelante de bloquer le processus (E_ATT_LECT). 
01650  * \param pid : num du processus
01651  * \param c : le caractere a lire
01652  * \return 
01653  * - -1 en cas d'erreur inconnue
01654  * - -2 rien a lire
01655  * - -3 tampon verrouille
01656  * - 0  sinon
01657  */
01658 int lire_stdin (int pid, char* c) {
01659   mot_t mot,mot_tampon;
01660   int num_tab_pages,num_p_tampon;
01661   int deb, longueur;
01662 
01663   // Cherche la table des pages du processus
01664   if (lire_mot_mem(pid,NUM_PAGE_META,mot) == -1)
01665     return -1;
01666   if (lire_etat(mot) == E_MORT) {
01667     fprintf(stderr,"Tentative d'ecriture dans une page d'un processus mort (%d)\n",pid);
01668     return -1;
01669   }
01670   switch (lire_type_pp(mot)) {
01671   case PP_RAM:
01672     num_tab_pages = mot[3];
01673     break;
01674   case PP_SWAP:
01675     // Ramene la table des pages du proc en mem RAM
01676     if ((num_tab_pages=rapatrier_page_swap(pid,(int)mot[3])) < 0)
01677       return -1;
01678     break;
01679   }
01680   // Verrouille le tampon
01681   switch (verrouiller_tampon(pid,NUM_MOT_IN)) {
01682   case -1:
01683     return -1;
01684   case -3:
01685     return -3;
01686   }
01687   // Cherche la page contenant le tampon d'entree
01688   if (lire_mot_mem(NUM_MOT_IN,num_tab_pages,mot) == -1) {
01689     deverrouiller_tampon(pid,NUM_MOT_IN);
01690     return -1;
01691   }
01692   switch ((int)mot[2]) {
01693   case PP_NULL:
01694     // On n'a encore jamais rien ecrit ds le tampon
01695     deverrouiller_tampon(pid,NUM_MOT_IN);
01696     return -2;
01697   case PP_SWAP:
01698     //On rapatrie le tampon en mem RAM
01699     if ((num_p_tampon=rapatrier_page_swap(pid,(int)mot[3])) < 0) {
01700       deverrouiller_tampon(pid,NUM_MOT_IN);
01701       return -1;
01702     }
01703     break;
01704   case PP_RAM:
01705     num_p_tampon = (int)mot[3];
01706     break;
01707   default:
01708     fprintf(stderr,"Table des pages %d du processus %d incoherente\n",num_tab_pages,pid);
01709     deverrouiller_tampon(pid,NUM_MOT_IN);
01710     return -1;
01711   }
01712   deb = (int)mot[0];
01713   longueur = (int)mot[1];
01714   // Teste s'il y a quelque chose a lire
01715   if (longueur == 0) {
01716     deverrouiller_tampon(pid,NUM_MOT_IN);
01717     return -2;
01718   }
01719   // On lit le caractere
01720   if (lire_mot_mem(deb/T_MOT,num_p_tampon,mot_tampon) == -1) {
01721     deverrouiller_tampon(pid,NUM_MOT_IN);
01722     return -1;
01723   }
01724   *c = (char)mot_tampon[deb%T_MOT];
01725   // MAJ de la table des pages
01726   mot[0] = (octet_t)deb+1;
01727   mot[1] = (octet_t)longueur-1;
01728   if (ecrire_mot_mem(NUM_MOT_IN,num_tab_pages,mot) == -1) {
01729     deverrouiller_tampon(pid,NUM_MOT_IN);
01730     return -1;
01731   }
01732   // Deverrouille le tampon
01733   if (deverrouiller_tampon(pid,NUM_MOT_IN) == -1)
01734     return -1;
01735   return 0;
01736 }
01737 
01738 /**
01739  * Fonction qui ecrit un caractere dans le tampon d'entree d'un processus.\n
01740  * La fonction n'est pas bloquante mais elle retourne un code d'erreur qui permet
01741  * a la fonction appelante de bloquer le processus (E_ATT_ECRIT). 
01742  * \param pid : num du processus
01743  * \param c : le caractere a ecrire
01744  * \return 
01745  * - -1 en cas d'erreur inconnue
01746  * - -2 plus de place dans le tampon
01747  * - -3 tampon verrouille
01748  * - 0  sinon
01749  */
01750 int ecrire_stdout (int pid, char c) {
01751   mot_t mot,mot_tampon;
01752   int num_tab_pages,num_p_tampon;
01753   int deb, longueur,fin;
01754 
01755   // Cherche la table des pages du processus
01756   if (lire_mot_mem(pid,NUM_PAGE_META,mot) == -1)
01757     return -1;
01758   if (lire_etat(mot) == E_MORT) {
01759     fprintf(stderr,"Tentative d'ecriture dans une page d'un processus mort (%d)\n",pid);
01760     return -1;
01761   }
01762   switch (lire_type_pp(mot)) {
01763   case PP_RAM:
01764     num_tab_pages = mot[3];
01765     break;
01766   case PP_SWAP:
01767     // Ramene la table des pages du proc en mem RAM
01768     if ((num_tab_pages=rapatrier_page_swap(pid,(int)mot[3])) < 0)
01769       return -1;
01770     break;
01771   }
01772   // Verrouille le tampon
01773   switch (verrouiller_tampon(pid,NUM_MOT_OUT)) {
01774   case -1:
01775     return -1;
01776   case -3:
01777     return -3;
01778   }
01779   // Cherche la page contenant le tampon d'entree
01780   if (lire_mot_mem(NUM_MOT_OUT,num_tab_pages,mot) == -1) {
01781     deverrouiller_tampon(pid,NUM_MOT_OUT);
01782     return -1;
01783   }
01784   switch ((int)mot[2]) {
01785   case PP_NULL:
01786     // On n'a encore jamais rien ecrit ds le tampon
01787     if ((num_p_tampon=page_forcee(pid)) < 0) {
01788       deverrouiller_tampon(pid,NUM_MOT_OUT);
01789       return -1;
01790     }
01791     // Met a jour la table des pages
01792     mot[0] = 0;
01793     mot[1] = 0;
01794     mot[2] = PP_RAM;
01795     mot[3] = num_p_tampon;
01796     if (ecrire_mot_mem(NUM_MOT_OUT,num_tab_pages,mot) == -1) {
01797       deverrouiller_tampon(pid,NUM_MOT_OUT);
01798       liberer_page(num_p_tampon);
01799       return -1;
01800     }
01801     break;
01802   case PP_SWAP:
01803     //On rapatrie le tampon en mem RAM
01804     if ((num_p_tampon=rapatrier_page_swap(pid,(int)mot[3])) < 0) {
01805       deverrouiller_tampon(pid,NUM_MOT_OUT);
01806       return -1;
01807     }
01808     break;
01809   case PP_RAM:
01810     num_p_tampon = (int)mot[3];
01811     break;
01812   default:
01813     fprintf(stderr,"Table des pages %d du processus %d incoherente\n",num_tab_pages,pid);
01814     deverrouiller_tampon(pid,NUM_MOT_OUT);
01815     return -1;
01816   }
01817   deb = (int)mot[0];
01818   longueur = (int)mot[1];
01819   // Teste s'il reste de la place
01820   if (longueur == T_MAX_TAMPON) {
01821     deverrouiller_tampon(pid,NUM_MOT_OUT);
01822     return -2;
01823   }
01824   fin = (deb + longueur) % T_MAX_TAMPON;
01825   // On ecrit le caractere
01826   if (lire_mot_mem(fin/T_MOT,num_p_tampon,mot_tampon) == -1) {
01827     deverrouiller_tampon(pid,NUM_MOT_OUT);
01828     return -1;
01829   }
01830   mot_tampon[fin%T_MOT] = (octet_t)c;
01831   if (ecrire_mot_mem(fin/T_MOT,num_p_tampon,mot_tampon) == -1) {
01832     deverrouiller_tampon(pid,NUM_MOT_OUT);
01833     return -1;
01834   }
01835   // MAJ de la table des pages
01836   mot[1] = (octet_t)longueur+1;
01837   if (ecrire_mot_mem(NUM_MOT_OUT,num_tab_pages,mot) == -1) {
01838     deverrouiller_tampon(pid,NUM_MOT_OUT);
01839     return -1;
01840   }
01841   // Deverrouille le tampon
01842   if (deverrouiller_tampon(pid,NUM_MOT_OUT) == -1)
01843     return -1;
01844   return 0;
01845 }
01846 
01847 /**
01848  * Fonction qui lit un caractere dans le tampon de sortie d'un processus.\n
01849  * Elle est non bloquante.\n
01850  * Reveille le proc pid s'il etait en E_ATT_ECRIT
01851  * \param pid : num du processus
01852  * \param c : le caractere a lire
01853  * \return 
01854  * - -1 en cas d'erreur inconnue
01855  * - -2 rien a lire
01856  * - -3 tampon verrouille
01857  * - 0  sinon
01858  */
01859 int lire_stdout (int pid, char* c) {
01860   mot_t mot,mot_tampon;
01861   int num_tab_pages,num_p_tampon;
01862   int deb, longueur;
01863 
01864   // Cherche la table des pages du processus
01865   if (lire_mot_mem(pid,NUM_PAGE_META,mot) == -1)
01866     return -1;
01867   if (lire_etat(mot) == E_MORT) {
01868     fprintf(stderr,"Tentative d'ecriture dans une page d'un processus mort (%d)\n",pid);
01869     return -1;
01870   }
01871   switch (lire_type_pp(mot)) {
01872   case PP_RAM:
01873     num_tab_pages = mot[3];
01874     break;
01875   case PP_SWAP:
01876     // Ramene la table des pages du proc en mem RAM
01877     if ((num_tab_pages=rapatrier_page_swap(pid,(int)mot[3])) < 0)
01878       return -1;
01879     break;
01880   }
01881   // Verrouille le tampon
01882   switch (verrouiller_tampon(pid,NUM_MOT_OUT)) {
01883   case -1:
01884     return -1;
01885   case -3:
01886     return -3;
01887   }
01888   // Cherche la page contenant le tampon d'entree
01889   if (lire_mot_mem(NUM_MOT_OUT,num_tab_pages,mot) == -1) {
01890     deverrouiller_tampon(pid,NUM_MOT_OUT);
01891     return -1;
01892   }
01893   switch ((int)mot[2]) {
01894   case PP_NULL:
01895     // On n'a encore jamais rien ecrit ds le tampon
01896     deverrouiller_tampon(pid,NUM_MOT_OUT);
01897     return -2;
01898   case PP_SWAP:
01899     //On rapatrie le tampon en mem RAM
01900     if ((num_p_tampon=rapatrier_page_swap(pid,(int)mot[3])) < 0) {
01901       deverrouiller_tampon(pid,NUM_MOT_OUT);
01902       return -1;
01903     }
01904     break;
01905   case PP_RAM:
01906     num_p_tampon = (int)mot[3];
01907     break;
01908   default:
01909     fprintf(stderr,"Table des pages %d du processus %d incoherente\n",num_tab_pages,pid);
01910     deverrouiller_tampon(pid,NUM_MOT_OUT);
01911     return -1;
01912   }
01913   deb = (int)mot[0];
01914   longueur = (int)mot[1];
01915   // Teste s'il y a quelque chose a lire
01916   if (longueur == 0) {
01917     deverrouiller_tampon(pid,NUM_MOT_OUT);
01918     return -2;
01919   }
01920   // On lit le caractere
01921   if (lire_mot_mem(deb/T_MOT,num_p_tampon,mot_tampon) == -1) {
01922     deverrouiller_tampon(pid,NUM_MOT_OUT);
01923     return -1;
01924   }
01925   *c = (char)mot_tampon[deb%T_MOT];
01926   // MAJ de la table des pages
01927   mot[0] = (octet_t)deb+1;
01928   mot[1] = (octet_t)longueur-1;
01929   if (ecrire_mot_mem(NUM_MOT_OUT,num_tab_pages,mot) == -1) {
01930     deverrouiller_tampon(pid,NUM_MOT_OUT);
01931     return -1;
01932   }
01933   // Deverrouille le tampon
01934   if (deverrouiller_tampon(pid,NUM_MOT_OUT) == -1)
01935     return -1;
01936   // Reveille le proc pid s'il etait en E_ATT_ECRIT
01937   if (lire_mot_mem(pid,NUM_PAGE_META,mot) != -1) {
01938     if (lire_etat(mot) == E_ATT_ECRIT) {
01939       // Reveille le processus i
01940       liste_add_pid(liste_proc,pid);
01941       // MAJ la table des processus
01942       changer_etat(E_ELIGIBLE,mot);
01943       if (ecrire_mot_mem(pid,NUM_PAGE_META,mot) != -1)
01944         return 0;
01945       liste_supp_pid(liste_proc,pid);
01946     }
01947   }
01948   return 0;
01949 }
01950 
01951 /**
01952  * Fonction qui cree un fichier contenant l'image de toute la memoire du systeme
01953  * \param pid : num du processus qui a fait appel a la fonction\n
01954  *              (permet de donner un nom au fichier image)
01955  * \return rien
01956  */
01957 void creer_image_totale (int pid) {
01958   char *nom, *comment;
01959   int desc;
01960   page_t *pp;
01961 
01962   // Nom du fichier
01963   nom = malloc((1+2+5)*sizeof(char));
01964   sprintf(nom,"%d.image",pid);
01965   // Ouverture du fichier
01966   if ((desc=open(nom,O_CREAT|O_TRUNC|O_WRONLY,0666)) == -1) {
01967     fprintf(stderr,"Impossible d'ouvrir le fichier %s pour image de la mem\n",nom);
01968     return;
01969   }
01970   fprintf(stderr,"Creation de l'image de toutes la mem du sys\n");
01971   // La mem principale
01972   strcpy(comment,"--Image de la mem principale--");
01973   if (write(desc,comment,sizeof(page_t)) != sizeof(page_t)) {
01974     fprintf(stderr,"Image de la mem non terminee\n");
01975     close(desc);
01976     return;
01977   }
01978   if (write(desc,mem,NPP*sizeof(page_t)) != NPP*sizeof(page_t)) {
01979     fprintf(stderr,"Image de la mem non terminee\n");
01980     close(desc);
01981     return;
01982   }
01983   // La mem secondaire
01984   strcpy(comment,"--Image de la mem secondaire--");
01985   if (write(desc,comment,sizeof(page_t)) != sizeof(page_t)) {
01986     fprintf(stderr,"Image de la mem non terminee\n");
01987     close(desc);
01988     return;
01989   }
01990   if (lseek(swap_d,0,SEEK_SET) == -1) {
01991     fprintf(stderr,"Image de la mem non terminee\n");
01992     close(desc);
01993     return;
01994   }
01995   if (read(swap_d,pp,NPPS*sizeof(page_t)) != NPPS*sizeof(page_t)) {
01996     fprintf(stderr,"Image de la mem non terminee\n");
01997     close(desc);
01998     return;
01999   }
02000   if (write(desc,pp,NPPS*sizeof(page_t)) != NPPS*sizeof(page_t)) {
02001     fprintf(stderr,"Image de la mem non terminee\n");
02002     close(desc);
02003     return;
02004   }
02005   return;
02006 }
02007 
02008 /**
02009  * Fonction qui cree un fichier contenant l'image du processus a un instant donne.\n
02010  * Cette image represente:
02011  * - la table des processus\n
02012  *   (si le processus pid n'est pas lisible ou est mort, toute la mem est recopiee)
02013  * - la table des pages du processus
02014  * - toutes les pages associes (code, pile, donnee et tampons E/S)
02015  * \param pid : num du processus
02016  * \return rien
02017  */
02018 void creer_image_mem (int pid) {
02019   mot_t mot;
02020   char *nom, *comment;
02021   int desc;
02022   mot_t *pp, *ptp;
02023   int num_pp;
02024   int i,j;
02025   int num_mot;
02026 
02027   // Nom du fichier
02028   nom = malloc((1+2+5)*sizeof(char));
02029   sprintf(nom,"%d.image",pid);
02030   // Ouverture du fichier
02031   if ((desc=open(nom,O_CREAT|O_TRUNC|O_WRONLY,0666)) == -1) {
02032     fprintf(stderr,"Impossible d'ouvrir le fichier %s pour image de la mem\n",nom);
02033     return;
02034   }
02035   // Lecture de la table des processus
02036   if (lire_mot_mem(pid,NUM_PAGE_META,mot) == -1) {
02037     creer_image_totale(pid);
02038     return;
02039   }
02040   if (lire_etat(mot) == E_MORT) {
02041     creer_image_totale(pid);
02042     return;
02043   }
02044   // Copie de la table des processus
02045   comment = malloc(sizeof(page_t));
02046   strcpy(comment,"--Table des processus--");
02047   if (write(desc,comment,sizeof(page_t)) != sizeof(page_t)) {
02048     fprintf(stderr,"Image de la mem non terminee\n");
02049     close(desc);
02050     return;
02051   }
02052   if (write(desc,mem,sizeof(page_t)) != sizeof(page_t)) {
02053     fprintf(stderr,"Image de la mem non terminee\n");
02054     close(desc);
02055     return;
02056   }
02057   // Copie de la table des pages
02058   switch (lire_type_pp(mot)) {
02059   case PP_RAM:
02060     num_pp = (int)mot[3];
02061     ptp = mem[num_pp];
02062     if (write(desc,ptp,sizeof(page_t)) != sizeof(page_t)) {
02063       fprintf(stderr,"Image de la mem non terminee\n");
02064       close(desc);
02065       return;
02066     }
02067     break;
02068   case PP_SWAP:
02069     num_pp = (int)mot[3];
02070     if (lseek(swap_d,num_pp*sizeof(page_t),SEEK_SET) == -1) {
02071       fprintf(stderr,"Image de la mem non terminee\n");
02072       close(desc);
02073       return;
02074     }
02075     if (read(swap_d,ptp,sizeof(page_t)) != sizeof(page_t)) {
02076       fprintf(stderr,"Image de la mem non terminee\n");
02077       close(desc);
02078       return;
02079     }
02080     if (write(desc,ptp,sizeof(page_t)) != sizeof(page_t)) {
02081       fprintf(stderr,"Image de la mem non terminee\n");
02082       close(desc);
02083       return;
02084     }
02085     break;
02086   }
02087   // Copie des pages de code, donnees et pile
02088   for (i=0 ; i<3 ; i++) {
02089     for (j=T_MAX_ZONES*i ; j<T_MAX_ZONES*(i+1) ; j++) {
02090       if (ptp[j][2] == PP_NULL)
02091         break;
02092       else if (ptp[j][2] == PP_RAM) {
02093         num_pp = ptp[j][3];
02094         sprintf(comment,"Page %d en RAM\n",num_pp);
02095         if (write(desc,comment,sizeof(page_t)) != sizeof(page_t)) {
02096           fprintf(stderr,"Image de la mem non terminee\n");
02097           close(desc);
02098           return;
02099         }
02100         pp = mem[num_pp];
02101         if (write(desc,pp,sizeof(page_t)) != sizeof(page_t)) {
02102           fprintf(stderr,"Image de la mem non terminee\n");
02103           close(desc);
02104           return;
02105         }
02106       }
02107       else if (ptp[j][2] == PP_SWAP) {
02108         num_pp = ptp[j][3];
02109         sprintf(comment,"Page %d en SWAP\n",num_pp);
02110         if (write(desc,comment,sizeof(page_t)) != sizeof(page_t)) {
02111           fprintf(stderr,"Image de la mem non terminee\n");
02112           close(desc);
02113           return;
02114         }
02115         if (lseek(swap_d,num_pp*sizeof(page_t),SEEK_SET) == -1) {
02116           fprintf(stderr,"Image de la mem non terminee\n");
02117           close(desc);
02118           return;
02119         }
02120         if (read(swap_d,pp,sizeof(page_t)) != sizeof(page_t)) {
02121           fprintf(stderr,"Image de la mem non terminee\n");
02122           close(desc);
02123           return;
02124         }
02125         if (write(desc,pp,sizeof(page_t)) != sizeof(page_t)) {
02126           fprintf(stderr,"Image de la mem non terminee\n");
02127           close(desc);
02128           return;
02129         }
02130       }
02131     }
02132   }
02133   // Copie des tampons d'E/S
02134   for (i=0 ; i<2 ; i++) {
02135     if (i == 0)
02136       num_mot = NUM_MOT_IN;
02137     else
02138       num_mot = NUM_MOT_OUT;
02139     if (ptp[num_mot][2] == PP_NULL)
02140       break;
02141     else if (ptp[num_mot][2] == PP_RAM) {
02142       num_pp = ptp[num_mot][3];
02143       sprintf(comment,"Page %d en RAM\n",num_pp);
02144       if (write(desc,comment,sizeof(page_t)) != sizeof(page_t)) {
02145         fprintf(stderr,"Image de la mem non terminee\n");
02146         close(desc);
02147         return;
02148       }
02149       pp = mem[num_pp];
02150       if (write(desc,pp,sizeof(page_t)) != sizeof(page_t)) {
02151         fprintf(stderr,"Image de la mem non terminee\n");
02152         close(desc);
02153         return;
02154       }
02155     }
02156     else if (ptp[num_mot][2] == PP_SWAP) {
02157       num_pp = ptp[num_mot][3];
02158       sprintf(comment,"Page %d en SWAP\n",num_pp);
02159       if (write(desc,comment,sizeof(page_t)) != sizeof(page_t)) {
02160         fprintf(stderr,"Image de la mem non terminee\n");
02161         close(desc);
02162         return;
02163       }
02164       if (lseek(swap_d,num_pp*sizeof(page_t),SEEK_SET) == -1) {
02165         fprintf(stderr,"Image de la mem non terminee\n");
02166         close(desc);
02167         return;
02168       }
02169       if (read(swap_d,pp,sizeof(page_t)) != sizeof(page_t)) {
02170         fprintf(stderr,"Image de la mem non terminee\n");
02171         close(desc);
02172         return;
02173       }
02174       if (write(desc,pp,sizeof(page_t)) != sizeof(page_t)) {
02175         fprintf(stderr,"Image de la mem non terminee\n");
02176         close(desc);
02177         return;
02178       }
02179     }
02180   }
02181 }
02182 
02183 
02184 /**
02185  * Fonction qui interprete les signaux pendant d'un processus
02186  * \param pid : num du processus
02187  * \return rien
02188  */
02189 void interprete_signaux (int pid) {
02190   signal_t *sig;
02191   mot_t mot_proc,mot_pile;
02192   vad_t adv_pile;
02193 
02194   mot_pile[0] = (octet_t)M_UT;
02195   adv_pile.num = 0;
02196   adv_pile.zone = Z_PILE;
02197   // Verifie que le num de processus est valide
02198   if (pid < 0 || pid > N_MAX_PROC) {
02199     fprintf(stderr, "Le proc %d n'existe pas\n", pid);
02200     return;
02201   }
02202   // Lit l'entree du processus ds la table des processus
02203   if (lire_mot_mem(pid,NUM_PAGE_META,mot_proc) == -1)
02204     return;
02205   // Regarde si le processus est toujours actif
02206   if (lire_etat(mot_proc) == E_MORT)
02207     return;
02208   // Regarde si le processus a des signaux pendants
02209   if (SIFUNSIG(mot_proc[0]))
02210     return;
02211   // Regarde quels signaux sont pendants
02212   if (SIFKILL(mot_proc[0])){
02213     printf("Mort du proc %d par Arme fatale\n",pid);
02214     if (terminer_proc(pid) != 0)
02215       fprintf(stderr,"Processus %d non termine\n",pid);
02216     return;
02217   }
02218   if (SIFMEM(mot_proc[0])) {
02219     printf("Violation de memoire au processus %d ", pid);
02220     // Regarde si le signal est capture par le proc
02221     if ((sig=rechercher_sig(pid,S_MEM)) == NULL) {
02222       // Comportement par defaut
02223       printf("comportement par defaut\n");
02224       // Cree une image mem
02225       creer_image_mem(pid);
02226       // Termine le proc
02227       if (terminer_proc(pid) != 0)
02228         fprintf(stderr,"Processus %d non termine\n",pid);
02229       return;
02230     }
02231     else {
02232       // Le signal est capture
02233       // Incremente de 2 la pile pour y mettre:
02234       // P1: le signal capture
02235       /* Je ne sais pas comment faire pour supprimer le param en sortant du handler
02236       changer_esp(pid,1);
02237       mot_pile[3] = (octet_t)sig_lib2ksinu(S_MEM);
02238       if (ecrire_mot(pid,adv_pile,mot_pile) < 0)
02239         fprintf(stderr,"Capture de S_MEM echouee\n");
02240       else {
02241       */
02242         // P0: le compteur programme de retour (ie actuel)
02243         changer_esp(pid,1);
02244         mot_pile[3] = mot_proc[1];
02245         if (ecrire_mot(pid,adv_pile,mot_pile) < 0)
02246           fprintf(stderr,"Capture de S_MEM echouee\n");
02247         else {
02248           // Change le compteur programme
02249           mot_proc[1] = (octet_t)sig->cp;
02250           if (ecrire_mot_mem(pid,NUM_PAGE_META,mot_proc) == -1)
02251             fprintf(stderr,"Capture de S_MEM echouee\n");
02252         }
02253     }
02254   }
02255   if (SIFSUSP(mot_proc[0])) {
02256     printf("Suspension du processus %d\n",pid);
02257     // Regarde si le signal est ignore par le proc
02258     if ((sig=rechercher_sig(pid,S_SUSP)) == NULL) {
02259       // Comportement par defaut
02260       printf("comportement par defaut\n");
02261       // Suspension de l'execution
02262       liste_supp_pid(liste_proc,pid);
02263       changer_etat(E_SUSP,mot_proc);
02264       if (ecrire_mot_mem(pid,NUM_PAGE_META,mot_proc) == -1) {
02265         fprintf(stderr,"Suspension du proc %d echouee\n",pid);
02266         liste_add_pid(liste_proc,pid);
02267       }
02268     }
02269   }
02270   if (SIFREP(mot_proc[0])) {
02271     printf("Reprise du processus %d\n", pid);
02272     if (lire_etat(mot_proc) == E_SUSP) {
02273       liste_add_pid(liste_proc,pid);
02274       changer_etat(E_ELIGIBLE,mot_proc);
02275       if (ecrire_mot_mem(pid,NUM_PAGE_META,mot_proc) == -1) {
02276         fprintf(stderr,"Reprise du proc %d echouee\n",pid);
02277         liste_supp_pid(liste_proc,pid);
02278       }
02279     }
02280   }
02281   if (SIFUSR1(mot_proc[0])) {
02282     printf("Signal non definie 1 recu par processus %d\n",pid);
02283     // Regarde si le signal est capture ou ignore par le proc
02284     if ((sig=rechercher_sig(pid,S_USR1)) == NULL) {
02285       // Comportement par defaut
02286       printf("comportement par defaut\n");
02287       // Termine le proc
02288       if (terminer_proc(pid) != 0)
02289         fprintf(stderr,"Processus %d non termine\n",pid);
02290       return;
02291     }
02292     else if (sig->cp != 0) {
02293       // Le signal est capture
02294       // Incremente de 2 la pile pour y mettre:
02295       // P1: le signal capture
02296       /*
02297       changer_esp(pid,1);
02298       mot_pile[3] = (octet_t)sig_lib2ksinu(S_USR1);
02299       if (ecrire_mot(pid,adv_pile,mot_pile) < 0)
02300         fprintf(stderr,"Capture de S_USR1 echouee\n");
02301       else {
02302       */
02303         // P0: le compteur programme de retour (ie actuel)
02304         changer_esp(pid,1);
02305         mot_pile[3] = mot_proc[1];
02306         if (ecrire_mot(pid,adv_pile,mot_pile) < 0)
02307           fprintf(stderr,"Capture de S_USR1 echouee\n");
02308         else {
02309           // Change le compteur programme
02310           mot_proc[1] = (octet_t)sig->cp;
02311           if (ecrire_mot_mem(pid,NUM_PAGE_META,mot_proc) == -1)
02312             fprintf(stderr,"Capture de S_USR1 echouee\n");
02313         }
02314     }
02315   }
02316   if (SIFUSR2(mot_proc[0])) {
02317     printf("Signal non definie 2 recu par processus %d\n",pid);
02318     // Regarde si le signal est capture par le proc
02319     if ((sig=rechercher_sig(pid,S_USR2)) == NULL) {
02320       // Comportement par defaut
02321       printf("comportement par defaut\n");
02322       // Cree une image mem
02323       creer_image_mem(pid);
02324       // Termine le proc
02325       if (terminer_proc(pid) != 0)
02326         fprintf(stderr,"Processus %d non termine\n",pid);
02327       return;
02328     }
02329     else if (sig->cp != 0) {
02330       // Le signal est capture
02331       // Incremente de 2 la pile pour y mettre:
02332       // P1: le signal capture
02333       /*
02334       changer_esp(pid,1);
02335       mot_pile[3] = (octet_t)sig_lib2ksinu(S_USR2);
02336       if (ecrire_mot(pid,adv_pile,mot_pile) < 0)
02337         fprintf(stderr,"Capture de S_USR2 echouee\n");
02338       else {
02339       */
02340         // P0: le compteur programme de retour (ie actuel)
02341         changer_esp(pid,1);
02342         mot_pile[3] = mot_proc[1];
02343         if (ecrire_mot(pid,adv_pile,mot_pile) < 0)
02344           fprintf(stderr,"Capture de S_USR2 echouee\n");
02345         else {
02346           // Change le compteur programme
02347           mot_proc[1] = (octet_t)sig->cp;
02348           if (ecrire_mot_mem(pid,NUM_PAGE_META,mot_proc) == -1)
02349             fprintf(stderr,"Capture de S_USR2 echouee\n");
02350         }
02351     }
02352   }
02353   if (SIFINSTI(mot_proc[0])) {
02354     printf("Instruction illegale ds le processus %d\n",pid);
02355     // Regarde si le signal est capture par le proc
02356     if ((sig=rechercher_sig(pid,S_INSTI)) == NULL) {
02357       // Comportement par defaut
02358       printf("comportement par defaut\n");
02359       // Cree une image mem
02360       creer_image_mem(pid);
02361       // Termine le proc
02362       if (terminer_proc(pid) != 0)
02363         fprintf(stderr,"Processus %d non termine\n",pid);
02364       return;
02365     }
02366     else {
02367       // Le signal est capture
02368       // Incremente de 2 la pile pour y mettre:
02369       // P1: le signal capture
02370       /*
02371       changer_esp(pid,1);
02372       mot_pile[3] = (octet_t)sig_lib2ksinu(S_INSTI);
02373       if (ecrire_mot(pid,adv_pile,mot_pile) < 0)
02374         fprintf(stderr,"Capture de S_INSTI echouee\n");
02375       else {
02376       */
02377         // P0: le compteur programme de retour (ie actuel)
02378         changer_esp(pid,1);
02379         mot_pile[3] = mot_proc[1];
02380         if (ecrire_mot(pid,adv_pile,mot_pile) < 0)
02381           fprintf(stderr,"Capture de S_INSTI echouee\n");
02382         else {
02383           // Change le compteur programme
02384           mot_proc[1] = (octet_t)sig->cp;
02385           if (ecrire_mot_mem(pid,NUM_PAGE_META,mot_proc) == -1)
02386             fprintf(stderr,"Capture de S_INSTI echouee\n");
02387         }
02388     }
02389   }
02390 }
02391 
02392 /**
02393  * Fonction qui execute l'instruction courante du processus donne en param
02394  * \param pid : num du processus
02395  * \return rien
02396  */
02397 void next_inst (int pid) {
02398   mot_t mot,mot_proc;
02399   vad_t ad_v;
02400   int ret=0;
02401 
02402   // Verifie que le num de processus est valide
02403   if (pid < 0 || pid > N_MAX_PROC) {
02404     fprintf(stderr, "Le proc %d n'existe pas\n", pid);
02405     return;
02406   }
02407   else {
02408     if (lire_mot_mem(pid,NUM_PAGE_META,mot_proc) == -1)
02409       return;
02410     if (lire_etat(mot_proc) == E_MORT) {
02411       fprintf(stderr, "Tentative d'execution d'un proc termine (%d est vide)\n", pid);
02412       return;
02413     }
02414   }
02415   // Lit l'instruction courante
02416   ad_v.zone = Z_CODE;
02417   ad_v.num = (int)mot_proc[1];
02418   switch (lire_mot(pid, ad_v, mot)) {
02419   case -1:
02420     ret = -1;
02421     break;
02422   case -2:
02423     ret = -2;
02424     break;
02425   default:
02426     switch ((int)mot[0]) {
02427     case I_AFFECT:
02428       ret = cmd_affect(pid,mot);
02429       break;
02430     case I_AFFECTP:
02431       ret = cmd_affectp(pid,mot);
02432       break;
02433     case I_SI:
02434       ret = cmd_si(pid,mot);
02435       break;
02436     case I_SAUT:
02437       ret = cmd_saut(pid,mot);
02438       break;
02439     case I_CPILE:
02440       ret = cmd_cpile(pid,mot);
02441       break;
02442     case I_DPILE:
02443       ret = cmd_dpile(pid,mot);
02444       break;
02445     case I_APPEL:
02446       ret = cmd_appel(pid,mot);
02447       break;
02448     case I_RETOUR:
02449       ret = cmd_retour(pid);
02450       break;
02451     case I_TEST:
02452       ret = cmd_test(pid,mot);
02453       break;
02454     case I_TRAPPE:
02455       switch ((int)mot[2]) {
02456       case T_CLONE:
02457         ret = cmd_clone(pid);
02458         break;
02459       case T_RECOUVRE:
02460         ret = cmd_recouvre(pid);
02461         break;
02462       case T_ATTENDS:
02463         ret = cmd_attends(pid);
02464         break;
02465       case T_FIN:
02466         ret = cmd_fin(pid);
02467         break;
02468       case T_CAPTURE:
02469         ret = cmd_capture(pid);
02470         break;
02471       case T_EMETS:
02472         ret = cmd_emets(pid);
02473         break;
02474       case T_ID:
02475         ret = cmd_id(pid);
02476         break;
02477       case T_IDP:
02478         ret = cmd_idp(pid);
02479         break;
02480       case T_LIT:
02481         ret = cmd_lit(pid);
02482         break;
02483       case T_ECRIT:
02484         ret = cmd_ecrit(pid);
02485         break;
02486       default:
02487         ret = -1;
02488       }
02489       break;
02490     case I_AFFECTSP:
02491       ret = cmd_affectsp(pid,mot);
02492       break;
02493     case I_DONNEES:
02494       ret = cmd_donnees(pid,mot);
02495       break;
02496     default:
02497       ret = -1;
02498     }
02499   }
02500   switch (ret) {
02501   case -1:
02502     fprintf(stderr, "Instructioin illegale du proc %d\n",pid);
02503     mot_proc[0] = (octet_t)mot_proc[0] | S_INSTI;
02504     if (ecrire_mot_mem(pid,NUM_PAGE_META,mot_proc) == -1) {
02505       // Termine le processus
02506       terminer_proc(pid);
02507       return;
02508     }
02509     break;
02510   case -2:
02511     fprintf(stderr, "Violation de memoire dans le proc %d\n",pid);
02512     mot_proc[0] = (octet_t)mot_proc[0] | S_MEM;
02513     if (ecrire_mot_mem(pid,NUM_PAGE_META,mot_proc) == -1) {
02514       // Termine le processus
02515       terminer_proc(pid);
02516       return;
02517     }
02518     break;
02519   }
02520 }

Généré le Sun Sep 29 22:47:22 2002 pour KSInu par doxygen1.2.16