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