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