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  */
00005 
00006 #include "interpreteur.h"
00007 
00008 /**
00009  * Fonction retournant un numero de processus libre
00010  * \return 
00011  * - -1 en cas d'erreur
00012  * - -2 S'il n'y a plus de pid libre
00013  * - un num de processus libre
00014  */
00015 int pid_libre ( ) {
00016   mot_t mot,mot2;
00017   int pid_libre;
00018   int i;
00019 
00020   // Lit le mot ou est stocke le plus petit pid libre
00021   if (lire_mot_mem(0, NUM_PAGE_META, mot) == -1)
00022     return -1;
00023   // Verifie qu'il reste au moins un pid libre
00024   if ((pid_libre=(int)mot[3]) == NO_MORE_PID) {
00025     fprintf(stderr,"Il n'y a plus de pid libre\n");
00026     return -2;
00027   }
00028   // Recherche le prochain pid libre
00029   for (i=pid_libre+1 ; i<N_MAX_PROC+1 ; i++) {
00030     if (lire_mot_mem(i, NUM_PAGE_META, mot2) == -1)
00031       return -1;
00032     if ((int)mot2[2] == PP_NULL) {
00033       // Met a jour le mot ou est stocke le plus petit pid libre 
00034       mot[3] = (octet_t)i;
00035       if (ecrire_mot_mem(0, NUM_PAGE_META, mot) == -1)
00036         return -1;
00037       // Renvoie un pid libre
00038       return pid_libre;
00039     }
00040   }
00041   // il n'y a pas d'autre pid libre
00042   // Met a jour le mot ou est stocke le plus petit pid libre 
00043   mot[3] = (octet_t)NO_MORE_PID;
00044   if (ecrire_mot_mem(0, NUM_PAGE_META, mot) == -1)
00045     return -1;
00046   // Renvoie un pid libre
00047   return pid_libre;
00048 }
00049 
00050 /**
00051  * Fonction permettant de liberer un num de processus apres sa mort
00052  * \param pid : Numero du processus mort qu'il faut donc declare comme libre
00053  * \return 
00054  * - -1 erreur : le numero de processus n'a pas ete libere
00055  * - -2 erreur : le numero de processus a ete libere mais le numero de le plus petit pid
00056  *               n'est peut-etre plus exact
00057  * - 0  succes
00058  */
00059 int liberer_pid (int pid) {
00060   mot_t mot,mot2;
00061 
00062   // Libere le num de pid
00063   mot2[2] = PP_NULL;
00064   if (ecrire_mot_mem(pid,NUM_PAGE_META, mot2) == -1)
00065     return -1;
00066   // Modifie eventuellement le num du plus petit pid libre
00067   if (lire_mot_mem(0, NUM_PAGE_META, mot) == -1)
00068     return -2;
00069   if (pid < (int)mot[3]) {
00070     mot[3] = (octet_t)pid;
00071     if (ecrire_mot_mem(0,NUM_PAGE_META, mot) == -1)
00072       return -2;
00073   }
00074   return 0;
00075 }
00076 
00077 /**
00078  * Fonction retournant un num de page physique libre ds la memoire afin
00079  * de l'attacher a un processus.
00080  * \param pid : Numero du processus auquel on veut attacher cette page
00081  * \return 
00082  * - -1 en cas d'erreur
00083  * - -2 S'il n'y a plus de page libre en memoire principale
00084  * - un num de page libre
00085  */
00086 int page_libre (int pid) {
00087   int page_libre;
00088   int i,j;
00089   int num_mot, num_octet;
00090   mot_t mot, mot2;
00091 
00092   // Lit le mot ou est stocke le plus petit pid libre
00093   if (lire_mot_mem(DEBUT_T_PAGES, NUM_PAGE_META, mot) == -1)
00094     return -1;
00095   // Verifie qu'il reste au moins une page libre
00096   if ((page_libre=(int)mot[0]) == NO_MORE_PAGE) {
00097     fprintf(stdout,"Il n'y a plus de page libre en memoire\n");
00098     return -2;
00099   }
00100   // Recherche la prochaine page libre
00101   num_mot = (page_libre + 1) / T_MOT + DEBUT_T_PAGES;
00102   num_octet = (page_libre + 1) % T_MOT;
00103   for (i=num_mot ; i<NMPPP ; i++) {
00104     if (lire_mot_mem(i, NUM_PAGE_META, mot2) == -1)
00105       return -1;
00106     for (j=num_octet ; j<T_MOT ; j++) {
00107       if (mot2[j] == PAGE_VIDE) {
00108         // Met a jour le mot ou est stocke le plus petit pid libre 
00109         mot[0] = (octet_t)(i - DEBUT_T_PAGES) * T_MOT + j;
00110         if (ecrire_mot_mem(DEBUT_T_PAGES, NUM_PAGE_META, mot) == -1)
00111           return -1;
00112         // Ajoute la page retournee a la liste des pages memoire utilisees
00113         liste_add_page(liste_pages,page_libre);
00114         return page_libre;
00115       }
00116     }
00117     num_octet = 0;
00118   }
00119   // il n'y a pas d'autre page libre
00120   // Met a jour le mot ou est stocke le plus petit pid libre 
00121   mot[0] = (octet_t)NO_MORE_PAGE;
00122   if (ecrire_mot_mem(DEBUT_T_PAGES, NUM_PAGE_META, mot) == -1)
00123     return -1;
00124   // Ajoute la page retournee a la liste des pages memoire utilisees
00125   liste_add_page(liste_pages,page_libre);
00126   // Attache la page au processus passe en parametre
00127   num_mot = page_libre / T_MOT + DEBUT_T_PAGES;
00128   num_octet = page_libre % T_MOT;
00129   if (lire_mot_mem(num_mot, NUM_PAGE_META, mot2) == -1) {
00130     liberer_page(page_libre);
00131     return -1;
00132   }
00133   mot2[num_octet] = (octet_t)pid;
00134   if (ecrire_mot_mem(num_mot, NUM_PAGE_META, mot2) == -1) {
00135     liberer_page(page_libre);
00136     return -1;
00137   }
00138   return page_libre;
00139 }
00140 
00141 /**
00142  * Fonction permettant de liberer un numero de page physique ds la memoire
00143  * \param page : Numero de la page non utilisee (a liberer)
00144  * \return 
00145  * - -1 erreur : le numero de page n'a pas ete libere
00146  * - -2 erreur : le numero de page a ete libere mais le numero de la plus petite page
00147  *               n'est peut-etre plus exact
00148  * - 0  succes
00149  */
00150 int liberer_page(int page) {
00151   mot_t mot;
00152   int num_mot,num_octet;
00153 
00154   // Libere le num de la page
00155   num_mot = page/T_MOT + DEBUT_T_PAGES;
00156   num_octet = page % T_MOT;
00157   if (lire_mot_mem(num_mot, NUM_PAGE_META, mot) == -1)
00158     return -1;
00159   mot[num_octet] = PAGE_VIDE;
00160   if (ecrire_mot_mem(num_mot,NUM_PAGE_META, mot) == -1)
00161     return -1;
00162   // Modifie eventuellement le num de la plus petite page libre
00163   if (lire_mot_mem(DEBUT_T_PAGES, NUM_PAGE_META, mot) == -1)
00164     return -2;
00165   if (page < (int)mot[0]) {
00166     mot[0] = (octet_t)page;
00167     if (ecrire_mot_mem(DEBUT_T_PAGES,NUM_PAGE_META, mot) == -1)
00168       return -2;
00169   }
00170   // Supprime cette page de la liste des pages memoire
00171   // Mise a jour de la liste des pages memoire
00172   if (liste_supp_page(liste_pages,page) != 0) {
00173     fprintf(stderr,"La table des pages memoire utilisees n'etait pas coherente.\n");
00174     // On continue tout de meme car elle est peut-etre de nouveau coherente
00175   }
00176   return 0;
00177 }
00178 
00179 /**
00180  * Fonction retournant un numero de page physique du swap libre 
00181  * \return 
00182  * - -1  En cas d'erreur
00183  * - -2 S'il n'y a plus de page libre en memoire principale
00184  * - un num de page libre
00185  */
00186 int page_swap_libre () {
00187   mot_t mot,mot2;
00188   int pc,num_mot,num_page_libre;
00189 
00190   // Lecture de la position courante ds la table des pages swap libres
00191   if (lire_mot_mem(DEBUT_T_PAGES, NUM_PAGE_META, mot) == -1)
00192     return -1;
00193   pc = (int)mot[1];
00194   // Lecture du num de la page swap libre
00195   num_mot = pc / T_MOT;
00196   if (lire_mot_mem(num_mot, NUM_PAGE_SWAP, mot2) == -1) 
00197     return -1;
00198   num_page_libre = (int)mot2[pc%T_MOT];
00199   if (num_page_libre == NO_MORE_SWAP) {
00200     fprintf(stderr,"Il n'y a plus de page libre dans le swap\n");
00201     return -2;
00202   }
00203   // Deplacement du pointeur courant
00204   pc ++;
00205   // Rechargement du debut de la liste des pages swap libres si necessaire
00206   if (pc >= NMPPP*T_MOT) {
00207     if (page_swap2mem(num_page_libre, NUM_PAGE_SWAP) == -1)
00208       return -1;
00209     mot[1] = (octet_t)0;
00210     if (ecrire_mot_mem(DEBUT_T_PAGES, NUM_PAGE_META, mot) == -1) {
00211       fprintf(stderr,"Position courante de la table des pages swap libres incoherente\n");
00212       return -1;
00213     }
00214   }
00215   return num_page_libre;
00216 }
00217 
00218 /**
00219  * Fonction permettant de liberer un numero de page physique ds le swap
00220  * \param page : Numero de la page non utilisee (a liberer)
00221  * \return 
00222  * - -1 erreur : le numero de page n'a pas ete libere
00223  * - -2 erreur : le numero de page a ete libere mais le pointeur courant n'a pas ete mis a jour
00224  * - 0  succes
00225  */
00226 int liberer_page_swap (int page) {
00227   mot_t mot,mot2;
00228   int pc,num_mot;
00229 
00230   // Lecture de la position courante ds la table des pages swap libres
00231   if (lire_mot_mem(DEBUT_T_PAGES, NUM_PAGE_META, mot) == -1)
00232     return -1;
00233   pc = (int)mot[1];
00234   if (pc > 0) {
00235     pc --;
00236     num_mot = pc / T_MOT;
00237     if (lire_mot_mem(num_mot, NUM_PAGE_SWAP, mot2) == -1) 
00238       return -1;
00239     mot2[pc%T_MOT] = (octet_t)page;
00240     // Libere le num de la page
00241     if (ecrire_mot_mem(num_mot,NUM_PAGE_SWAP, mot2) == -1)
00242       return -1;
00243     // Modifie le pointeur courant
00244     mot[1] = (octet_t)pc;
00245     if (ecrire_mot_mem(DEBUT_T_PAGES,NUM_PAGE_META, mot) == -1)
00246       return -2;
00247   }
00248   else {
00249     // Sauvegarde dans le swap de cette page de la liste des pages swap libres
00250     if (page_mem2swap(NUM_PAGE_SWAP,page) == -1)
00251       return -1;
00252     // Creation de la nouvelle page de la liste des pages swap libres
00253     mot2[3] = (octet_t)page;
00254     if (ecrire_mot_mem(NMPPP-1,NUM_PAGE_SWAP,mot2) == -1)
00255       return -1;
00256     pc = NMPPP*T_MOT-1;
00257     mot[1] = (octet_t)pc;
00258     if (ecrire_mot_mem(DEBUT_T_PAGES,NUM_PAGE_META, mot) == -1)
00259       return -2;
00260   }
00261   return 0;
00262 }
00263 
00264 /**
00265  * Fonction permettant de mettre en memoire principale une page du processus 'pid'
00266  * se trouvant dans le swap.
00267  * \param page : Numero de la page swap qu'on veut mettre en memoire principale
00268  * \return 
00269  * - -1 en cas d'erreur
00270  * - le numero de la page memoire dans laquelle a ete copiee la page swap
00271  */
00272 int rapatrier_page_swap (int pid, int page) {
00273   int num_page_mem,num_page_swap,num_table_pages;
00274   int old_pid;
00275   int find=0;
00276   mot_t mot_tab_page,mot_proc;
00277   int *tab,taille;
00278   int i,j;
00279 
00280   // Regarde s'il y a des pages libres en mem
00281   num_page_mem = page_libre(pid);
00282   if (num_page_mem > 0) { // Il reste au moins une page libre en mem 
00283     // Rapatrie la page swap ds cette page libre
00284     if (page_swap2mem(page, num_page_mem) == -1)
00285       return -1;
00286   }
00287   else if (num_page_mem == -1) {
00288     return -1;
00289   }
00290   else { // Il n'y a plus de page libre en mem
00291     // On cherche la page la moins utilisee
00292     if ((num_page_mem=liste_old_page(liste_pages)) == -1)
00293       return -1;
00294     // On met cette page en swap
00295     if ((num_page_swap=page_swap_libre()) == -1)
00296       return -1;
00297     if (page_mem2swap(num_page_mem,num_page_swap) == -1)
00298       return -1;
00299     // On cherche le num du processus auquel appartient la page
00300     if (lire_mot_mem(DEBUT_T_PAGES+num_page_mem/T_MOT,NUM_PAGE_META,mot_tab_page) == -1)
00301       return -1;
00302     old_pid =(int) mot_tab_page[num_page_mem%T_MOT];
00303     // On modifie la table des pages du processus associe a cette page
00304     if (lire_mot_mem(old_pid,NUM_PAGE_META,mot_proc) == -1) 
00305       return -1;
00306     num_table_pages = (int)mot_proc[3];
00307     if (num_table_pages == num_page_mem) {
00308       // La page mise en swap correspond a la table des pages du processus
00309       mot_proc[3] = (octet_t)num_page_swap;
00310       mot_proc[2] = (octet_t)PP_SWAP;
00311       if (ecrire_mot_mem(old_pid,NUM_PAGE_META,mot_proc) == -1) 
00312         return -1;
00313       // Change le num du processus proprietaire de la page
00314       mot_tab_page[num_page_mem%T_MOT] = (octet_t)pid;
00315       if (ecrire_mot_mem(DEBUT_T_PAGES+num_page_mem/T_MOT,NUM_PAGE_META,mot_tab_page) == -1) {
00316         // Reviens a l'ancien etat de la table des processus
00317         mot_proc[3] = (octet_t)num_page_mem;
00318         mot_proc[2] = (octet_t)PP_RAM;
00319         ecrire_mot_mem(old_pid,NUM_PAGE_META,mot_proc);
00320         return -1;
00321       }
00322     }
00323     else {
00324       // La page est une page de code, de donnees ou de de pile
00325       for (i=0 ; (i<3) && (find==0) ; i++) {
00326         for (j=0 ; j<8 ; j++) {
00327           if (lire_mot_mem(i*8+j,num_table_pages,mot_proc) == -1) 
00328             return -1;
00329           if ((int)mot_proc[2] == PP_NULL)
00330             break;
00331           if (mot_proc[3] == num_page_mem) {
00332             // On a trouve ds la table des pages du processus, l'entree correspondant a 
00333             // la page mise en swap. Il faut la modifier en consequence
00334             mot_proc[2] = (octet_t)PP_SWAP;
00335             mot_proc[3] = (octet_t)num_page_swap;
00336             if (ecrire_mot_mem(i*8+j,num_table_pages,mot_proc) == -1) 
00337               return -1;
00338             find = 1;
00339             break;
00340           }
00341         }
00342       }
00343       if (find == 0) {
00344         // La page n'a pas ete trouvee ds la table des pages du processus
00345         fprintf(stderr,"La table des pages du processus %d n'est pas coherente avec la ",old_pid);
00346         fprintf(stderr,"table des pages de la memoire principale.\n");
00347         return -1;
00348       }
00349     }
00350   }
00351   // Libere la page swap ramenee en memoire principale
00352 
00353   return num_page_mem;
00354 }
00355 
00356 /**
00357  * Fonction permettant de lire un mot se trouvant ds la mem principale
00358  * \param num_pp : Numero de la page physique en memoire ds laquelle on veut lire un mot
00359  * \param num_mot : Numero du mot qu'on veut lire ds cette page
00360  * \param mot : Structure qui sera remplie apres lecture
00361  * \return 
00362  * - -1 en cas d'erreur
00363  * -  0 sinon
00364  */
00365 int lire_mot_mem(int num_mot, int num_pp, mot_t mot) {
00366   unsigned char *p_mot;
00367 
00368   // Verifie que les coordonnees du mot sont valides
00369   if (num_pp < 0 || num_pp > NPP-1) {
00370     fprintf(stderr,"%d n'est pas un numero de page physique en memoire correct\n",num_pp);
00371     return -1;
00372   }
00373   if (num_mot < 0 || num_mot > NMPPP-1) {
00374     fprintf(stderr,"%d n'est pas un numero de mot correct\n",num_mot);
00375     return -1;
00376   }
00377   // Lecture du mot
00378   p_mot = mem[num_pp][num_mot];
00379   // Remplissage de la structure mot_t
00380   memcpy(mot,p_mot,sizeof(mot_t));
00381   // Mise a jour de la liste des pages memoire
00382   if (liste_acces_page(liste_pages,num_pp) != 0) {
00383     fprintf(stderr,"Tentative de lecture ds une page non reservee (%d)\n",num_pp);
00384     return -1;
00385   }
00386   return 0;
00387 }
00388 
00389 /**
00390  * Fonction permettant d'ecrire un mot dans la mem principale
00391  * \param num_pp : Numero de la page physique en memoire ds laquelle on veut ecrire un mot
00392  * \param num_mot : Emplacement ds cette page ou on veut ecrire le mot
00393  * \param mot : Le mot a ecrire
00394  * \return 
00395  * - -1 en cas d'erreur
00396  * -  0 sinon
00397  */
00398 int ecrire_mot_mem(int num_mot, int num_pp, mot_t mot) {
00399   unsigned char *p_mot;
00400 
00401   // Verifie que les coordonnees du mot sont valides
00402   if (num_pp < 0 || num_pp > NPP-1) {
00403     fprintf(stderr,"%d n'est pas un numero de page physique en memoire correct\n",num_pp);
00404     return -1;
00405   }
00406   if (num_mot < 0 || num_mot > NMPPP-1) {
00407     fprintf(stderr,"%d n'est pas un numero de mot correct\n",num_mot);
00408     return -1;
00409   }
00410   // Ecriture du mot
00411   p_mot = mem[num_pp][num_mot];
00412   memcpy(p_mot,mot,sizeof(mot_t));
00413   // Mise a jour de la liste des pages memoire
00414   if (liste_acces_page(liste_pages,num_pp) != 0) {
00415     fprintf(stderr,"Tentative d'ecriture ds une page non reservee (%d)\n",num_pp);
00416     return -1;
00417   }
00418   return 0;
00419 }
00420 
00421 /**
00422  *  Fonction retournant a partir d'une adresse virtuelle :
00423  * - le numero de la page physique a laquelle elle correspond
00424  * - le type (memoire principale ou seacondaire) de cette page
00425  * - les droits avec lesquels on y accede
00426  * \param pid : num du processus auquel appartient l'adresse virtuelle
00427  * \param ad_v : adresse virtuelle dont on veut connaitre l'adresse physique correspondante
00428  * \param info : structure qui sera remplie par l'adresse physique, son type et ses droits
00429  * \return 
00430  * - -1 en cas d'erreur
00431  * - 0  sinon
00432  */
00433 int adresse_phys (int pid, vad_t ad_v, info_page_t info) {
00434   int num_page, num_mot;
00435   mot_t mot;
00436 
00437   // Lecture de la table des pages du processus pid
00438   if (lire_mot_mem(pid,NUM_PAGE_META,mot) == -1)
00439     return -1;
00440   switch ((int)mot[2]) {
00441   case PP_NULL:
00442     // Ce num de processus ne correspond a aucune page physique
00443     fprintf(stderr,"Le num de processus %d ne correspond a aucune page physique\n",pid);
00444     return -1;
00445   case PP_SWAP:
00446     // La table des pages du processus pid se trouve ds le swap
00447     // On la ramene en mem principale
00448     if ((num_page=rapatrier_page_swap(pid,(int)mot[3])) == -1)
00449       return -1;
00450     break;
00451   case PP_RAM:
00452     num_page = (int)mot[3];
00453     break;
00454   default:
00455     //cas impossible
00456     fprintf(stderr,"La table des processus est incoherente\n");
00457   }
00458   num_mot = ad_v.zone*8+ad_v.num/NMPPP;
00459   if (lire_mot_mem(num_mot, num_page, mot) == -1)
00460     return -1;
00461   // Remplissage de la structure info_page_t
00462   info.type = (int)mot[2];
00463   info.droits = (int)mot[1];
00464   info.num = (int)mot[3];
00465   return 0;
00466 }
00467 
00468 /**
00469  * Fonction permettant de copier une page du swap dans la memoire princale
00470  * \param num_page_swap : numero de la page a copier
00471  * \param num_page_mem : numero de la page memoire dans laquelle on veut faire la copie
00472  * \return 
00473  * - -1 en cas d'erreur
00474  * - 0  sinon
00475  */
00476 int page_swap2mem (int num_page_swap, int num_page_mem) {
00477   if (lseek(swap_d,num_page_swap*T_PAGE,SEEK_SET) == (off_t)-1)
00478     return -1;
00479   if (read(swap_d,mem[num_page_mem],T_PAGE) != T_PAGE)
00480     return -1;
00481   return 0;
00482 }
00483 
00484 /**
00485  * Fonction permettant de copier une page de la mem princale ds le swap
00486  * \param num_page_mem : numero de la page a copier
00487  * \param num_page_swap : numero de la page swap dans laquelle on veut faire la copie
00488  * \return 
00489  * - -1 en cas d'erreur
00490  * - 0  sinon
00491  */
00492 int page_mem2swap (int num_page_mem, int num_page_swap) {
00493   if (lseek(swap_d,num_page_swap*T_PAGE,SEEK_SET) == -1)
00494     return -1;
00495   if (write(swap_d,mem[num_page_mem],T_PAGE) != T_PAGE)
00496     return -1;
00497   return 0;
00498 }
00499 
00500 /**
00501  * Fonction qui execute l'instruction courante du processus donne en param
00502  * \param pid : num du processus
00503  * \return rien
00504  */
00505 void next_inst (int pid) {
00506   mot_t mot;
00507   vad_t ad_v;
00508 
00509   // Verifie que le num de processus est valide
00510   if (pid < 0 || pid > N_MAX_PROC) {
00511     fprintf(stderr, "Le proc %d n'existe pas\n", pid);
00512     return;
00513   }
00514   else {
00515     if (lire_mot_mem(pid,NUM_PAGE_META,mot) == -1)
00516       return;
00517     if ((int)mot[2] == PP_NULL) {
00518       fprintf(stderr, "Tentative d'execution d'un proc termine (%d est vide)\n", pid);
00519       return;
00520     }
00521   }
00522   // Lit l'instruction courante
00523   ad_v.zone = Z_CODE;
00524   ad_v.num = (int)mot[1];
00525   if (lire_mot(pid, ad_v, mot) == -1)
00526     return;
00527   switch ((int)mot[0]) {
00528   case I_AFFECT:
00529     break;
00530   case I_AFFECTP:
00531     break;
00532   case I_SI:
00533     break;
00534   case I_SAUT:
00535     break;
00536   case I_CPILE:
00537     break;
00538   case I_DPILE:
00539     break;
00540   case I_APPEL:
00541     break;
00542   case I_RETOUR:
00543     break;
00544   case I_TEST:
00545     break;
00546   case I_TRAPPE:
00547     switch ((int)mot[2]) {
00548     case T_CLONE:
00549       break;
00550     case T_RECOUVRE:
00551       break;
00552     case T_ATTENDS:
00553       break;
00554     case T_FIN:
00555       break;
00556     case T_CAPTURE:
00557       break;
00558     case T_EMETS:
00559       break;
00560     case T_ID:
00561       break;
00562     case T_IDP:
00563       break;
00564     case T_LIT:
00565       break;
00566     case T_ECRIT:
00567       break;
00568     default:
00569       // Erreur
00570       return;
00571     }
00572     break;
00573   case I_AFFECTSP:
00574     break;
00575   case I_DONNEES:
00576     break;
00577   default:
00578     // Erreur
00579     return;
00580   }
00581 }

Généré le Fri Jun 7 09:49:32 2002 pour KSInu par doxygen1.2.16