File:  [local] / rpl / src / profilage.c
Revision 1.21: download - view: text, annotated - select for diffs - revision graph
Tue Jun 21 15:26:35 2011 UTC (12 years, 10 months ago) by bertrand
Branches: MAIN
CVS tags: HEAD
Correction d'une réinitialisation sauvage de la pile des variables par niveau
dans la copie de la structure de description du processus. Cela corrige
la fonction SPAWN qui échouait sur un segmentation fault car la pile des
variables par niveau était vide alors même que l'arbre des variables contenait
bien les variables. Passage à la prerelease 2.

    1: /*
    2: ================================================================================
    3:   RPL/2 (R) version 4.1.0.prerelease.2
    4:   Copyright (C) 1989-2011 Dr. BERTRAND Joël
    5: 
    6:   This file is part of RPL/2.
    7: 
    8:   RPL/2 is free software; you can redistribute it and/or modify it
    9:   under the terms of the CeCILL V2 License as published by the french
   10:   CEA, CNRS and INRIA.
   11:  
   12:   RPL/2 is distributed in the hope that it will be useful, but WITHOUT
   13:   ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
   14:   FITNESS FOR A PARTICULAR PURPOSE.  See the CeCILL V2 License
   15:   for more details.
   16:  
   17:   You should have received a copy of the CeCILL License
   18:   along with RPL/2. If not, write to info@cecill.info.
   19: ================================================================================
   20: */
   21: 
   22: 
   23: #include "rpl-conv.h"
   24: 
   25: 
   26: /*
   27: ================================================================================
   28:   Fonction de profilage
   29: ================================================================================
   30:   Entrées : pointeur sur une structure processus
   31: --------------------------------------------------------------------------------
   32:   Sorties :
   33: --------------------------------------------------------------------------------
   34:   Effets de bord : néant
   35: ================================================================================
   36: */
   37: 
   38: // Si *fonction est non nul, profilage considère un appel à la fonction
   39: // *fonction. Si *fonction est nul, il s'agit du retour de la fonction.
   40: 
   41: void
   42: profilage(struct_processus *s_etat_processus, unsigned char *fonction)
   43: {
   44:     struct_liste_profilage      *l_element_cible;
   45:     struct_liste_profilage      *l_element_courant;
   46:     struct_liste_profilage2     *l_element_fonction;
   47: 
   48:     struct timeval              horodatage;
   49:     struct timeval              temps;
   50: 
   51:     /*
   52:      * Les statistiques sont écrites dans un fichier rpl-profile-pid-tid
   53:      * à chaque minute.
   54:      */
   55: 
   56:     gettimeofday(&horodatage, NULL);
   57: 
   58:     if (fonction != NULL)
   59:     {
   60:         /*
   61:          * Recherche d'une occurrence de l'appel de la fonction
   62:          * et arrêt du compteur de la fonction appelante
   63:          */
   64: 
   65:         l_element_courant = (*s_etat_processus).pile_profilage;
   66:         l_element_cible = NULL;
   67: 
   68:         while(l_element_courant != NULL)
   69:         {
   70:             if (strcmp((*l_element_courant).fonction, fonction) == 0)
   71:             {
   72:                 l_element_cible = l_element_courant;
   73:             }
   74: 
   75:             if ((*s_etat_processus).pile_profilage_fonctions != NULL)
   76:             {
   77:                 if (strcmp((*l_element_courant).fonction,
   78:                         (*(*s_etat_processus).pile_profilage_fonctions)
   79:                         .fonction) == 0)
   80:                 {
   81:                     if (horodatage.tv_usec < (*l_element_courant)
   82:                             .dernier_appel.tv_usec)
   83:                     {
   84:                         // Avec retenue
   85:                         temps.tv_usec = (1000000 + horodatage.tv_usec)
   86:                                 - (*l_element_courant).dernier_appel.tv_usec;
   87:                         temps.tv_sec = horodatage.tv_sec
   88:                                 - ((*l_element_courant).dernier_appel.tv_sec
   89:                                 + 1);
   90:                     }
   91:                     else
   92:                     {
   93:                         // Sans retenue
   94:                         temps.tv_usec = horodatage.tv_usec
   95:                                 - (*l_element_courant).dernier_appel.tv_usec;
   96:                         temps.tv_sec = horodatage.tv_sec
   97:                                 - (*l_element_courant).dernier_appel.tv_sec;
   98:                     }
   99: 
  100:                     // Cumul
  101: 
  102:                     (*l_element_courant).cumul.tv_usec += temps.tv_usec;
  103:                     (*l_element_courant).cumul.tv_sec += temps.tv_sec;
  104: 
  105:                     if ((*l_element_courant).cumul.tv_usec >= 1000000)
  106:                     {
  107:                         (*l_element_courant).cumul.tv_usec -= 1000000;
  108:                         (*l_element_courant).cumul.tv_sec++;
  109:                     }
  110:                 }
  111:             }
  112: 
  113:             l_element_courant = (*l_element_courant).suivant;
  114:         }
  115: 
  116:         l_element_courant = l_element_cible;
  117: 
  118:         if (l_element_courant == NULL)
  119:         {
  120:             // Nouvel appel
  121: 
  122:             if ((l_element_courant = malloc(sizeof(struct_liste_profilage)))
  123:                     == NULL)
  124:             {
  125:                 (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;
  126:                 return;
  127:             }
  128: 
  129:             (*l_element_courant).suivant = (*s_etat_processus).pile_profilage;
  130:             (*s_etat_processus).pile_profilage = l_element_courant;
  131: 
  132:             if (((*l_element_courant).fonction = malloc((strlen(fonction) + 1) *
  133:                     sizeof(unsigned char))) == NULL)
  134:             {
  135:                 (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;
  136:                 return;
  137:             }
  138: 
  139:             strcpy((*l_element_courant).fonction, fonction);
  140: 
  141:             (*l_element_courant).cumul.tv_sec = 0;
  142:             (*l_element_courant).cumul.tv_usec = 0;
  143:             (*l_element_courant).nombre_appels = 0;
  144:         }
  145: 
  146:         (*l_element_courant).dernier_appel = horodatage;
  147:         (*l_element_courant).nombre_appels++;
  148: 
  149:         // Empilement
  150: 
  151:         if ((l_element_fonction = malloc(sizeof(struct_liste_profilage2)))
  152:                 == NULL)
  153:         {
  154:             (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;
  155:             return;
  156:         }
  157: 
  158:         if (((*l_element_fonction).fonction = malloc((strlen(fonction) + 1) *
  159:                 sizeof(unsigned char))) == NULL)
  160:         {
  161:             (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;
  162:             return;
  163:         }
  164: 
  165:         strcpy((*l_element_fonction).fonction, fonction);
  166:         (*l_element_fonction).suivant = (*s_etat_processus)
  167:                 .pile_profilage_fonctions;
  168:         (*s_etat_processus).pile_profilage_fonctions = l_element_fonction;
  169:     }
  170:     else
  171:     {
  172:         if ((*s_etat_processus).pile_profilage_fonctions == NULL)
  173:         {
  174:             (*s_etat_processus).erreur_execution = d_ex_erreur_profilage;
  175:             return;
  176:         }
  177: 
  178:         l_element_courant = (*s_etat_processus).pile_profilage;
  179: 
  180:         while(l_element_courant != NULL)
  181:         {
  182:             if (strcmp((*l_element_courant).fonction,
  183:                     (*(*s_etat_processus).pile_profilage_fonctions).fonction)
  184:                     == 0)
  185:             {
  186:                 break;
  187:             }
  188: 
  189:             l_element_courant = (*l_element_courant).suivant;
  190:         }
  191: 
  192:         BUG(l_element_courant == NULL, printf("Function %s not found!\n",
  193:                 (*(*s_etat_processus).pile_profilage_fonctions).fonction));
  194: 
  195:         // Soustraction des temps
  196: 
  197:         if (horodatage.tv_usec < (*l_element_courant).dernier_appel.tv_usec)
  198:         {
  199:             // Avec retenue
  200:             temps.tv_usec = (1000000 + horodatage.tv_usec)
  201:                     - (*l_element_courant).dernier_appel.tv_usec;
  202:             temps.tv_sec = horodatage.tv_sec
  203:                     - ((*l_element_courant).dernier_appel.tv_sec + 1);
  204:         }
  205:         else
  206:         {
  207:             // Sans retenue
  208:             temps.tv_usec = horodatage.tv_usec
  209:                     - (*l_element_courant).dernier_appel.tv_usec;
  210:             temps.tv_sec = horodatage.tv_sec
  211:                     - (*l_element_courant).dernier_appel.tv_sec;
  212:         }
  213: 
  214:         // Cumul
  215: 
  216:         (*l_element_courant).cumul.tv_usec += temps.tv_usec;
  217:         (*l_element_courant).cumul.tv_sec += temps.tv_sec;
  218: 
  219:         if ((*l_element_courant).cumul.tv_usec >= 1000000)
  220:         {
  221:             (*l_element_courant).cumul.tv_usec -= 1000000;
  222:             (*l_element_courant).cumul.tv_sec++;
  223:         }
  224: 
  225:         // Dépilement
  226: 
  227:         l_element_fonction = (*s_etat_processus).pile_profilage_fonctions;
  228:         (*s_etat_processus).pile_profilage_fonctions =
  229:                 (*l_element_fonction).suivant;
  230: 
  231:         free((*l_element_fonction).fonction);
  232:         free(l_element_fonction);
  233: 
  234:         // Relance du compteur de la fonction en cours
  235: 
  236:         if ((*s_etat_processus).pile_profilage_fonctions != NULL)
  237:         {
  238:             l_element_courant = (*s_etat_processus).pile_profilage;
  239: 
  240:             while(l_element_courant != NULL)
  241:             {
  242:                 if (strcmp((*l_element_courant).fonction, (*(*s_etat_processus)
  243:                         .pile_profilage_fonctions).fonction) == 0)
  244:                 {
  245:                     break;
  246:                 }
  247: 
  248:                 l_element_courant = (*l_element_courant).suivant;
  249:             }
  250: 
  251:             BUG(l_element_courant == NULL, printf("Function %s not found!\n",
  252:                     (*(*s_etat_processus).pile_profilage_fonctions).fonction));
  253:             (*l_element_courant).dernier_appel = horodatage;
  254:         }
  255:     }
  256: 
  257:     if ((horodatage.tv_sec - (*s_etat_processus).horodatage_profilage.tv_sec)
  258:             >= 60)
  259:     {
  260:         ecriture_profil(s_etat_processus);
  261:         (*s_etat_processus).horodatage_profilage = horodatage;
  262:     }
  263: 
  264:     return;
  265: }
  266: 
  267: void
  268: ecriture_profil(struct_processus *s_etat_processus)
  269: {
  270:     double                      fraction;
  271:     double                      temps;
  272:     double                      total;
  273: 
  274:     file                        *fichier;
  275: 
  276:     struct_liste_profilage      *l_element_courant;
  277: 
  278:     struct timeval              cumul;
  279: 
  280:     unsigned char               *nom;
  281: 
  282:     l_element_courant = (*s_etat_processus).pile_profilage;
  283: 
  284:     // Calcul du temps total
  285: 
  286:     cumul.tv_sec = 0;
  287:     cumul.tv_usec = 0;
  288: 
  289:     while(l_element_courant != NULL)
  290:     {
  291:         cumul.tv_usec += (*l_element_courant).cumul.tv_usec;
  292:         cumul.tv_sec += (*l_element_courant).cumul.tv_sec;
  293: 
  294:         if (cumul.tv_usec >= 1000000)
  295:         {
  296:             cumul.tv_usec -= 1000000;
  297:             cumul.tv_sec++;
  298:         }
  299: 
  300:         l_element_courant = (*l_element_courant).suivant;
  301:     }
  302: 
  303:     total = cumul.tv_sec + (((double) cumul.tv_usec) / 1000000);
  304: 
  305:     // Création du fichier
  306: 
  307:     if ((nom = malloc((strlen(ds_rplprofile) + 64 + 1) * sizeof(unsigned char)))
  308:             == NULL)
  309:     {
  310:         (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;
  311:         return;
  312:     }
  313: 
  314:     snprintf(nom, strlen(ds_rplprofile) + 64 + 1,
  315:             "%s-%lu-%lu", ds_rplprofile, (unsigned long) getpid(),
  316:             (unsigned long) pthread_self());
  317: 
  318:     if ((fichier = fopen(nom, "w+")) == NULL)
  319:     {
  320:         (*s_etat_processus).erreur_systeme = d_es_erreur_fichier;
  321:         free(nom);
  322: 
  323:         return;
  324:     }
  325: 
  326:     free(nom);
  327: 
  328:     // Préparation du résultat
  329: 
  330:     if (fprintf(fichier, "RPL/2 statistics\n\n") < 0)
  331:     {
  332:         (*s_etat_processus).erreur_systeme = d_es_erreur_fichier;
  333:         return;
  334:     }
  335: 
  336:     if (fprintf(fichier, "Process      : %lu\n", (unsigned long)
  337:                 getpid()) < 0)
  338:     {
  339:         (*s_etat_processus).erreur_systeme = d_es_erreur_fichier;
  340:         return;
  341:     }
  342: 
  343:     if (fprintf(fichier, "Thread       : %lu\n", (unsigned long)
  344:                 pthread_self()) < 0)
  345:     {
  346:         (*s_etat_processus).erreur_systeme = d_es_erreur_fichier;
  347:         return;
  348:     }
  349: 
  350:     if (fprintf(fichier, "Elapsed Time : %.2fs\n\n", total) < 0)
  351:     {
  352:         (*s_etat_processus).erreur_systeme = d_es_erreur_fichier;
  353:         return;
  354:     }
  355: 
  356:     if (fprintf(fichier, "Calls_________ Time____________  Ratio__ Normal_ "
  357:             "   Object______________________\n") < 0)
  358:     {
  359:         (*s_etat_processus).erreur_systeme = d_es_erreur_fichier;
  360:         return;
  361:     }
  362: 
  363:     l_element_courant = (*s_etat_processus).pile_profilage;
  364: 
  365:     while(l_element_courant != NULL)
  366:     {
  367:         temps = (*l_element_courant).cumul.tv_sec +
  368:                 (((double) (*l_element_courant).cumul.tv_usec) / 1000000);
  369:         fraction = 100 * (temps / total);
  370: 
  371:         if (fprintf(fichier, "<%012lld> %15.2fs (%6.2f%%/%6.2f%%) : %s\n",
  372:                 (*l_element_courant).nombre_appels,
  373:                 temps, fraction, fraction / (*l_element_courant).nombre_appels,
  374:                 (*l_element_courant).fonction) < 0)
  375:         {
  376:             (*s_etat_processus).erreur_systeme = d_es_erreur_fichier;
  377:             return;
  378:         }
  379: 
  380:         l_element_courant = (*l_element_courant).suivant;
  381:     }
  382: 
  383:     if (fclose(fichier) != 0)
  384:     {
  385:         (*s_etat_processus).erreur_systeme = d_es_erreur_fichier;
  386:         return;
  387:     }
  388: 
  389:     return;
  390: }
  391: 
  392: void
  393: liberation_profil(struct_processus *s_etat_processus)
  394: {
  395:     struct_liste_profilage      *l_element_courant;
  396:     struct_liste_profilage2     *l_element_fonction;
  397: 
  398:     while((*s_etat_processus).pile_profilage != NULL)
  399:     {
  400:         l_element_courant = (*s_etat_processus).pile_profilage;
  401:         (*s_etat_processus).pile_profilage =
  402:                 (*(*s_etat_processus).pile_profilage).suivant;
  403: 
  404:         free((*l_element_courant).fonction);
  405:         free(l_element_courant);
  406:     }
  407: 
  408:     while((*s_etat_processus).pile_profilage_fonctions != NULL)
  409:     {
  410:         l_element_fonction = (*s_etat_processus).pile_profilage_fonctions;
  411:         (*s_etat_processus).pile_profilage_fonctions =
  412:                 (*(*s_etat_processus).pile_profilage_fonctions).suivant;
  413: 
  414:         free((*l_element_fonction).fonction);
  415:         free(l_element_fonction);
  416:     }
  417: 
  418:     return;
  419: }
  420: 
  421: // vim: ts=4

CVSweb interface <joel.bertrand@systella.fr>