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 (13 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>