/* ================================================================================ RPL/2 (R) version 4.1.32 Copyright (C) 1989-2020 Dr. BERTRAND Joël This file is part of RPL/2. RPL/2 is free software; you can redistribute it and/or modify it under the terms of the CeCILL V2 License as published by the french CEA, CNRS and INRIA. RPL/2 is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the CeCILL V2 License for more details. You should have received a copy of the CeCILL License along with RPL/2. If not, write to info@cecill.info. ================================================================================ */ #include "rpl-conv.h" /* ================================================================================ Fonction d'affectation des interruptions aux différentes queues ================================================================================ Entrées : s_etat_processus -------------------------------------------------------------------------------- Sorties : -------------------------------------------------------------------------------- Effets de bord : néant ================================================================================ */ void affectation_interruptions_logicielles(struct_processus *s_etat_processus) { int interruption; int ios; sig_atomic_t registre; volatile struct_liste_chainee *l_element_courant; struct_liste_chainee *l_element; struct_objet *s_objet_processus; if ((*s_etat_processus).var_volatile_requete_arret == -1) { // Si une requête d'arrêt est reçue par le processus durant la // phase de verrouillage, on n'empile rien car la structure // processus peut déjà être libérée par le thread de surveillance. (*s_etat_processus).nombre_interruptions_non_affectees = 0; return; } if ((ios = pthread_mutex_trylock(&((*s_etat_processus) .mutex_pile_processus))) != 0) { if (ios != EBUSY) { (*s_etat_processus).erreur_systeme = d_es_processus; } return; } l_element_courant = (*s_etat_processus).l_base_pile_processus; while(l_element_courant != NULL) { /* * On regarde s'il y a quelque chose dans le pipe d'interruptions * du processus fils. * * Cette routine est interruptible par l'arrivée d'une interruption * de type SWI. */ if ((*(*l_element_courant).donnee).type != PRC) { pthread_mutex_unlock(&((*s_etat_processus).mutex_pile_processus)); (*s_etat_processus).erreur_systeme = d_es_processus; return; } if (pthread_mutex_lock(&((*(*((struct_processus_fils *) (*(*l_element_courant).donnee).objet)).thread).mutex)) != 0) { pthread_mutex_unlock(&((*s_etat_processus).mutex_pile_processus)); (*s_etat_processus).erreur_systeme = d_es_processus; return; } if ((*(*((struct_processus_fils *) (*(*l_element_courant).donnee) .objet)).thread).nombre_interruptions_dans_pipe > 0) { registre = (*s_etat_processus).var_volatile_traitement_retarde_stop; (*s_etat_processus).var_volatile_traitement_retarde_stop = 1; if (read_atomic(s_etat_processus, (*(*((struct_processus_fils *) (*(*l_element_courant).donnee) .objet)).thread).pipe_interruptions[0], &interruption, sizeof(interruption)) == sizeof(interruption)) { if (registre == 0) { if ((*s_etat_processus).var_volatile_traitement_retarde_stop == -1) { (*s_etat_processus).var_volatile_requete_arret = -1; } (*s_etat_processus).var_volatile_traitement_retarde_stop = registre; } if ((interruption < 1) || (interruption > d_NOMBRE_INTERRUPTIONS)) { pthread_mutex_unlock(&((*(*((struct_processus_fils *) (*(*l_element_courant).donnee).objet)).thread) .mutex)); pthread_mutex_unlock(&((*s_etat_processus) .mutex_pile_processus)); (*s_etat_processus).erreur_systeme = d_es_interruption_invalide; return; } /* * On ne pousse dans les queues des interruptions que les * interruptions qui ne sont pas masquées. */ if ((*s_etat_processus).masque_interruptions[interruption - 1] != 'I') { if ((s_objet_processus = copie_objet(s_etat_processus, (*l_element_courant).donnee, 'P')) == NULL) { pthread_mutex_unlock(&((*(*((struct_processus_fils *) (*(*l_element_courant).donnee).objet)).thread) .mutex)); pthread_mutex_unlock(&((*s_etat_processus) .mutex_pile_processus)); (*s_etat_processus).erreur_systeme = d_es_allocation_memoire; return; } // Pile LIFO if (empilement(s_etat_processus, &((*s_etat_processus) .pile_origine_interruptions[interruption - 1]), s_objet_processus) == d_erreur) { pthread_mutex_unlock(&((*(*((struct_processus_fils *) (*(*l_element_courant).donnee).objet)).thread) .mutex)); if (pthread_mutex_unlock(&((*s_etat_processus) .mutex_pile_processus)) != 0) { (*s_etat_processus).erreur_systeme = d_es_processus; return; } return; } (*s_etat_processus).queue_interruptions[interruption - 1]++; (*s_etat_processus).nombre_interruptions_en_queue++; // Transformation en FIFO if ((*s_etat_processus).queue_interruptions [interruption - 1] > 1) { l_element = (*s_etat_processus) .pile_origine_interruptions[interruption - 1]; while((*l_element).suivant != NULL) { l_element = (*l_element).suivant; } (*l_element).suivant = (*s_etat_processus) .pile_origine_interruptions[interruption - 1]; (*s_etat_processus).pile_origine_interruptions [interruption - 1] = (*(*l_element).suivant).suivant; (*(*l_element).suivant).suivant = NULL; } if ((*s_etat_processus).debug == d_vrai) if (((*s_etat_processus).type_debug & d_traitement_interruption) != 0) { if ((*(*((struct_processus_fils *) (*s_objet_processus) .objet)).thread).processus_detache == d_vrai) { if ((*s_etat_processus).langue == 'F') { printf("[%d] Interruption logicielle " "%d empilée en " "provenance du processus %d\n", (int) getpid(), interruption, (int) (*(*((struct_processus_fils *) (*s_objet_processus).objet)).thread) .pid); } else { printf("[%d] Software interrupt %d stacked from" " process %d\n", interruption, (int) getpid(), (int) (*(*((struct_processus_fils *) (*s_objet_processus).objet)).thread) .pid); } } else { if ((*s_etat_processus).langue == 'F') { printf("[%d] Interruption logicielle " "%d empilée en " "provenance du thread %lld\n", (int) getpid(), interruption, (integer8) (*(*((struct_processus_fils *) (*s_objet_processus).objet)).thread) .tid); } else { printf("[%d] Software interrupt %d stacked from" " process %lld\n", interruption, (int) getpid(), (integer8) (*(*((struct_processus_fils *) (*s_objet_processus).objet)).thread) .tid); } } fflush(stdout); } } (*(*((struct_processus_fils *) (*(*l_element_courant).donnee) .objet)).thread).nombre_interruptions_dans_pipe--; (*s_etat_processus).nombre_interruptions_non_affectees--; } else { pthread_mutex_unlock(&((*(*((struct_processus_fils *) (*(*l_element_courant).donnee).objet)).thread).mutex)); pthread_mutex_unlock(&((*s_etat_processus) .mutex_pile_processus)); if (registre == 0) { if ((*s_etat_processus).var_volatile_traitement_retarde_stop == -1) { (*s_etat_processus).var_volatile_requete_arret = -1; } (*s_etat_processus).var_volatile_traitement_retarde_stop = registre; } (*s_etat_processus).erreur_systeme = d_es_interruption_invalide; return; } } if (pthread_mutex_unlock(&((*(*((struct_processus_fils *) (*(*l_element_courant).donnee).objet)).thread).mutex)) != 0) { (*s_etat_processus).erreur_systeme = d_es_processus; return; } l_element_courant = (*l_element_courant).suivant; } if (pthread_mutex_unlock(&((*s_etat_processus).mutex_pile_processus)) != 0) { (*s_etat_processus).erreur_systeme = d_es_processus; return; } return; } /* ================================================================================ Fonction de traitement des différentes interruptions ================================================================================ Entrées : s_etat_processus -------------------------------------------------------------------------------- Sorties : -------------------------------------------------------------------------------- Effets de bord : néant ================================================================================ */ void traitement_interruptions_logicielles(struct_processus *s_etat_processus) { int i; logical1 drapeau_erreur; logical1 processus; logical1 registre_arret_si_exception; pid_t pid; pthread_t tid; struct_objet *s_objet_processus; unsigned char registre; unsigned char tampon[22]; /* * Les interruptions sont non interruptibles. */ if (((*s_etat_processus).traitement_interruption == 'Y') || ((*s_etat_processus).traitement_interruptible == 'N')) { return; } registre = (*s_etat_processus).traitement_interruption; (*s_etat_processus).traitement_interruption = 'Y'; /* * Lancement d'une interruption. Les interruptions sont d'autant plus * prioritaires que leur numéro est faible. */ for(i = 0; i < d_NOMBRE_INTERRUPTIONS; i++) { pid = 0; tid = 0; processus = d_faux; if ((*s_etat_processus).queue_interruptions[i] > 0) { if ((*s_etat_processus).masque_interruptions[i] == 'N') { /* * Exécution de la i-ème interruption si celle-ci existe. Dans * le cas contraire, une erreur d'exécution est renvoyée. */ if (((*s_etat_processus).corps_interruptions[i] != NULL) && ((*s_etat_processus).pile_origine_interruptions[i] != NULL)) { if (depilement(s_etat_processus, &((*s_etat_processus) .pile_origine_interruptions[i]), &s_objet_processus) == d_erreur) { (*s_etat_processus).traitement_interruption = registre; (*s_etat_processus).erreur_execution = d_ex_interruption_invalide; return; } if (empilement(s_etat_processus, &((*s_etat_processus) .l_base_pile), s_objet_processus) == d_erreur) { (*s_etat_processus).traitement_interruption = registre; return; } if ((*s_etat_processus).debug == d_vrai) if (((*s_etat_processus).type_debug & d_traitement_interruption) != 0) { if ((*s_etat_processus).langue == 'F') { if ((processus = (*(*((struct_processus_fils *) (*s_objet_processus).objet)).thread) .processus_detache) == d_faux) { printf("[%d] Traitement de l'interruption " "logicielle %d en provenance du thread " "%llu\n", (int) getpid(), i + 1, (unsigned long long) (tid = (*(*((struct_processus_fils *) (*s_objet_processus).objet)).thread) .tid)); } else { printf("[%d] Traitement de l'interruption " "logicielle %d en provenance du " "processus " "%d\n", (int) getpid(), i + 1, (int) (pid = (*(*((struct_processus_fils *) (*s_objet_processus).objet)).thread) .pid)); } } else { if ((processus = (*(*((struct_processus_fils *) (*s_objet_processus).objet)).thread) .processus_detache) == d_faux) { printf("[%d] Start software interrupt " "%d from thread " "%llu\n", (int) getpid(), i + 1, (unsigned long long) (tid = (*(*((struct_processus_fils *) (*s_objet_processus).objet)).thread) .tid)); } else { printf("[%d] Start software interrupt " "%d from process " "%d\n", (int) getpid(), i + 1, (int) (pid = (*(*((struct_processus_fils *) (*s_objet_processus).objet)).thread) .pid)); } } fflush(stdout); } (*s_etat_processus).nombre_interruptions_en_queue--; (*s_etat_processus).queue_interruptions[i]--; registre_arret_si_exception = (*s_etat_processus).arret_si_exception; (*s_etat_processus).arret_si_exception = d_vrai; if ((*s_etat_processus).profilage == d_vrai) { sprintf(tampon, "Software interrupt %-2d", i + 1); profilage(s_etat_processus, tampon); if ((*s_etat_processus).erreur_systeme != d_es) { return; } } drapeau_erreur = evaluation(s_etat_processus, (*s_etat_processus).corps_interruptions[i], 'E'); if ((*s_etat_processus).profilage == d_vrai) { profilage(s_etat_processus, NULL); } if (drapeau_erreur == d_absence_erreur) { (*s_etat_processus).arret_si_exception = registre_arret_si_exception; } else { if ((((*s_etat_processus).erreur_execution != d_ex) || ((*s_etat_processus).exception != d_ep) || ((*s_etat_processus).erreur_systeme != d_es)) && ((*s_etat_processus).core == d_vrai) && ((*s_etat_processus) .var_volatile_traitement_sigint == 0)) { printf("\n"); if ((*s_etat_processus).langue == 'F') { printf("+++Information : " "Génération du fichier rpl-core " "[%d]\n", (int) getpid()); } else { printf("+++Information : " "Writing rpl-core file [%d]\n", (int) getpid()); } rplcore(s_etat_processus); if ((*s_etat_processus).langue == 'F') { printf("+++Information : " "Processus tracé [%d]\n", (int) getpid()); } else { printf("+++Information : Done [%d]\n", (int) getpid()); } printf("\n"); fflush(stdout); } } if ((*s_etat_processus).debug == d_vrai) if (((*s_etat_processus).type_debug & d_traitement_interruption) != 0) { if ((*s_etat_processus).langue == 'F') { if (processus == d_faux) { printf("[%d] Fin de l'interruption logicielle" " %d en provenance du thread %llu\n", (int) getpid(), i + 1, (unsigned long long) tid); } else { printf("[%d] Fin de l'interruption logicielle" " %d en provenance du processus %d\n", (int) getpid(), i + 1, (int) pid); } } else { if (processus == d_faux) { printf("[%d] Stop software interrupt " "%d from thread " "%llu\n", (int) getpid(), i + 1, (unsigned long long) pid); } else { printf("[%d] Stop software interrupt " "%d from process " "%d\n", (int) getpid(), i + 1, (int) pid); } } fflush(stdout); } if ((drapeau_erreur == d_erreur) && ((*s_etat_processus).erreur_execution == d_ex)) { if (((*s_etat_processus).erreur_execution == d_ex) && ((*s_etat_processus).erreur_systeme == d_es)) { (*s_etat_processus).erreur_execution = d_ex_erreur_evaluation; } } } else { (*s_etat_processus).erreur_execution = d_ex_interruption_invalide; } } } } (*s_etat_processus).traitement_interruption = registre; return; } // vim: ts=4