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