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