1: /*
2: ================================================================================
3: RPL/2 (R) version 4.1.36
4: Copyright (C) 1989-2025 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 = ((double) 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-%llu-%llu", ds_rplprofile, (unsigned long long) getpid(),
316: (unsigned long 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 : %llu\n", (unsigned long long)
337: getpid()) < 0)
338: {
339: (*s_etat_processus).erreur_systeme = d_es_erreur_fichier;
340: return;
341: }
342:
343: if (fprintf(fichier, "Thread : %llu\n", (unsigned long 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 = ((double) (*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, temps, fraction,
373: fraction / ((double) (*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>