Diff for /rpl/src/interruptions.c between versions 1.34 and 1.35

version 1.34, 2010/08/23 08:04:40 version 1.35, 2010/08/25 09:06:49
Line 1730  deverrouillage_gestionnaire_signaux() Line 1730  deverrouillage_gestionnaire_signaux()
 #define nombre_queues   13  #define nombre_queues   13
   
 static int              *fifos;  static int              *fifos;
   static int              markov;
 static int              segment;  static int              segment;
 static sem_t            *semaphores[nombre_queues];  static sem_t            *semaphores[nombre_queues];
 static sem_t            *semaphore_global;  static sem_t            *semaphore_global;
Line 1824  creation_fifos_signaux(struct_processus Line 1825  creation_fifos_signaux(struct_processus
      * SIGSTART, SIGINJECT, SIGABORT, SIGFABORT       * SIGSTART, SIGINJECT, SIGABORT, SIGFABORT
      */       */
   
       int                             i;
   
       unsigned char                   *nom;
   
 #   ifndef IPCS_SYSV // POSIX  #   ifndef IPCS_SYSV // POSIX
   
       if ((nom = nom_segment((*s_etat_processus).chemin_fichiers_temporaires,
               getpid())) == NULL)
       {
           (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;
           return;
       }
   
       if ((segment = shm_open(nom, O_RDWR | O_CREAT | O_EXCL,
               S_IRUSR | S_IWUSR)) == -1)
       {
           free(nom);
           (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;
           return;
       }
   
       if (ftruncate(segment, nombre_queues * ((2 * longueur_queue) + 4) *
               sizeof(int)) == -1)
       {
           free(nom);
           (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;
           return;
       }
   
       fifos = mmap(NULL, nombre_queues * ((2 * longueur_queue) + 4) * sizeof(int),
               PROT_READ | PROT_WRITE, MAP_SHARED, segment, 0);
       close(segment);
   
       if (((void *) fifos) == ((void *) -1))
       {
           if (shm_unlink(nom) == -1)
           {
               free(nom);
               (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;
               return;
           }
   
           free(nom);
           (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;
           return;
       }
   
       free(nom);
   
 #   else // SystemV  #   else // SystemV
   
     file                            *desc;      file                            *desc;
   
     int                             i;  
   
     key_t                           clef;      key_t                           clef;
   
     unsigned char                   *nom;  
   
     // Création d'un segment de données associé au PID du processus courant      // Création d'un segment de données associé au PID du processus courant
   
     chemin = (*s_etat_processus).chemin_fichiers_temporaires;      chemin = (*s_etat_processus).chemin_fichiers_temporaires;
Line 1863  creation_fifos_signaux(struct_processus Line 1908  creation_fifos_signaux(struct_processus
     free(nom);      free(nom);
   
     if ((segment = shmget(clef,      if ((segment = shmget(clef,
             nombre_queues * (longueur_queue + 4) * sizeof(int),              nombre_queues * ((2 * longueur_queue) + 4) * sizeof(int),
             IPC_CREAT | IPC_EXCL | S_IRUSR | S_IWUSR)) == -1)              IPC_CREAT | IPC_EXCL | S_IRUSR | S_IWUSR)) == -1)
     {      {
         (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;          (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;
Line 1893  creation_fifos_signaux(struct_processus Line 1938  creation_fifos_signaux(struct_processus
      * 2 : longueur de la queue (int)       * 2 : longueur de la queue (int)
      * 3 : éléments restants (int)       * 3 : éléments restants (int)
      * 4 à 4 + (2) : queue (int)       * 4 à 4 + (2) : queue (int)
        * 4 + (2) + 1 ) 4 + 2 * (2) : horodatage en centième de secondes.
      */       */
   
     for(i = 0; i < nombre_queues; i++)      for(i = 0; i < nombre_queues; i++)
Line 1945  creation_fifos_signaux(struct_processus Line 1991  creation_fifos_signaux(struct_processus
   
     free(nom);      free(nom);
   
       markov = 0;
   
     return;      return;
 }  }
   
Line 1953  liberation_fifos_signaux(struct_processu Line 2001  liberation_fifos_signaux(struct_processu
 {  {
     int                 i;      int                 i;
   
   #   ifdef IPCS_SYSV // SystemV
   
     if (shmdt(fifos) == -1)      if (shmdt(fifos) == -1)
     {      {
         (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;          (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;
         return;          return;
     }      }
   
   #   else // POSIX
   
       if (munmap(fifos, nombre_queues * ((2 * longueur_queue) + 4) * sizeof(int))
               != 0)
       {
           (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;
           return;
       }
   
   #   endif
   
     for(i = 0; i < nombre_queues; i++)      for(i = 0; i < nombre_queues; i++)
     {      {
         if (sem_close(semaphores[i]) != 0)          if (sem_close(semaphores[i]) != 0)
Line 1984  destruction_fifos_signaux(struct_process Line 2045  destruction_fifos_signaux(struct_process
   
     unsigned char       *nom;      unsigned char       *nom;
   
   #   ifdef IPCS_SYSV // SystemV
   
     if (shmdt(fifos) == -1)      if (shmdt(fifos) == -1)
     {      {
         (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;          (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;
Line 2006  destruction_fifos_signaux(struct_process Line 2069  destruction_fifos_signaux(struct_process
     unlink(nom);      unlink(nom);
     free(nom);      free(nom);
   
   #   else // POSIX
   
       if (munmap(fifos, nombre_queues * ((2 * longueur_queue) + 4) * sizeof(int))
               != 0)
       {
           (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;
           return;
       }
   
       if ((nom = nom_segment(NULL, getpid())) == NULL)
       {
           (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;
           return;
       }
   
       if (shm_unlink(nom) != 0)
       {
           free(nom);
           (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;
           return;
       }
   
       free(nom);
   
   #   endif
   
     for(i = 0; i < nombre_queues; i++)      for(i = 0; i < nombre_queues; i++)
     {      {
         if ((nom = nom_semaphore(getpid(), i)) == NULL)          if ((nom = nom_semaphore(getpid(), i)) == NULL)
Line 2040  destruction_fifos_signaux(struct_process Line 2129  destruction_fifos_signaux(struct_process
     return;      return;
 }  }
   
 int  inline int
 queue_in(pid_t pid, int signal)  horodatage()
 {  {
 #undef printf      int             ts;
 // Transformer ce truc en POSIX ! On ne fait du SysV que si on n'a pas le choix  
   
 #   ifndef IPCS_SYSV      struct timeval  tv;
 #   else // Traitement à l'aide d'IPCS SystemV  
       gettimeofday(&tv, NULL);
       ts = (int) ((tv.tv_sec * 100) + (tv.tv_usec / 10000));
   
       return(ts);
   }
   
   int
   queue_in(pid_t pid, int signal)
   {
       int             queue;
     int             *base;      int             *base;
     int             *buffer;      int             *buffer;
     int             *projection_fifos;      int             horodatage_initial;
     int             queue;  
     int             identifiant;      int             identifiant;
       int             *projection_fifos;
     key_t           clef;  
   
     sem_t           *semaphore;      sem_t           *semaphore;
   
     struct stat     s_stat;      queue = queue_de_signal(signal);
   
     unsigned char   *nom;      unsigned char   *nom;
   
     queue = queue_de_signal(signal);  #   ifndef IPCS_SYSV
   
       // Ouverture des projections
   
       if ((nom = nom_segment(NULL, pid)) == NULL)
       {
           return(-1);
       }
   
       // Dans le cas de SIGSTART, premier signal envoyé à un processus fils,
       // il convient d'attendre que le fichier support soit effectivement
       // accessible. Dans tous les autres cas, ce fichier doit exister. S'il
       // n'existe plus, le processus associé n'existe plus.
   
       if (signal == SIGSTART)
       {
           horodatage_initial = horodatage();
   
           while((identifiant = shm_open(nom, O_RDWR, S_IRUSR | S_IWUSR)) == -1)
           {
               if (abs(horodatage_initial - horodatage()) > 500)
               {
                   return(-1);
               }
           }
       }
       else
       {
           if ((identifiant = shm_open(nom, O_RDWR, S_IRUSR | S_IWUSR)) == -1)
           {
               return(-1);
           }
       }
   
       projection_fifos = mmap(NULL, nombre_queues * ((2 * longueur_queue) + 4)
               * sizeof(int), PROT_READ | PROT_WRITE, MAP_SHARED, identifiant, 0);
       close(identifiant);
   
       if (((void *) projection_fifos) == ((void *) -1))
       {
           return(-1);
       }
   
   #   else // Traitement à l'aide d'IPCS SystemV
   
       key_t           clef;
   
       struct stat     s_stat;
   
     // Ouverture des projections      // Ouverture des projections
   
Line 2081  queue_in(pid_t pid, int signal) Line 2223  queue_in(pid_t pid, int signal)
     {      {
         // On attend que le fichier sois présent          // On attend que le fichier sois présent
   
         while(stat(nom, &s_stat) != 0);          horodatage_initial = horodatage();
   
           while(stat(nom, &s_stat) != 0)
           {
               if (abs(horodatage_initial - horodatage()) > 500)
               {
                   return(-1);
               }
           }
     }      }
   
     if ((clef = ftok(nom, 1)) == -1)      if ((clef = ftok(nom, 1)) == -1)
Line 2094  queue_in(pid_t pid, int signal) Line 2244  queue_in(pid_t pid, int signal)
     if (signal == SIGSTART)      if (signal == SIGSTART)
     {      {
         while((identifiant = shmget(clef,          while((identifiant = shmget(clef,
                 nombre_queues * (longueur_queue + 4) * sizeof(int),                  nombre_queues * ((2 * longueur_queue) + 4) * sizeof(int),
                 S_IRUSR | S_IWUSR)) == -1);                  S_IRUSR | S_IWUSR)) == -1);
     }      }
     else      else
     {      {
         if ((identifiant = shmget(clef,          if ((identifiant = shmget(clef,
                 nombre_queues * (longueur_queue + 4) * sizeof(int),                  nombre_queues * ((2 * longueur_queue) + 4) * sizeof(int),
                 S_IRUSR | S_IWUSR)) == -1)                  S_IRUSR | S_IWUSR)) == -1)
         {          {
             return(-1);              return(-1);
Line 2114  queue_in(pid_t pid, int signal) Line 2264  queue_in(pid_t pid, int signal)
         return(-1);          return(-1);
     }      }
   
   #   endif
   
     if ((nom = nom_semaphore(pid, queue)) == NULL)      if ((nom = nom_semaphore(pid, queue)) == NULL)
     {      {
   #       ifdef IPCS_SYSV
         shmdt(projection_fifos);          shmdt(projection_fifos);
   #       else
           munmap(projection_fifos, nombre_queues * ((2 * longueur_queue) + 4)
                   * sizeof(int));
   #       endif
         return(-1);          return(-1);
     }      }
   
     while((semaphore = sem_open(nom, 0)) == SEM_FAILED);      while((semaphore = sem_open(nom, 0)) == SEM_FAILED);
       free(nom);
   
     if (sem_wait(semaphore) != 0)      while(sem_wait(semaphore) != 0)
     {      {
         shmdt(projection_fifos);          if (errno != EINTR)
         return(-1);          {
   #           ifdef IPCS_SYSV
               shmdt(projection_fifos);
   #           else
               munmap(projection_fifos, nombre_queues * ((2 * longueur_queue) + 4)
                       * sizeof(int));
   #           endif
               return(-1);
           }
     }      }
   
     // Il ne faut pas empiler plusieurs SIGSTART car SIGSTART peut provenir  
     // de l'instruction SWI. Plusieurs threads peuvent interrompre de façon  
     // asynchrone le processus père durant une phase de signaux masqués.  
   
     base = &(projection_fifos[(longueur_queue + 4) * queue]);      base = &(projection_fifos[(longueur_queue + 4) * queue]);
     buffer = &(base[4]);      buffer = &(base[4]);
   
Line 2141  queue_in(pid_t pid, int signal) Line 2303  queue_in(pid_t pid, int signal)
     {      {
         sem_post(semaphore);          sem_post(semaphore);
         sem_close(semaphore);          sem_close(semaphore);
   #       ifdef IPCS_SYSV
         shmdt(projection_fifos);          shmdt(projection_fifos);
   #       else
           munmap(projection_fifos, nombre_queues * ((2 * longueur_queue) + 4)
                   * sizeof(int));
   #       endif
         return(-1);          return(-1);
     }      }
   
     base[3]--;      base[3]--;
   
     // base[1] contient le prochain élément à écrire      // base[1] contient le prochain élément à écrire
   
       buffer[base[1] + (nombre_queues * base[2])] = horodatage();
     buffer[base[1]++] = (int) pid;      buffer[base[1]++] = (int) pid;
     base[1] %= base[2];      base[1] %= base[2];
   
     if (sem_post(semaphore) != 0)      if (sem_post(semaphore) != 0)
     {      {
   #       ifdef IPCS_SYSV
         shmdt(projection_fifos);          shmdt(projection_fifos);
   #       else
           munmap(projection_fifos, nombre_queues * ((2 * longueur_queue) + 4)
                   * sizeof(int));
   #       endif
         sem_close(semaphore);          sem_close(semaphore);
         return(-1);          return(-1);
     }      }
Line 2161  queue_in(pid_t pid, int signal) Line 2335  queue_in(pid_t pid, int signal)
     sem_close(semaphore);      sem_close(semaphore);
   
     // Fermeture des projections      // Fermeture des projections
   #   ifdef IPCS_SYSV
     shmdt(projection_fifos);      shmdt(projection_fifos);
   #   else
       munmap(projection_fifos, nombre_queues * ((2 * longueur_queue) + 4)
               * sizeof(int));
 #   endif  #   endif
   
     return(0);      return(0);
 }  }
   
   inline int
   chaine_markov(int markov, int delta)
   {
       double      memoire = 0.9;
       int         valeur;
   
       valeur = (int) ((memoire * markov) + ((1 - memoire) * delta));
       valeur = (valeur < 10) ? 10 : valeur;
   
       return(valeur);
   }
   
 pid_t  pid_t
 origine_signal(int signal)  origine_signal(int signal)
 {  {
       logical1        drapeau;
   
     int             *base;      int             *base;
     int             *buffer;      int             *buffer;
       int             delta;
     int             pid;      int             pid;
     int             queue;      int             queue;
   
Line 2181  origine_signal(int signal) Line 2373  origine_signal(int signal)
     BUG(queue == -1, uprintf("[%d] Unknown signal %d in this context\n",      BUG(queue == -1, uprintf("[%d] Unknown signal %d in this context\n",
             (int) getpid(), signal));              (int) getpid(), signal));
   
     if (sem_wait(semaphores[queue]) != 0)      while(sem_wait(semaphores[queue]) != 0)
     {      {
         return(-1);          if (errno != EINTR)
           {
               return(-1);
           }
     }      }
   
     // Le signal SIGCONT peut être envoyé de façon totalement asynchrone.      // On retire les interruptions anciennes qui ont été ratées sauf s'il
     // Il peut y avoir plus de signaux envoyés que d'interruptions traitées.      // s'agit de la dernière dans la queue.
     // Il convient donc de rectifier la queue lors du traitement de  
     // l'interruption correspondante. Le gestionnaire étant installé sans      base = &(fifos[(longueur_queue + 4) * queue]);
     // l'option NODEFER, la queue reste cohérente.      buffer = &(base[4]);
   
     if (signal == SIGCONT)      if (base[3] == (base[2] - 1))
     {  
         base = &(fifos[(longueur_queue + 4) * queue]);  
         buffer = &(base[4]);  
         base[0] = (base[1] - 1) % base[2];  
         pid = buffer[base[0]++];  
         base[3] = base[2];  
     }  
     else  
     {      {
         base = &(fifos[(longueur_queue + 4) * queue]);          delta = abs(horodatage() -
         buffer = &(base[4]);                   buffer[base[0] + (nombre_queues * base[2])]);
           // Une seule interruption dans la queue.
         pid = buffer[base[0]++];          pid = buffer[base[0]++];
         base[0] %= base[2];          base[0] %= base[2];
         base[3]++;          base[3]++;
   
           markov = chaine_markov(markov, delta);
     }      }
       else if (base[3] >= base[2])
       {
           // Aucune interruption n'est dans la queue.
           // On a retiré trop d'interruptions de la queue.
   
     if (base[3] > base[2])          // (base[3] - base[2]) + 1 : nombre d'interruptions manquantes
           // base[0] - 1             : dernière interruption lue
           pid = buffer[((((base[0] + base[2] - 1) % base[2])
                   - ((base[3] - base[2]) + 1)) + base[2]) % base[2]];
       }
       else
     {      {
         sem_post(semaphores[queue]);          // Plusieurs interruptions à distribuer.
         return(-1);          drapeau = d_vrai;
   
           do
           {
               delta = abs(horodatage() -
                        buffer[base[0] + (nombre_queues * base[2])]);
               pid = buffer[base[0]++];
               base[0] %= base[2];
               base[3]++;
   
               if ((delta > (2 * markov)) && (base[3] < base[2]))
               {
                   drapeau = d_vrai;
               }
               else
               {
                   drapeau = d_faux;
               }
           } while(drapeau == d_vrai);
   
           markov = chaine_markov(markov, delta);
     }      }
   
     if (sem_post(semaphores[queue]) != 0)      if (sem_post(semaphores[queue]) != 0)
Line 2981  kill_broken_siginfo(pid_t pid, int signa Line 3200  kill_broken_siginfo(pid_t pid, int signa
         return(-1);          return(-1);
     }      }
   
     if ((semaphore = sem_open(nom, 0)) == SEM_FAILED)      while((semaphore = sem_open(nom, 0)) == SEM_FAILED);
     {  
         free(nom);  
         return(-1);  
     }  
   
     free(nom);      free(nom);
   
     if (sem_wait(semaphore) == -1)      while(sem_wait(semaphore) != 0)
     {      {
         return(-1);          if (errno != EINTR)
           {
               return(-1);
           }
     }      }
   
     if ((signal != 0) && (signal != SIGINT))      if ((signal != 0) && (signal != SIGINT))
Line 3028  pthread_kill_broken_siginfo(pthread_t ti Line 3245  pthread_kill_broken_siginfo(pthread_t ti
         return(-1);          return(-1);
     }      }
   
     if ((semaphore = sem_open(nom, 0)) == SEM_FAILED)      while((semaphore = sem_open(nom, 0)) == SEM_FAILED);
     {  
         free(nom);  
         return(-1);  
     }  
   
     free(nom);      free(nom);
   
     if (sem_wait(semaphore) == -1)      while(sem_wait(semaphore) != 0)
     {      {
         return(-1);          if (errno != EINTR)
           {
               return(-1);
           }
     }      }
   
     if ((signal != 0) && (signal != SIGINT))      if ((signal != 0) && (signal != SIGINT))

Removed from v.1.34  
changed lines
  Added in v.1.35


CVSweb interface <joel.bertrand@systella.fr>