trying to introduce cumulative time
[lttv.git] / ltt / branches / poly / lttv / lttv / stats.c
1 /* This file is part of the Linux Trace Toolkit viewer
2 * Copyright (C) 2003-2004 Michel Dagenais
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License Version 2 as
6 * published by the Free Software Foundation;
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with this program; if not, write to the Free Software
15 * Foundation, Inc., 59 Temple Place - Suite 330, Boston,
16 * MA 02111-1307, USA.
17 */
18
19 #ifdef HAVE_CONFIG_H
20 #include <config.h>
21 #endif
22
23 #include <stdio.h>
24 #include <lttv/module.h>
25 #include <lttv/stats.h>
26 #include <lttv/lttv.h>
27 #include <lttv/attribute.h>
28 #include <ltt/facility.h>
29 #include <ltt/trace.h>
30 #include <ltt/event.h>
31 #include <ltt/type.h>
32
33 #define BUF_SIZE 256
34 #define MAX_64_HEX_STRING_LEN 19
35
36 GQuark
37 LTTV_STATS_PROCESS_UNKNOWN,
38 LTTV_STATS_PROCESSES,
39 LTTV_STATS_CPU,
40 LTTV_STATS_MODE_TYPES,
41 LTTV_STATS_MODES,
42 LTTV_STATS_SUBMODES,
43 LTTV_STATS_FUNCTIONS,
44 LTTV_STATS_EVENT_TYPES,
45 LTTV_STATS_CPU_TIME,
46 LTTV_STATS_CUMULATIVE_CPU_TIME,
47 LTTV_STATS_ELAPSED_TIME,
48 LTTV_STATS_EVENTS,
49 LTTV_STATS_EVENTS_COUNT,
50 LTTV_STATS_USE_COUNT,
51 LTTV_STATS,
52 LTTV_STATS_TRACEFILES,
53 LTTV_STATS_SUMMED,
54 LTTV_STATS_BEFORE_HOOKS,
55 LTTV_STATS_AFTER_HOOKS;
56
57 static void
58 find_event_tree(LttvTracefileStats *tfcs, GQuark pid_time, guint cpu,
59 guint64 function,
60 GQuark mode, GQuark sub_mode, LttvAttribute **events_tree,
61 LttvAttribute **event_types_tree);
62
63
64 static void lttv_stats_init(LttvTracesetStats *self)
65 {
66 guint i, j, nb_trace, nb_tracefile;
67
68 LttvTraceContext *tc;
69
70 LttvTraceStats *tcs;
71
72 LttvTracefileContext *tfc;
73
74 LttvTracefileContext **tfs;
75 LttvTracefileStats *tfcs;
76
77 LttTime timestamp = {0,0};
78
79 LttvAttributeValue v;
80
81 LttvAttribute
82 *stats_tree,
83 *tracefiles_stats;
84
85 LttvTraceset *ts = self->parent.parent.ts;
86
87 self->stats = lttv_attribute_find_subdir(
88 lttv_traceset_attribute(self->parent.parent.ts),
89 LTTV_STATS);
90 lttv_attribute_find(lttv_traceset_attribute(self->parent.parent.ts),
91 LTTV_STATS_USE_COUNT,
92 LTTV_UINT, &v);
93
94 (*(v.v_uint))++;
95 if(*(v.v_uint) == 1) {
96 g_assert(lttv_attribute_get_number(self->stats) == 0);
97 }
98
99 nb_trace = lttv_traceset_number(ts);
100
101 for(i = 0 ; i < nb_trace ; i++) {
102 tc = self->parent.parent.traces[i];
103 tcs = LTTV_TRACE_STATS(tc);
104
105 tcs->stats = lttv_attribute_find_subdir(tcs->parent.parent.t_a,LTTV_STATS);
106 tracefiles_stats = lttv_attribute_find_subdir(tcs->parent.parent.t_a,
107 LTTV_STATS_TRACEFILES);
108 lttv_attribute_find(tcs->parent.parent.t_a, LTTV_STATS_USE_COUNT,
109 LTTV_UINT, &v);
110
111 (*(v.v_uint))++;
112 if(*(v.v_uint) == 1) {
113 g_assert(lttv_attribute_get_number(tcs->stats) == 0);
114 }
115
116 nb_tracefile = tc->tracefiles->len;
117
118 for(j = 0 ; j < nb_tracefile ; j++) {
119 tfs = &g_array_index(tc->tracefiles,
120 LttvTracefileContext*, j);
121 tfcs = LTTV_TRACEFILE_STATS(*tfs);
122 tfcs->stats = lttv_attribute_find_subdir(tracefiles_stats,
123 ltt_tracefile_long_name(tfcs->parent.parent.tf));
124 guint cpu = tfcs->parent.cpu;
125 find_event_tree(tfcs, LTTV_STATS_PROCESS_UNKNOWN,
126 cpu,
127 0x0ULL,
128 LTTV_STATE_MODE_UNKNOWN,
129 LTTV_STATE_SUBMODE_UNKNOWN, &tfcs->current_events_tree,
130 &tfcs->current_event_types_tree);
131 }
132 }
133
134 }
135
136 static void lttv_stats_fini(LttvTracesetStats *self)
137 {
138 guint i, j, nb_trace, nb_tracefile;
139
140 LttvTraceset *ts;
141
142 LttvTraceContext *tc;
143
144 LttvTraceStats *tcs;
145
146 LttvTracefileContext *tfc;
147
148 LttvTracefileStats *tfcs;
149
150 LttTime timestamp = {0,0};
151
152 LttvAttributeValue v;
153
154 LttvAttribute *tracefiles_stats;
155
156 lttv_attribute_find(self->parent.parent.ts_a, LTTV_STATS_USE_COUNT,
157 LTTV_UINT, &v);
158 (*(v.v_uint))--;
159
160 if(*(v.v_uint) == 0) {
161 lttv_attribute_remove_by_name(self->parent.parent.ts_a, LTTV_STATS);
162 }
163 self->stats = NULL;
164
165 ts = self->parent.parent.ts;
166 nb_trace = lttv_traceset_number(ts);
167
168 for(i = 0 ; i < nb_trace ; i++) {
169 tcs = (LttvTraceStats *)(tc = (LTTV_TRACESET_CONTEXT(self)->traces[i]));
170
171 lttv_attribute_find(tcs->parent.parent.t_a, LTTV_STATS_USE_COUNT,
172 LTTV_UINT, &v);
173 (*(v.v_uint))--;
174
175 if(*(v.v_uint) == 0) {
176 lttv_attribute_remove_by_name(tcs->parent.parent.t_a,LTTV_STATS);
177 tracefiles_stats = lttv_attribute_find_subdir(tcs->parent.parent.t_a,
178 LTTV_STATS_TRACEFILES);
179 lttv_attribute_remove_by_name(tcs->parent.parent.t_a,
180 LTTV_STATS_TRACEFILES);
181 }
182 tcs->stats = NULL;
183
184 nb_tracefile = tc->tracefiles->len;
185
186 for(j = 0 ; j < nb_tracefile ; j++) {
187 tfc = g_array_index(tc->tracefiles,
188 LttvTracefileContext*, j);
189 tfcs = (LttvTracefileStats *)tfc;
190 tfcs->stats = NULL;
191 tfcs->current_events_tree = NULL;
192 tfcs->current_event_types_tree = NULL;
193 }
194 }
195 }
196
197
198 void lttv_stats_reset(LttvTracesetStats *self)
199 {
200 lttv_stats_fini(self);
201 lttv_stats_init(self);
202 }
203
204
205
206 static void
207 init(LttvTracesetStats *self, LttvTraceset *ts)
208 {
209 LTTV_TRACESET_CONTEXT_CLASS(g_type_class_peek(LTTV_TRACESET_STATE_TYPE))->
210 init((LttvTracesetContext *)self, ts);
211
212 lttv_stats_init(self);
213 }
214
215
216 static void
217 fini(LttvTracesetStats *self)
218 {
219 lttv_stats_fini(self);
220
221 LTTV_TRACESET_CONTEXT_CLASS(g_type_class_peek(LTTV_TRACESET_STATE_TYPE))->
222 fini((LttvTracesetContext *)self);
223 }
224
225
226 static LttvTracesetContext *
227 new_traceset_context(LttvTracesetContext *self)
228 {
229 return LTTV_TRACESET_CONTEXT(g_object_new(LTTV_TRACESET_STATS_TYPE, NULL));
230 }
231
232
233 static LttvTraceContext *
234 new_trace_context(LttvTracesetContext *self)
235 {
236 return LTTV_TRACE_CONTEXT(g_object_new(LTTV_TRACE_STATS_TYPE, NULL));
237 }
238
239
240 static LttvTracefileContext *
241 new_tracefile_context(LttvTracesetContext *self)
242 {
243 return LTTV_TRACEFILE_CONTEXT(g_object_new(LTTV_TRACEFILE_STATS_TYPE, NULL));
244 }
245
246
247 static void
248 traceset_stats_instance_init (GTypeInstance *instance, gpointer g_class)
249 {
250 }
251
252
253 static void
254 traceset_stats_finalize (LttvTracesetStats *self)
255 {
256 G_OBJECT_CLASS(g_type_class_peek(LTTV_TRACESET_STATE_TYPE))->
257 finalize(G_OBJECT(self));
258 }
259
260
261 static void
262 traceset_stats_class_init (LttvTracesetContextClass *klass)
263 {
264 GObjectClass *gobject_class = G_OBJECT_CLASS(klass);
265
266 gobject_class->finalize = (void (*)(GObject *self)) traceset_stats_finalize;
267 klass->init = (void (*)(LttvTracesetContext *self, LttvTraceset *ts))init;
268 klass->fini = (void (*)(LttvTracesetContext *self))fini;
269 klass->new_traceset_context = new_traceset_context;
270 klass->new_trace_context = new_trace_context;
271 klass->new_tracefile_context = new_tracefile_context;
272 }
273
274
275 GType
276 lttv_traceset_stats_get_type(void)
277 {
278 static GType type = 0;
279 if (type == 0) {
280 static const GTypeInfo info = {
281 sizeof (LttvTracesetStatsClass),
282 NULL, /* base_init */
283 NULL, /* base_finalize */
284 (GClassInitFunc) traceset_stats_class_init, /* class_init */
285 NULL, /* class_finalize */
286 NULL, /* class_data */
287 sizeof (LttvTracesetStats),
288 0, /* n_preallocs */
289 (GInstanceInitFunc) traceset_stats_instance_init, /* instance_init */
290 NULL /* Value handling */
291 };
292
293 type = g_type_register_static (LTTV_TRACESET_STATE_TYPE,
294 "LttvTracesetStatsType",
295 &info, 0);
296 }
297 return type;
298 }
299
300
301 static void
302 trace_stats_instance_init (GTypeInstance *instance, gpointer g_class)
303 {
304 }
305
306
307 static void
308 trace_stats_finalize (LttvTraceStats *self)
309 {
310 G_OBJECT_CLASS(g_type_class_peek(LTTV_TRACE_STATE_TYPE))->
311 finalize(G_OBJECT(self));
312 }
313
314
315 static void
316 trace_stats_class_init (LttvTraceContextClass *klass)
317 {
318 GObjectClass *gobject_class = G_OBJECT_CLASS(klass);
319
320 gobject_class->finalize = (void (*)(GObject *self)) trace_stats_finalize;
321 }
322
323
324 GType
325 lttv_trace_stats_get_type(void)
326 {
327 static GType type = 0;
328 if (type == 0) {
329 static const GTypeInfo info = {
330 sizeof (LttvTraceStatsClass),
331 NULL, /* base_init */
332 NULL, /* base_finalize */
333 (GClassInitFunc) trace_stats_class_init, /* class_init */
334 NULL, /* class_finalize */
335 NULL, /* class_data */
336 sizeof (LttvTraceStats),
337 0, /* n_preallocs */
338 (GInstanceInitFunc) trace_stats_instance_init, /* instance_init */
339 NULL /* Value handling */
340 };
341
342 type = g_type_register_static (LTTV_TRACE_STATE_TYPE,
343 "LttvTraceStatsType", &info, 0);
344 }
345 return type;
346 }
347
348
349 static void
350 tracefile_stats_instance_init (GTypeInstance *instance, gpointer g_class)
351 {
352 }
353
354
355 static void
356 tracefile_stats_finalize (LttvTracefileStats *self)
357 {
358 G_OBJECT_CLASS(g_type_class_peek(LTTV_TRACEFILE_STATE_TYPE))->
359 finalize(G_OBJECT(self));
360 }
361
362
363 static void
364 tracefile_stats_class_init (LttvTracefileStatsClass *klass)
365 {
366 GObjectClass *gobject_class = G_OBJECT_CLASS(klass);
367
368 gobject_class->finalize = (void (*)(GObject *self)) tracefile_stats_finalize;
369 }
370
371
372 GType
373 lttv_tracefile_stats_get_type(void)
374 {
375 static GType type = 0;
376 if (type == 0) {
377 static const GTypeInfo info = {
378 sizeof (LttvTracefileStatsClass),
379 NULL, /* base_init */
380 NULL, /* base_finalize */
381 (GClassInitFunc) tracefile_stats_class_init, /* class_init */
382 NULL, /* class_finalize */
383 NULL, /* class_data */
384 sizeof (LttvTracefileStats),
385 0, /* n_preallocs */
386 (GInstanceInitFunc) tracefile_stats_instance_init, /* instance_init */
387 NULL /* Value handling */
388 };
389
390 type = g_type_register_static (LTTV_TRACEFILE_STATE_TYPE,
391 "LttvTracefileStatsType", &info, 0);
392 }
393 return type;
394 }
395
396
397 static void
398 find_event_tree(LttvTracefileStats *tfcs,
399 GQuark pid_time,
400 guint cpu,
401 guint64 function,
402 GQuark mode,
403 GQuark sub_mode,
404 LttvAttribute **events_tree,
405 LttvAttribute **event_types_tree)
406 {
407 LttvAttribute *a, *prev_a;
408 gchar fstring[MAX_64_HEX_STRING_LEN];
409 gint ret;
410
411 ret = snprintf(fstring, MAX_64_HEX_STRING_LEN-1,
412 "0x%llX", function) > 0;
413 g_assert(ret > 0);
414 fstring[MAX_64_HEX_STRING_LEN-1] = '\0';
415
416 LttvTraceStats *tcs = (LttvTraceStats*)tfcs->parent.parent.t_context;
417 a = lttv_attribute_find_subdir(tcs->stats, LTTV_STATS_PROCESSES);
418 a = lttv_attribute_find_subdir(a, pid_time);
419 a = lttv_attribute_find_subdir(a, LTTV_STATS_CPU);
420 a = lttv_attribute_find_subdir_unnamed(a, cpu);
421 a = lttv_attribute_find_subdir(a, LTTV_STATS_FUNCTIONS);
422 a = lttv_attribute_find_subdir(a, g_quark_from_string(fstring));
423 a = lttv_attribute_find_subdir(a, LTTV_STATS_MODE_TYPES);
424 a = lttv_attribute_find_subdir(a, mode);
425 a = lttv_attribute_find_subdir(a, LTTV_STATS_SUBMODES);
426 a = lttv_attribute_find_subdir(a, sub_mode);
427 *events_tree = a;
428 a = lttv_attribute_find_subdir(a, LTTV_STATS_EVENT_TYPES);
429 *event_types_tree = a;
430 }
431
432
433 static void update_event_tree(LttvTracefileStats *tfcs)
434 {
435 LttvTraceState *ts = (LttvTraceState *)tfcs->parent.parent.t_context;
436 guint cpu = tfcs->parent.cpu;
437 LttvProcessState *process = ts->running_process[cpu];
438 LttvExecutionState *es = process->state;
439
440 find_event_tree(tfcs, process->pid_time,
441 cpu,
442 process->current_function,
443 es->t, es->n, &(tfcs->current_events_tree),
444 &(tfcs->current_event_types_tree));
445 }
446
447
448 static void mode_change(LttvTracefileStats *tfcs)
449 {
450 LttvTraceState *ts = (LttvTraceState *)tfcs->parent.parent.t_context;
451 guint cpu = tfcs->parent.cpu;
452 LttvProcessState *process = ts->running_process[cpu];
453 LttvAttributeValue cpu_time, cum_cpu_time;
454
455 LttTime delta;
456
457 delta = ltt_time_sub(tfcs->parent.parent.timestamp,
458 process->state->change);
459
460 lttv_attribute_find(tfcs->current_events_tree, LTTV_STATS_CPU_TIME,
461 LTTV_TIME, &cpu_time);
462 *(cpu_time.v_time) = ltt_time_add(*(cpu_time.v_time), delta);
463
464 process->state->cum_cpu_time = ltt_time_add(process->state->cum_cpu_time,
465 delta);
466 }
467
468 /* Note : every mode_end must come with a cumulative cpu time update in the
469 * after hook */
470 static void mode_end(LttvTracefileStats *tfcs)
471 {
472 LttvTraceState *ts = (LttvTraceState *)tfcs->parent.parent.t_context;
473 guint cpu = tfcs->parent.cpu;
474 LttvProcessState *process = ts->running_process[cpu];
475 LttvAttributeValue elapsed_time, cpu_time, cum_cpu_time;
476
477 LttTime delta;
478
479 lttv_attribute_find(tfcs->current_events_tree, LTTV_STATS_ELAPSED_TIME,
480 LTTV_TIME, &elapsed_time);
481 delta = ltt_time_sub(tfcs->parent.parent.timestamp,
482 process->state->entry);
483 *(elapsed_time.v_time) = ltt_time_add(*(elapsed_time.v_time), delta);
484
485 lttv_attribute_find(tfcs->current_events_tree, LTTV_STATS_CPU_TIME,
486 LTTV_TIME, &cpu_time);
487 delta = ltt_time_sub(tfcs->parent.parent.timestamp,
488 process->state->change);
489 *(cpu_time.v_time) = ltt_time_add(*(cpu_time.v_time), delta);
490 process->state->cum_cpu_time = ltt_time_add(process->state->cum_cpu_time,
491 delta);
492
493 lttv_attribute_find(tfcs->current_events_tree, LTTV_STATS_CUMULATIVE_CPU_TIME,
494 LTTV_TIME, &cum_cpu_time);
495 *(cum_cpu_time.v_time) = ltt_time_add(*(cum_cpu_time.v_time),
496 process->state->cum_cpu_time);
497 }
498
499
500 static void after_mode_end(LttvTracefileStats *tfcs)
501 {
502 LttvTraceState *ts = (LttvTraceState *)tfcs->parent.parent.t_context;
503 guint cpu = tfcs->parent.cpu;
504 LttvProcessState *process = ts->running_process[cpu];
505 LttvAttributeValue cum_cpu_time;
506
507 LttTime nested_delta;
508
509 nested_delta = process->state->cum_cpu_time;
510 process->state->cum_cpu_time = ltt_time_zero; /* For after traceset hook */
511
512 update_event_tree(tfcs);
513
514 process->state->cum_cpu_time = ltt_time_add(process->state->cum_cpu_time,
515 nested_delta);
516 }
517
518 static gboolean before_syscall_entry(void *hook_data, void *call_data)
519 {
520 mode_change((LttvTracefileStats *)call_data);
521 return FALSE;
522 }
523
524
525 static gboolean after_syscall_entry(void *hook_data, void *call_data)
526 {
527 update_event_tree((LttvTracefileStats *)call_data);
528 return FALSE;
529 }
530
531
532 gboolean before_syscall_exit(void *hook_data, void *call_data)
533 {
534 mode_end((LttvTracefileStats *)call_data);
535 return FALSE;
536 }
537
538
539 static gboolean after_syscall_exit(void *hook_data, void *call_data)
540 {
541 after_mode_end((LttvTracefileStats *)call_data);
542 return FALSE;
543 }
544
545
546 gboolean before_trap_entry(void *hook_data, void *call_data)
547 {
548 mode_change((LttvTracefileStats *)call_data);
549 return FALSE;
550 }
551
552
553 static gboolean after_trap_entry(void *hook_data, void *call_data)
554 {
555 update_event_tree((LttvTracefileStats *)call_data);
556 return FALSE;
557 }
558
559
560 gboolean before_trap_exit(void *hook_data, void *call_data)
561 {
562 mode_end((LttvTracefileStats *)call_data);
563 return FALSE;
564 }
565
566
567 gboolean after_trap_exit(void *hook_data, void *call_data)
568 {
569 after_mode_end((LttvTracefileStats *)call_data);
570 return FALSE;
571 }
572
573
574 gboolean before_irq_entry(void *hook_data, void *call_data)
575 {
576 mode_change((LttvTracefileStats *)call_data);
577 return FALSE;
578 }
579
580 gboolean after_irq_entry(void *hook_data, void *call_data)
581 {
582 update_event_tree((LttvTracefileStats *)call_data);
583 return FALSE;
584 }
585
586
587 gboolean before_irq_exit(void *hook_data, void *call_data)
588 {
589 mode_end((LttvTracefileStats *)call_data);
590 return FALSE;
591 }
592
593
594 gboolean after_irq_exit(void *hook_data, void *call_data)
595 {
596 after_mode_end((LttvTracefileStats *)call_data);
597 return FALSE;
598 }
599
600
601 gboolean before_soft_irq_entry(void *hook_data, void *call_data)
602 {
603 mode_change((LttvTracefileStats *)call_data);
604 return FALSE;
605 }
606
607 gboolean after_soft_irq_entry(void *hook_data, void *call_data)
608 {
609 update_event_tree((LttvTracefileStats *)call_data);
610 return FALSE;
611 }
612
613
614 gboolean before_soft_irq_exit(void *hook_data, void *call_data)
615 {
616 mode_end((LttvTracefileStats *)call_data);
617 return FALSE;
618 }
619
620
621 gboolean after_soft_irq_exit(void *hook_data, void *call_data)
622 {
623 after_mode_end((LttvTracefileStats *)call_data);
624 return FALSE;
625 }
626
627 gboolean before_function_entry(void *hook_data, void *call_data)
628 {
629 mode_change((LttvTracefileStats *)call_data);
630 return FALSE;
631 }
632
633 gboolean after_function_entry(void *hook_data, void *call_data)
634 {
635 update_event_tree((LttvTracefileStats *)call_data);
636 return FALSE;
637 }
638
639 gboolean before_function_exit(void *hook_data, void *call_data)
640 {
641 mode_end((LttvTracefileStats *)call_data);
642 return FALSE;
643 }
644
645 gboolean after_function_exit(void *hook_data, void *call_data)
646 {
647 after_mode_end((LttvTracefileStats *)call_data);
648 return FALSE;
649 }
650
651
652 gboolean before_schedchange(void *hook_data, void *call_data)
653 {
654 LttvTracefileStats *tfcs = (LttvTracefileStats *)call_data;
655
656 LttvTraceState *ts = (LttvTraceState*)tfcs->parent.parent.t_context;
657
658 LttEvent *e = ltt_tracefile_get_event(tfcs->parent.parent.tf);
659
660 LttvTraceHookByFacility *thf = (LttvTraceHookByFacility *)hook_data;
661
662 guint pid_in, pid_out;
663
664 gint state_out;
665
666 pid_out = ltt_event_get_unsigned(e, thf->f1);
667 pid_in = ltt_event_get_unsigned(e, thf->f2);
668 state_out = ltt_event_get_int(e, thf->f3);
669
670 /* compute the time for the process to schedule out */
671
672 mode_change(tfcs);
673
674 return FALSE;
675 }
676
677 gboolean after_schedchange(void *hook_data, void *call_data)
678 {
679 LttvTracefileStats *tfcs = (LttvTracefileStats *)call_data;
680
681 LttvTraceState *ts = (LttvTraceState*)tfcs->parent.parent.t_context;
682
683 LttEvent *e = ltt_tracefile_get_event(tfcs->parent.parent.tf);
684
685 LttvTraceHookByFacility *thf = (LttvTraceHookByFacility *)hook_data;
686
687 guint pid_in, pid_out;
688
689 gint state_out;
690
691 LttvProcessState *process;
692
693 pid_out = ltt_event_get_unsigned(e, thf->f1);
694 pid_in = ltt_event_get_unsigned(e, thf->f2);
695 state_out = ltt_event_get_int(e, thf->f3);
696
697 /* get the information for the process scheduled in */
698 guint cpu = tfcs->parent.cpu;
699 process = ts->running_process[cpu];
700
701 find_event_tree(tfcs, process->pid_time,
702 cpu,
703 process->current_function,
704 process->state->t, process->state->n, &(tfcs->current_events_tree),
705 &(tfcs->current_event_types_tree));
706
707 /* compute the time waiting for the process to schedule in */
708 mode_change(tfcs);
709
710 return FALSE;
711 }
712
713 gboolean process_fork(void *hook_data, void *call_data)
714 {
715 /* nothing to do for now */
716 return FALSE;
717 }
718
719
720 gboolean process_exit(void *hook_data, void *call_data)
721 {
722 /* We should probably exit all modes here or we could do that at
723 schedule out. */
724 return FALSE;
725 }
726
727 gboolean process_free(void *hook_data, void *call_data)
728 {
729 return FALSE;
730 }
731
732 gboolean every_event(void *hook_data, void *call_data)
733 {
734 LttvTracefileStats *tfcs = (LttvTracefileStats *)call_data;
735
736 LttEvent *e = ltt_tracefile_get_event(tfcs->parent.parent.tf);
737
738 LttvAttributeValue v;
739
740 /* The current branch corresponds to the tracefile/process/interrupt state.
741 Statistics are added within it, to count the number of events of this
742 type occuring in this context. A quark has been pre-allocated for each
743 event type and is used as name. */
744
745 lttv_attribute_find(tfcs->current_event_types_tree,
746 ltt_eventtype_name(ltt_event_eventtype(e)),
747 LTTV_UINT, &v);
748 (*(v.v_uint))++;
749 return FALSE;
750 }
751
752 static void lttv_stats_cleanup_process_state(gpointer key, gpointer value,
753 gpointer user_data)
754 {
755 LttvTraceStats *tcs = (LttvTraceStats *)user_data;
756 LttvTraceState *ts = (LttvTraceState *)user_data;
757 LttvTracesetContext *tsc = ts->parent.ts_context;
758 LttvProcessState *process = (LttvProcessState *)value;
759 int i;
760 LttvTracefileStats **tfs = (LttvTracefileStats **)
761 &g_array_index(ts->parent.tracefiles, LttvTracefileContext*,
762 process->cpu);
763 int cleanup_empty = 0;
764
765 do {
766 if(ltt_time_compare(process->state->cum_cpu_time, ltt_time_zero) != 0) {
767 find_event_tree(*tfs, process->pid_time,
768 process->cpu,
769 process->current_function,
770 process->state->t, process->state->n, &((*tfs)->current_events_tree),
771 &((*tfs)->current_event_types_tree));
772 /* FIXME : ok, this is a hack. The time is infinite here :( */
773 LttTime save_time = (*tfs)->parent.parent.timestamp;
774 LttTime start, end;
775 ltt_trace_time_span_get(ts->parent.t, &start, &end);
776 (*tfs)->parent.parent.timestamp = end;
777 mode_end(*tfs);
778 (*tfs)->parent.parent.timestamp = save_time;
779 }
780 cleanup_empty = lttv_state_pop_state_cleanup(process,
781 (LttvTracefileState *)*tfs);
782 } while(cleanup_empty != 1);
783 }
784
785 /* For each process in the state, for each of their stacked states,
786 * perform sum of needed values. */
787 static void lttv_stats_cleanup_state(LttvTraceStats *tcs)
788 {
789 LttvTraceState *ts = (LttvTraceState *)tcs;
790
791 #if 0
792 /* Does not work correctly FIXME. */
793 g_hash_table_foreach(ts->processes, lttv_stats_cleanup_process_state,
794 tcs);
795 #endif //0
796 }
797
798 void
799 lttv_stats_sum_trace(LttvTraceStats *self, LttvAttribute *ts_stats)
800 {
801 LttvAttribute *sum_container = self->stats;
802
803 LttvAttributeType type;
804
805 LttvAttributeValue value;
806
807 LttvAttributeName name;
808
809 gboolean is_named;
810
811 unsigned sum;
812
813 int trace_is_summed;
814
815 int i, j, k, l, m, nb_process, nb_cpu, nb_mode_type, nb_submode,
816 nb_event_type, nf, nb_functions;
817
818 LttvAttribute *main_tree, *processes_tree, *process_tree, *cpus_tree,
819 *cpu_tree, *mode_tree, *mode_types_tree, *submodes_tree,
820 *submode_tree, *event_types_tree, *mode_events_tree,
821 *cpu_functions_tree,
822 *function_tree,
823 *function_mode_types_tree,
824 *trace_cpu_tree;
825
826
827 main_tree = sum_container;
828
829 lttv_attribute_find(sum_container,
830 LTTV_STATS_SUMMED,
831 LTTV_UINT, &value);
832 trace_is_summed = *(value.v_uint);
833 *(value.v_uint) = 1;
834
835 /* First cleanup the state : sum all stalled information (never ending
836 * states). */
837 if(!trace_is_summed)
838 lttv_stats_cleanup_state(self);
839
840 processes_tree = lttv_attribute_find_subdir(main_tree,
841 LTTV_STATS_PROCESSES);
842 nb_process = lttv_attribute_get_number(processes_tree);
843
844 for(i = 0 ; i < nb_process ; i++) {
845 type = lttv_attribute_get(processes_tree, i, &name, &value, &is_named);
846 process_tree = LTTV_ATTRIBUTE(*(value.v_gobject));
847
848 cpus_tree = lttv_attribute_find_subdir(process_tree, LTTV_STATS_CPU);
849 nb_cpu = lttv_attribute_get_number(cpus_tree);
850
851 for(j = 0 ; j < nb_cpu ; j++) {
852 type = lttv_attribute_get(cpus_tree, j, &name, &value, &is_named);
853 cpu_tree = LTTV_ATTRIBUTE(*(value.v_gobject));
854
855 trace_cpu_tree = lttv_attribute_find_subdir(main_tree, LTTV_STATS_CPU);
856 trace_cpu_tree = lttv_attribute_find_subdir_unnamed(trace_cpu_tree, name);
857 cpu_functions_tree = lttv_attribute_find_subdir(cpu_tree,
858 LTTV_STATS_FUNCTIONS);
859 nb_functions = lttv_attribute_get_number(cpu_functions_tree);
860
861 for(nf=0; nf < nb_functions; nf++) {
862 type = lttv_attribute_get(cpu_functions_tree, nf, &name, &value,
863 &is_named);
864 function_tree = LTTV_ATTRIBUTE(*(value.v_gobject));
865 function_mode_types_tree = lttv_attribute_find_subdir(function_tree,
866 LTTV_STATS_MODE_TYPES);
867 nb_mode_type = lttv_attribute_get_number(function_mode_types_tree);
868 for(k = 0 ; k < nb_mode_type ; k++) {
869 type = lttv_attribute_get(function_mode_types_tree, k, &name, &value,
870 &is_named);
871 mode_tree = LTTV_ATTRIBUTE(*(value.v_gobject));
872
873 submodes_tree = lttv_attribute_find_subdir(mode_tree,
874 LTTV_STATS_SUBMODES);
875 mode_events_tree = lttv_attribute_find_subdir(mode_tree,
876 LTTV_STATS_EVENTS);
877 mode_types_tree = lttv_attribute_find_subdir(mode_tree,
878 LTTV_STATS_MODE_TYPES);
879
880 nb_submode = lttv_attribute_get_number(submodes_tree);
881
882 for(l = 0 ; l < nb_submode ; l++) {
883 type = lttv_attribute_get(submodes_tree, l, &name, &value,
884 &is_named);
885 submode_tree = LTTV_ATTRIBUTE(*(value.v_gobject));
886
887 event_types_tree = lttv_attribute_find_subdir(submode_tree,
888 LTTV_STATS_EVENT_TYPES);
889 nb_event_type = lttv_attribute_get_number(event_types_tree);
890
891 sum = 0;
892 for(m = 0 ; m < nb_event_type ; m++) {
893 type = lttv_attribute_get(event_types_tree, m, &name, &value,
894 &is_named);
895 sum += *(value.v_uint);
896 }
897 lttv_attribute_find(submode_tree, LTTV_STATS_EVENTS_COUNT,
898 LTTV_UINT, &value);
899 *(value.v_uint) = sum;
900
901 type = lttv_attribute_get(submodes_tree, l, &name, &value,
902 &is_named);
903 submode_tree = LTTV_ATTRIBUTE(*(value.v_gobject));
904 if(!trace_is_summed) {
905 lttv_attribute_recursive_add(mode_events_tree, event_types_tree);
906 lttv_attribute_recursive_add(mode_types_tree, submode_tree);
907 }
908 }
909 if(!trace_is_summed) {
910 //lttv_attribute_recursive_add(function_tree, mode_types_tree);
911 }
912 }
913 if(!trace_is_summed) {
914 //lttv_attribute_recursive_add(cpu_tree, function_tree);
915 //lttv_attribute_recursive_add(process_tree, function_tree);
916 //lttv_attribute_recursive_add(trace_cpu_tree, function_tree);
917 //lttv_attribute_recursive_add(main_tree, function_tree);
918 }
919 //lttv_attribute_recursive_add(ts_stats, function_tree);
920 }
921 }
922 }
923 }
924
925
926 gboolean lttv_stats_sum_traceset_hook(void *hook_data, void *call_data)
927 {
928 lttv_stats_sum_traceset((LttvTracesetStats *)call_data);
929 return 0;
930 }
931
932 void
933 lttv_stats_sum_traceset(LttvTracesetStats *self)
934 {
935 LttvTraceset *traceset = self->parent.parent.ts;
936 LttvAttribute *sum_container = self->stats;
937
938 LttvTraceStats *tcs;
939
940 int i, nb_trace;
941
942 LttvAttribute *main_tree;
943
944 LttvAttributeValue value;
945
946 lttv_attribute_find(sum_container, LTTV_STATS_SUMMED,
947 LTTV_UINT, &value);
948 if(*(value.v_uint) != 0) return;
949 *(value.v_uint) = 1;
950
951 nb_trace = lttv_traceset_number(traceset);
952
953 for(i = 0 ; i < nb_trace ; i++) {
954 tcs = (LttvTraceStats *)(self->parent.parent.traces[i]);
955 lttv_stats_sum_trace(tcs, self->stats);
956 // lttv_attribute_recursive_add(sum_container, tcs->stats);
957 }
958 }
959
960
961 // Hook wrapper. call_data is a traceset context.
962 gboolean lttv_stats_hook_add_event_hooks(void *hook_data, void *call_data)
963 {
964 LttvTracesetStats *tss = (LttvTracesetStats*)call_data;
965
966 lttv_stats_add_event_hooks(tss);
967
968 return 0;
969 }
970
971 void lttv_stats_add_event_hooks(LttvTracesetStats *self)
972 {
973 LttvTraceset *traceset = self->parent.parent.ts;
974
975 guint i, j, k, l, nb_trace, nb_tracefile;
976
977 LttvTraceStats *ts;
978
979 LttvTracefileStats *tfs;
980
981 GArray *hooks, *before_hooks, *after_hooks;
982
983 LttvTraceHook *hook;
984
985 LttvTraceHookByFacility *thf;
986
987 LttvAttributeValue val;
988
989 gint ret;
990 gint hn;
991
992 nb_trace = lttv_traceset_number(traceset);
993 for(i = 0 ; i < nb_trace ; i++) {
994 ts = (LttvTraceStats *)self->parent.parent.traces[i];
995
996 /* Find the eventtype id for the following events and register the
997 associated by id hooks. */
998
999 hooks = g_array_sized_new(FALSE, FALSE, sizeof(LttvTraceHook), 11);
1000 g_array_set_size(hooks, 11);
1001 hn=0;
1002
1003 ret = lttv_trace_find_hook(ts->parent.parent.t,
1004 LTT_FACILITY_KERNEL_ARCH, LTT_EVENT_SYSCALL_ENTRY,
1005 LTT_FIELD_SYSCALL_ID, 0, 0,
1006 before_syscall_entry, NULL,
1007 &g_array_index(hooks, LttvTraceHook, hn++));
1008 if(ret) hn--;
1009
1010 ret = lttv_trace_find_hook(ts->parent.parent.t,
1011 LTT_FACILITY_KERNEL_ARCH, LTT_EVENT_SYSCALL_EXIT,
1012 0, 0, 0,
1013 before_syscall_exit, NULL,
1014 &g_array_index(hooks, LttvTraceHook, hn++));
1015 if(ret) hn--;
1016
1017 ret = lttv_trace_find_hook(ts->parent.parent.t,
1018 LTT_FACILITY_KERNEL, LTT_EVENT_TRAP_ENTRY,
1019 LTT_FIELD_TRAP_ID, 0, 0,
1020 before_trap_entry, NULL,
1021 &g_array_index(hooks, LttvTraceHook, hn++));
1022 if(ret) hn--;
1023
1024 ret = lttv_trace_find_hook(ts->parent.parent.t,
1025 LTT_FACILITY_KERNEL, LTT_EVENT_TRAP_EXIT,
1026 0, 0, 0,
1027 before_trap_exit, NULL,
1028 &g_array_index(hooks, LttvTraceHook, hn++));
1029 if(ret) hn--;
1030
1031 ret = lttv_trace_find_hook(ts->parent.parent.t,
1032 LTT_FACILITY_KERNEL, LTT_EVENT_IRQ_ENTRY,
1033 LTT_FIELD_IRQ_ID, 0, 0,
1034 before_irq_entry, NULL,
1035 &g_array_index(hooks, LttvTraceHook, hn++));
1036 if(ret) hn--;
1037
1038 ret = lttv_trace_find_hook(ts->parent.parent.t,
1039 LTT_FACILITY_KERNEL, LTT_EVENT_IRQ_EXIT,
1040 0, 0, 0,
1041 before_irq_exit, NULL,
1042 &g_array_index(hooks, LttvTraceHook, hn++));
1043 if(ret) hn--;
1044
1045 ret = lttv_trace_find_hook(ts->parent.parent.t,
1046 LTT_FACILITY_KERNEL, LTT_EVENT_SOFT_IRQ_ENTRY,
1047 LTT_FIELD_SOFT_IRQ_ID, 0, 0,
1048 before_soft_irq_entry, NULL,
1049 &g_array_index(hooks, LttvTraceHook, hn++));
1050 if(ret) hn--;
1051
1052 ret = lttv_trace_find_hook(ts->parent.parent.t,
1053 LTT_FACILITY_KERNEL, LTT_EVENT_SOFT_IRQ_EXIT,
1054 0, 0, 0,
1055 before_soft_irq_exit, NULL,
1056 &g_array_index(hooks, LttvTraceHook, hn++));
1057 if(ret) hn--;
1058
1059 ret = lttv_trace_find_hook(ts->parent.parent.t,
1060 LTT_FACILITY_PROCESS, LTT_EVENT_SCHEDCHANGE,
1061 LTT_FIELD_OUT, LTT_FIELD_IN, LTT_FIELD_OUT_STATE,
1062 before_schedchange, NULL,
1063 &g_array_index(hooks, LttvTraceHook, hn++));
1064 if(ret) hn--;
1065
1066 ret = lttv_trace_find_hook(ts->parent.parent.t,
1067 LTT_FACILITY_USER_GENERIC, LTT_EVENT_FUNCTION_ENTRY,
1068 LTT_FIELD_THIS_FN, LTT_FIELD_CALL_SITE, 0,
1069 before_function_entry, NULL,
1070 &g_array_index(hooks, LttvTraceHook, hn++));
1071 if(ret) hn--;
1072
1073 ret = lttv_trace_find_hook(ts->parent.parent.t,
1074 LTT_FACILITY_USER_GENERIC, LTT_EVENT_FUNCTION_EXIT,
1075 LTT_FIELD_THIS_FN, LTT_FIELD_CALL_SITE, 0,
1076 before_function_exit, NULL,
1077 &g_array_index(hooks, LttvTraceHook, hn++));
1078 if(ret) hn--;
1079
1080 g_array_set_size(hooks, hn);
1081
1082 before_hooks = hooks;
1083
1084 hooks = g_array_sized_new(FALSE, FALSE, sizeof(LttvTraceHook), 14);
1085 g_array_set_size(hooks, 14);
1086 hn=0;
1087
1088 ret = lttv_trace_find_hook(ts->parent.parent.t,
1089 LTT_FACILITY_KERNEL_ARCH, LTT_EVENT_SYSCALL_ENTRY,
1090 LTT_FIELD_SYSCALL_ID, 0, 0,
1091 after_syscall_entry, NULL,
1092 &g_array_index(hooks, LttvTraceHook, hn++));
1093 if(ret) hn--;
1094
1095 ret = lttv_trace_find_hook(ts->parent.parent.t,
1096 LTT_FACILITY_KERNEL_ARCH, LTT_EVENT_SYSCALL_EXIT,
1097 0, 0, 0,
1098 after_syscall_exit, NULL,
1099 &g_array_index(hooks, LttvTraceHook, hn++));
1100 if(ret) hn--;
1101
1102 ret = lttv_trace_find_hook(ts->parent.parent.t,
1103 LTT_FACILITY_KERNEL, LTT_EVENT_TRAP_ENTRY,
1104 LTT_FIELD_TRAP_ID, 0, 0,
1105 after_trap_entry, NULL,
1106 &g_array_index(hooks, LttvTraceHook, hn++));
1107 if(ret) hn--;
1108
1109 ret = lttv_trace_find_hook(ts->parent.parent.t,
1110 LTT_FACILITY_KERNEL, LTT_EVENT_TRAP_EXIT,
1111 0, 0, 0,
1112 after_trap_exit, NULL,
1113 &g_array_index(hooks, LttvTraceHook, hn++));
1114 if(ret) hn--;
1115
1116 ret = lttv_trace_find_hook(ts->parent.parent.t,
1117 LTT_FACILITY_KERNEL, LTT_EVENT_IRQ_ENTRY,
1118 LTT_FIELD_IRQ_ID, 0, 0,
1119 after_irq_entry, NULL,
1120 &g_array_index(hooks, LttvTraceHook, hn++));
1121 if(ret) hn--;
1122
1123 ret = lttv_trace_find_hook(ts->parent.parent.t,
1124 LTT_FACILITY_KERNEL, LTT_EVENT_IRQ_EXIT,
1125 0, 0, 0,
1126 after_irq_exit, NULL,
1127 &g_array_index(hooks, LttvTraceHook, hn++));
1128 if(ret) hn--;
1129
1130 ret = lttv_trace_find_hook(ts->parent.parent.t,
1131 LTT_FACILITY_KERNEL, LTT_EVENT_SOFT_IRQ_ENTRY,
1132 LTT_FIELD_SOFT_IRQ_ID, 0, 0,
1133 after_irq_entry, NULL,
1134 &g_array_index(hooks, LttvTraceHook, hn++));
1135 if(ret) hn--;
1136
1137 ret = lttv_trace_find_hook(ts->parent.parent.t,
1138 LTT_FACILITY_KERNEL, LTT_EVENT_SOFT_IRQ_EXIT,
1139 0, 0, 0,
1140 after_soft_irq_exit, NULL,
1141 &g_array_index(hooks, LttvTraceHook, hn++));
1142 if(ret) hn--;
1143
1144 ret = lttv_trace_find_hook(ts->parent.parent.t,
1145 LTT_FACILITY_PROCESS, LTT_EVENT_SCHEDCHANGE,
1146 LTT_FIELD_OUT, LTT_FIELD_IN, LTT_FIELD_OUT_STATE,
1147 after_schedchange, NULL,
1148 &g_array_index(hooks, LttvTraceHook, hn++));
1149 if(ret) hn--;
1150
1151 ret = lttv_trace_find_hook(ts->parent.parent.t,
1152 LTT_FACILITY_PROCESS, LTT_EVENT_FORK,
1153 LTT_FIELD_PARENT_PID, LTT_FIELD_CHILD_PID, 0,
1154 process_fork, NULL,
1155 &g_array_index(hooks, LttvTraceHook, hn++));
1156 if(ret) hn--;
1157
1158 ret = lttv_trace_find_hook(ts->parent.parent.t,
1159 LTT_FACILITY_PROCESS, LTT_EVENT_EXIT,
1160 LTT_FIELD_PID, 0, 0,
1161 process_exit, NULL,
1162 &g_array_index(hooks, LttvTraceHook, hn++));
1163 if(ret) hn--;
1164
1165 ret = lttv_trace_find_hook(ts->parent.parent.t,
1166 LTT_FACILITY_PROCESS, LTT_EVENT_FREE,
1167 LTT_FIELD_PID, 0, 0,
1168 process_free, NULL,
1169 &g_array_index(hooks, LttvTraceHook, hn++));
1170 if(ret) hn--;
1171
1172 ret = lttv_trace_find_hook(ts->parent.parent.t,
1173 LTT_FACILITY_USER_GENERIC, LTT_EVENT_FUNCTION_ENTRY,
1174 LTT_FIELD_THIS_FN, LTT_FIELD_CALL_SITE, 0,
1175 after_function_entry, NULL,
1176 &g_array_index(hooks, LttvTraceHook, hn++));
1177 if(ret) hn--;
1178
1179 ret = lttv_trace_find_hook(ts->parent.parent.t,
1180 LTT_FACILITY_USER_GENERIC, LTT_EVENT_FUNCTION_EXIT,
1181 LTT_FIELD_THIS_FN, LTT_FIELD_CALL_SITE, 0,
1182 after_function_exit, NULL,
1183 &g_array_index(hooks, LttvTraceHook, hn++));
1184 if(ret) hn--;
1185
1186 g_array_set_size(hooks, hn);
1187
1188 after_hooks = hooks;
1189
1190 /* Add these hooks to each event_by_id hooks list */
1191
1192 nb_tracefile = ts->parent.parent.tracefiles->len;
1193
1194 for(j = 0 ; j < nb_tracefile ; j++) {
1195 tfs = LTTV_TRACEFILE_STATS(g_array_index(ts->parent.parent.tracefiles,
1196 LttvTracefileContext*, j));
1197 lttv_hooks_add(tfs->parent.parent.event, every_event, NULL,
1198 LTTV_PRIO_DEFAULT);
1199
1200 for(k = 0 ; k < before_hooks->len ; k++) {
1201 hook = &g_array_index(before_hooks, LttvTraceHook, k);
1202 for(l = 0; l<hook->fac_list->len;l++) {
1203 thf = g_array_index(hook->fac_list, LttvTraceHookByFacility*, l);
1204 lttv_hooks_add(
1205 lttv_hooks_by_id_find(tfs->parent.parent.event_by_id, thf->id),
1206 thf->h,
1207 thf,
1208 LTTV_PRIO_STATS_BEFORE_STATE);
1209 }
1210 }
1211 for(k = 0 ; k < after_hooks->len ; k++) {
1212 hook = &g_array_index(after_hooks, LttvTraceHook, k);
1213 for(l = 0; l<hook->fac_list->len;l++) {
1214 thf = g_array_index(hook->fac_list, LttvTraceHookByFacility*, l);
1215 lttv_hooks_add(
1216 lttv_hooks_by_id_find(tfs->parent.parent.event_by_id, thf->id),
1217 thf->h,
1218 thf,
1219 LTTV_PRIO_STATS_AFTER_STATE);
1220 }
1221 }
1222 }
1223 lttv_attribute_find(self->parent.parent.a, LTTV_STATS_BEFORE_HOOKS,
1224 LTTV_POINTER, &val);
1225 *(val.v_pointer) = before_hooks;
1226 lttv_attribute_find(self->parent.parent.a, LTTV_STATS_AFTER_HOOKS,
1227 LTTV_POINTER, &val);
1228 *(val.v_pointer) = after_hooks;
1229 }
1230 }
1231
1232 // Hook wrapper. call_data is a traceset context.
1233 gboolean lttv_stats_hook_remove_event_hooks(void *hook_data, void *call_data)
1234 {
1235 LttvTracesetStats *tss = (LttvTracesetStats*)call_data;
1236
1237 lttv_stats_remove_event_hooks(tss);
1238
1239 return 0;
1240 }
1241
1242 void lttv_stats_remove_event_hooks(LttvTracesetStats *self)
1243 {
1244 LttvTraceset *traceset = self->parent.parent.ts;
1245
1246 guint i, j, k, l, nb_trace, nb_tracefile;
1247
1248 LttvTraceStats *ts;
1249
1250 LttvTracefileStats *tfs;
1251
1252 void *hook_data;
1253
1254 GArray *before_hooks, *after_hooks;
1255
1256 LttvTraceHook *hook;
1257
1258 LttvTraceHookByFacility *thf;
1259
1260 LttvAttributeValue val;
1261
1262 nb_trace = lttv_traceset_number(traceset);
1263 for(i = 0 ; i < nb_trace ; i++) {
1264 ts = (LttvTraceStats*)self->parent.parent.traces[i];
1265 lttv_attribute_find(self->parent.parent.a, LTTV_STATS_BEFORE_HOOKS,
1266 LTTV_POINTER, &val);
1267 before_hooks = *(val.v_pointer);
1268 lttv_attribute_find(self->parent.parent.a, LTTV_STATS_AFTER_HOOKS,
1269 LTTV_POINTER, &val);
1270 after_hooks = *(val.v_pointer);
1271
1272 /* Remove these hooks from each event_by_id hooks list */
1273
1274 nb_tracefile = ts->parent.parent.tracefiles->len;
1275
1276 for(j = 0 ; j < nb_tracefile ; j++) {
1277 tfs = LTTV_TRACEFILE_STATS(g_array_index(ts->parent.parent.tracefiles,
1278 LttvTracefileContext*, j));
1279 lttv_hooks_remove_data(tfs->parent.parent.event, every_event,
1280 NULL);
1281
1282 for(k = 0 ; k < before_hooks->len ; k++) {
1283 hook = &g_array_index(before_hooks, LttvTraceHook, k);
1284 for(l = 0 ; l < hook->fac_list->len ; l++) {
1285 thf = g_array_index(hook->fac_list, LttvTraceHookByFacility*, l);
1286 lttv_hooks_remove_data(
1287 lttv_hooks_by_id_find(tfs->parent.parent.event_by_id, thf->id),
1288 thf->h,
1289 thf);
1290 }
1291 }
1292 for(k = 0 ; k < after_hooks->len ; k++) {
1293 hook = &g_array_index(after_hooks, LttvTraceHook, k);
1294 for(l = 0 ; l < hook->fac_list->len ; l++) {
1295 thf = g_array_index(hook->fac_list, LttvTraceHookByFacility*, l);
1296 lttv_hooks_remove_data(
1297 lttv_hooks_by_id_find(tfs->parent.parent.event_by_id, thf->id),
1298 thf->h,
1299 thf);
1300 }
1301 }
1302 }
1303 g_debug("lttv_stats_remove_event_hooks()");
1304 g_array_free(before_hooks, TRUE);
1305 g_array_free(after_hooks, TRUE);
1306 }
1307 }
1308
1309
1310 static void module_init()
1311 {
1312 LTTV_STATS_PROCESS_UNKNOWN = g_quark_from_string("unknown process");
1313 LTTV_STATS_PROCESSES = g_quark_from_string("processes");
1314 LTTV_STATS_CPU = g_quark_from_string("cpu");
1315 LTTV_STATS_MODE_TYPES = g_quark_from_string("mode_types");
1316 LTTV_STATS_MODES = g_quark_from_string("modes");
1317 LTTV_STATS_SUBMODES = g_quark_from_string("submodes");
1318 LTTV_STATS_FUNCTIONS = g_quark_from_string("functions");
1319 LTTV_STATS_EVENT_TYPES = g_quark_from_string("event_types");
1320 LTTV_STATS_CPU_TIME = g_quark_from_string("cpu time");
1321 LTTV_STATS_CUMULATIVE_CPU_TIME = g_quark_from_string("cumulative cpu time (includes nested routines and modes)");
1322 LTTV_STATS_ELAPSED_TIME = g_quark_from_string("elapsed time (includes per process waiting time)");
1323 LTTV_STATS_EVENTS = g_quark_from_string("events");
1324 LTTV_STATS_EVENTS_COUNT = g_quark_from_string("events count");
1325 LTTV_STATS_BEFORE_HOOKS = g_quark_from_string("saved stats before hooks");
1326 LTTV_STATS_AFTER_HOOKS = g_quark_from_string("saved stats after hooks");
1327 LTTV_STATS_USE_COUNT = g_quark_from_string("stats_use_count");
1328 LTTV_STATS = g_quark_from_string("statistics");
1329 LTTV_STATS_TRACEFILES = g_quark_from_string("tracefiles statistics");
1330 LTTV_STATS_SUMMED = g_quark_from_string("statistics summed");
1331 }
1332
1333 static void module_destroy()
1334 {
1335 }
1336
1337
1338 LTTV_MODULE("stats", "Compute processes statistics", \
1339 "Accumulate statistics for event types, processes and CPUs", \
1340 module_init, module_destroy, "state");
1341
1342 /* Change the places where stats are called (create/read/write stats)
1343
1344 Check for options in batchtest.c to reduce writing and see what tests are
1345 best candidates for performance analysis. Once OK, commit, move to main
1346 and run tests. Update the gui for statistics. */
This page took 0.055993 seconds and 4 git commands to generate.