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

commandes.c

Aller à la documentation de ce fichier.
00001 /**
00002   @file commandes.c
00003   Source contenant les definitions de toutes les commandes du langage KSI
00004 */
00005 
00006 #include "commandes.h"
00007 #include "systeme.h"
00008 
00009 /**************************************************************************************
00010  Fait par Martin Ludovic
00011 **************************************************************************************/
00012 
00013 /**
00014  * Termine un processus proprement : 
00015  * avant du supprimer completement un processus (fonction supprimer_proc), il faut
00016  * - regarder qui est le pere de ce processus.
00017  *   - le pere est mort -> erreur !
00018  *   - ppid = NO_PERE -> On supprime completement ce processus \n
00019  *         (NO_PERE (0) est le "processus" qui tue tous les orphelins)
00020  *   - ppid != 0 -> On regarde s'il attend la mort d'un fils.
00021  *     - si oui :
00022  *       - ecrit ds P0 du pere le pid
00023  *       - lit $n ds P1 du pere et ecrit ds M$n du pere la valeur de sortie du processus
00024  *       - le reveille
00025  *     - si non : 
00026  *       - ecrit P0 (valeur de retour du processus) dans le mot NUM_MOT_EXIT de la table 
00027  *         des pages du processus
00028  *       - se met en E_ZOMBI
00029  * - regarder l'etat de ses fils:
00030  *   - E_ZOMBI -> les supprimer completement
00031  *   - autre -> les rendre orphelins
00032  * \param pid : Numero du processus qu'on veut supprimer
00033  * \return 
00034  * - -1 erreur: processus inchange
00035  * - -2 erreur: processus partiellement supprime (des pages sont probablement perdues)
00036  * - 0 sinon
00037  */
00038 int terminer_proc (int pid) {
00039   mot_t mot_pid,mot_fils,mot_pere,mot_retour;
00040   int num_tab_p;
00041   int i;
00042   int erreur=0;
00043   int ppid;
00044   vad_t vad,vad2,vad3;
00045 
00046   if (lire_mot_mem(pid,NUM_PAGE_META,mot_pid) == -1)
00047     return -1;
00048   if (lire_etat(mot_pid) == E_MORT) {
00049     // Ce num de processus ne correspond a aucune page physique
00050     fprintf(stderr,"Tentative de terminaison d'un proc mort (%d)\n",pid);
00051     return -1;
00052   }
00053   switch (lire_type_pp(mot_pid)) {
00054   case PP_SWAP:
00055     // La table des pages du processus pid se trouve ds le swap
00056     // On la ramene en mem principale
00057     if ((num_tab_p=rapatrier_page_swap(pid,(int)mot_pid[3])) < 0)
00058       return -1;
00059     break;
00060   case PP_RAM:
00061     num_tab_p = (int)mot_pid[3];
00062     break;
00063   }
00064   // Recherche ses fils
00065   for (i=1 ; i<N_MAX_PROC+1 ; i++) {
00066     switch (ppid=lire_ppid(i)) {
00067     case -1:
00068       if (lire_mot_mem(i,NUM_PAGE_META,mot_fils) == -1) {
00069         erreur = 1;
00070         break;
00071       }
00072       if (lire_etat(mot_fils) != E_MORT) 
00073         erreur = 1; 
00074       break;
00075     default:
00076       if (ppid == pid) {
00077         // Le proc i est un fils du processus a supprimer
00078         if (lire_mot_mem(i,NUM_PAGE_META,mot_fils) == -1) {
00079           erreur = 1;
00080           break;
00081         }
00082         switch (lire_etat(mot_fils)) {
00083         case E_ZOMBI:
00084           // Le fils est un zombi, on le supprime
00085           if (supprimer_proc(i) < 0)
00086             erreur = 1;
00087           break;
00088         default:
00089           // Le fils est processus actif, on le met orphelin
00090           if (changer_ppid(i,NO_PERE) == -1)
00091             erreur = 1;
00092           break;
00093         }
00094       }
00095     }
00096   }
00097   // Recherche son pere
00098   switch (ppid=lire_ppid(pid)) {
00099   case -1:
00100     erreur = 1;
00101     break;
00102   case NO_PERE:
00103     // Le processus a terminer est orphelin, on le supprime entierement
00104     if (supprimer_proc(pid) == -1)
00105       return -1;
00106     return 0;
00107   default:
00108     // Le proc pid n'est pas orphelin, son pere est ppid
00109     if (lire_mot_mem(ppid,NUM_PAGE_META,mot_pere) == -1) {
00110       erreur = 1;
00111       break;
00112     }
00113     switch (lire_etat(mot_pere)) {
00114     case E_MORT:
00115       // Le pere ne peut pas etre mort
00116       erreur = 1;
00117       // Mais on supprime qd meme le processus
00118       supprimer_proc(pid);
00119       break;
00120     case E_ATT_FILS:
00121       // Le pere attend la mort de son fils
00122       // Ecrit la pid ds P0 du pere
00123       vad2.num = 0;
00124       vad2.zone = Z_PILE;
00125       mot_retour[3] = (octet_t)pid;
00126       mot_retour[0] = (octet_t)M_UT;
00127       if (ecrire_mot(ppid,vad2,mot_retour) != 0)
00128         erreur = -1;
00129       // Lit P1 du pere
00130       vad2.num = 1;
00131       vad2.zone = Z_PILE;
00132       if (lire_mot(ppid,vad2,mot_retour) != 0)
00133         erreur = -1;
00134       // Ecrit ds M$n du pere la valeur de retour du proc
00135       vad2.num = (int)mot_retour[3];
00136       vad2.zone = Z_DONNEES;
00137       vad3.num = 0;
00138       vad3.zone = Z_PILE;
00139       if (lire_mot(pid,vad3,mot_retour) != 0)
00140         erreur = -1;
00141       if (ecrire_mot(ppid,vad2,mot_retour) != 0)
00142         erreur = -1;
00143       // On reveille le pere
00144       changer_etat(E_ELIGIBLE,mot_pere);
00145       if (ecrire_mot_mem(ppid,NUM_PAGE_META,mot_pere) == -1) {
00146         erreur = 1;
00147       }
00148       liste_add_pid(liste_proc,ppid);
00149       // On supprime completement son fils
00150       if (supprimer_proc(pid) < 0)
00151         erreur = 1;
00152       break;
00153     default:
00154       // Son pere n'attend pas sa mort
00155       // On sauvegarde la valeur de retour du proc
00156       vad.num = 0;
00157       vad.zone = Z_PILE;
00158       if (lire_mot(pid,vad,mot_retour) != 0)
00159         erreur = -1;
00160       if (ecrire_mot_mem(NUM_MOT_EXIT,num_tab_p,mot_retour) == -1)
00161         erreur = -1;
00162       // On marque le processus a terminer comme zombi
00163       changer_etat(E_ZOMBI,mot_pid);
00164       if (ecrire_mot_mem(pid,NUM_PAGE_META,mot_pid) == -1) 
00165         erreur = 1;
00166       // On supprime toutes ses pages mais on garde une entree ds la table des proc
00167       if (supprimer_partie_proc(pid) < 0)
00168         erreur = 1;
00169     }
00170   }
00171   if (erreur == 0)
00172     return 0;
00173   return -2;
00174 }
00175 
00176 /**
00177  * Supprime un proc :
00178  * - libere son numero dans la table des processus
00179  * - libere toutes ses pages physiques (en memoire principale ou secondaire) 
00180  * \param pid : Numero du processus qu'on veut supprimer
00181  * \return 
00182  * - -1 erreur: processus inchange
00183  * - -2 erreur: processus partiellement supprime (des pages sont probablement perdues)
00184  * - 0 sinon
00185  */
00186 int supprimer_proc(int pid) {
00187   mot_t mot_pid;
00188   int num_tab_p;
00189   int erreur = 0;
00190 
00191   // Cherche le num de la table des pages du processus pid
00192   if (lire_mot_mem(pid,NUM_PAGE_META,mot_pid) == -1)
00193     return -1;
00194   if (lire_etat(mot_pid) == E_MORT) {
00195     // Ce num de processus ne correspond a aucune page physique
00196     fprintf(stderr,"Tentative de suppression d'un proc mort (%d)\n",pid);
00197     return -1;
00198   }
00199   switch (lire_type_pp(mot_pid)) {
00200   case PP_SWAP:
00201     // La table des pages du processus pid se trouve ds le swap
00202     // On la ramene en mem principale
00203     if ((num_tab_p=rapatrier_page_swap(pid,(int)mot_pid[3])) < 0)
00204       return -1;
00205     break;
00206   case PP_RAM:
00207     num_tab_p = (int)mot_pid[3];
00208     break;
00209   }
00210   // Libere les pages attachees au processus
00211   if (supprimer_partie_proc(pid) < 0)
00212     erreur = 1;
00213   // Librere la page contenant la table des pages du processus
00214   if (liberer_page(num_tab_p) == -1)
00215     erreur = 1;
00216   // Libere le numero du processus
00217   if (liberer_pid(pid) == -1)
00218     erreur = 1;
00219   // Suppression de la liste des processus
00220   liste_supp_pid(liste_proc,pid);
00221   if (erreur == 0)
00222     return 0;
00223   else
00224     return -2;
00225 }
00226 
00227 /**
00228  * Supprime partiellement un processus :
00229  * - Supprime les pages physiques attachees au processus sauf la page qui contient 
00230  *   la table des pages car elle contient aussi 
00231  *   - le ppid (qui n'a pas pu etre mis dans la table des processus faute de place).
00232  *   - la valeur de retour du processus
00233  * - Supprime les signaux a intercepter de table_capture
00234  * \param pid : Numero du processus qu'on veut supprimer
00235  * \return 
00236  * - -1 erreur: processus inchange
00237  * - -2 erreur: processus partiellement supprime (des pages sont probablement perdues)
00238  * - 0 sinon
00239  */
00240 int supprimer_partie_proc (int pid) {
00241   mot_t mot,mot_pid;
00242   int i,j;
00243   int num_tab_p;
00244   int num_mot;
00245   int erreur = 0;
00246 
00247   // Cherche le num de la table des pages du processus pid
00248   if (lire_mot_mem(pid,NUM_PAGE_META,mot_pid) == -1)
00249     return -1;
00250   if (lire_etat(mot_pid) == E_MORT) {
00251     // Ce num de processus ne correspond a aucune page physique
00252     fprintf(stderr,"Impossible de supprimer un proc mort (%d)\n",pid);
00253     return -1;
00254   }
00255   switch (lire_type_pp(mot_pid)) {
00256   case PP_SWAP:
00257     // La table des pages du processus pid se trouve ds le swap
00258     // On la ramene en mem principale
00259     if ((num_tab_p=rapatrier_page_swap(pid,(int)mot_pid[3])) < 0)
00260       return -1;
00261     break;
00262   case PP_RAM:
00263     num_tab_p = (int)mot_pid[3];
00264     break;
00265   }
00266   // Supprime les signaux captures
00267   supp_all_sig(pid);
00268   // Libere ses pages physiques
00269   for (i=0 ; i<3 ; i++) {
00270     for (j=i*T_MAX_ZONES ; j<(i+1)*T_MAX_ZONES ; j++) {
00271       if (lire_mot_mem(j,num_tab_p,mot) == -1)
00272         erreur = 1;
00273       else {
00274         if ((int)mot[2] == PP_SWAP) {
00275           // Supprime la page de la mem physique
00276           if (liberer_page_swap((int)mot[3]) != 0)
00277             erreur = 1;
00278           // Supprime l'entree ds la table des pages
00279           mot[2]= (octet_t)PP_NULL;
00280           if (ecrire_mot_mem(j,num_tab_p,mot) == -1)
00281             erreur = 1;
00282         }
00283         else if ((int)mot[2] == PP_RAM) {
00284           // Supprime la page de la mem physique
00285           if (liberer_page((int)mot[3]) != 0)
00286             erreur = 1;
00287           // Supprime l'entree ds la table des pages
00288           mot[2]= (octet_t)PP_NULL;
00289           if (ecrire_mot_mem(j,num_tab_p,mot) == -1)
00290             erreur = 1;
00291         }
00292         else if ((int)mot[2] == PP_NULL) {
00293           break;
00294         }
00295       }
00296     }
00297   }
00298   // Libere les pages tampon
00299   for (i=0 ; i<2; i++) {
00300     if (i == 0)
00301       num_mot = NUM_MOT_IN;
00302     else
00303       num_mot = NUM_MOT_OUT;
00304     if (lire_mot_mem(num_mot,num_tab_p,mot) == -1)
00305       erreur = 1;
00306     else {
00307       switch ((int)mot[2]) {
00308       case PP_SWAP:
00309         if (liberer_page_swap((int)mot[3]) != 0)
00310           erreur = 1;
00311         break;
00312       case PP_RAM:
00313         if (liberer_page((int)mot[3]) != 0)
00314           erreur = 1;
00315         break;
00316       }
00317     }
00318   }
00319   if (erreur == 0)
00320     return 0;
00321   else
00322     return -2;
00323 }
00324 
00325 /**
00326  * Regarde l'etat du drapeau du saut conditionnel.
00327  * L'information est stockee sur le 4eme bit de poids fort (00010000) du mot.
00328  * \param mot : mot correspondant a l'entree du processus ds la table des processus
00329  * \return 
00330  * - 1 si le drapeau est leve (ie la condition est vraie)
00331  * - 0 si le drapeau est baisse
00332  */
00333 int condition_vraie (mot_t mot) {
00334   return ((mot[2] & 0x10) >> 4);
00335 }
00336 
00337 /**
00338  * Modifie l'etat du drapeau du saut conditionnel
00339  * L'information est stockee sur le 4eme bit de poids fort (00010000) du mot.
00340  * \param condition : le nouvel etat du drapeau
00341  * \param mot : mot correspondant a l'entree du processus ds la table des processus
00342  * \return l'ancien etat
00343  */
00344 int changer_condition (int condition, mot_t mot) {
00345   int old;
00346 
00347   old = ((mot[2] & 0x10) >> 4);
00348   mot[2] = (mot[2] & 0xEF) | (condition << 4);
00349   return old;
00350 }
00351 
00352 /**
00353  * Parse un mot contenant une instruction. Extrait de ce mot, les 2 parmetres
00354  * de l'instruction ranges dans une structure.Cette fonction effectue egalement 
00355  * un pre-traitement en traitant le cas des indirections.
00356  * \param mot : mot contenant une instruction
00357  * \param tab_param : tableau ou sera stocke les 2 parametres
00358  * \param nb : nombre de parametres a parser
00359  * \return 
00360  * - -1 en cas d'erreur inconnue
00361  * - -2 en cas d'indirection erronnee
00362  * - 0 sinon
00363  */
00364 int parser_param (int pid, mot_t mot, param_t tab_param[2], int nb) {
00365   int indirecte, ad, type, zone;
00366   vad_t ad_v;
00367   mot_t mot_ind;
00368   int i;
00369 
00370   for (i=0 ; i<nb ; i++) {
00371     if (i == 0) {
00372       // 1er parametre
00373       ad = (int)mot[2];
00374       zone = (int)((mot[1] & 0x10) >> 4) + 1;
00375       type = (int)((mot[1] & 0x20) >> 5);
00376       indirecte = (int)((mot[1] & 0x08) >> 3);
00377     }
00378     else {
00379       // 2eme parametre
00380       zone = (int)((mot[1] & 0x02) >> 1) + 1;
00381       ad = (int)mot[3];
00382       type = (int)((mot[1] & 0x04) >> 2);
00383       indirecte = (int)(mot[1] & 0x01);
00384     }
00385     // Traitement de l'indirection
00386     if (indirecte == P_INDIR) {
00387       ad_v.num = ad;
00388       ad_v.zone = zone;
00389       switch (lire_mot(pid,ad_v,mot_ind)) {
00390       case -1:
00391         return -1;
00392       case -2:
00393         return -2;
00394       default:
00395         ad = (int)mot_ind[3];
00396         zone = Z_DONNEES;
00397       }
00398     }
00399     tab_param[i].ad = ad;
00400     tab_param[i].type = type;
00401     tab_param[i].zone = zone;
00402   }
00403   return 0;
00404 }
00405 
00406 /**
00407  * Commande d'appel de fonction :
00408  * - Memorise le compteur programme sur la pile
00409  * - Modifie le compteur programme pour qu'il pointe sur la 1ere instruction de la fonction appelee
00410  * \param pid : num du processus en cours d'execution
00411  * \param mot : mot correspondant a l'instruction
00412  * \return
00413  * - -1 en cas d'echec
00414  * - -2 en cas de violation de memoire
00415  * - 0 sinon
00416  */
00417 int cmd_appel(int pid,mot_t mot) {
00418   int cp;
00419   mot_t mot_proc, mot_pile;
00420   vad_t ad_v;
00421   param_t tab_param[2];
00422 
00423   switch (parser_param(pid, mot, tab_param, 1)) {
00424   case -1:
00425     return -1;
00426   case -2:
00427     return -2;
00428   }
00429   // Lit le compteur programme actuel
00430   if (lire_mot_mem(pid,NUM_PAGE_META,mot_proc) == -1)
00431     return -1;
00432   if (lire_etat(mot_proc) == E_MORT) {
00433     fprintf(stderr,"Tentative de modification d'un proc mort (%d)\n",pid);
00434     return -1;
00435   }
00436   cp = (int)mot_proc[1];
00437   // Memorise le compteur programme actuel
00438   if (changer_esp(pid,1) == -1)
00439     return -1;
00440   ad_v.num = 0;
00441   ad_v.zone = Z_PILE;
00442   mot_pile[0] = M_UT;
00443   mot_pile[3] = cp+1;
00444   switch (ecrire_mot(pid, ad_v, mot_pile)) {
00445   case -1:
00446     changer_esp(pid,-1);
00447     return -1;
00448   case -2:
00449     changer_esp(pid,-1);
00450     return -2;
00451   }
00452   // Modifie le compteur programme
00453   mot_proc[1] = (octet_t)tab_param[0].ad;
00454   if (ecrire_mot_mem(pid,NUM_PAGE_META,mot_proc) == -1) {
00455     changer_esp(pid,-1);
00456     return -1;
00457   }
00458   return 0;
00459 }
00460 
00461 /**
00462  * Commande de retour de fonction
00463  * - Lit l'adresse de retour sur le haut de la pile
00464  * - Depile la pile de 1
00465  * - Modifie le compteur programme
00466  * \param pid : num du processus en cours d'execution
00467  * \return
00468  * - -1 en cas d'erreur
00469  * - -2 en cas de violation de memoire
00470  * - 0 sino
00471  */
00472 int cmd_retour(int pid) {
00473   int cp;
00474   mot_t mot_proc, mot_pile;
00475   vad_t ad_v;
00476 
00477   if (lire_mot_mem(pid,NUM_PAGE_META,mot_proc) == -1)
00478     return -1;
00479   if (lire_etat(mot_proc) == E_MORT) {
00480     fprintf(stderr,"Tentative de modification d'un proc mort (%d)\n",pid);
00481     return -1;
00482   }
00483   // Lit l'adresse de retour
00484   ad_v.num = 0;
00485   ad_v.zone = Z_PILE;
00486   switch (lire_mot(pid, ad_v, mot_pile)) {
00487   case -1:
00488     return -1;
00489   case -2:
00490     return -2;
00491   default:
00492     cp = (int)mot_pile[3];
00493   }
00494   // Modifie le compteur programme
00495   mot_proc[1] = (octet_t)cp;
00496   if (ecrire_mot_mem(pid,NUM_PAGE_META,mot_proc) == -1)
00497     return -1;
00498   // Depile la pile
00499   if (changer_esp(pid,-1) == -1)
00500     return -1;
00501   return 0;
00502 }
00503 
00504 /**
00505  * Commande pour fixer la taille de la zone de donnees.\n
00506  * Elle ne peut etre appelee qu'en debut de programme (compteur programme = 0)
00507  * \param pid : num du processus en cours d'execution
00508  * \param mot : mot correspondant a l'instruction
00509  * \return
00510  * - -1 en cas d'erreur
00511  * - 0 sinon
00512  */
00513 int cmd_donnees(int pid,mot_t mot) {
00514   mot_t mot_proc,mot_donnee, mot_tab;
00515   param_t tab_param[2];
00516   int cp;
00517   int taille;
00518   int num_page, num_tp;
00519   int i;
00520 
00521   if (parser_param(pid, mot, tab_param,1) == -1)
00522     return -1;
00523   // Verifie le type du 1er parametre
00524   if (tab_param[0].type != P_CONST) 
00525     return -1;
00526   // Cherche le compteur programme
00527   if (lire_mot_mem(pid,NUM_PAGE_META,mot_proc) == -1)
00528     return -1;
00529   if (lire_etat(mot_proc) == E_MORT) {
00530     fprintf(stderr,"Tentative de modification d'un proc mort (%d)\n",pid);
00531     return -1;
00532   }
00533   cp = (int)mot_proc[1];
00534   // DONNEES doit etre la 1ere instruction
00535   if (cp != 0)
00536     return -1;
00537   // Cherche la table des pages
00538   switch (lire_type_pp(mot_proc)) {
00539   case PP_RAM:
00540     num_tp = (int)mot_proc[3];
00541     break;
00542   case PP_SWAP:
00543     if ((num_tp=rapatrier_page_swap(pid,(int)mot_proc[3])) == -1)
00544       return -1;
00545     break;
00546   }
00547   // Initialise un mot de donnee
00548   mot_donnee[0] = (octet_t)M_UT;
00549   mot_donnee[3] = (octet_t)0;
00550   // Reserve la place necessaire aux donnees
00551   i = 0;
00552   taille = tab_param[0].ad;
00553   while (taille > 0) {
00554     // Rajoute une page a la zone de donnees
00555     if ((num_page=page_forcee(pid)) < 0)
00556       return -1;
00557     mot_tab[3] = (octet_t)num_page;
00558     mot_tab[2] = (octet_t)PP_RAM;
00559     if (ecrire_mot_mem(i+T_MAX_ZONES,num_tp,mot_tab) == -1)
00560       return -1;
00561     // Marque tous les mots de la zone de donnees comme utils
00562     for (i=0 ; (i<taille) && (i<NMPPP) ; i++) {
00563       if (ecrire_mot_mem(i,num_page,mot_donnee) == -1)
00564         return -1;
00565     }
00566     taille -= NMPPP;
00567     i++;
00568   }
00569   // Marque les mots en dehors de la zone de donnees comme inutilises
00570   mot_donnee[0] = (octet_t)M_NU;
00571   for (i=NMPPP+taille ; i<NMPPP ; i++) {
00572     if (ecrire_mot_mem(i,num_page,mot_donnee) == -1)
00573         return -1;
00574   }
00575   // Incremente le compteur programme
00576   cp ++;
00577   mot_proc[1] = (octet_t)cp;
00578   if (ecrire_mot_mem(pid,NUM_PAGE_META,mot_proc) == -1)
00579     return -1;
00580   return 0;
00581 }
00582 
00583 /**
00584  * Execute l'instruction AFFECTE ref = ref_cst.\n
00585  * Stocke a l'adresse du 1er arg la valeur du 2eme arg . Puis
00586  * deplace le compteur programme sur l'instruction suivante
00587  * \param pid : pid du processus
00588  * \param mot : mot correspondant à l'instruction
00589  * \return
00590  * - -1 en cas d'erreur
00591  * - -2 en cas de violation de memoire
00592  * - 0 sinon
00593  */
00594 int cmd_affect (int pid, mot_t mot) {
00595   param_t tab_param[2];
00596   mot_t mot_val,mot_proc;
00597   vad_t adv;
00598 
00599   switch (parser_param(pid,mot, tab_param,2)) {
00600   case -1:
00601     return -1;
00602   case -2:
00603     return -2;
00604   }
00605   // Verifie que le type des parametres est correct
00606   if (tab_param[0].type != P_REF)
00607     return -1;
00608   // Cherche la valeur du 2eme arg
00609   if (tab_param[1].type == P_CONST) {
00610     mot_val[3] = (octet_t)tab_param[1].ad;
00611     mot_val[2] = (octet_t)0;
00612     mot_val[1] = (octet_t)0;
00613     mot_val[0] = (octet_t)M_UT;
00614   }
00615   else {
00616     adv.num = tab_param[1].ad;
00617     adv.zone = tab_param[1].zone;
00618     switch (lire_mot(pid,adv,mot_val)) {
00619     case -1:
00620       return -1;
00621     case -2:
00622       return -2;
00623     }
00624   }
00625   // Ecrit cette valeur a l'adresse du 1er arg
00626   adv.num = tab_param[0].ad;
00627   adv.zone = tab_param[0].zone;
00628   switch (ecrire_mot(pid,adv,mot_val)) {
00629   case -1:
00630     return -1;
00631   case -2:
00632     return -2;
00633   }
00634   // Deplace le compteur programme sur l'instruction suivante
00635   if (lire_mot_mem(pid,NUM_PAGE_META,mot_proc) == -1) 
00636     return -1;
00637   mot_proc[1] = (octet_t)((int)mot_proc[1] + 1);
00638   if (ecrire_mot_mem(pid,NUM_PAGE_META,mot_proc) == -1) 
00639     return -1;  
00640   return 0;
00641 }
00642 
00643 /**
00644  * Execute l'instruction AFFECTE+ ref += ref_cst\n
00645  * Stocke a l'adresse du 1er arg la valeur du 2eme arg ajoutee a la valeur du 1er . Puis
00646  * deplace le compteur programme sur l'instruction suivante
00647  * \param pid : pid du processus
00648  * \param mot : mot correspondant à l'instruction
00649  * \return
00650  * - -1 en cas d'erreur
00651  * - -2 en cas de violation de memoire
00652  * - 0 sinon
00653  */
00654 int cmd_affectp (int pid,mot_t mot) { 
00655   param_t tab_param[2];
00656   mot_t mot_val,mot_proc;
00657   vad_t adv;
00658   int val;
00659 
00660   switch (parser_param(pid,mot, tab_param, 2)) {
00661   case -1:
00662     return -1;
00663   case -2:
00664     return -2;
00665   }
00666   // Verifie que le type des parametres est correct
00667   if (tab_param[0].type != P_REF)
00668     return -1;
00669   // Cherche la valeur du 1er arg
00670   adv.num = tab_param[0].ad;
00671   adv.zone = tab_param[0].zone;
00672   switch (lire_mot(pid,adv,mot_val)) {
00673   case -1:
00674     return -1;
00675   case -2:
00676     return -2;
00677   }
00678   val = (int)mot_val[3];
00679   // Cherche la valeur du 2eme arg
00680   if (tab_param[1].type == P_CONST) {
00681     mot_val[3] = (octet_t)(tab_param[1].ad + val);
00682     mot_val[0] = (octet_t)M_UT;
00683   }
00684   else {
00685     adv.num = tab_param[1].ad;
00686     adv.zone = tab_param[1].zone;
00687     switch (lire_mot(pid,adv,mot_val)) {
00688     case -1:
00689       return -1;
00690     case -2:
00691       return -2;
00692     }
00693     mot_val[3] = (octet_t)((int)mot_val[3] + val);
00694   }
00695   // Ecrit cette valeur a l'adresse du 1er arg
00696   adv.num = tab_param[0].ad;
00697   adv.zone = tab_param[0].zone;
00698   switch (ecrire_mot(pid,adv,mot_val)) {
00699   case -1:
00700     return -1;
00701   case -2:
00702     return -2;
00703   }
00704   // Deplace le compteur programme sur l'instruction suivante
00705   if (lire_mot_mem(pid,NUM_PAGE_META,mot_proc) == -1) 
00706     return -1;
00707   mot_proc[1] = (octet_t)((int)mot_proc[1] + 1);
00708   if (ecrire_mot_mem(pid,NUM_PAGE_META,mot_proc) == -1) 
00709     return -1;  
00710   return 0;
00711 }
00712 
00713 /**
00714  * Execute l'instruction AFFECTESP
00715  * Stocke a l'adresse du 1er arg la valeur du 2eme arg qui correspond a un pointeur
00716  * sur fonction.Puis deplace le compteur programme sur l'instruction suivante.
00717  * \param pid : pid du processus
00718  * \param mot : mot correspondant à l'instruction
00719  * \return
00720  * - -1 en cas d'erreur
00721  * - -2 en cas de violation de memoire
00722  * - 0 sinon
00723  */
00724 int cmd_affectsp (int pid, mot_t mot) {
00725   param_t tab_param[2];
00726   mot_t mot_val,mot_proc;
00727   vad_t adv;
00728 
00729   switch (parser_param(pid,mot, tab_param,2)) {
00730   case -1:
00731     return -1;
00732   case -2:
00733     return -2;
00734   }
00735   // Cherche la valeur du 2eme arg
00736   mot_val[3] = (octet_t)tab_param[1].ad;
00737   mot_val[0] = (octet_t)M_UT;
00738   // Ecrit cette valeur a l'adresse du 1er arg
00739   adv.num = tab_param[0].ad;
00740   adv.zone = tab_param[0].zone;
00741   switch (ecrire_mot(pid,adv,mot_val)) {
00742   case -1:
00743     return -1;
00744   case -2:
00745     return -2;
00746   }
00747   // Deplace le compteur programme sur l'instruction suivante
00748   if (lire_mot_mem(pid,NUM_PAGE_META,mot_proc) == -1) 
00749     return -1;
00750   mot_proc[1] = (octet_t)((int)mot_proc[1] + 1);
00751   if (ecrire_mot_mem(pid,NUM_PAGE_META,mot_proc) == -1) 
00752     return -1;  
00753   return 0;
00754 }
00755 
00756 /**
00757  * Execute l'instruction TEST.\n
00758  * Cette commande verifie l'egalite (en valeur) des 2 parametres puis leve ou abaisse
00759  * en consequence le drapeau pour le saut conditionnnel. Elle incremente aussi le 
00760  * compteur programme.
00761  * \param pid : pid du processus
00762  * \param mot : mot correspondant à l'instruction
00763  * \return
00764  * - -1 en cas d'erreur
00765  * - -2 en cas de violation de memoire
00766  * - 0 sinon
00767  */
00768 int cmd_test(int pid,mot_t mot) {
00769   param_t tab_param[2];
00770   int val1,val2;
00771   mot_t mot_val,mot_proc;
00772   vad_t adv;
00773 
00774   switch (parser_param(pid,mot, tab_param, 2)) {
00775   case -1:
00776     return -1;
00777   case -2:
00778     return -2;
00779   }
00780   // Cherche la valeur du 1er arg
00781   if (tab_param[0].type == P_CONST) {
00782     val1 = tab_param[0].ad;
00783   }
00784   else {
00785     adv.num = tab_param[0].ad;
00786     adv.zone = tab_param[0].zone;
00787     switch (lire_mot(pid,adv,mot_val)) {
00788     case -1:
00789       return -1;
00790     case -2:
00791       return -2;
00792     }
00793     val1 = (int)mot_val[3];
00794   }
00795   // Cherche la valeur du 2eme arg
00796   if (tab_param[1].type == P_CONST) {
00797     val2 = tab_param[1].ad;
00798   }
00799   else {
00800     adv.num = tab_param[1].ad;
00801     adv.zone = tab_param[1].zone;
00802     switch (lire_mot(pid,adv,mot_val)) {
00803     case -1:
00804       return -1;
00805     case -2:
00806       return -2;
00807     }
00808     val2 = (int)mot_val[3];
00809   }
00810   // Deplace le compteur programme sur l'instruction suivante
00811   if (lire_mot_mem(pid,NUM_PAGE_META,mot_proc) == -1)
00812     return -1;
00813   mot_proc[1] = (octet_t)((int)mot_proc[1] + 1);
00814   // Compare les 2 valeurs
00815   if (val2 == val1)
00816     changer_condition(C_VRAI,mot_proc);
00817   else
00818     changer_condition(C_FAUX,mot_proc);
00819   //  MAJ de la table des processus
00820   if (ecrire_mot_mem(pid,NUM_PAGE_META,mot_proc) == -1)
00821     return -1;
00822   return 0;
00823 }
00824 
00825 /**
00826  * Execute l'instruction SI :
00827  * - si le drapeau des sauts conditionnel est leve -> effectue le saut
00828  * - sinon deplace juste le compteur programme a l'instruction suivante
00829  * \param pid : pid du processus
00830  * \param mot : mot correspondant à l'instruction
00831  * \return
00832  * - -1 en cas d'erreur
00833  * - -2 en cas de violation de memoire
00834  * - 0 sinon
00835  */
00836 int cmd_si (int pid,mot_t mot){
00837   param_t tab_param[2];
00838   mot_t mot_proc;
00839 
00840   switch (parser_param(pid,mot, tab_param, 1)) {
00841   case -1:
00842     return -1;
00843   case -2:
00844     return -2;
00845   }
00846   // Lecture de l'entree du proc ds la table des processus
00847   if (lire_mot_mem(pid, NUM_PAGE_META,mot_proc) == -1)
00848     return -1;
00849   // Calcule du nouveau compteur programme
00850   if (condition_vraie(mot_proc)) 
00851     mot_proc[1] = (octet_t)tab_param[0].ad;
00852   else 
00853     mot_proc[1] = (octet_t)((int)mot_proc[1] + 1);
00854   // MAJ de la table des proc
00855   if (ecrire_mot_mem(pid, NUM_PAGE_META, mot_proc) == -1)
00856     return -1;
00857   return 0;
00858 }
00859 
00860 /**
00861  * Execute l'instruction SAUT.\n
00862  * Deplace le compteur programme a l'endroit indique par le 1er parametre.
00863  * \param pid : pid du processus
00864  * \param mot : mot correspondant à l'instruction
00865  * \return
00866  * - -1 en cas d'erreur
00867  * - -2 en cas de violation de memoire
00868  * - 0 sinon
00869  */
00870 int cmd_saut (int pid,mot_t mot) {
00871   param_t tab_param[2];
00872   mot_t mot_proc;
00873 
00874   switch (parser_param(pid,mot, tab_param, 1)) {
00875   case -1:
00876     return -1;
00877   case -2:
00878     return -2;
00879   }
00880   // Lecture de l'entree du proc ds la table des processus
00881   if (lire_mot_mem(pid, NUM_PAGE_META,mot_proc) == -1)
00882     return -1;
00883   mot_proc[1] = (octet_t)tab_param[0].ad;
00884   // MAJ de la table des proc
00885   if (ecrire_mot_mem(pid, NUM_PAGE_META, mot_proc) == -1)
00886     return -1;
00887   return 0;
00888 }
00889 
00890 /**
00891  * Commande TRAPPE qui retourne le pid du processus. C'est a dire qui l'ecrit sur la pile\n
00892  * Incremente le compteur programme.
00893  * \param pid : pid du processus
00894  * \return
00895  * - -1 en cas d'erreur
00896  * - -2 en cas de violation de memoire
00897  * - 0 sinon
00898  */
00899 int cmd_id (int pid) {
00900   vad_t adv;
00901   mot_t mot,mot_proc;
00902 
00903   // Ecrit le pid en haut de la pile
00904   mot[0] = (octet_t)M_UT;
00905   mot[3] = (octet_t)pid;
00906   adv.num = 0;
00907   adv.zone = Z_PILE;
00908   switch (ecrire_mot(pid,adv,mot)) {
00909   case -1:
00910     return -1;
00911   case -2:
00912     return -2;
00913   }
00914   // Deplace le compteur programme sur l'instruction suivante
00915   if (lire_mot_mem(pid,NUM_PAGE_META,mot_proc) == -1) {
00916     mot[3] = (int)0;
00917     ecrire_mot(pid,adv,mot);
00918     return -1;
00919   }
00920   mot_proc[1] = (octet_t)((int)mot_proc[1] + 1);
00921   if (ecrire_mot_mem(pid,NUM_PAGE_META,mot_proc) == -1) {
00922     mot[3] = (int)0;
00923     ecrire_mot(pid,adv,mot);
00924     return -1;  
00925   }
00926   return 0;
00927 }
00928 
00929 /**
00930  * Commande TRAPPE qui ecrit sur le haut de la pile le ppid du processus.\n
00931  * Incremente le compteur programme.
00932  * \param pid : pid du processus
00933  * \return
00934  * - -1 en cas d'erreur
00935  * - -2 en cas de violation de memoire
00936  * - 0 sinon
00937  */
00938 int cmd_idp(int pid){
00939   vad_t adv;
00940   mot_t mot,mot_proc;
00941   int ppid;
00942 
00943   // Cherche le ppid du processus
00944   if ((ppid=lire_ppid(pid)) == -1)
00945     return -1;
00946   // Ecrit le ppid en haut de la pile
00947   mot[0] = (octet_t)M_UT;
00948   mot[3] = (octet_t)ppid;
00949   adv.num = 0;
00950   adv.zone = Z_PILE;
00951   switch (ecrire_mot(pid,adv,mot)) {
00952   case -1:
00953     return -1;
00954   case -2:
00955     return -2;
00956   }
00957   // Deplace le compteur programme sur l'instruction suivante
00958   if (lire_mot_mem(pid,NUM_PAGE_META,mot_proc) == -1) {
00959     mot[3] = (int)0;
00960     ecrire_mot(pid,adv,mot);
00961     return -1;
00962   }
00963   mot_proc[1] = (octet_t)((int)mot_proc[1] + 1);
00964   if (ecrire_mot_mem(pid,NUM_PAGE_META,mot_proc) == -1) {
00965     mot[3] = (int)0;
00966     ecrire_mot(pid,adv,mot);
00967     return -1;  
00968   }
00969   return 0;
00970 }
00971 
00972 /**
00973  * Commande TRAPPE qui associe un handler a un signal pour le processus.\n
00974  * Incremente le compteur programme.\n
00975  * Ses arguments:
00976  * - P1: le signal
00977  * - P2: pointeur sur le handler
00978  * \param pid : pid du processus
00979  * \return
00980  * - -1 en cas d'erreur
00981  * - -2 en cas de violation de memoire
00982  * - 0 sinon
00983  */
00984 int cmd_capture (int pid) {
00985   vad_t adv, adv_err;
00986   mot_t mot_arg, mot_err, mot_proc;
00987   signal_t *sig;
00988 
00989   // Retourne 255 en cas d'erreur
00990   adv_err.num = 0;
00991   adv_err.zone = Z_PILE;
00992   mot_err[0] = (octet_t)M_UT;
00993   mot_err[3] = (octet_t)255;
00994   // Cherche le signal a capturer (dans P1)
00995   adv.num = 1;
00996   adv.zone = Z_PILE;
00997   switch (lire_mot(pid,adv,mot_arg)) {
00998   case -1:
00999     ecrire_mot(pid,adv_err,mot_err);
01000     return -1;
01001   case -2:
01002     ecrire_mot(pid,adv_err,mot_err);
01003     return -2;
01004   }
01005   sig = malloc(sizeof(signal_t));
01006   if ((sig->signal=sig_ksinu2lib((int)mot_arg[3])) == -1) {
01007     ecrire_mot(pid,adv_err,mot_err);
01008     free(sig);
01009     return -1;
01010   }
01011   // Associe a ce signal son nouveau comportement (dans P2)
01012   adv.num = 2;
01013   adv.zone = Z_PILE;
01014   switch (lire_mot(pid,adv,mot_arg)) {
01015   case -1:
01016     ecrire_mot(pid,adv_err,mot_err);
01017     free(sig);
01018     return -1;
01019   case -2:
01020     ecrire_mot(pid,adv_err,mot_err);
01021     free(sig);
01022     return -2;
01023   }
01024   sig->cp = (int)mot_arg[3];
01025   add_sig(pid,sig);
01026   // Deplace le compteur programme sur l'instruction suivante
01027   if (lire_mot_mem(pid,NUM_PAGE_META,mot_proc) == -1) {
01028     ecrire_mot(pid,adv_err,mot_err);
01029     return -1;
01030   }
01031   mot_proc[1] = (octet_t)((int)mot_proc[1] + 1);
01032   if (ecrire_mot_mem(pid,NUM_PAGE_META,mot_proc) == -1) {
01033     ecrire_mot(pid,adv_err,mot_err);
01034     return -1;  
01035   } 
01036   // Retourne 0 en cas de reussite
01037   mot_err[3] = (int)0;
01038   ecrire_mot(pid,adv_err,mot_err);
01039   return 0;
01040 }
01041 
01042 /**
01043  * Commande TRAPPE qui envoie a un processus un signal\n
01044  * Incremente le compteur programme.\n
01045  * Ses arguments:
01046  * - P1: le numero de processus
01047  * - P2: le signal
01048  * \param pid : pid du processus
01049  * \return
01050  * - -1 en cas d'erreur
01051  * - -2 en cas de violation de memoire
01052  * - 0 sinon
01053  */
01054 int cmd_emets (int pid) {
01055   vad_t adv,adv_err;
01056   mot_t mot_arg, mot_err, mot_proc;
01057   int pid2;
01058   int sig;
01059 
01060   // Retourne 255 en cas d'erreur
01061   adv_err.num = 0;
01062   adv_err.zone = Z_PILE;
01063   mot_err[0] = (octet_t)M_UT;
01064   mot_err[3] = (octet_t)255;
01065   // Lecture du num de processus auquel envoyer le signal
01066   adv.zone = Z_PILE;
01067   adv.num = 1;
01068   switch (lire_mot(pid,adv,mot_arg)) {
01069   case -1:
01070     ecrire_mot(pid,adv_err,mot_err);
01071     return -1;
01072   case -2:
01073     ecrire_mot(pid,adv_err,mot_err);
01074     return -2;
01075   }
01076   pid2 = (int)mot_arg[3];
01077   // Lecture du signal a envoyer
01078   adv.num = 2;
01079   adv.zone = Z_PILE;
01080   switch (lire_mot(pid,adv,mot_arg)) {
01081   case -1:
01082     ecrire_mot(pid,adv_err,mot_err);
01083     return -1;
01084   case -2:
01085     ecrire_mot(pid,adv_err,mot_err);
01086     return -2;
01087   }
01088   if ((sig=sig_ksinu2lib((int)mot_arg[3])) == -1) {
01089     ecrire_mot(pid,adv_err,mot_err);
01090     return -1;
01091   }
01092   // Envoie du signal
01093   if (lire_mot_mem(pid2,NUM_PAGE_META, mot_proc) == -1) {
01094     ecrire_mot(pid,adv_err,mot_err);
01095     return -1;
01096   }
01097   mot_proc[0] = mot_proc[0] | sig;
01098   if (ecrire_mot_mem(pid2,NUM_PAGE_META, mot_proc) == -1) {
01099     ecrire_mot(pid,adv_err,mot_err);
01100     return -1;
01101   }
01102   // Deplace le compteur programme sur l'instruction suivante
01103   if (lire_mot_mem(pid,NUM_PAGE_META,mot_proc) == -1) {
01104     ecrire_mot(pid,adv_err,mot_err);
01105     return -1;
01106   }
01107   mot_proc[1] = (octet_t)((int)mot_proc[1] + 1);
01108   if (ecrire_mot_mem(pid,NUM_PAGE_META,mot_proc) == -1) {
01109     ecrire_mot(pid,adv_err,mot_err);
01110     return -1;  
01111   } 
01112   // Retourne 0 en cas de reussite
01113   mot_err[3] = (int)0;
01114   ecrire_mot(pid,adv_err,mot_err);
01115   return 0;
01116 }
01117 
01118 /**
01119  * Commande TRAPPE qui lit une lettre ds le tube d'entree. La lecture est bloquante.\n
01120  * Incremente le compteur programme.\n
01121  * Ses arguments:
01122  * - P1: l'adresse (Mx) ou on ecrit le caractere
01123  * - P2: le nombre de carateres a lire (bloque ici a 1)
01124  * \param pid : pid du processus
01125  * \return
01126  * - -1 en cas d'erreur
01127  * - -2 en cas de violation de memoire
01128  * - 0 sinon
01129  */
01130 int cmd_lit (int pid){
01131   char c;
01132   mot_t mot_proc, mot_err,mot_pile;
01133   vad_t adv_err,adv;
01134   int ad,nb;
01135 
01136   // Retourne 255 en cas d'erreur
01137   adv_err.num = 0;
01138   adv_err.zone = Z_PILE;
01139   mot_err[0] = (octet_t)M_UT;
01140   mot_err[3] = (octet_t)255;
01141   // Lit l'entree du proc ds la table des processus
01142   if (lire_mot_mem(pid,NUM_PAGE_META,mot_proc) == -1) {
01143     ecrire_mot(pid,adv_err,mot_err);
01144     return -1;
01145   }
01146   // Lecture du 1er arg (P1)
01147   adv.num = 1;
01148   adv.zone = Z_PILE;
01149   switch (lire_mot(pid,adv,mot_pile)) {
01150   case -1:
01151     ecrire_mot(pid,adv_err,mot_err);
01152     return -1;
01153   case -2:
01154     ecrire_mot(pid,adv_err,mot_err);
01155     return -2;
01156   }
01157   ad = (int)mot_pile[3];
01158   // Lecture du 2eme arg (P2)
01159   adv.num = 2;
01160   adv.zone = Z_PILE;
01161   switch (lire_mot(pid,adv,mot_pile)) {
01162   case -1:
01163     ecrire_mot(pid,adv_err,mot_err);
01164     return -1;
01165   case -2:
01166     ecrire_mot(pid,adv_err,mot_err);
01167     return -2;
01168   }
01169   nb = 1; // normalement nb = (int)mot_pile[3];
01170   // for (i=0 ; i<nb ; i++) ...
01171   // Lit un caractere du tampon d'entree
01172   switch (lire_stdin(pid,&c)) {
01173   case -1:
01174     ecrire_mot(pid,adv_err,mot_err);
01175     return -1;
01176   case -2:
01177   case -3:
01178     // Mettre le processus en attente de lecture
01179     changer_etat(E_ATT_LECT,mot_proc);
01180     if (ecrire_mot_mem(pid,NUM_PAGE_META,mot_proc) == -1) {
01181       ecrire_mot(pid,adv_err,mot_err);
01182       return -1;
01183     }
01184     liste_supp_pid(liste_proc,pid);
01185     return 0;
01186   default:
01187     // Lecture reussie -> on ecrit le caract lu ds M ad
01188     adv.num = ad;
01189     adv.zone = Z_DONNEES;
01190     mot_pile[0] = (octet_t)M_UT;
01191     mot_pile[3] = (octet_t)c;
01192     switch (ecrire_mot(pid,adv,mot_pile)) {
01193     case -1:
01194       ecrire_mot(pid,adv_err,mot_err);
01195       return -1;
01196     case -2:
01197       ecrire_mot(pid,adv_err,mot_err);
01198       return -2;
01199     }
01200   }
01201   // Deplace le compteur programme sur l'instruction suivante
01202   mot_proc[1] = (octet_t)((int)mot_proc[1] + 1);
01203   if (ecrire_mot_mem(pid,NUM_PAGE_META,mot_proc) == -1) {
01204     ecrire_mot(pid,adv_err,mot_err);
01205     return -1;  
01206   } 
01207   // Retourne 0 ds P0
01208   adv.num = 0;
01209   adv.zone = Z_PILE;
01210   mot_pile[0] = (octet_t)M_UT;
01211   mot_pile[3] = (octet_t)0;
01212   switch (ecrire_mot(pid,adv,mot_pile)) {
01213   case -1:
01214     ecrire_mot(pid,adv_err,mot_err);
01215     return -1;
01216   case -2:
01217     ecrire_mot(pid,adv_err,mot_err);
01218     return -2;
01219   }
01220   return 0;
01221 }
01222 
01223 /**
01224  * Commande TRAPPE qui ecrit une lettre ds le tube de sortie. Commande bloquante\n
01225  * Incremente le compteur programme.\n
01226  * Ses arguments:
01227  * - P1: l'adresse (Mx) ou est stocke le caractere a ecrire
01228  * - P2: le nombre de carateres a ecrire (bloque ici a 1)
01229  * \param pid : pid du processus
01230  * \return
01231  * - -1 en cas d'erreur
01232  * - -2 en cas de violation de memoire
01233  * - 0 sinon
01234  */
01235 int cmd_ecrit(int pid){
01236   char c;
01237   mot_t mot_proc, mot_err,mot_pile;
01238   vad_t adv_err,adv;
01239   int ad,nb;
01240 
01241   // Retourne 255 en cas d'erreur
01242   adv_err.num = 0;
01243   adv_err.zone = Z_PILE;
01244   mot_err[0] = (octet_t)M_UT;
01245   mot_err[3] = (octet_t)255;
01246   // Lit l'entree du proc ds la table des processus
01247   if (lire_mot_mem(pid,NUM_PAGE_META,mot_proc) == -1) {
01248     ecrire_mot(pid,adv_err,mot_err);
01249     return -1;
01250   }
01251   // Lecture du 1er arg (P1)
01252   adv.num = 1;
01253   adv.zone = Z_PILE;
01254   switch (lire_mot(pid,adv,mot_pile)) {
01255   case -1:
01256     ecrire_mot(pid,adv_err,mot_err);
01257     return -1;
01258   case -2:
01259     ecrire_mot(pid,adv_err,mot_err);
01260     return -2;
01261   }
01262   ad = (int)mot_pile[3];
01263   // Lecture du caract a ecrire
01264   adv.num = ad;
01265   adv.zone = Z_DONNEES;
01266   switch (lire_mot(pid,adv,mot_pile)) {
01267   case -1:
01268     ecrire_mot(pid,adv_err,mot_err);
01269     return -1;
01270   case -2:
01271     ecrire_mot(pid,adv_err,mot_err);
01272     return -2;
01273   }
01274   c = (char)mot_pile[3];
01275   // Lecture du 2eme arg (P2)
01276   adv.num = 2;
01277   adv.zone = Z_PILE;
01278   switch (lire_mot(pid,adv,mot_pile)) {
01279   case -1:
01280     ecrire_mot(pid,adv_err,mot_err);
01281     return -1;
01282   case -2:
01283     ecrire_mot(pid,adv_err,mot_err);
01284     return -2;
01285   }
01286   nb = 1; // normalement nb = (int)mot_pile[3];
01287   // for (i=0 ; i<nb ; i++) ...
01288   // Lit un caractere du tampon d'entree
01289   switch (ecrire_stdout(pid,c)) {
01290   case -1:
01291     ecrire_mot(pid,adv_err,mot_err);
01292     return -1;
01293   case -2:
01294   case -3:
01295     // Mettre le processus en attente de lecture
01296     changer_etat(E_ATT_ECRIT,mot_proc);
01297     if (ecrire_mot_mem(pid,NUM_PAGE_META,mot_proc) == -1) {
01298       ecrire_mot(pid,adv_err,mot_err);
01299       return -1;
01300     }
01301     liste_supp_pid(liste_proc,pid);
01302     return 0;
01303   }
01304   // Deplace le compteur programme sur l'instruction suivante
01305   mot_proc[1] = (octet_t)((int)mot_proc[1] + 1);
01306   if (ecrire_mot_mem(pid,NUM_PAGE_META,mot_proc) == -1) {
01307     ecrire_mot(pid,adv_err,mot_err);
01308     return -1;  
01309   } 
01310   // Ecriture reussie -> retourne 0 ds P0
01311   adv.num = 0;
01312   adv.zone = Z_PILE;
01313   mot_pile[0] = (octet_t)M_UT;
01314   mot_pile[3] = (octet_t)0;
01315   switch (ecrire_mot(pid,adv,mot_pile)) {
01316   case -1:
01317     ecrire_mot(pid,adv_err,mot_err);
01318     return -1;
01319   case -2:
01320     ecrire_mot(pid,adv_err,mot_err);
01321     return -2;
01322   }
01323   return 0;
01324 }
01325 
01326 /**
01327  * Commande TRAPPE terminant le processus\n
01328  * Incremente le compteur programme.\n
01329  * Ses arguments:
01330  * - P0: la valeur de retour du processus
01331  * \param pid : pid du processus
01332  * \return
01333  * - -1 en cas d'erreur
01334  * - -2 en cas de violation de memoire
01335  * - 0 sinon
01336  */
01337 int cmd_fin(int pid){
01338   printf("TRAPPE FIN proc %d\n",pid);
01339   if (terminer_proc(pid) < 0)
01340     return -1;
01341   return 0;
01342 }
01343 
01344 /**
01345  * Commande TRAPPE qui recouvre l'espace memoire d'un processus pour executer un autre programme.\n
01346  * Incremente le compteur programme.\n
01347  * Argument : l'adresse ou est stocke le nom du fichier objet (1 caractere)
01348  * Retourne : 
01349  * - -1 en cas d'erreur
01350  * - rien sinon
01351  * \param pid : pid du processus
01352  * \return
01353  * - -1 en cas d'erreur
01354  * - -2 en cas de violation de memoire
01355  * - 0 sinon
01356  */
01357 int cmd_recouvre (int pid) {
01358   vad_t adv_err,adv;
01359   mot_t mot_pile,mot_err,mot_proc;
01360   char *nom;
01361   int ppid;
01362 
01363   // Retourne 255 en cas d'erreur
01364   adv_err.num = 0;
01365   adv_err.zone = Z_PILE;
01366   mot_err[0] = (octet_t)M_UT;
01367   mot_err[3] = (octet_t)255;
01368   // Lit l'entree du proc ds la table des processus
01369   if (lire_mot_mem(pid,NUM_PAGE_META,mot_proc) == -1) {
01370     ecrire_mot(pid,adv_err,mot_err);
01371     return -1;
01372   }
01373   if (lire_etat(mot_proc) == E_MORT) {
01374     ecrire_mot(pid,adv_err,mot_err);
01375     return -1;
01376   }
01377   // Lit l'argument
01378   adv.num = 1;
01379   adv.zone = Z_PILE;
01380   switch (lire_mot(pid,adv,mot_pile)) {
01381   case -1:
01382     ecrire_mot(pid,adv_err,mot_err);
01383     return -1;
01384   case -2:
01385     ecrire_mot(pid,adv_err,mot_err);
01386     return -2;
01387   }
01388   nom = malloc(8);
01389   sprintf(nom,"%c.objet",(char)mot_pile[3]);
01390   // Supprime partiellemnt le processus
01391   if (supprimer_partie_proc(pid) < 0) {
01392     ecrire_mot(pid,adv_err,mot_err);
01393     free(nom);
01394     return -1; 
01395   }
01396   // Sauvegarde le pid du pere
01397   if ((ppid=lire_ppid(pid)) == -1) {
01398     free(nom);
01399     return -1;
01400   }
01401   // Supprime la table des pages
01402   switch (lire_type_pp(mot_proc)) {
01403   case PP_SWAP:
01404     if (liberer_page_swap((int)mot_proc[3]) == -1) {
01405       free(nom);
01406       return -1;
01407     }
01408   case PP_RAM:
01409     if (liberer_page((int)mot_proc[3]) == -1) {
01410       free(nom);
01411       return -1;
01412     }
01413   }
01414   // Lance le nouveau programme
01415   if (lancer_prog(nom,pid) == -1) {
01416     free(nom);
01417     return -1;
01418   }
01419   // Indique son ppid
01420   if (changer_ppid(pid,ppid) == -1) {
01421     free(nom);
01422     return -1;
01423   }
01424   free(nom);
01425   return 0;
01426 }
01427 
01428 /**
01429  * Commande TRAPPE qui duplique l'espace memoire\n
01430  * Incremente le compteur programme.\n
01431  * Aucun argument.\n
01432  * Retourne :
01433  * - 0 ds l'espace memoire du fils 
01434  * - le pid du fils si on est ds l'espace memoire du pere
01435  * \param pid : pid du processus
01436  * \return
01437  * - -1 en cas d'erreur
01438  * - -2 en cas de violation de memoire
01439  * - 0 sinon
01440  */
01441 int cmd_clone (int pid) {
01442   int ppid_f = pid;
01443   int pid_f;
01444   int i,j;
01445   mot_t mot_proc, mot_proc_f, mot_tp_f, mot_tp, mot_pp, mot_err;
01446   vad_t adv_err;
01447   int num_tp, num_tp_f, num_pp_f, num_pp;
01448 
01449   // Retourne 255 en cas d'erreur
01450   adv_err.num = 0;
01451   adv_err.zone = Z_PILE;
01452   mot_err[0] = (octet_t)M_UT;
01453   mot_err[3] = (octet_t)255;
01454   // Lit l'entree du proc ds la table des processus
01455   if (lire_mot_mem(pid,NUM_PAGE_META,mot_proc) == -1) {
01456     ecrire_mot(pid,adv_err,mot_err);
01457     return -1;
01458   }
01459   if (lire_etat(mot_proc) == E_MORT) {
01460     ecrire_mot(pid,adv_err,mot_err);
01461     return -1;
01462   }
01463   // Lecture de la table des pages
01464   switch (lire_type_pp(mot_proc)) {
01465   case PP_RAM:
01466     num_tp = (int)mot_proc[3];
01467     liste_acces_page(liste_pages,num_tp);
01468     break;
01469   case PP_SWAP:
01470     if ((num_tp=rapatrier_page_swap(pid,(int)mot_proc[3])) < 0) {
01471       ecrire_mot(pid,adv_err,mot_err);
01472       return -1;
01473     }
01474     break;
01475   }
01476   // Obtient un nouveau pid
01477   if ((pid_f=pid_libre()) == -1) {
01478     ecrire_mot(pid,adv_err,mot_err);
01479     return -1;
01480   }
01481   // Obtient une nouvelle table des pages
01482   if ((num_tp_f=page_forcee(pid_f)) < 0) {
01483     liberer_pid(pid_f);
01484     ecrire_mot(pid,adv_err,mot_err);
01485     return -1;
01486   }
01487   // Incremente le compteur programme
01488   if (lire_mot_mem(pid,NUM_PAGE_META,mot_proc) == -1) {
01489     ecrire_mot(pid,adv_err,mot_err);
01490     return -1;
01491   }
01492   mot_proc[1] = (octet_t)((int)mot_proc[1]+1);
01493   if (ecrire_mot_mem(pid,NUM_PAGE_META,mot_proc) == -1) {
01494     ecrire_mot(pid,adv_err,mot_err);
01495     return -1;
01496   }
01497   // Initialisation de l'entree ds la table des proc
01498   mot_proc_f[0] = mot_proc[0];
01499   mot_proc_f[1] = mot_proc[1];
01500   mot_proc_f[2] = mot_proc[2];
01501   changer_type_pp(PP_RAM,mot_proc_f);
01502   mot_proc_f[3] = num_tp_f;
01503   if (ecrire_mot_mem(pid_f,NUM_PAGE_META,mot_proc_f) == -1) {
01504     liberer_pid(pid_f);
01505     ecrire_mot(pid,adv_err,mot_err);
01506     return -1;
01507   }
01508   // Remplissage de la table des pages du fils
01509   for (i=0 ; i<3*T_MAX_ZONES+3 ; i++) {
01510     if (i != NUM_MOT_IN+1) { // NUM_MOT_IN+1 n'est pas un mot pointant sur une page
01511       // Obtient une page RAM libre
01512       if ((num_pp_f=page_forcee(pid_f)) == -1) {
01513         supprimer_proc(pid_f);
01514         ecrire_mot(pid,adv_err,mot_err);
01515         return -1;
01516       }
01517       // Lecture du mot de la table du pere
01518       if (lire_mot_mem(i, num_tp, mot_tp) == -1) {
01519         supprimer_proc(pid_f);
01520         ecrire_mot(pid,adv_err,mot_err);
01521         liberer_page(num_pp_f);
01522         return -1;
01523       }
01524       switch ((int)mot_tp[2]) {
01525       case PP_NULL:
01526         // Recopie du mot
01527         mot_tp_f[2] = (octet_t)PP_NULL;
01528         mot_tp_f[3] = (octet_t)0;
01529         if (ecrire_mot_mem(i,num_tp_f,mot_tp_f) == -1) {
01530           supprimer_proc(pid_f);
01531           ecrire_mot(pid,adv_err,mot_err);
01532           liberer_page(num_pp_f);
01533           return -1;
01534         }
01535         // mais pas de la page
01536         liberer_page(num_pp_f);
01537         num_pp_f = -1;
01538         break;
01539       case PP_RAM:
01540         num_pp = (int)mot_tp[3];
01541         break;
01542       case PP_SWAP:
01543         if ((num_pp=rapatrier_page_swap(pid,(int)mot_tp[3])) == -1) {
01544           supprimer_proc(pid_f);
01545           liberer_page(num_pp_f);
01546           ecrire_mot(pid,adv_err,mot_err);
01547           return -1;
01548         }
01549         break;
01550       }
01551       if (num_pp_f != -1) {
01552         // Recopie de la page mot par mot
01553         for (j=0 ; j<NMPPP ; j++) {
01554           if (lire_mot_mem(j,num_pp,mot_pp) == -1) {
01555             supprimer_proc(pid_f);
01556             ecrire_mot(pid,adv_err,mot_err);
01557             liberer_page(num_pp_f);
01558             return -1;
01559           }
01560           if (ecrire_mot_mem(j,num_pp_f,mot_pp) == -1) {
01561             supprimer_proc(pid_f);
01562             liberer_page(num_pp_f);
01563             ecrire_mot(pid,adv_err,mot_err);
01564             return -1;
01565           }
01566         }
01567         // Inscrit cette page ds la table des pages du fils
01568         mot_tp_f[3] = (octet_t)num_pp_f;
01569         mot_tp_f[2] = (octet_t)PP_RAM;
01570         mot_tp_f[0] = mot_tp[0];
01571         mot_tp_f[1] = mot_tp[1];
01572         if (ecrire_mot_mem(i, num_tp_f, mot_tp_f) == -1) {
01573           supprimer_proc(pid_f);
01574           liberer_page(num_pp_f);
01575           ecrire_mot(pid,adv_err,mot_err);
01576           return -1;
01577         }
01578       }
01579     }
01580   }
01581   // Initialise la derniere zone de la table des pages
01582   // MAJ la taille de la pile
01583   if (lire_mot_mem(NUM_MOT_ESP,num_tp,mot_tp) == -1) {
01584     supprimer_proc(pid_f);
01585     ecrire_mot(pid,adv_err,mot_err);
01586     return -1;
01587   }
01588   if (ecrire_mot_mem(NUM_MOT_ESP,num_tp_f,mot_tp) == -1) {
01589     supprimer_proc(pid_f);
01590     ecrire_mot(pid,adv_err,mot_err);
01591     return -1;
01592   }
01593   // Deverrouillage de tampons
01594   mot_tp_f[3] = (octet_t)F_UNLOCK;
01595   if (ecrire_mot_mem(NUM_MOT_IN+1,num_tp_f,mot_tp_f) == -1) {
01596     supprimer_proc(pid_f);
01597     ecrire_mot(pid,adv_err,mot_err);
01598     return -1;
01599   }
01600   if (ecrire_mot_mem(NUM_MOT_OUT+1,num_tp_f,mot_tp_f) == -1) {
01601     supprimer_proc(pid_f);
01602     ecrire_mot(pid,adv_err,mot_err);
01603     return -1;
01604   }
01605   // Indiquer ppid
01606   mot_tp_f[3] = (octet_t)ppid_f;
01607   if (ecrire_mot_mem(NUM_MOT_PPID,num_tp_f,mot_tp_f) == -1) {
01608     supprimer_proc(pid_f);
01609     ecrire_mot(pid,adv_err,mot_err);
01610     return -1;
01611   }
01612   // Retourne le pid du fils en haut de la pile du pere
01613   mot_err[3] = (octet_t)pid_f;
01614   ecrire_mot(pid,adv_err,mot_err);
01615   // Retourne 0 en haut de la pile du fils
01616   mot_err[3] = (octet_t)0;
01617   ecrire_mot(pid_f,adv_err,mot_err);
01618   return 0;
01619 }
01620 
01621 /**
01622  * Commande TRAPPE qui suspend le processus jusqu'à la mort d'un fils.\n
01623  * Incremente le compteur programme.\n
01624  * Un argument : P1 l'adresse memoire ou stocker la valeur de retour du fils
01625  * Retourne :
01626  * - 255 en cas d'echec
01627  * - le pid du fils sinon
01628  * \param pid : pid du processus
01629  * \return
01630  * - -1 en cas d'erreur
01631  * - -2 en cas de violation de memoire
01632  * - 0 sinon
01633  */
01634 int cmd_attends(int pid) {
01635   int i;
01636   mot_t mot_proc, mot_err, mot_fils, mot_retour, mot_ad;
01637   vad_t adv_err,adv_ad;
01638   int num_tp_f;
01639   int ppid;
01640 
01641   printf("TRAPPE ATTENDS proc %d\n",pid);
01642   // Retourne 255 en cas d'erreur
01643   adv_err.num = 0;
01644   adv_err.zone = Z_PILE;
01645   mot_err[0] = (octet_t)M_UT;
01646   mot_err[3] = (octet_t)255;
01647   // Lit l'entree du proc ds la table des processus
01648   if (lire_mot_mem(pid,NUM_PAGE_META,mot_proc) == -1) {
01649     ecrire_mot(pid,adv_err,mot_err);
01650     return -1;
01651   }
01652   if (lire_etat(mot_proc) == E_MORT) {
01653     ecrire_mot(pid,adv_err,mot_err);
01654     return -1;
01655   }
01656   // Incremente le compteur programme
01657   mot_proc[1] = (octet_t)((int)mot_proc[1]+1);
01658   if (ecrire_mot_mem(pid,NUM_PAGE_META,mot_proc) == -1) {
01659     ecrire_mot(pid,adv_err,mot_err);
01660     return -1;
01661   }
01662   // Recherche ses fils
01663   for (i=1 ; i<N_MAX_PROC+1 ; i++) {
01664     if (i != pid) {
01665       switch (ppid=lire_ppid(i)) {
01666       case -1:
01667         if (lire_mot_mem(i,NUM_PAGE_META,mot_fils) == -1) {
01668           ecrire_mot(pid,adv_err,mot_err);
01669           return -1;
01670         }
01671         if (lire_etat(mot_fils) != E_MORT) {
01672           ecrire_mot(pid,adv_err,mot_err);
01673           return -1;
01674         }
01675         break;
01676       default:
01677         if (ppid == pid) {
01678           // Le proc i est un fils du processus a supprimer
01679           if (lire_mot_mem(i,NUM_PAGE_META,mot_fils) == -1) {
01680             ecrire_mot(pid,adv_err,mot_err);
01681             return -1;
01682           }
01683           if (lire_etat(mot_fils) == E_ZOMBI) { // Le fils est un zombi
01684             // Lecture de sa table des pages (pour la valeur de retour)
01685             switch (lire_type_pp(mot_fils)) {
01686             case PP_RAM:
01687               num_tp_f = (int)mot_fils[3];
01688               break;
01689             case PP_SWAP:
01690               if ((num_tp_f=rapatrier_page_swap(i,(int)mot_fils[3])) == -1) {
01691                 ecrire_mot(pid,adv_err,mot_err);
01692                 return -1;
01693               }
01694               break;
01695             }
01696             // Recupere la valeur de retour du fils
01697             if (lire_mot_mem(NUM_MOT_EXIT,num_tp_f,mot_retour) == -1) {
01698               ecrire_mot(pid,adv_err,mot_err);
01699               return -1;
01700             }
01701             // On lit l'argument de la commande
01702             adv_ad.num = 1;
01703             adv_ad.zone = Z_PILE;
01704             switch (lire_mot(pid,adv_ad,mot_ad)) {
01705             case -1:
01706               ecrire_mot(pid,adv_err,mot_err);
01707               return -1;
01708             case -2:
01709               ecrire_mot(pid,adv_err,mot_err);
01710               return -2;
01711             }
01712             // On ecrit la valeur de retour a l'adresse donnee par l'argument
01713             adv_ad.num = (int)mot_ad[3];
01714             adv_ad.zone = Z_DONNEES;
01715             mot_retour[0] = (octet_t)M_UT;
01716             switch (ecrire_mot(pid,adv_ad,mot_retour)) {
01717             case -1:
01718               ecrire_mot(pid,adv_err,mot_err);
01719               return -1;
01720             case -2:
01721               ecrire_mot(pid,adv_err,mot_err);
01722               return -2;
01723             }
01724             // On retourne le pid du fils
01725             adv_ad.num = 0;
01726             adv_ad.zone = Z_PILE;
01727             mot_retour[3] = (octet_t)i;
01728             switch (ecrire_mot(pid,adv_ad,mot_retour)) {
01729             case -1:
01730               ecrire_mot(pid,adv_err,mot_err);
01731               return -1;
01732             case -2:
01733               ecrire_mot(pid,adv_err,mot_err);
01734               return -2;
01735             }
01736             // On supprime le fils
01737             if (supprimer_proc(i) < 0) {
01738               ecrire_mot(pid,adv_err,mot_err);
01739               return -1;
01740             }
01741             return 0;
01742           }
01743         }
01744       }
01745     }
01746   }
01747   // Aucun fils n'est deja mort
01748   // Le processus change d'etat
01749   changer_etat(E_ATT_FILS,mot_proc);
01750   if (ecrire_mot_mem(pid,NUM_PAGE_META,mot_proc) == -1) {
01751     ecrire_mot(pid,adv_err,mot_err);
01752     return -1;
01753   }
01754   liste_supp_pid(liste_proc,pid);
01755   return 0;
01756 }
01757 
01758 
01759 
01760 /**************************************************************************************
01761  Fait par Ouachani Mourad
01762 **************************************************************************************/
01763 
01764 
01765 
01766 /**
01767  * Augmente la taille de la pile.\n
01768  * Et incremente la valeur du compteur programme
01769  * \param pid : numero du processus dont on veut augementer la taille de la pile
01770  * \param nbre : nombre de mot a augementer 
01771  * \return 
01772  * - -1 en cas d'erreur
01773  * - -2 en cas de violation de memoire
01774  * - 0 sinon
01775  */
01776 int cmd_cpile(int pid,mot_t mot){
01777   int i;
01778   int op = 1;
01779   param_t tab_param[2];
01780   int nbre;
01781   mot_t mot_proc;
01782 
01783   switch (parser_param(pid, mot, tab_param, 1)) {
01784   case -1:
01785     return -1;
01786   case -2:
01787     return -2;
01788   }
01789   // Verifie que le type des parametres est correct
01790   if (tab_param[0].type != P_CONST)
01791     return -1;
01792   nbre = tab_param[0].ad;
01793   if(nbre < 1){
01794     printf("Verifier le nombre de mot a augementer dans la pile");
01795     return -1;
01796   }
01797   for(i=0; i< nbre;i++){
01798     if(changer_esp(pid,op) == -1){
01799       printf("erreur : impossible d'incrementer la hauteur de la pile\n");
01800       return -1;
01801     }
01802   }
01803   // Incremente le compteur programme
01804   if (lire_mot_mem(pid,NUM_PAGE_META,mot_proc) == -1) {
01805     return -1;
01806   }
01807   mot_proc[1] = (octet_t)((int)mot_proc[1] + 1);
01808   if (ecrire_mot_mem(pid,NUM_PAGE_META,mot_proc) == -1) {
01809     return -1;  
01810   }
01811   return 0;
01812 }
01813 
01814 /**
01815  * Diminue la taille de la pile.\n
01816  * En plus de modifier la taille :
01817  * - incremente la valeur du compteur programme\n
01818  * \param pid : numero du processus dont on veut diminuer la taille de la pile
01819  * \param nbre : nombre de mot a diminuer 
01820  * \return 
01821  * - -1 en cas d'erreur
01822  * - -2 en cas de violation de memoire
01823  * - 0 sinon
01824  */
01825 int cmd_dpile(int pid,mot_t mot){
01826   int i;
01827   int op = -1;
01828   param_t tab_param[2];
01829   int nbre;
01830   mot_t mot_proc;
01831 
01832   switch (parser_param(pid,mot, tab_param, 2)) {
01833   case -1:
01834     return -1;
01835   case -2:
01836     return -2;
01837   }
01838   // Verifie que le type des parametres est correct
01839   if (tab_param[0].type != P_CONST)
01840     return -1;
01841   nbre = tab_param[0].ad;
01842   if(nbre < 1){
01843     printf("Verifier le nombre de mot a diminuer dans la pile");
01844     return -1;
01845   }
01846   for(i=0; i< nbre;i++){
01847     if(changer_esp(pid,op) == -1){
01848       printf("erreur : impossible de decrementer la hauteur de la pile\n");
01849       return -1;
01850     }
01851   }
01852   // Incremente le compteur programme
01853   if (lire_mot_mem(pid,NUM_PAGE_META,mot_proc) == -1) {
01854     return -1;
01855   }
01856   mot_proc[1] = (octet_t)((int)mot_proc[1] + 1);
01857   if (ecrire_mot_mem(pid,NUM_PAGE_META,mot_proc) == -1) {
01858     return -1;  
01859   }
01860   return 0;
01861 }

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