add eventdefs exclusion in open_tracefiles
[lttv.git] / ltt / branches / poly / lttv / lttv / stats.c
CommitLineData
9c312311 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
4e4d11b3 19#ifdef HAVE_CONFIG_H
20#include <config.h>
21#endif
b445142a 22
9f797243 23#include <stdio.h>
08b1c66e 24#include <lttv/module.h>
b445142a 25#include <lttv/stats.h>
2a2fa4f0 26#include <lttv/lttv.h>
f95bc830 27#include <lttv/attribute.h>
b445142a 28#include <ltt/facility.h>
29#include <ltt/trace.h>
30#include <ltt/event.h>
826f1ab2 31#include <ltt/type.h>
b445142a 32
9f797243 33#define BUF_SIZE 256
34
b445142a 35GQuark
36 LTTV_STATS_PROCESS_UNKNOWN,
37 LTTV_STATS_PROCESSES,
38 LTTV_STATS_CPU,
39 LTTV_STATS_MODE_TYPES,
40 LTTV_STATS_MODES,
41 LTTV_STATS_SUBMODES,
42 LTTV_STATS_EVENT_TYPES,
43 LTTV_STATS_CPU_TIME,
44 LTTV_STATS_ELAPSED_TIME,
45 LTTV_STATS_EVENTS,
f95bc830 46 LTTV_STATS_EVENTS_COUNT,
47 LTTV_STATS_USE_COUNT,
48 LTTV_STATS,
49 LTTV_STATS_TRACEFILES,
50 LTTV_STATS_SUMMED;
b445142a 51
52static GQuark
53 LTTV_STATS_BEFORE_HOOKS,
54 LTTV_STATS_AFTER_HOOKS;
55
b445142a 56static void
00e74b69 57find_event_tree(LttvTracefileStats *tfcs, GQuark pid_time, GQuark cpu,
b445142a 58 GQuark mode, GQuark sub_mode, LttvAttribute **events_tree,
59 LttvAttribute **event_types_tree);
60
61static void
62init(LttvTracesetStats *self, LttvTraceset *ts)
63{
dbb7bb09 64 guint i, j, nb_trace, nb_tracefile;
b445142a 65
66 LttvTraceContext *tc;
67
68 LttvTraceStats *tcs;
69
70 LttvTracefileContext *tfc;
71
3c9bb8b1 72 LttvTracefileContext **tfs;
b445142a 73 LttvTracefileStats *tfcs;
74
75 LttTime timestamp = {0,0};
76
f95bc830 77 LttvAttributeValue v;
78
79 LttvAttribute
80 *stats_tree,
81 *tracefiles_stats;
82
b445142a 83 LTTV_TRACESET_CONTEXT_CLASS(g_type_class_peek(LTTV_TRACESET_STATE_TYPE))->
84 init((LttvTracesetContext *)self, ts);
85
d3e01c7a 86 self->stats = lttv_attribute_find_subdir(
87 lttv_traceset_attribute(self->parent.parent.ts),
88 LTTV_STATS);
89 lttv_attribute_find(lttv_traceset_attribute(self->parent.parent.ts),
90 LTTV_STATS_USE_COUNT,
91 LTTV_UINT, &v);
f95bc830 92
93 *(v.v_uint)++;
94 if(*(v.v_uint) == 1) {
95 g_assert(lttv_attribute_get_number(self->stats) == 0);
96 }
97
b445142a 98 nb_trace = lttv_traceset_number(ts);
99
100 for(i = 0 ; i < nb_trace ; i++) {
021eeb41 101 tc = self->parent.parent.traces[i];
102 tcs = LTTV_TRACE_STATS(tc);
f95bc830 103
104 tcs->stats = lttv_attribute_find_subdir(tcs->parent.parent.t_a,LTTV_STATS);
105 tracefiles_stats = lttv_attribute_find_subdir(tcs->parent.parent.t_a,
106 LTTV_STATS_TRACEFILES);
107 lttv_attribute_find(tcs->parent.parent.t_a, LTTV_STATS_USE_COUNT,
108 LTTV_UINT, &v);
109
110 *(v.v_uint)++;
111 if(*(v.v_uint) == 1) {
112 g_assert(lttv_attribute_get_number(tcs->stats) == 0);
113 }
b445142a 114
eed2ef37 115 nb_tracefile = tc->tracefiles->len;
b445142a 116
dbb7bb09 117 for(j = 0 ; j < nb_tracefile ; j++) {
3c9bb8b1 118 tfs = &g_array_index(tc->tracefiles,
119 LttvTracefileContext*, j);
120 tfcs = LTTV_TRACEFILE_STATS(*tfs);
f95bc830 121 tfcs->stats = lttv_attribute_find_subdir(tracefiles_stats,
122 tfcs->parent.cpu_name);
b445142a 123 find_event_tree(tfcs, LTTV_STATS_PROCESS_UNKNOWN,
124 tfcs->parent.cpu_name, LTTV_STATE_MODE_UNKNOWN,
125 LTTV_STATE_SUBMODE_UNKNOWN, &tfcs->current_events_tree,
126 &tfcs->current_event_types_tree);
127 }
128 }
129}
130
b445142a 131static void
132fini(LttvTracesetStats *self)
133{
134 guint i, j, nb_trace, nb_tracefile;
135
136 LttvTraceset *ts;
137
138 LttvTraceContext *tc;
139
140 LttvTraceStats *tcs;
141
142 LttvTracefileContext *tfc;
143
144 LttvTracefileStats *tfcs;
145
146 LttTime timestamp = {0,0};
147
f95bc830 148 LttvAttributeValue v;
149
150 LttvAttribute *tracefiles_stats;
151
152 lttv_attribute_find(self->parent.parent.ts_a, LTTV_STATS_USE_COUNT,
153 LTTV_UINT, &v);
154 *(v.v_uint)--;
155
156 if(*(v.v_uint) == 0) {
157 lttv_attribute_remove_by_name(self->parent.parent.ts_a, LTTV_STATS);
f95bc830 158 }
159 self->stats = NULL;
160
b445142a 161 ts = self->parent.parent.ts;
162 nb_trace = lttv_traceset_number(ts);
163
164 for(i = 0 ; i < nb_trace ; i++) {
f95bc830 165 tcs = (LttvTraceStats *)(tc = (LTTV_TRACESET_CONTEXT(self)->traces[i]));
166
167 lttv_attribute_find(tcs->parent.parent.t_a, LTTV_STATS_USE_COUNT,
168 LTTV_UINT, &v);
169 *(v.v_uint)--;
170
171 if(*(v.v_uint) == 0) {
172 lttv_attribute_remove_by_name(tcs->parent.parent.t_a,LTTV_STATS);
f95bc830 173 tracefiles_stats = lttv_attribute_find_subdir(tcs->parent.parent.t_a,
174 LTTV_STATS_TRACEFILES);
175 lttv_attribute_remove_by_name(tcs->parent.parent.t_a,
176 LTTV_STATS_TRACEFILES);
f95bc830 177 }
178 tcs->stats = NULL;
b445142a 179
eed2ef37 180 nb_tracefile = tc->tracefiles->len;
b445142a 181
b445142a 182 for(j = 0 ; j < nb_tracefile ; j++) {
cb03932a 183 tfc = g_array_index(tc->tracefiles,
184 LttvTracefileContext*, j);
359b2948 185 tfcs = (LttvTracefileStats *)tfc;
f95bc830 186 tfcs->stats = NULL;
b445142a 187 tfcs->current_events_tree = NULL;
188 tfcs->current_event_types_tree = NULL;
189 }
190 }
191 LTTV_TRACESET_CONTEXT_CLASS(g_type_class_peek(LTTV_TRACESET_STATE_TYPE))->
192 fini((LttvTracesetContext *)self);
193}
194
195
196static LttvTracesetContext *
197new_traceset_context(LttvTracesetContext *self)
198{
199 return LTTV_TRACESET_CONTEXT(g_object_new(LTTV_TRACESET_STATS_TYPE, NULL));
200}
201
202
203static LttvTraceContext *
204new_trace_context(LttvTracesetContext *self)
205{
206 return LTTV_TRACE_CONTEXT(g_object_new(LTTV_TRACE_STATS_TYPE, NULL));
207}
208
209
210static LttvTracefileContext *
211new_tracefile_context(LttvTracesetContext *self)
212{
213 return LTTV_TRACEFILE_CONTEXT(g_object_new(LTTV_TRACEFILE_STATS_TYPE, NULL));
214}
215
216
217static void
218traceset_stats_instance_init (GTypeInstance *instance, gpointer g_class)
219{
220}
221
222
223static void
224traceset_stats_finalize (LttvTracesetStats *self)
225{
226 G_OBJECT_CLASS(g_type_class_peek(LTTV_TRACESET_STATE_TYPE))->
227 finalize(G_OBJECT(self));
228}
229
230
231static void
232traceset_stats_class_init (LttvTracesetContextClass *klass)
233{
234 GObjectClass *gobject_class = G_OBJECT_CLASS(klass);
235
236 gobject_class->finalize = (void (*)(GObject *self)) traceset_stats_finalize;
237 klass->init = (void (*)(LttvTracesetContext *self, LttvTraceset *ts))init;
238 klass->fini = (void (*)(LttvTracesetContext *self))fini;
239 klass->new_traceset_context = new_traceset_context;
240 klass->new_trace_context = new_trace_context;
241 klass->new_tracefile_context = new_tracefile_context;
242}
243
244
245GType
246lttv_traceset_stats_get_type(void)
247{
248 static GType type = 0;
249 if (type == 0) {
250 static const GTypeInfo info = {
251 sizeof (LttvTracesetStatsClass),
252 NULL, /* base_init */
253 NULL, /* base_finalize */
254 (GClassInitFunc) traceset_stats_class_init, /* class_init */
255 NULL, /* class_finalize */
256 NULL, /* class_data */
dbb7bb09 257 sizeof (LttvTracesetStats),
b445142a 258 0, /* n_preallocs */
00e74b69 259 (GInstanceInitFunc) traceset_stats_instance_init, /* instance_init */
260 NULL /* Value handling */
b445142a 261 };
262
00e74b69 263 type = g_type_register_static (LTTV_TRACESET_STATE_TYPE,
264 "LttvTracesetStatsType",
265 &info, 0);
b445142a 266 }
267 return type;
268}
269
270
271static void
272trace_stats_instance_init (GTypeInstance *instance, gpointer g_class)
273{
274}
275
276
277static void
278trace_stats_finalize (LttvTraceStats *self)
279{
280 G_OBJECT_CLASS(g_type_class_peek(LTTV_TRACE_STATE_TYPE))->
281 finalize(G_OBJECT(self));
282}
283
284
285static void
286trace_stats_class_init (LttvTraceContextClass *klass)
287{
288 GObjectClass *gobject_class = G_OBJECT_CLASS(klass);
289
290 gobject_class->finalize = (void (*)(GObject *self)) trace_stats_finalize;
291}
292
293
294GType
295lttv_trace_stats_get_type(void)
296{
297 static GType type = 0;
298 if (type == 0) {
299 static const GTypeInfo info = {
300 sizeof (LttvTraceStatsClass),
301 NULL, /* base_init */
302 NULL, /* base_finalize */
303 (GClassInitFunc) trace_stats_class_init, /* class_init */
304 NULL, /* class_finalize */
305 NULL, /* class_data */
306 sizeof (LttvTraceStats),
307 0, /* n_preallocs */
00e74b69 308 (GInstanceInitFunc) trace_stats_instance_init, /* instance_init */
309 NULL /* Value handling */
b445142a 310 };
311
312 type = g_type_register_static (LTTV_TRACE_STATE_TYPE,
313 "LttvTraceStatsType", &info, 0);
314 }
315 return type;
316}
317
318
319static void
320tracefile_stats_instance_init (GTypeInstance *instance, gpointer g_class)
321{
322}
323
324
325static void
326tracefile_stats_finalize (LttvTracefileStats *self)
327{
328 G_OBJECT_CLASS(g_type_class_peek(LTTV_TRACEFILE_STATE_TYPE))->
329 finalize(G_OBJECT(self));
330}
331
332
333static void
334tracefile_stats_class_init (LttvTracefileStatsClass *klass)
335{
336 GObjectClass *gobject_class = G_OBJECT_CLASS(klass);
337
338 gobject_class->finalize = (void (*)(GObject *self)) tracefile_stats_finalize;
339}
340
341
342GType
343lttv_tracefile_stats_get_type(void)
344{
345 static GType type = 0;
346 if (type == 0) {
347 static const GTypeInfo info = {
348 sizeof (LttvTracefileStatsClass),
349 NULL, /* base_init */
350 NULL, /* base_finalize */
351 (GClassInitFunc) tracefile_stats_class_init, /* class_init */
352 NULL, /* class_finalize */
353 NULL, /* class_data */
354 sizeof (LttvTracefileStats),
355 0, /* n_preallocs */
00e74b69 356 (GInstanceInitFunc) tracefile_stats_instance_init, /* instance_init */
357 NULL /* Value handling */
b445142a 358 };
359
360 type = g_type_register_static (LTTV_TRACEFILE_STATE_TYPE,
361 "LttvTracefileStatsType", &info, 0);
362 }
363 return type;
364}
365
366
367static void
00e74b69 368find_event_tree(LttvTracefileStats *tfcs,
369 GQuark pid_time,
370 GQuark cpu,
371 GQuark mode,
372 GQuark sub_mode,
373 LttvAttribute **events_tree,
374 LttvAttribute **event_types_tree)
b445142a 375{
376 LttvAttribute *a;
377
3c9bb8b1 378 LttvTraceStats *tcs = (LttvTraceStats*)tfcs->parent.parent.t_context;
b445142a 379 a = lttv_attribute_find_subdir(tcs->stats, LTTV_STATS_PROCESSES);
00e74b69 380 a = lttv_attribute_find_subdir(a, pid_time);
b445142a 381 a = lttv_attribute_find_subdir(a, LTTV_STATS_CPU);
00e74b69 382 a = lttv_attribute_find_subdir(a, cpu);
b445142a 383 a = lttv_attribute_find_subdir(a, LTTV_STATS_MODE_TYPES);
00e74b69 384 a = lttv_attribute_find_subdir(a, mode);
b445142a 385 a = lttv_attribute_find_subdir(a, LTTV_STATS_SUBMODES);
00e74b69 386 a = lttv_attribute_find_subdir(a, sub_mode);
b445142a 387 *events_tree = a;
388 a = lttv_attribute_find_subdir(a, LTTV_STATS_EVENT_TYPES);
389 *event_types_tree = a;
390}
391
392
393static void update_event_tree(LttvTracefileStats *tfcs)
394{
395 LttvExecutionState *es = tfcs->parent.process->state;
396
00e74b69 397 find_event_tree(tfcs, tfcs->parent.process->pid_time,
398 tfcs->parent.cpu_name,
b445142a 399 es->t, es->n, &(tfcs->current_events_tree),
400 &(tfcs->current_event_types_tree));
401}
402
403
404static void mode_change(LttvTracefileStats *tfcs)
405{
406 LttvAttributeValue cpu_time;
407
408 LttTime delta;
409
410 lttv_attribute_find(tfcs->current_events_tree, LTTV_STATS_CPU_TIME,
411 LTTV_TIME, &cpu_time);
308711e5 412 delta = ltt_time_sub(tfcs->parent.parent.timestamp,
b445142a 413 tfcs->parent.process->state->change);
308711e5 414 *(cpu_time.v_time) = ltt_time_add(*(cpu_time.v_time), delta);
b445142a 415}
416
417
418static void mode_end(LttvTracefileStats *tfcs)
419{
420 LttvAttributeValue elapsed_time, cpu_time;
421
422 LttTime delta;
423
424 lttv_attribute_find(tfcs->current_events_tree, LTTV_STATS_ELAPSED_TIME,
425 LTTV_TIME, &elapsed_time);
308711e5 426 delta = ltt_time_sub(tfcs->parent.parent.timestamp,
b445142a 427 tfcs->parent.process->state->entry);
308711e5 428 *(elapsed_time.v_time) = ltt_time_add(*(elapsed_time.v_time), delta);
b445142a 429
430 lttv_attribute_find(tfcs->current_events_tree, LTTV_STATS_CPU_TIME,
431 LTTV_TIME, &cpu_time);
308711e5 432 delta = ltt_time_sub(tfcs->parent.parent.timestamp,
b445142a 433 tfcs->parent.process->state->change);
308711e5 434 *(cpu_time.v_time) = ltt_time_add(*(cpu_time.v_time), delta);
b445142a 435}
436
437
438static gboolean before_syscall_entry(void *hook_data, void *call_data)
439{
440 mode_change((LttvTracefileStats *)call_data);
441 return FALSE;
442}
443
444
445static gboolean after_syscall_entry(void *hook_data, void *call_data)
446{
447 update_event_tree((LttvTracefileStats *)call_data);
448 return FALSE;
449}
450
451
452gboolean before_syscall_exit(void *hook_data, void *call_data)
453{
454 mode_end((LttvTracefileStats *)call_data);
455 return FALSE;
456}
457
458
459static gboolean after_syscall_exit(void *hook_data, void *call_data)
460{
461 update_event_tree((LttvTracefileStats *)call_data);
462 return FALSE;
463}
464
465
466gboolean before_trap_entry(void *hook_data, void *call_data)
467{
468 mode_change((LttvTracefileStats *)call_data);
469 return FALSE;
470}
471
472
473static gboolean after_trap_entry(void *hook_data, void *call_data)
474{
475 update_event_tree((LttvTracefileStats *)call_data);
476 return FALSE;
477}
478
479
480gboolean before_trap_exit(void *hook_data, void *call_data)
481{
482 mode_end((LttvTracefileStats *)call_data);
483 return FALSE;
484}
485
486
487gboolean after_trap_exit(void *hook_data, void *call_data)
488{
489 update_event_tree((LttvTracefileStats *)call_data);
490 return FALSE;
491}
492
493
494gboolean before_irq_entry(void *hook_data, void *call_data)
495{
496 mode_change((LttvTracefileStats *)call_data);
497 return FALSE;
498}
499
500
501gboolean after_irq_entry(void *hook_data, void *call_data)
502{
503 update_event_tree((LttvTracefileStats *)call_data);
504 return FALSE;
505}
506
507
508gboolean before_irq_exit(void *hook_data, void *call_data)
509{
510 mode_end((LttvTracefileStats *)call_data);
511 return FALSE;
512}
513
514
515gboolean after_irq_exit(void *hook_data, void *call_data)
516{
517 update_event_tree((LttvTracefileStats *)call_data);
518 return FALSE;
519}
520
521
522gboolean before_schedchange(void *hook_data, void *call_data)
523{
b445142a 524 LttvTracefileStats *tfcs = (LttvTracefileStats *)call_data;
525
eed2ef37 526 LttEvent *e = ltt_tracefile_get_event(tfcs->parent.parent.tf);
527
d052ffc3 528 LttvTraceHookByFacility *thf = (LttvTraceHookByFacility *)hook_data;
eed2ef37 529
d7cf605c 530 guint pid_in, pid_out;
531
532 gint state_out;
b445142a 533
534 LttvProcessState *process;
535
eed2ef37 536 pid_out = ltt_event_get_unsigned(e, thf->f1);
537 pid_in = ltt_event_get_unsigned(e, thf->f2);
d7cf605c 538 state_out = ltt_event_get_int(e, thf->f3);
b445142a 539
540 /* compute the time for the process to schedule out */
541
542 mode_change(tfcs);
543
544 /* get the information for the process scheduled in */
545
2a2fa4f0 546 process = lttv_state_find_process_or_create(&(tfcs->parent), pid_in);
b445142a 547
548 find_event_tree(tfcs, process->pid_time, tfcs->parent.cpu_name,
549 process->state->t, process->state->n, &(tfcs->current_events_tree),
550 &(tfcs->current_event_types_tree));
551
552 /* compute the time waiting for the process to schedule in */
553
554 mode_change(tfcs);
555 return FALSE;
556}
557
558
559gboolean process_fork(void *hook_data, void *call_data)
560{
561 /* nothing to do for now */
562 return FALSE;
563}
564
565
566gboolean process_exit(void *hook_data, void *call_data)
567{
568 /* We should probably exit all modes here or we could do that at
569 schedule out. */
570 return FALSE;
571}
572
eed2ef37 573gboolean process_free(void *hook_data, void *call_data)
574{
575 return FALSE;
576}
b445142a 577
578gboolean every_event(void *hook_data, void *call_data)
579{
580 LttvTracefileStats *tfcs = (LttvTracefileStats *)call_data;
581
eed2ef37 582 LttEvent *e = ltt_tracefile_get_event(tfcs->parent.parent.tf);
583
b445142a 584 LttvAttributeValue v;
585
586 /* The current branch corresponds to the tracefile/process/interrupt state.
587 Statistics are added within it, to count the number of events of this
588 type occuring in this context. A quark has been pre-allocated for each
589 event type and is used as name. */
590
591 lttv_attribute_find(tfcs->current_event_types_tree,
eed2ef37 592 ltt_eventtype_name(ltt_event_eventtype(e)),
b445142a 593 LTTV_UINT, &v);
594 (*(v.v_uint))++;
595 return FALSE;
596}
597
598
f95bc830 599void
600lttv_stats_sum_trace(LttvTraceStats *self)
b445142a 601{
d3e01c7a 602 LttvAttribute *sum_container = self->stats;
b445142a 603
b445142a 604 LttvAttributeType type;
605
606 LttvAttributeValue value;
607
608 LttvAttributeName name;
609
610 unsigned sum;
611
f95bc830 612 int i, j, k, l, m, nb_process, nb_cpu, nb_mode_type, nb_submode,
b445142a 613 nb_event_type;
614
615 LttvAttribute *main_tree, *processes_tree, *process_tree, *cpus_tree,
616 *cpu_tree, *mode_tree, *mode_types_tree, *submodes_tree,
617 *submode_tree, *event_types_tree, *mode_events_tree,
618 *cpu_events_tree, *process_modes_tree, *trace_cpu_tree,
f95bc830 619 *trace_modes_tree;
620
d3e01c7a 621 main_tree = sum_container;
f95bc830 622
d3e01c7a 623 lttv_attribute_find(sum_container,
624 LTTV_STATS_SUMMED,
625 LTTV_UINT, &value);
f95bc830 626 if(*(value.v_uint) != 0) return;
627 *(value.v_uint) = 1;
628
629 processes_tree = lttv_attribute_find_subdir(main_tree,
d3e01c7a 630 LTTV_STATS_PROCESSES);
631 trace_modes_tree = lttv_attribute_find_subdir(main_tree,
632 LTTV_STATS_MODES);
f95bc830 633 nb_process = lttv_attribute_get_number(processes_tree);
634
635 for(i = 0 ; i < nb_process ; i++) {
636 type = lttv_attribute_get(processes_tree, i, &name, &value);
637 process_tree = LTTV_ATTRIBUTE(*(value.v_gobject));
638
639 cpus_tree = lttv_attribute_find_subdir(process_tree, LTTV_STATS_CPU);
640 process_modes_tree = lttv_attribute_find_subdir(process_tree,
641 LTTV_STATS_MODES);
642 nb_cpu = lttv_attribute_get_number(cpus_tree);
643
644 for(j = 0 ; j < nb_cpu ; j++) {
645 type = lttv_attribute_get(cpus_tree, j, &name, &value);
646 cpu_tree = LTTV_ATTRIBUTE(*(value.v_gobject));
647
648 mode_types_tree = lttv_attribute_find_subdir(cpu_tree,
649 LTTV_STATS_MODE_TYPES);
650 cpu_events_tree = lttv_attribute_find_subdir(cpu_tree,
651 LTTV_STATS_EVENTS);
652 trace_cpu_tree = lttv_attribute_find_subdir(main_tree, LTTV_STATS_CPU);
653 trace_cpu_tree = lttv_attribute_find_subdir(trace_cpu_tree, name);
654 nb_mode_type = lttv_attribute_get_number(mode_types_tree);
655
656 for(k = 0 ; k < nb_mode_type ; k++) {
657 type = lttv_attribute_get(mode_types_tree, k, &name, &value);
658 mode_tree = LTTV_ATTRIBUTE(*(value.v_gobject));
659
660 submodes_tree = lttv_attribute_find_subdir(mode_tree,
661 LTTV_STATS_SUBMODES);
662 mode_events_tree = lttv_attribute_find_subdir(mode_tree,
663 LTTV_STATS_EVENTS);
664 nb_submode = lttv_attribute_get_number(submodes_tree);
b445142a 665
f95bc830 666 for(l = 0 ; l < nb_submode ; l++) {
667 type = lttv_attribute_get(submodes_tree, l, &name, &value);
668 submode_tree = LTTV_ATTRIBUTE(*(value.v_gobject));
b445142a 669
f95bc830 670 event_types_tree = lttv_attribute_find_subdir(submode_tree,
671 LTTV_STATS_EVENT_TYPES);
672 nb_event_type = lttv_attribute_get_number(event_types_tree);
b445142a 673
f95bc830 674 sum = 0;
675 for(m = 0 ; m < nb_event_type ; m++) {
676 type = lttv_attribute_get(event_types_tree, m, &name, &value);
677 sum += *(value.v_uint);
b445142a 678 }
f95bc830 679 lttv_attribute_find(submode_tree, LTTV_STATS_EVENTS_COUNT,
680 LTTV_UINT, &value);
681 *(value.v_uint) = sum;
682 lttv_attribute_recursive_add(mode_events_tree, submode_tree);
b445142a 683 }
f95bc830 684 lttv_attribute_recursive_add(cpu_events_tree, mode_events_tree);
b445142a 685 }
f95bc830 686 lttv_attribute_recursive_add(process_modes_tree, cpu_tree);
687 lttv_attribute_recursive_add(trace_cpu_tree, cpu_tree);
b445142a 688 }
f95bc830 689 lttv_attribute_recursive_add(trace_modes_tree, process_modes_tree);
690 }
691}
692
693
d3e01c7a 694gboolean lttv_stats_sum_traceset_hook(void *hook_data, void *call_data)
695{
696 lttv_stats_sum_traceset((LttvTracesetStats *)call_data);
697 return 0;
698}
699
f95bc830 700void
701lttv_stats_sum_traceset(LttvTracesetStats *self)
702{
703 LttvTraceset *traceset = self->parent.parent.ts;
d3e01c7a 704 LttvAttribute *sum_container = self->stats;
f95bc830 705
706 LttvTraceStats *tcs;
707
708 int i, nb_trace;
709
710 LttvAttribute *main_tree, *trace_modes_tree, *traceset_modes_tree;
711
712 LttvAttributeValue value;
713
d3e01c7a 714 lttv_attribute_find(sum_container, LTTV_STATS_SUMMED,
f95bc830 715 LTTV_UINT, &value);
716 if(*(value.v_uint) != 0) return;
717 *(value.v_uint) = 1;
718
d3e01c7a 719 traceset_modes_tree = lttv_attribute_find_subdir(sum_container,
f95bc830 720 LTTV_STATS_MODES);
721 nb_trace = lttv_traceset_number(traceset);
722
723 for(i = 0 ; i < nb_trace ; i++) {
724 tcs = (LttvTraceStats *)(self->parent.parent.traces[i]);
725 lttv_stats_sum_trace(tcs);
726 main_tree = tcs->stats;
727 trace_modes_tree = lttv_attribute_find_subdir(main_tree, LTTV_STATS_MODES);
b445142a 728 lttv_attribute_recursive_add(traceset_modes_tree, trace_modes_tree);
729 }
b445142a 730}
731
732
d3e01c7a 733// Hook wrapper. call_data is a traceset context.
00e74b69 734gboolean lttv_stats_hook_add_event_hooks(void *hook_data, void *call_data)
d3e01c7a 735{
736 LttvTracesetStats *tss = (LttvTracesetStats*)call_data;
737
738 lttv_stats_add_event_hooks(tss);
739
740 return 0;
741}
742
00e74b69 743void lttv_stats_add_event_hooks(LttvTracesetStats *self)
b445142a 744{
745 LttvTraceset *traceset = self->parent.parent.ts;
746
eed2ef37 747 guint i, j, k, l, nb_trace, nb_tracefile;
b445142a 748
b445142a 749 LttvTraceStats *ts;
750
751 LttvTracefileStats *tfs;
752
b445142a 753 GArray *hooks, *before_hooks, *after_hooks;
754
eed2ef37 755 LttvTraceHook *hook;
756
757 LttvTraceHookByFacility *thf;
b445142a 758
759 LttvAttributeValue val;
760
9d239bd9 761 gint ret;
762
b445142a 763 nb_trace = lttv_traceset_number(traceset);
764 for(i = 0 ; i < nb_trace ; i++) {
765 ts = (LttvTraceStats *)self->parent.parent.traces[i];
766
767 /* Find the eventtype id for the following events and register the
768 associated by id hooks. */
769
eed2ef37 770 hooks = g_array_sized_new(FALSE, FALSE, sizeof(LttvTraceHook), 7);
b445142a 771 g_array_set_size(hooks, 7);
772
9d239bd9 773 ret = lttv_trace_find_hook(ts->parent.parent.t,
eed2ef37 774 LTT_FACILITY_KERNEL, LTT_EVENT_SYSCALL_ENTRY,
775 LTT_FIELD_SYSCALL_ID, 0, 0,
776 before_syscall_entry,
b445142a 777 &g_array_index(hooks, LttvTraceHook, 0));
9d239bd9 778 g_assert(!ret);
b445142a 779
9d239bd9 780 ret = lttv_trace_find_hook(ts->parent.parent.t,
eed2ef37 781 LTT_FACILITY_KERNEL, LTT_EVENT_SYSCALL_EXIT,
782 0, 0, 0,
783 before_syscall_exit,
b445142a 784 &g_array_index(hooks, LttvTraceHook, 1));
9d239bd9 785 g_assert(!ret);
b445142a 786
9d239bd9 787 ret = lttv_trace_find_hook(ts->parent.parent.t,
eed2ef37 788 LTT_FACILITY_KERNEL, LTT_EVENT_TRAP_ENTRY,
789 LTT_FIELD_TRAP_ID, 0, 0,
790 before_trap_entry,
b445142a 791 &g_array_index(hooks, LttvTraceHook, 2));
9d239bd9 792 g_assert(!ret);
b445142a 793
9d239bd9 794 ret = lttv_trace_find_hook(ts->parent.parent.t,
eed2ef37 795 LTT_FACILITY_KERNEL, LTT_EVENT_TRAP_EXIT,
796 0, 0, 0,
797 before_trap_exit, &g_array_index(hooks, LttvTraceHook, 3));
9d239bd9 798 g_assert(!ret);
eed2ef37 799
9d239bd9 800 ret = lttv_trace_find_hook(ts->parent.parent.t,
eed2ef37 801 LTT_FACILITY_KERNEL, LTT_EVENT_IRQ_ENTRY,
802 LTT_FIELD_IRQ_ID, 0, 0,
803 before_irq_entry, &g_array_index(hooks, LttvTraceHook, 4));
9d239bd9 804 g_assert(!ret);
eed2ef37 805
9d239bd9 806 ret = lttv_trace_find_hook(ts->parent.parent.t,
eed2ef37 807 LTT_FACILITY_KERNEL, LTT_EVENT_IRQ_EXIT,
808 0, 0, 0,
809 before_irq_exit, &g_array_index(hooks, LttvTraceHook, 5));
9d239bd9 810 g_assert(!ret);
eed2ef37 811
9d239bd9 812 ret = lttv_trace_find_hook(ts->parent.parent.t,
eed2ef37 813 LTT_FACILITY_PROCESS, LTT_EVENT_SCHEDCHANGE,
814 LTT_FIELD_OUT, LTT_FIELD_IN, LTT_FIELD_OUT_STATE,
815 before_schedchange,
816 &g_array_index(hooks, LttvTraceHook, 6));
9d239bd9 817 g_assert(!ret);
b445142a 818
819 before_hooks = hooks;
820
eed2ef37 821 hooks = g_array_sized_new(FALSE, FALSE, sizeof(LttvTraceHook), 9);
822 g_array_set_size(hooks, 9);
b445142a 823
9d239bd9 824 ret = lttv_trace_find_hook(ts->parent.parent.t,
eed2ef37 825 LTT_FACILITY_KERNEL, LTT_EVENT_SYSCALL_ENTRY,
826 LTT_FIELD_SYSCALL_ID, 0, 0,
827 after_syscall_entry,
b445142a 828 &g_array_index(hooks, LttvTraceHook, 0));
9d239bd9 829 g_assert(!ret);
b445142a 830
9d239bd9 831 ret = lttv_trace_find_hook(ts->parent.parent.t,
eed2ef37 832 LTT_FACILITY_KERNEL, LTT_EVENT_SYSCALL_EXIT,
833 0, 0, 0,
834 after_syscall_exit,
b445142a 835 &g_array_index(hooks, LttvTraceHook, 1));
9d239bd9 836 g_assert(!ret);
b445142a 837
9d239bd9 838 ret = lttv_trace_find_hook(ts->parent.parent.t,
eed2ef37 839 LTT_FACILITY_KERNEL, LTT_EVENT_TRAP_ENTRY,
840 LTT_FIELD_TRAP_ID, 0, 0,
841 after_trap_entry, &g_array_index(hooks, LttvTraceHook, 2));
9d239bd9 842 g_assert(!ret);
eed2ef37 843
9d239bd9 844 ret = lttv_trace_find_hook(ts->parent.parent.t,
eed2ef37 845 LTT_FACILITY_KERNEL, LTT_EVENT_TRAP_EXIT,
846 0, 0, 0,
847 after_trap_exit, &g_array_index(hooks, LttvTraceHook, 3));
9d239bd9 848 g_assert(!ret);
b445142a 849
9d239bd9 850 ret = lttv_trace_find_hook(ts->parent.parent.t,
eed2ef37 851 LTT_FACILITY_KERNEL, LTT_EVENT_IRQ_ENTRY,
852 LTT_FIELD_IRQ_ID, 0, 0,
853 after_irq_entry, &g_array_index(hooks, LttvTraceHook, 4));
9d239bd9 854 g_assert(!ret);
b445142a 855
9d239bd9 856 ret = lttv_trace_find_hook(ts->parent.parent.t,
eed2ef37 857 LTT_FACILITY_KERNEL, LTT_EVENT_IRQ_EXIT,
858 0, 0, 0,
859 after_irq_exit, &g_array_index(hooks, LttvTraceHook, 5));
9d239bd9 860 g_assert(!ret);
b445142a 861
b445142a 862
9d239bd9 863 ret = lttv_trace_find_hook(ts->parent.parent.t,
eed2ef37 864 LTT_FACILITY_PROCESS, LTT_EVENT_FORK,
865 LTT_FIELD_PARENT_PID, LTT_FIELD_CHILD_PID, 0,
866 process_fork,
b445142a 867 &g_array_index(hooks, LttvTraceHook, 6));
9d239bd9 868 g_assert(!ret);
b445142a 869
9d239bd9 870 ret = lttv_trace_find_hook(ts->parent.parent.t,
eed2ef37 871 LTT_FACILITY_PROCESS, LTT_EVENT_EXIT,
872 LTT_FIELD_PID, 0, 0,
873 process_exit, &g_array_index(hooks, LttvTraceHook, 7));
9d239bd9 874 g_assert(!ret);
eed2ef37 875
9d239bd9 876 ret = lttv_trace_find_hook(ts->parent.parent.t,
eed2ef37 877 LTT_FACILITY_PROCESS, LTT_EVENT_FREE,
878 LTT_FIELD_PID, 0, 0,
d7cf605c 879 process_free, &g_array_index(hooks, LttvTraceHook, 8));
9d239bd9 880 g_assert(!ret);
eed2ef37 881
b445142a 882
883 after_hooks = hooks;
884
359b2948 885 /* Add these hooks to each event_by_id hooks list */
b445142a 886
eed2ef37 887 nb_tracefile = ts->parent.parent.tracefiles->len;
b445142a 888
dbb7bb09 889 for(j = 0 ; j < nb_tracefile ; j++) {
d7cf605c 890 tfs = LTTV_TRACEFILE_STATS(g_array_index(ts->parent.parent.tracefiles,
891 LttvTracefileContext*, j));
359b2948 892 lttv_hooks_add(tfs->parent.parent.event, every_event, NULL,
893 LTTV_PRIO_DEFAULT);
b445142a 894
895 for(k = 0 ; k < before_hooks->len ; k++) {
eed2ef37 896 hook = &g_array_index(before_hooks, LttvTraceHook, k);
897 for(l = 0; l<hook->fac_list->len;l++) {
898 thf = g_array_index(hook->fac_list, LttvTraceHookByFacility*, l);
899 lttv_hooks_add(
900 lttv_hooks_by_id_find(tfs->parent.parent.event_by_id, thf->id),
901 thf->h,
d052ffc3 902 thf,
eed2ef37 903 LTTV_PRIO_STATS_BEFORE_STATE);
904 }
b445142a 905 }
906 for(k = 0 ; k < after_hooks->len ; k++) {
eed2ef37 907 hook = &g_array_index(after_hooks, LttvTraceHook, k);
908 for(l = 0; l<hook->fac_list->len;l++) {
909 thf = g_array_index(hook->fac_list, LttvTraceHookByFacility*, l);
910 lttv_hooks_add(
911 lttv_hooks_by_id_find(tfs->parent.parent.event_by_id, thf->id),
912 thf->h,
d052ffc3 913 thf,
eed2ef37 914 LTTV_PRIO_STATS_AFTER_STATE);
915 }
b445142a 916 }
917 }
918 lttv_attribute_find(self->parent.parent.a, LTTV_STATS_BEFORE_HOOKS,
919 LTTV_POINTER, &val);
920 *(val.v_pointer) = before_hooks;
921 lttv_attribute_find(self->parent.parent.a, LTTV_STATS_AFTER_HOOKS,
922 LTTV_POINTER, &val);
923 *(val.v_pointer) = after_hooks;
924 }
b445142a 925}
926
d3e01c7a 927// Hook wrapper. call_data is a traceset context.
00e74b69 928gboolean lttv_stats_hook_remove_event_hooks(void *hook_data, void *call_data)
d3e01c7a 929{
930 LttvTracesetStats *tss = (LttvTracesetStats*)call_data;
931
932 lttv_stats_remove_event_hooks(tss);
933
934 return 0;
935}
b445142a 936
00e74b69 937void lttv_stats_remove_event_hooks(LttvTracesetStats *self)
b445142a 938{
939 LttvTraceset *traceset = self->parent.parent.ts;
940
eed2ef37 941 guint i, j, k, l, nb_trace, nb_tracefile;
b445142a 942
943 LttvTraceStats *ts;
944
945 LttvTracefileStats *tfs;
946
947 void *hook_data;
948
949 GArray *before_hooks, *after_hooks;
950
eed2ef37 951 LttvTraceHook *hook;
952
953 LttvTraceHookByFacility *thf;
b445142a 954
955 LttvAttributeValue val;
956
957 nb_trace = lttv_traceset_number(traceset);
958 for(i = 0 ; i < nb_trace ; i++) {
ae80b609 959 ts = (LttvTraceStats*)self->parent.parent.traces[i];
b445142a 960 lttv_attribute_find(self->parent.parent.a, LTTV_STATS_BEFORE_HOOKS,
961 LTTV_POINTER, &val);
962 before_hooks = *(val.v_pointer);
963 lttv_attribute_find(self->parent.parent.a, LTTV_STATS_AFTER_HOOKS,
964 LTTV_POINTER, &val);
965 after_hooks = *(val.v_pointer);
966
359b2948 967 /* Remove these hooks from each event_by_id hooks list */
b445142a 968
eed2ef37 969 nb_tracefile = ts->parent.parent.tracefiles->len;
b445142a 970
dbb7bb09 971 for(j = 0 ; j < nb_tracefile ; j++) {
cb03932a 972 tfs = LTTV_TRACEFILE_STATS(g_array_index(ts->parent.parent.tracefiles,
973 LttvTracefileContext*, j));
359b2948 974 lttv_hooks_remove_data(tfs->parent.parent.event, every_event,
b445142a 975 NULL);
976
977 for(k = 0 ; k < before_hooks->len ; k++) {
eed2ef37 978 hook = &g_array_index(before_hooks, LttvTraceHook, k);
979 for(l = 0 ; l < hook->fac_list->len ; l++) {
980 thf = g_array_index(hook->fac_list, LttvTraceHookByFacility*, l);
981 lttv_hooks_remove_data(
982 lttv_hooks_by_id_find(tfs->parent.parent.event_by_id, thf->id),
983 thf->h,
d052ffc3 984 thf);
eed2ef37 985 }
b445142a 986 }
987 for(k = 0 ; k < after_hooks->len ; k++) {
eed2ef37 988 hook = &g_array_index(after_hooks, LttvTraceHook, k);
989 for(l = 0 ; l < hook->fac_list->len ; l++) {
990 thf = g_array_index(hook->fac_list, LttvTraceHookByFacility*, l);
991 lttv_hooks_remove_data(
992 lttv_hooks_by_id_find(tfs->parent.parent.event_by_id, thf->id),
993 thf->h,
d052ffc3 994 thf);
eed2ef37 995 }
b445142a 996 }
997 }
2a2fa4f0 998 g_debug("lttv_stats_remove_event_hooks()");
b445142a 999 g_array_free(before_hooks, TRUE);
1000 g_array_free(after_hooks, TRUE);
1001 }
9f797243 1002}
08b1c66e 1003
1004
1005static void module_init()
1006{
1007 LTTV_STATS_PROCESS_UNKNOWN = g_quark_from_string("unknown process");
1008 LTTV_STATS_PROCESSES = g_quark_from_string("processes");
1009 LTTV_STATS_CPU = g_quark_from_string("cpu");
1010 LTTV_STATS_MODE_TYPES = g_quark_from_string("mode_types");
1011 LTTV_STATS_MODES = g_quark_from_string("modes");
1012 LTTV_STATS_SUBMODES = g_quark_from_string("submodes");
1013 LTTV_STATS_EVENT_TYPES = g_quark_from_string("event_types");
1014 LTTV_STATS_CPU_TIME = g_quark_from_string("cpu time");
1015 LTTV_STATS_ELAPSED_TIME = g_quark_from_string("elapsed time");
1016 LTTV_STATS_EVENTS = g_quark_from_string("events");
1017 LTTV_STATS_EVENTS_COUNT = g_quark_from_string("events count");
1018 LTTV_STATS_BEFORE_HOOKS = g_quark_from_string("saved stats before hooks");
1019 LTTV_STATS_AFTER_HOOKS = g_quark_from_string("saved stats after hooks");
f95bc830 1020 LTTV_STATS_USE_COUNT = g_quark_from_string("stats_use_count");
1021 LTTV_STATS = g_quark_from_string("statistics");
1022 LTTV_STATS_TRACEFILES = g_quark_from_string("tracefiles statistics");
1023 LTTV_STATS_SUMMED = g_quark_from_string("statistics summed");
08b1c66e 1024}
1025
1026static void module_destroy()
1027{
1028}
1029
1030
1031LTTV_MODULE("stats", "Compute processes statistics", \
1032 "Accumulate statistics for event types, processes and CPUs", \
1033 module_init, module_destroy, "state");
f95bc830 1034
1035/* Change the places where stats are called (create/read/write stats)
1036
1037 Check for options in batchtest.c to reduce writing and see what tests are
1038 best candidates for performance analysis. Once OK, commit, move to main
1039 and run tests. Update the gui for statistics. */
This page took 0.075514 seconds and 4 git commands to generate.