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