/* ================================================================================ RPL/2 (R) version 4.0.15 Copyright (C) 1989-2010 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 de profilage ================================================================================ Entrées : pointeur sur une structure processus -------------------------------------------------------------------------------- Sorties : -------------------------------------------------------------------------------- Effets de bord : néant ================================================================================ */ // Si *fonction est non nul, profilage considère un appel à la fonction // *fonction. Si *fonction est nul, il s'agit du retour de la fonction. void profilage(struct_processus *s_etat_processus, unsigned char *fonction) { struct_liste_profilage *l_element_cible; struct_liste_profilage *l_element_courant; struct_liste_profilage2 *l_element_fonction; struct timeval horodatage; struct timeval temps; /* * Les statistiques sont écrites dans un fichier rpl-profile-pid-tid * à chaque minute. */ gettimeofday(&horodatage, NULL); if (fonction != NULL) { /* * Recherche d'une occurrence de l'appel de la fonction * et arrêt du compteur de la fonction appelante */ l_element_courant = (*s_etat_processus).pile_profilage; l_element_cible = NULL; while(l_element_courant != NULL) { if (strcmp((*l_element_courant).fonction, fonction) == 0) { l_element_cible = l_element_courant; } if ((*s_etat_processus).pile_profilage_fonctions != NULL) { if (strcmp((*l_element_courant).fonction, (*(*s_etat_processus).pile_profilage_fonctions) .fonction) == 0) { if (horodatage.tv_usec < (*l_element_courant) .dernier_appel.tv_usec) { // Avec retenue temps.tv_usec = (1000000 + horodatage.tv_usec) - (*l_element_courant).dernier_appel.tv_usec; temps.tv_sec = horodatage.tv_sec - ((*l_element_courant).dernier_appel.tv_sec + 1); } else { // Sans retenue temps.tv_usec = horodatage.tv_usec - (*l_element_courant).dernier_appel.tv_usec; temps.tv_sec = horodatage.tv_sec - (*l_element_courant).dernier_appel.tv_sec; } // Cumul (*l_element_courant).cumul.tv_usec += temps.tv_usec; (*l_element_courant).cumul.tv_sec += temps.tv_sec; if ((*l_element_courant).cumul.tv_usec >= 1000000) { (*l_element_courant).cumul.tv_usec -= 1000000; (*l_element_courant).cumul.tv_sec++; } } } l_element_courant = (*l_element_courant).suivant; } l_element_courant = l_element_cible; if (l_element_courant == NULL) { // Nouvel appel if ((l_element_courant = malloc(sizeof(struct_liste_profilage))) == NULL) { (*s_etat_processus).erreur_systeme = d_es_allocation_memoire; return; } (*l_element_courant).suivant = (*s_etat_processus).pile_profilage; (*s_etat_processus).pile_profilage = l_element_courant; if (((*l_element_courant).fonction = malloc((strlen(fonction) + 1) * sizeof(unsigned char))) == NULL) { (*s_etat_processus).erreur_systeme = d_es_allocation_memoire; return; } strcpy((*l_element_courant).fonction, fonction); (*l_element_courant).cumul.tv_sec = 0; (*l_element_courant).cumul.tv_usec = 0; (*l_element_courant).nombre_appels = 0; } (*l_element_courant).dernier_appel = horodatage; (*l_element_courant).nombre_appels++; // Empilement if ((l_element_fonction = malloc(sizeof(struct_liste_profilage2))) == NULL) { (*s_etat_processus).erreur_systeme = d_es_allocation_memoire; return; } if (((*l_element_fonction).fonction = malloc((strlen(fonction) + 1) * sizeof(unsigned char))) == NULL) { (*s_etat_processus).erreur_systeme = d_es_allocation_memoire; return; } strcpy((*l_element_fonction).fonction, fonction); (*l_element_fonction).suivant = (*s_etat_processus) .pile_profilage_fonctions; (*s_etat_processus).pile_profilage_fonctions = l_element_fonction; } else { if ((*s_etat_processus).pile_profilage_fonctions == NULL) { (*s_etat_processus).erreur_execution = d_ex_erreur_profilage; return; } l_element_courant = (*s_etat_processus).pile_profilage; while(l_element_courant != NULL) { if (strcmp((*l_element_courant).fonction, (*(*s_etat_processus).pile_profilage_fonctions).fonction) == 0) { break; } l_element_courant = (*l_element_courant).suivant; } BUG(l_element_courant == NULL, printf("Function %s not found!\n", (*(*s_etat_processus).pile_profilage_fonctions).fonction)); // Soustraction des temps if (horodatage.tv_usec < (*l_element_courant).dernier_appel.tv_usec) { // Avec retenue temps.tv_usec = (1000000 + horodatage.tv_usec) - (*l_element_courant).dernier_appel.tv_usec; temps.tv_sec = horodatage.tv_sec - ((*l_element_courant).dernier_appel.tv_sec + 1); } else { // Sans retenue temps.tv_usec = horodatage.tv_usec - (*l_element_courant).dernier_appel.tv_usec; temps.tv_sec = horodatage.tv_sec - (*l_element_courant).dernier_appel.tv_sec; } // Cumul (*l_element_courant).cumul.tv_usec += temps.tv_usec; (*l_element_courant).cumul.tv_sec += temps.tv_sec; if ((*l_element_courant).cumul.tv_usec >= 1000000) { (*l_element_courant).cumul.tv_usec -= 1000000; (*l_element_courant).cumul.tv_sec++; } // Dépilement l_element_fonction = (*s_etat_processus).pile_profilage_fonctions; (*s_etat_processus).pile_profilage_fonctions = (*l_element_fonction).suivant; free((*l_element_fonction).fonction); free(l_element_fonction); // Relance du compteur de la fonction en cours if ((*s_etat_processus).pile_profilage_fonctions != NULL) { l_element_courant = (*s_etat_processus).pile_profilage; while(l_element_courant != NULL) { if (strcmp((*l_element_courant).fonction, (*(*s_etat_processus) .pile_profilage_fonctions).fonction) == 0) { break; } l_element_courant = (*l_element_courant).suivant; } BUG(l_element_courant == NULL, printf("Function %s not found!\n", (*(*s_etat_processus).pile_profilage_fonctions).fonction)); (*l_element_courant).dernier_appel = horodatage; } } if ((horodatage.tv_sec - (*s_etat_processus).horodatage_profilage.tv_sec) >= 60) { ecriture_profil(s_etat_processus); (*s_etat_processus).horodatage_profilage = horodatage; } return; } void ecriture_profil(struct_processus *s_etat_processus) { double fraction; double temps; double total; file *fichier; struct_liste_profilage *l_element_courant; struct timeval cumul; unsigned char *nom; l_element_courant = (*s_etat_processus).pile_profilage; // Calcul du temps total cumul.tv_sec = 0; cumul.tv_usec = 0; while(l_element_courant != NULL) { cumul.tv_usec += (*l_element_courant).cumul.tv_usec; cumul.tv_sec += (*l_element_courant).cumul.tv_sec; if (cumul.tv_usec >= 1000000) { cumul.tv_usec -= 1000000; cumul.tv_sec++; } l_element_courant = (*l_element_courant).suivant; } total = cumul.tv_sec + (((double) cumul.tv_usec) / 1000000); // Création du fichier if ((nom = malloc((strlen(ds_rplprofile) + 64 + 1) * sizeof(unsigned char))) == NULL) { (*s_etat_processus).erreur_systeme = d_es_allocation_memoire; return; } snprintf(nom, strlen(ds_rplprofile) + 64 + 1, "%s-%lu-%lu", ds_rplprofile, (unsigned long) getpid(), (unsigned long) pthread_self()); if ((fichier = fopen(nom, "w+")) == NULL) { (*s_etat_processus).erreur_systeme = d_es_erreur_fichier; free(nom); return; } free(nom); // Préparation du résultat if (fprintf(fichier, "RPL/2 statistics\n\n") < 0) { (*s_etat_processus).erreur_systeme = d_es_erreur_fichier; return; } if (fprintf(fichier, "Process : %lu\n", (unsigned long) getpid()) < 0) { (*s_etat_processus).erreur_systeme = d_es_erreur_fichier; return; } if (fprintf(fichier, "Thread : %lu\n", (unsigned long) pthread_self()) < 0) { (*s_etat_processus).erreur_systeme = d_es_erreur_fichier; return; } if (fprintf(fichier, "Elapsed Time : %.2fs\n\n", total) < 0) { (*s_etat_processus).erreur_systeme = d_es_erreur_fichier; return; } if (fprintf(fichier, "Calls_________ Time____________ Ratio__ Normal_ " " Object______________________\n") < 0) { (*s_etat_processus).erreur_systeme = d_es_erreur_fichier; return; } l_element_courant = (*s_etat_processus).pile_profilage; while(l_element_courant != NULL) { temps = (*l_element_courant).cumul.tv_sec + (((double) (*l_element_courant).cumul.tv_usec) / 1000000); fraction = 100 * (temps / total); if (fprintf(fichier, "<%012lld> %15.2fs (%6.2f%%/%6.2f%%) : %s\n", (*l_element_courant).nombre_appels, temps, fraction, fraction / (*l_element_courant).nombre_appels, (*l_element_courant).fonction) < 0) { (*s_etat_processus).erreur_systeme = d_es_erreur_fichier; return; } l_element_courant = (*l_element_courant).suivant; } if (fclose(fichier) != 0) { (*s_etat_processus).erreur_systeme = d_es_erreur_fichier; return; } return; } void liberation_profil(struct_processus *s_etat_processus) { struct_liste_profilage *l_element_courant; struct_liste_profilage2 *l_element_fonction; while((*s_etat_processus).pile_profilage != NULL) { l_element_courant = (*s_etat_processus).pile_profilage; (*s_etat_processus).pile_profilage = (*(*s_etat_processus).pile_profilage).suivant; free((*l_element_courant).fonction); free(l_element_courant); } while((*s_etat_processus).pile_profilage_fonctions != NULL) { l_element_fonction = (*s_etat_processus).pile_profilage_fonctions; (*s_etat_processus).pile_profilage_fonctions = (*(*s_etat_processus).pile_profilage_fonctions).suivant; free((*l_element_fonction).fonction); free(l_element_fonction); } return; } // vim: ts=4