"Fossies" - the Fresh Open Source Software Archive 
Member "FunctionCheck-3.2.0/src/fcmanager/fc_context.c" (26 May 2012, 17534 Bytes) of package /linux/privat/old/FunctionCheck-3.2.0.tar.gz:
As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style:
standard) with prefixed line numbers and
code folding option.
Alternatively you can here
view or
download the uninterpreted source code file.
1 /*
2 * FunctionCheck profiler
3 * (C) Copyright 2000-2012 Yannick Perret
4 *
5 * This program is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU General Public License as
7 * published by the Free Software Foundation; either version 2 of the
8 * License, or (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
18 */
19 /* fc_context.c: manage contexts for profile stats */
20
21 #include <time.h>
22 #include <limits.h>
23 #include "fc_context.h"
24 #include "fc_functions.h"
25 #include "fc_com.h"
26 #include "fc_com_manager.h"
27 #include "fc_global.h"
28
29 /* the active context */
30 FC_Context *fc_current_context = NULL;
31 int fc_current_context_id = 0;
32
33 /* default values for stack, func et graph sizes */
34 int fc_ctx_stack_size = 128;
35 int fc_ctx_func_size = 256;
36 int fc_ctx_graph_size = 512;
37 int fc_ctx_memory_size = 512;
38 char fc_ctx_name[512] = {'b', 'a', 'd', '_', 'i', 'n', 'i', 't', '\0'};
39 char fc_ctx_path[512] = {'\0'};
40 int fc_ctx_usepid = 0;
41
42 /* starting and ending time */
43 struct tm fc_ctx_start_time;
44 struct tm fc_ctx_stop_time;
45
46 /* unique ID for this particular execution */
47 char fc_ctx_unique_id[256] = "ndef";
48
49 /* mode of the profile */
50 int fc_ctx_pmode = FC_MODE_SINGLE;
51
52 /* list of existing contexts (for management purpose) */
53 FC_Context **fc_context_list = NULL;
54 int fc_nb_context_list = 0;
55 int fc_nb_context_max = 0;
56
57 /** current list of dynamic libraries **/
58 FC_LDYN *fc_list_ldyn = NULL;
59 int fc_nb_list_ldyn = 0;
60
61 /* set the current profile mode */
62 void fc_context_set_mode(int mode)
63 {
64 fc_ctx_pmode = mode;
65 }
66
67 /* add an entry in the ldyn list */
68 int fc_ldyn_add(FC_LDYN *ldyn)
69 {
70 int i;
71
72 /* first check if the entry still exists */
73 for (i = 0; i < fc_nb_list_ldyn; i++)
74 {
75 if (fc_list_ldyn[i].addr == ldyn->addr)
76 return (1);
77 }
78
79 /* reallocate the table */
80 if (fc_nb_list_ldyn == 0)
81 {
82 fc_nb_list_ldyn = 1;
83 fc_list_ldyn = malloc(sizeof (FC_LDYN) * fc_nb_list_ldyn);
84 }
85 else
86 {
87 fc_nb_list_ldyn++;
88 fc_list_ldyn = realloc(fc_list_ldyn, sizeof (FC_LDYN) * fc_nb_list_ldyn);
89 }
90
91 if (fc_list_ldyn == NULL)
92 {
93 fc_nb_list_ldyn = 0;
94 fc_message("cannot (re)allocate %d bytes for dynamic lib list.",
95 sizeof (FC_LDYN) * fc_nb_list_ldyn);
96 return (0);
97 }
98
99 /* add the element */
100 fc_list_ldyn[fc_nb_list_ldyn - 1] = *ldyn;
101 return (1);
102 }
103
104 /* loop on contexts */
105 int fc_context_loops = 0;
106
107 FC_Context *fc_context_first()
108 {
109 fc_context_loops = 0;
110 if (fc_nb_context_list == 0)
111 return (NULL);
112 return (fc_context_list[fc_context_loops]);
113 }
114
115 FC_Context *fc_context_next()
116 {
117 fc_context_loops++;
118 if (fc_context_loops >= fc_nb_context_list)
119 {
120 fc_context_loops = 0;
121 return (NULL);
122 }
123 return (fc_context_list[fc_context_loops]);
124 }
125
126 /* register a new context in the list */
127 void fc_context_register(FC_Context *ctx)
128 {
129 if (fc_context_list == NULL)
130 {/* allocate the table */
131 fc_context_list = malloc(sizeof (FC_Context*)*64);
132 if (fc_context_list == NULL)
133 {
134 fc_message("cannot allocate initial context list!");
135 fc_message_fatal(FC_ERR_MEM, "all data lost!");
136 }
137 fc_nb_context_max = 64;
138 }
139
140 fc_context_list[fc_nb_context_list++] = ctx;
141 fc_debug("register context %d", fc_nb_context_list - 1);
142 if (fc_nb_context_list == fc_nb_context_max)
143 {/* reallocate the table */
144 fc_context_list = realloc(fc_context_list, sizeof (FC_Context*)*
145 (fc_nb_context_max + 64));
146 if (fc_context_list == NULL)
147 {
148 fc_message("cannot reallocate context list!");
149 fc_message_fatal(FC_ERR_MEM, "all data lost!");
150 }
151 fc_nb_context_max += 64;
152 }
153 }
154
155 /* create a new context */
156 FC_Context *fc_context_create(int id, unsigned int first, int stack_size,
157 int func_size, int graph_size, int memory_size)
158 {
159 int i;
160 FC_Context *tmp;
161
162 tmp = malloc(sizeof (FC_Context));
163 if (tmp == NULL)
164 {
165 fc_message("cannot allocate %d bytes for a context.", sizeof (FC_Context));
166 return (NULL);
167 }
168
169 /* init sub-structures */
170 tmp->graph = fc_graph_init(graph_size > 0 ? graph_size : 512);
171 if (tmp->graph == NULL)
172 {
173 fc_message("cannot finish context initialization (graph).");
174 free(tmp);
175 return (NULL);
176 }
177
178 tmp->stack = fc_stack_create(stack_size > 0 ? stack_size : 128);
179 if (tmp->stack == NULL)
180 {
181 fc_message("cannot finish context initialization (stack).");
182 fc_graph_free(tmp->graph);
183 free(tmp);
184 return (NULL);
185 }
186
187 tmp->functions = fc_fhash_create(func_size > 0 ? func_size : 512);
188 if (tmp->functions == NULL)
189 {
190 fc_message("cannot finish context initialization (functions).");
191 fc_graph_free(tmp->graph);
192 fc_stack_delete(tmp->stack);
193 free(tmp);
194 return (NULL);
195 }
196
197 /* TODO: real initialization */
198 tmp->memory = fc_memory_create(memory_size > 0 ? memory_size : 512);
199 if (tmp->memory == NULL)
200 {
201 fc_message("cannot finish context initialization (memory).");
202 fc_graph_free(tmp->graph);
203 fc_stack_delete(tmp->stack);
204 fc_fhash_delete(tmp->functions);
205 free(tmp);
206 return (NULL);
207 }
208
209 tmp->id = id;
210 tmp->pid = 0;
211 tmp->first_time = (unsigned long long) first;
212 tmp->last_time = (unsigned long long) first;
213 tmp->ulast_time = first;
214 tmp->time_pad = 0;
215
216 /* 1st call: set the default values */
217 if (fc_current_context == NULL)
218 {
219 fc_current_context = tmp;
220 fc_current_context_id = id;
221 fc_ctx_stack_size = stack_size;
222 fc_ctx_func_size = func_size;
223 fc_ctx_graph_size = graph_size;
224 fc_ctx_memory_size = memory_size;
225 /* set the unique ID */
226 sprintf(fc_ctx_unique_id, "%d_%d_%d", (int) getpid(), tmp->id,
227 (int) time(NULL));
228 }
229 else
230 {/* in case of fork mode, create a set of empty functions
231 to allow exits from unknown functions for childs */
232 if (fc_mcom_mode == FC_MODE_FORK)
233 {
234 fc_current_context = tmp;
235 for (i = 0; i < 16; i++)
236 fc_functions_enter(NULL, NULL, first);
237 }
238 }
239
240 return (tmp);
241 }
242
243 /* set the current context regards to the ID (create it if needed) */
244 void fc_context_set(int id, unsigned int first_time)
245 {
246 int i;
247 FC_Context *ctx;
248
249 /* still the good context */
250 if (id == fc_current_context_id)
251 return;
252
253 /* search the context */
254 for (i = 0; i < fc_nb_context_list; i++)
255 {
256 if (fc_context_list[i]->id == id)
257 {/* set the context */
258 fc_debug("set context %d", i);
259 fc_current_context = fc_context_list[i];
260 fc_current_context_id = id;
261 return;
262 }
263 }
264
265 /* not found. create a new one */
266 ctx = fc_context_create(id, first_time, fc_ctx_stack_size,
267 fc_ctx_func_size, fc_ctx_graph_size,
268 fc_ctx_memory_size);
269 if (ctx != NULL)
270 {
271 fc_context_register(ctx);
272 fc_current_context = ctx;
273 fc_current_context_id = id;
274 fc_debug("new ID (%d)", id);
275 }
276 else
277 {/* this is a priori fatal... */
278 fc_message("new context not created.");
279 }
280 }
281
282 /* delete a context */
283 void fc_context_delete(FC_Context *ctx)
284 {
285 /* delete parts of the structure */
286 fc_fhash_delete(ctx->functions);
287 fc_stack_delete(ctx->stack);
288 fc_graph_free(ctx->graph);
289 fc_memory_delete(ctx->memory);
290 /* delete the structure */
291 free(ctx);
292 }
293
294 /* compute the context file name */
295 int fc_context_getname(FC_Context *ctx, char *name)
296 {
297 char tname[512];
298
299 /* effective name */
300 if (fc_ctx_usepid)
301 sprintf(tname, "%s.%d.fc", fc_ctx_name, (int) getpid());
302 else
303 sprintf(tname, "%s.fc", fc_ctx_name);
304
305 if (fc_nb_context_list == 1) /* only one process */
306 sprintf(name, "%s/%s", fc_ctx_path, tname);
307 else
308 sprintf(name, "%s/%s.%d", fc_ctx_path, tname, ctx->id);
309
310 return (1);
311 }
312
313 /* dump an arc to the given FILE */
314 void fc_arc_dump(unsigned long long key, int val, void *ptr1, void *ptr2, void *user_data)
315 {
316 void *from, *to;
317 unsigned long long mask = 0;
318 unsigned int i;
319
320 /* mask for the 1st word */
321 for (i = 0; i<sizeof (int) *8; i++)
322 {
323 mask |= ((unsigned long long) 1 << i);
324 }
325
326 /* extract from/to */
327 to = (void*) ((unsigned int) (key & mask));
328 from = (void*) ((unsigned int) ((key >> (sizeof (int) *8)) & mask));
329
330 fprintf((FILE*) user_data, "%p %p %d\n", from, to, val);
331 }
332
333 /* save a given context */
334 int fc_context_save(FC_Context *ctx)
335 {
336 char fname[512];
337 FILE *f;
338 int i, j, nbl, nbf, nbr;
339
340 /* compute the file name */
341 fc_context_getname(ctx, fname);
342
343 if ((f = fopen(fname, "w")) == NULL)
344 {
345 fc_message("cannot create profile file '%s'.", fname);
346 return (0);
347 }
348
349 /* save the header */
350 fprintf(f, "%s\n", FC_CTX_HEADER);
351 /* the unique ID */
352 fprintf(f, "%s\n", fc_ctx_unique_id);
353 /* time mode */
354 fprintf(f, "%d\n", fc_get_time_type());
355 /* profile mode */
356 fprintf(f, "%d\n", fc_ctx_pmode);
357 /* ID */
358 fprintf(f, "%d\n", ctx->id);
359 /* Parent ID */
360 fprintf(f, "%d\n", ctx->pid);
361 /* execution time */
362 fprintf(f, "%lld\n", ctx->last_time - ctx->first_time);
363 /* save call-graph (arcs) */
364 fprintf(f, "%d\n", (int) fc_lhash_size(ctx->graph));
365 /* dump each data */
366 fc_lhash_foreach(ctx->graph, fc_arc_dump, (void *) f);
367
368 /* save functions stats */
369 /* check the real number of functions */
370 j = 0;
371 for (i = 0; i < ctx->functions->current_size; i++)
372 {
373 if (ctx->functions->functions[i].symbol != NULL)
374 {
375 j++;
376 }
377 }
378
379 fprintf(f, "%d\n", j);
380 for (i = 0; i < ctx->functions->current_size; i++) /*this may be in fc_hash */
381 {
382 if (ctx->functions->functions[i].symbol != NULL)
383 fprintf(f, "%p %u %lld %lld %lld %lld %lld %lld\n",
384 ctx->functions->functions[i].symbol,
385 ctx->functions->functions[i].calls,
386 ctx->functions->functions[i].local_time,
387 ctx->functions->functions[i].total_time,
388 ctx->functions->functions[i].min_time,
389 ctx->functions->functions[i].max_time,
390 ctx->functions->functions[i].min_ltime,
391 ctx->functions->functions[i].max_ltime);
392 }
393
394 /* list of dynamic lib */
395 fprintf(f, "%d\n", fc_nb_list_ldyn);
396 for (i = 0; i < fc_nb_list_ldyn; i++)
397 {
398 fprintf(f, "%p %s\n", fc_list_ldyn[i].addr, fc_list_ldyn[i].name);
399 }
400
401 /* list of memory leaks */
402 if ((ctx->memory == NULL) || (ctx->memory->list == NULL))
403 {/* no entry */
404 fprintf(f, "0\n");
405 fprintf(f, "0\n");
406 fprintf(f, "0\n");
407 fclose(f);
408 }
409
410 /* # of elements */
411 nbl = 0;
412 nbr = 0;
413 nbf = 0;
414 for (i = 0; i < ctx->memory->nb_elements; i++)
415 {
416 if (ctx->memory->list[i].set)
417 {
418 if (ctx->memory->list[i].size == UINT_MAX)
419 {/* invalid free or realloc */
420 if (ctx->memory->list[i].realloc_place == NULL)
421 {/* free */
422 nbf++;
423 }
424 else
425 {/* realloc */
426 nbr++;
427 }
428 }
429 else
430 {/* memory leak */
431 nbl++;
432 }
433 }
434 }
435
436 /* leaks */
437 fprintf(f, "%d\n", nbl);
438 for (i = 0; i < ctx->memory->nb_elements; i++)
439 {
440 if (ctx->memory->list[i].set)
441 {
442 if (ctx->memory->list[i].size != UINT_MAX)
443 {
444 fprintf(f, "%p %u %p %p", ctx->memory->list[i].pointer,
445 ctx->memory->list[i].size, ctx->memory->list[i].alloc_place,
446 ctx->memory->list[i].realloc_place);
447 /* call-stack */
448 j = 0;
449 while ((j < fc_memory_stack_size) && (ctx->memory->list[i].alloc_stack[j] != NULL))
450 {
451 fprintf(f, " %p", ctx->memory->list[i].alloc_stack[j]);
452 j++;
453 }
454 /* end of list */
455 fprintf(f, " %p\n", NULL);
456 }
457 }
458 }
459
460 /* invalid free */
461 fprintf(f, "%d\n", nbf);
462 for (i = 0; i < ctx->memory->nb_elements; i++)
463 {
464 if (ctx->memory->list[i].set)
465 {
466 if ((ctx->memory->list[i].size == UINT_MAX) &&
467 (ctx->memory->list[i].alloc_place != NULL))
468 {
469 fprintf(f, "%p %p", ctx->memory->list[i].alloc_place,
470 ctx->memory->list[i].pointer);
471 /* call-stack */
472 j = 0;
473 while ((j < fc_memory_stack_size) && (ctx->memory->list[i].alloc_stack[j] != NULL))
474 {
475 fprintf(f, " %p", ctx->memory->list[i].alloc_stack[j]);
476 j++;
477 }
478 /* end of list */
479 fprintf(f, " %p\n", NULL);
480 }
481 }
482 }
483
484 /* invalid realloc */
485 fprintf(f, "%d\n", nbr);
486 for (i = 0; i < ctx->memory->nb_elements; i++)
487 {
488 if (ctx->memory->list[i].set)
489 {
490 if ((ctx->memory->list[i].size == UINT_MAX) &&
491 (ctx->memory->list[i].realloc_place != NULL))
492 {
493 fprintf(f, "%p %p", ctx->memory->list[i].realloc_place,
494 ctx->memory->list[i].pointer);
495 /* call-stack */
496 j = 0;
497 while ((j < fc_memory_stack_size) && (ctx->memory->list[i].alloc_stack[j] != NULL))
498 {
499 fprintf(f, " %p", ctx->memory->list[i].alloc_stack[j]);
500 j++;
501 }
502 /* end of list */
503 fprintf(f, " %p\n", NULL);
504 }
505 }
506 }
507
508 fclose(f);
509 return (0);
510 }
511
512 /* save all existing contexts */
513 int fc_context_save_all()
514 {
515 int i, ret;
516 char name[512];
517 FILE *f;
518
519 ret = 1;
520 for (i = 0; i < fc_nb_context_list; i++)
521 ret &= fc_context_save(fc_context_list[i]);
522
523 /* if needed, create the execution-tree of processes */
524 if (fc_nb_context_list > 1)
525 {
526 if (fc_ctx_usepid)
527 sprintf(name, "%s/%s.%d.fcd", fc_ctx_path, fc_ctx_name, (int) getpid());
528 else
529 sprintf(name, "%s/%s.fcd", fc_ctx_path, fc_ctx_name);
530
531 if ((f = fopen(name, "w")) == NULL)
532 {
533 fc_message("cannot create FunctionCheck descriptor file '%s'.", name);
534 return (0);
535 }
536
537 fc_message("Profiles descriptor file is '%s'", name);
538 fprintf(f, "FunctionCheck descriptor file.\n");
539 fprintf(f, "%d processes treated.\n", fc_nb_context_list);
540 fprintf(f, "Treatments started at: %d/%02d/%02d %02d:%02d:%02d\n",
541 fc_ctx_start_time.tm_year + 1900, fc_ctx_start_time.tm_mon + 1,
542 fc_ctx_start_time.tm_mday, fc_ctx_start_time.tm_hour,
543 fc_ctx_start_time.tm_min, fc_ctx_start_time.tm_sec);
544 fprintf(f, "Treatments ended at: %d/%02d/%02d %02d:%02d:%02d\n",
545 fc_ctx_stop_time.tm_year + 1900, fc_ctx_stop_time.tm_mon + 1,
546 fc_ctx_stop_time.tm_mday, fc_ctx_stop_time.tm_hour,
547 fc_ctx_stop_time.tm_min, fc_ctx_stop_time.tm_sec);
548 fprintf(f, "\n");
549 for (i = 0; i < fc_nb_context_list; i++)
550 {
551 fc_context_getname(fc_context_list[i], name);
552 fprintf(f, "Process id: %d\n", fc_context_list[i]->id);
553 if (fc_context_list[i]->pid != 0)
554 fprintf(f, " parent: %d\n", fc_context_list[i]->pid);
555 else
556 fprintf(f, " parent: pthread_create\n");
557 fprintf(f, " file: %s\n", name);
558 fprintf(f, "\n");
559 }
560 fclose(f);
561 }
562 else
563 {
564 fc_context_getname(fc_context_list[i], name);
565 fc_message("Profile file is '%s'", name);
566 }
567
568 return (ret);
569 }
570
571 /* set default values */
572 inline void fc_context_set_functions(int n)
573 {
574 fc_ctx_func_size = n;
575 }
576
577 inline void fc_context_set_graph(int n)
578 {
579 fc_ctx_graph_size = n;
580 }
581
582 inline void fc_context_set_stack(int n)
583 {
584 fc_ctx_stack_size = n;
585 }
586
587 inline void fc_context_set_memory(int n)
588 {
589 fc_ctx_memory_size = n;
590 }
591
592 inline void fc_context_set_name(char *n)
593 {
594 sprintf(fc_ctx_name, "%s", n);
595 }
596
597 inline void fc_context_set_path(char *n)
598 {
599 sprintf(fc_ctx_path, "%s", n);
600 }
601
602 inline void fc_context_set_usepid(int n)
603 {
604 fc_ctx_usepid = n;
605 }
606
607 inline void fc_context_set_starttime(time_t start)
608 {
609 fc_ctx_start_time = *(localtime(&start));
610 }
611
612 inline void fc_context_set_stoptime(time_t stop)
613 {
614 fc_ctx_stop_time = *(localtime(&stop));
615 }
616
617