fix unexisting trace error path
[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
eed2ef37 113 nb_tracefile = tc->tracefiles->len;
b445142a 114
dbb7bb09 115 for(j = 0 ; j < nb_tracefile ; j++) {
cb03932a 116 tfcs = LTTV_TRACEFILE_STATS(g_array_index(tc->tracefiles,
117 LttvTracefileContext*, 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
eed2ef37 177 nb_tracefile = tc->tracefiles->len;
b445142a 178
b445142a 179 for(j = 0 ; j < nb_tracefile ; j++) {
cb03932a 180 tfc = g_array_index(tc->tracefiles,
181 LttvTracefileContext*, j);
359b2948 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{
b445142a 521 LttvTracefileStats *tfcs = (LttvTracefileStats *)call_data;
522
eed2ef37 523 LttEvent *e = ltt_tracefile_get_event(tfcs->parent.parent.tf);
524
d052ffc3 525 LttvTraceHookByFacility *thf = (LttvTraceHookByFacility *)hook_data;
eed2ef37 526
d7cf605c 527 guint pid_in, pid_out;
528
529 gint state_out;
b445142a 530
531 LttvProcessState *process;
532
eed2ef37 533 pid_out = ltt_event_get_unsigned(e, thf->f1);
534 pid_in = ltt_event_get_unsigned(e, thf->f2);
d7cf605c 535 state_out = ltt_event_get_int(e, thf->f3);
b445142a 536
537 /* compute the time for the process to schedule out */
538
539 mode_change(tfcs);
540
541 /* get the information for the process scheduled in */
542
2a2fa4f0 543 process = lttv_state_find_process_or_create(&(tfcs->parent), pid_in);
b445142a 544
545 find_event_tree(tfcs, process->pid_time, tfcs->parent.cpu_name,
546 process->state->t, process->state->n, &(tfcs->current_events_tree),
547 &(tfcs->current_event_types_tree));
548
549 /* compute the time waiting for the process to schedule in */
550
551 mode_change(tfcs);
552 return FALSE;
553}
554
555
556gboolean process_fork(void *hook_data, void *call_data)
557{
558 /* nothing to do for now */
559 return FALSE;
560}
561
562
563gboolean process_exit(void *hook_data, void *call_data)
564{
565 /* We should probably exit all modes here or we could do that at
566 schedule out. */
567 return FALSE;
568}
569
eed2ef37 570gboolean process_free(void *hook_data, void *call_data)
571{
572 return FALSE;
573}
b445142a 574
575gboolean every_event(void *hook_data, void *call_data)
576{
577 LttvTracefileStats *tfcs = (LttvTracefileStats *)call_data;
578
eed2ef37 579 LttEvent *e = ltt_tracefile_get_event(tfcs->parent.parent.tf);
580
b445142a 581 LttvAttributeValue v;
582
583 /* The current branch corresponds to the tracefile/process/interrupt state.
584 Statistics are added within it, to count the number of events of this
585 type occuring in this context. A quark has been pre-allocated for each
586 event type and is used as name. */
587
588 lttv_attribute_find(tfcs->current_event_types_tree,
eed2ef37 589 ltt_eventtype_name(ltt_event_eventtype(e)),
b445142a 590 LTTV_UINT, &v);
591 (*(v.v_uint))++;
592 return FALSE;
593}
594
595
f95bc830 596void
597lttv_stats_sum_trace(LttvTraceStats *self)
b445142a 598{
d3e01c7a 599 LttvAttribute *sum_container = self->stats;
b445142a 600
b445142a 601 LttvAttributeType type;
602
603 LttvAttributeValue value;
604
605 LttvAttributeName name;
606
607 unsigned sum;
608
f95bc830 609 int i, j, k, l, m, nb_process, nb_cpu, nb_mode_type, nb_submode,
b445142a 610 nb_event_type;
611
612 LttvAttribute *main_tree, *processes_tree, *process_tree, *cpus_tree,
613 *cpu_tree, *mode_tree, *mode_types_tree, *submodes_tree,
614 *submode_tree, *event_types_tree, *mode_events_tree,
615 *cpu_events_tree, *process_modes_tree, *trace_cpu_tree,
f95bc830 616 *trace_modes_tree;
617
d3e01c7a 618 main_tree = sum_container;
f95bc830 619
d3e01c7a 620 lttv_attribute_find(sum_container,
621 LTTV_STATS_SUMMED,
622 LTTV_UINT, &value);
f95bc830 623 if(*(value.v_uint) != 0) return;
624 *(value.v_uint) = 1;
625
626 processes_tree = lttv_attribute_find_subdir(main_tree,
d3e01c7a 627 LTTV_STATS_PROCESSES);
628 trace_modes_tree = lttv_attribute_find_subdir(main_tree,
629 LTTV_STATS_MODES);
f95bc830 630 nb_process = lttv_attribute_get_number(processes_tree);
631
632 for(i = 0 ; i < nb_process ; i++) {
633 type = lttv_attribute_get(processes_tree, i, &name, &value);
634 process_tree = LTTV_ATTRIBUTE(*(value.v_gobject));
635
636 cpus_tree = lttv_attribute_find_subdir(process_tree, LTTV_STATS_CPU);
637 process_modes_tree = lttv_attribute_find_subdir(process_tree,
638 LTTV_STATS_MODES);
639 nb_cpu = lttv_attribute_get_number(cpus_tree);
640
641 for(j = 0 ; j < nb_cpu ; j++) {
642 type = lttv_attribute_get(cpus_tree, j, &name, &value);
643 cpu_tree = LTTV_ATTRIBUTE(*(value.v_gobject));
644
645 mode_types_tree = lttv_attribute_find_subdir(cpu_tree,
646 LTTV_STATS_MODE_TYPES);
647 cpu_events_tree = lttv_attribute_find_subdir(cpu_tree,
648 LTTV_STATS_EVENTS);
649 trace_cpu_tree = lttv_attribute_find_subdir(main_tree, LTTV_STATS_CPU);
650 trace_cpu_tree = lttv_attribute_find_subdir(trace_cpu_tree, name);
651 nb_mode_type = lttv_attribute_get_number(mode_types_tree);
652
653 for(k = 0 ; k < nb_mode_type ; k++) {
654 type = lttv_attribute_get(mode_types_tree, k, &name, &value);
655 mode_tree = LTTV_ATTRIBUTE(*(value.v_gobject));
656
657 submodes_tree = lttv_attribute_find_subdir(mode_tree,
658 LTTV_STATS_SUBMODES);
659 mode_events_tree = lttv_attribute_find_subdir(mode_tree,
660 LTTV_STATS_EVENTS);
661 nb_submode = lttv_attribute_get_number(submodes_tree);
b445142a 662
f95bc830 663 for(l = 0 ; l < nb_submode ; l++) {
664 type = lttv_attribute_get(submodes_tree, l, &name, &value);
665 submode_tree = LTTV_ATTRIBUTE(*(value.v_gobject));
b445142a 666
f95bc830 667 event_types_tree = lttv_attribute_find_subdir(submode_tree,
668 LTTV_STATS_EVENT_TYPES);
669 nb_event_type = lttv_attribute_get_number(event_types_tree);
b445142a 670
f95bc830 671 sum = 0;
672 for(m = 0 ; m < nb_event_type ; m++) {
673 type = lttv_attribute_get(event_types_tree, m, &name, &value);
674 sum += *(value.v_uint);
b445142a 675 }
f95bc830 676 lttv_attribute_find(submode_tree, LTTV_STATS_EVENTS_COUNT,
677 LTTV_UINT, &value);
678 *(value.v_uint) = sum;
679 lttv_attribute_recursive_add(mode_events_tree, submode_tree);
b445142a 680 }
f95bc830 681 lttv_attribute_recursive_add(cpu_events_tree, mode_events_tree);
b445142a 682 }
f95bc830 683 lttv_attribute_recursive_add(process_modes_tree, cpu_tree);
684 lttv_attribute_recursive_add(trace_cpu_tree, cpu_tree);
b445142a 685 }
f95bc830 686 lttv_attribute_recursive_add(trace_modes_tree, process_modes_tree);
687 }
688}
689
690
d3e01c7a 691gboolean lttv_stats_sum_traceset_hook(void *hook_data, void *call_data)
692{
693 lttv_stats_sum_traceset((LttvTracesetStats *)call_data);
694 return 0;
695}
696
f95bc830 697void
698lttv_stats_sum_traceset(LttvTracesetStats *self)
699{
700 LttvTraceset *traceset = self->parent.parent.ts;
d3e01c7a 701 LttvAttribute *sum_container = self->stats;
f95bc830 702
703 LttvTraceStats *tcs;
704
705 int i, nb_trace;
706
707 LttvAttribute *main_tree, *trace_modes_tree, *traceset_modes_tree;
708
709 LttvAttributeValue value;
710
d3e01c7a 711 lttv_attribute_find(sum_container, LTTV_STATS_SUMMED,
f95bc830 712 LTTV_UINT, &value);
713 if(*(value.v_uint) != 0) return;
714 *(value.v_uint) = 1;
715
d3e01c7a 716 traceset_modes_tree = lttv_attribute_find_subdir(sum_container,
f95bc830 717 LTTV_STATS_MODES);
718 nb_trace = lttv_traceset_number(traceset);
719
720 for(i = 0 ; i < nb_trace ; i++) {
721 tcs = (LttvTraceStats *)(self->parent.parent.traces[i]);
722 lttv_stats_sum_trace(tcs);
723 main_tree = tcs->stats;
724 trace_modes_tree = lttv_attribute_find_subdir(main_tree, LTTV_STATS_MODES);
b445142a 725 lttv_attribute_recursive_add(traceset_modes_tree, trace_modes_tree);
726 }
b445142a 727}
728
729
d3e01c7a 730// Hook wrapper. call_data is a traceset context.
00e74b69 731gboolean lttv_stats_hook_add_event_hooks(void *hook_data, void *call_data)
d3e01c7a 732{
733 LttvTracesetStats *tss = (LttvTracesetStats*)call_data;
734
735 lttv_stats_add_event_hooks(tss);
736
737 return 0;
738}
739
00e74b69 740void lttv_stats_add_event_hooks(LttvTracesetStats *self)
b445142a 741{
742 LttvTraceset *traceset = self->parent.parent.ts;
743
eed2ef37 744 guint i, j, k, l, nb_trace, nb_tracefile;
b445142a 745
746 LttFacility *f;
747
748 LttEventType *et;
749
750 LttvTraceStats *ts;
751
752 LttvTracefileStats *tfs;
753
754 void *hook_data;
755
756 GArray *hooks, *before_hooks, *after_hooks;
757
eed2ef37 758 LttvTraceHook *hook;
759
760 LttvTraceHookByFacility *thf;
b445142a 761
762 LttvAttributeValue val;
763
9d239bd9 764 gint ret;
765
b445142a 766 nb_trace = lttv_traceset_number(traceset);
767 for(i = 0 ; i < nb_trace ; i++) {
768 ts = (LttvTraceStats *)self->parent.parent.traces[i];
769
770 /* Find the eventtype id for the following events and register the
771 associated by id hooks. */
772
eed2ef37 773 hooks = g_array_sized_new(FALSE, FALSE, sizeof(LttvTraceHook), 7);
b445142a 774 g_array_set_size(hooks, 7);
775
9d239bd9 776 ret = lttv_trace_find_hook(ts->parent.parent.t,
eed2ef37 777 LTT_FACILITY_KERNEL, LTT_EVENT_SYSCALL_ENTRY,
778 LTT_FIELD_SYSCALL_ID, 0, 0,
779 before_syscall_entry,
b445142a 780 &g_array_index(hooks, LttvTraceHook, 0));
9d239bd9 781 g_assert(!ret);
b445142a 782
9d239bd9 783 ret = lttv_trace_find_hook(ts->parent.parent.t,
eed2ef37 784 LTT_FACILITY_KERNEL, LTT_EVENT_SYSCALL_EXIT,
785 0, 0, 0,
786 before_syscall_exit,
b445142a 787 &g_array_index(hooks, LttvTraceHook, 1));
9d239bd9 788 g_assert(!ret);
b445142a 789
9d239bd9 790 ret = lttv_trace_find_hook(ts->parent.parent.t,
eed2ef37 791 LTT_FACILITY_KERNEL, LTT_EVENT_TRAP_ENTRY,
792 LTT_FIELD_TRAP_ID, 0, 0,
793 before_trap_entry,
b445142a 794 &g_array_index(hooks, LttvTraceHook, 2));
9d239bd9 795 g_assert(!ret);
b445142a 796
9d239bd9 797 ret = lttv_trace_find_hook(ts->parent.parent.t,
eed2ef37 798 LTT_FACILITY_KERNEL, LTT_EVENT_TRAP_EXIT,
799 0, 0, 0,
800 before_trap_exit, &g_array_index(hooks, LttvTraceHook, 3));
9d239bd9 801 g_assert(!ret);
eed2ef37 802
9d239bd9 803 ret = lttv_trace_find_hook(ts->parent.parent.t,
eed2ef37 804 LTT_FACILITY_KERNEL, LTT_EVENT_IRQ_ENTRY,
805 LTT_FIELD_IRQ_ID, 0, 0,
806 before_irq_entry, &g_array_index(hooks, LttvTraceHook, 4));
9d239bd9 807 g_assert(!ret);
eed2ef37 808
9d239bd9 809 ret = lttv_trace_find_hook(ts->parent.parent.t,
eed2ef37 810 LTT_FACILITY_KERNEL, LTT_EVENT_IRQ_EXIT,
811 0, 0, 0,
812 before_irq_exit, &g_array_index(hooks, LttvTraceHook, 5));
9d239bd9 813 g_assert(!ret);
eed2ef37 814
9d239bd9 815 ret = lttv_trace_find_hook(ts->parent.parent.t,
eed2ef37 816 LTT_FACILITY_PROCESS, LTT_EVENT_SCHEDCHANGE,
817 LTT_FIELD_OUT, LTT_FIELD_IN, LTT_FIELD_OUT_STATE,
818 before_schedchange,
819 &g_array_index(hooks, LttvTraceHook, 6));
9d239bd9 820 g_assert(!ret);
b445142a 821
822 before_hooks = hooks;
823
eed2ef37 824 hooks = g_array_sized_new(FALSE, FALSE, sizeof(LttvTraceHook), 9);
825 g_array_set_size(hooks, 9);
b445142a 826
9d239bd9 827 ret = lttv_trace_find_hook(ts->parent.parent.t,
eed2ef37 828 LTT_FACILITY_KERNEL, LTT_EVENT_SYSCALL_ENTRY,
829 LTT_FIELD_SYSCALL_ID, 0, 0,
830 after_syscall_entry,
b445142a 831 &g_array_index(hooks, LttvTraceHook, 0));
9d239bd9 832 g_assert(!ret);
b445142a 833
9d239bd9 834 ret = lttv_trace_find_hook(ts->parent.parent.t,
eed2ef37 835 LTT_FACILITY_KERNEL, LTT_EVENT_SYSCALL_EXIT,
836 0, 0, 0,
837 after_syscall_exit,
b445142a 838 &g_array_index(hooks, LttvTraceHook, 1));
9d239bd9 839 g_assert(!ret);
b445142a 840
9d239bd9 841 ret = lttv_trace_find_hook(ts->parent.parent.t,
eed2ef37 842 LTT_FACILITY_KERNEL, LTT_EVENT_TRAP_ENTRY,
843 LTT_FIELD_TRAP_ID, 0, 0,
844 after_trap_entry, &g_array_index(hooks, LttvTraceHook, 2));
9d239bd9 845 g_assert(!ret);
eed2ef37 846
9d239bd9 847 ret = lttv_trace_find_hook(ts->parent.parent.t,
eed2ef37 848 LTT_FACILITY_KERNEL, LTT_EVENT_TRAP_EXIT,
849 0, 0, 0,
850 after_trap_exit, &g_array_index(hooks, LttvTraceHook, 3));
9d239bd9 851 g_assert(!ret);
b445142a 852
9d239bd9 853 ret = lttv_trace_find_hook(ts->parent.parent.t,
eed2ef37 854 LTT_FACILITY_KERNEL, LTT_EVENT_IRQ_ENTRY,
855 LTT_FIELD_IRQ_ID, 0, 0,
856 after_irq_entry, &g_array_index(hooks, LttvTraceHook, 4));
9d239bd9 857 g_assert(!ret);
b445142a 858
9d239bd9 859 ret = lttv_trace_find_hook(ts->parent.parent.t,
eed2ef37 860 LTT_FACILITY_KERNEL, LTT_EVENT_IRQ_EXIT,
861 0, 0, 0,
862 after_irq_exit, &g_array_index(hooks, LttvTraceHook, 5));
9d239bd9 863 g_assert(!ret);
b445142a 864
b445142a 865
9d239bd9 866 ret = lttv_trace_find_hook(ts->parent.parent.t,
eed2ef37 867 LTT_FACILITY_PROCESS, LTT_EVENT_FORK,
868 LTT_FIELD_PARENT_PID, LTT_FIELD_CHILD_PID, 0,
869 process_fork,
b445142a 870 &g_array_index(hooks, LttvTraceHook, 6));
9d239bd9 871 g_assert(!ret);
b445142a 872
9d239bd9 873 ret = lttv_trace_find_hook(ts->parent.parent.t,
eed2ef37 874 LTT_FACILITY_PROCESS, LTT_EVENT_EXIT,
875 LTT_FIELD_PID, 0, 0,
876 process_exit, &g_array_index(hooks, LttvTraceHook, 7));
9d239bd9 877 g_assert(!ret);
eed2ef37 878
9d239bd9 879 ret = lttv_trace_find_hook(ts->parent.parent.t,
eed2ef37 880 LTT_FACILITY_PROCESS, LTT_EVENT_FREE,
881 LTT_FIELD_PID, 0, 0,
d7cf605c 882 process_free, &g_array_index(hooks, LttvTraceHook, 8));
9d239bd9 883 g_assert(!ret);
eed2ef37 884
b445142a 885
886 after_hooks = hooks;
887
359b2948 888 /* Add these hooks to each event_by_id hooks list */
b445142a 889
eed2ef37 890 nb_tracefile = ts->parent.parent.tracefiles->len;
b445142a 891
dbb7bb09 892 for(j = 0 ; j < nb_tracefile ; j++) {
d7cf605c 893 tfs = LTTV_TRACEFILE_STATS(g_array_index(ts->parent.parent.tracefiles,
894 LttvTracefileContext*, j));
359b2948 895 lttv_hooks_add(tfs->parent.parent.event, every_event, NULL,
896 LTTV_PRIO_DEFAULT);
b445142a 897
898 for(k = 0 ; k < before_hooks->len ; k++) {
eed2ef37 899 hook = &g_array_index(before_hooks, LttvTraceHook, k);
900 for(l = 0; l<hook->fac_list->len;l++) {
901 thf = g_array_index(hook->fac_list, LttvTraceHookByFacility*, l);
902 lttv_hooks_add(
903 lttv_hooks_by_id_find(tfs->parent.parent.event_by_id, thf->id),
904 thf->h,
d052ffc3 905 thf,
eed2ef37 906 LTTV_PRIO_STATS_BEFORE_STATE);
907 }
b445142a 908 }
909 for(k = 0 ; k < after_hooks->len ; k++) {
eed2ef37 910 hook = &g_array_index(after_hooks, LttvTraceHook, k);
911 for(l = 0; l<hook->fac_list->len;l++) {
912 thf = g_array_index(hook->fac_list, LttvTraceHookByFacility*, l);
913 lttv_hooks_add(
914 lttv_hooks_by_id_find(tfs->parent.parent.event_by_id, thf->id),
915 thf->h,
d052ffc3 916 thf,
eed2ef37 917 LTTV_PRIO_STATS_AFTER_STATE);
918 }
b445142a 919 }
920 }
921 lttv_attribute_find(self->parent.parent.a, LTTV_STATS_BEFORE_HOOKS,
922 LTTV_POINTER, &val);
923 *(val.v_pointer) = before_hooks;
924 lttv_attribute_find(self->parent.parent.a, LTTV_STATS_AFTER_HOOKS,
925 LTTV_POINTER, &val);
926 *(val.v_pointer) = after_hooks;
927 }
b445142a 928}
929
d3e01c7a 930// Hook wrapper. call_data is a traceset context.
00e74b69 931gboolean lttv_stats_hook_remove_event_hooks(void *hook_data, void *call_data)
d3e01c7a 932{
933 LttvTracesetStats *tss = (LttvTracesetStats*)call_data;
934
935 lttv_stats_remove_event_hooks(tss);
936
937 return 0;
938}
b445142a 939
00e74b69 940void lttv_stats_remove_event_hooks(LttvTracesetStats *self)
b445142a 941{
942 LttvTraceset *traceset = self->parent.parent.ts;
943
eed2ef37 944 guint i, j, k, l, nb_trace, nb_tracefile;
b445142a 945
946 LttvTraceStats *ts;
947
948 LttvTracefileStats *tfs;
949
950 void *hook_data;
951
952 GArray *before_hooks, *after_hooks;
953
eed2ef37 954 LttvTraceHook *hook;
955
956 LttvTraceHookByFacility *thf;
b445142a 957
958 LttvAttributeValue val;
959
960 nb_trace = lttv_traceset_number(traceset);
961 for(i = 0 ; i < nb_trace ; i++) {
962 ts = LTTV_TRACE_STATS(self->parent.parent.traces[i]);
963 lttv_attribute_find(self->parent.parent.a, LTTV_STATS_BEFORE_HOOKS,
964 LTTV_POINTER, &val);
965 before_hooks = *(val.v_pointer);
966 lttv_attribute_find(self->parent.parent.a, LTTV_STATS_AFTER_HOOKS,
967 LTTV_POINTER, &val);
968 after_hooks = *(val.v_pointer);
969
359b2948 970 /* Remove these hooks from each event_by_id hooks list */
b445142a 971
eed2ef37 972 nb_tracefile = ts->parent.parent.tracefiles->len;
b445142a 973
dbb7bb09 974 for(j = 0 ; j < nb_tracefile ; j++) {
cb03932a 975 tfs = LTTV_TRACEFILE_STATS(g_array_index(ts->parent.parent.tracefiles,
976 LttvTracefileContext*, j));
359b2948 977 lttv_hooks_remove_data(tfs->parent.parent.event, every_event,
b445142a 978 NULL);
979
980 for(k = 0 ; k < before_hooks->len ; k++) {
eed2ef37 981 hook = &g_array_index(before_hooks, LttvTraceHook, k);
982 for(l = 0 ; l < hook->fac_list->len ; l++) {
983 thf = g_array_index(hook->fac_list, LttvTraceHookByFacility*, l);
984 lttv_hooks_remove_data(
985 lttv_hooks_by_id_find(tfs->parent.parent.event_by_id, thf->id),
986 thf->h,
d052ffc3 987 thf);
eed2ef37 988 }
b445142a 989 }
990 for(k = 0 ; k < after_hooks->len ; k++) {
eed2ef37 991 hook = &g_array_index(after_hooks, LttvTraceHook, k);
992 for(l = 0 ; l < hook->fac_list->len ; l++) {
993 thf = g_array_index(hook->fac_list, LttvTraceHookByFacility*, l);
994 lttv_hooks_remove_data(
995 lttv_hooks_by_id_find(tfs->parent.parent.event_by_id, thf->id),
996 thf->h,
d052ffc3 997 thf);
eed2ef37 998 }
b445142a 999 }
1000 }
2a2fa4f0 1001 g_debug("lttv_stats_remove_event_hooks()");
b445142a 1002 g_array_free(before_hooks, TRUE);
1003 g_array_free(after_hooks, TRUE);
1004 }
9f797243 1005}
08b1c66e 1006
1007
1008static void module_init()
1009{
1010 LTTV_STATS_PROCESS_UNKNOWN = g_quark_from_string("unknown process");
1011 LTTV_STATS_PROCESSES = g_quark_from_string("processes");
1012 LTTV_STATS_CPU = g_quark_from_string("cpu");
1013 LTTV_STATS_MODE_TYPES = g_quark_from_string("mode_types");
1014 LTTV_STATS_MODES = g_quark_from_string("modes");
1015 LTTV_STATS_SUBMODES = g_quark_from_string("submodes");
1016 LTTV_STATS_EVENT_TYPES = g_quark_from_string("event_types");
1017 LTTV_STATS_CPU_TIME = g_quark_from_string("cpu time");
1018 LTTV_STATS_ELAPSED_TIME = g_quark_from_string("elapsed time");
1019 LTTV_STATS_EVENTS = g_quark_from_string("events");
1020 LTTV_STATS_EVENTS_COUNT = g_quark_from_string("events count");
1021 LTTV_STATS_BEFORE_HOOKS = g_quark_from_string("saved stats before hooks");
1022 LTTV_STATS_AFTER_HOOKS = g_quark_from_string("saved stats after hooks");
f95bc830 1023 LTTV_STATS_USE_COUNT = g_quark_from_string("stats_use_count");
1024 LTTV_STATS = g_quark_from_string("statistics");
1025 LTTV_STATS_TRACEFILES = g_quark_from_string("tracefiles statistics");
1026 LTTV_STATS_SUMMED = g_quark_from_string("statistics summed");
08b1c66e 1027}
1028
1029static void module_destroy()
1030{
1031}
1032
1033
1034LTTV_MODULE("stats", "Compute processes statistics", \
1035 "Accumulate statistics for event types, processes and CPUs", \
1036 module_init, module_destroy, "state");
f95bc830 1037
1038/* Change the places where stats are called (create/read/write stats)
1039
1040 Check for options in batchtest.c to reduce writing and see what tests are
1041 best candidates for performance analysis. Once OK, commit, move to main
1042 and run tests. Update the gui for statistics. */
This page took 0.07434 seconds and 4 git commands to generate.