warning fixes
[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
52 static GQuark
53 LTTV_STATS_BEFORE_HOOKS,
54 LTTV_STATS_AFTER_HOOKS;
55
56 static void
57 find_event_tree(LttvTracefileStats *tfcs, GQuark pid_time, GQuark cpu,
58 GQuark mode, GQuark sub_mode, LttvAttribute **events_tree,
59 LttvAttribute **event_types_tree);
60
61 static void
62 init(LttvTracesetStats *self, LttvTraceset *ts)
63 {
64 guint i, j, nb_trace, nb_tracefile;
65
66 LttvTraceContext *tc;
67
68 LttvTraceStats *tcs;
69
70 LttvTracefileContext *tfc;
71
72 LttvTracefileContext **tfs;
73 LttvTracefileStats *tfcs;
74
75 LttTime timestamp = {0,0};
76
77 LttvAttributeValue v;
78
79 LttvAttribute
80 *stats_tree,
81 *tracefiles_stats;
82
83 LTTV_TRACESET_CONTEXT_CLASS(g_type_class_peek(LTTV_TRACESET_STATE_TYPE))->
84 init((LttvTracesetContext *)self, ts);
85
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);
92
93 *(v.v_uint)++;
94 if(*(v.v_uint) == 1) {
95 g_assert(lttv_attribute_get_number(self->stats) == 0);
96 }
97
98 nb_trace = lttv_traceset_number(ts);
99
100 for(i = 0 ; i < nb_trace ; i++) {
101 tc = self->parent.parent.traces[i];
102 tcs = LTTV_TRACE_STATS(tc);
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 }
114
115 nb_tracefile = tc->tracefiles->len;
116
117 for(j = 0 ; j < nb_tracefile ; j++) {
118 tfs = &g_array_index(tc->tracefiles,
119 LttvTracefileContext*, j);
120 tfcs = LTTV_TRACEFILE_STATS(*tfs);
121 tfcs->stats = lttv_attribute_find_subdir(tracefiles_stats,
122 tfcs->parent.cpu_name);
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
131 static void
132 fini(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
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);
158 }
159 self->stats = NULL;
160
161 ts = self->parent.parent.ts;
162 nb_trace = lttv_traceset_number(ts);
163
164 for(i = 0 ; i < nb_trace ; i++) {
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);
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);
177 }
178 tcs->stats = NULL;
179
180 nb_tracefile = tc->tracefiles->len;
181
182 for(j = 0 ; j < nb_tracefile ; j++) {
183 tfc = g_array_index(tc->tracefiles,
184 LttvTracefileContext*, j);
185 tfcs = (LttvTracefileStats *)tfc;
186 tfcs->stats = NULL;
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
196 static LttvTracesetContext *
197 new_traceset_context(LttvTracesetContext *self)
198 {
199 return LTTV_TRACESET_CONTEXT(g_object_new(LTTV_TRACESET_STATS_TYPE, NULL));
200 }
201
202
203 static LttvTraceContext *
204 new_trace_context(LttvTracesetContext *self)
205 {
206 return LTTV_TRACE_CONTEXT(g_object_new(LTTV_TRACE_STATS_TYPE, NULL));
207 }
208
209
210 static LttvTracefileContext *
211 new_tracefile_context(LttvTracesetContext *self)
212 {
213 return LTTV_TRACEFILE_CONTEXT(g_object_new(LTTV_TRACEFILE_STATS_TYPE, NULL));
214 }
215
216
217 static void
218 traceset_stats_instance_init (GTypeInstance *instance, gpointer g_class)
219 {
220 }
221
222
223 static void
224 traceset_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
231 static void
232 traceset_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
245 GType
246 lttv_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 */
257 sizeof (LttvTracesetStats),
258 0, /* n_preallocs */
259 (GInstanceInitFunc) traceset_stats_instance_init, /* instance_init */
260 NULL /* Value handling */
261 };
262
263 type = g_type_register_static (LTTV_TRACESET_STATE_TYPE,
264 "LttvTracesetStatsType",
265 &info, 0);
266 }
267 return type;
268 }
269
270
271 static void
272 trace_stats_instance_init (GTypeInstance *instance, gpointer g_class)
273 {
274 }
275
276
277 static void
278 trace_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
285 static void
286 trace_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
294 GType
295 lttv_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 */
308 (GInstanceInitFunc) trace_stats_instance_init, /* instance_init */
309 NULL /* Value handling */
310 };
311
312 type = g_type_register_static (LTTV_TRACE_STATE_TYPE,
313 "LttvTraceStatsType", &info, 0);
314 }
315 return type;
316 }
317
318
319 static void
320 tracefile_stats_instance_init (GTypeInstance *instance, gpointer g_class)
321 {
322 }
323
324
325 static void
326 tracefile_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
333 static void
334 tracefile_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
342 GType
343 lttv_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 */
356 (GInstanceInitFunc) tracefile_stats_instance_init, /* instance_init */
357 NULL /* Value handling */
358 };
359
360 type = g_type_register_static (LTTV_TRACEFILE_STATE_TYPE,
361 "LttvTracefileStatsType", &info, 0);
362 }
363 return type;
364 }
365
366
367 static void
368 find_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)
375 {
376 LttvAttribute *a;
377
378 LttvTraceStats *tcs = (LttvTraceStats*)tfcs->parent.parent.t_context;
379 a = lttv_attribute_find_subdir(tcs->stats, LTTV_STATS_PROCESSES);
380 a = lttv_attribute_find_subdir(a, pid_time);
381 a = lttv_attribute_find_subdir(a, LTTV_STATS_CPU);
382 a = lttv_attribute_find_subdir(a, cpu);
383 a = lttv_attribute_find_subdir(a, LTTV_STATS_MODE_TYPES);
384 a = lttv_attribute_find_subdir(a, mode);
385 a = lttv_attribute_find_subdir(a, LTTV_STATS_SUBMODES);
386 a = lttv_attribute_find_subdir(a, sub_mode);
387 *events_tree = a;
388 a = lttv_attribute_find_subdir(a, LTTV_STATS_EVENT_TYPES);
389 *event_types_tree = a;
390 }
391
392
393 static void update_event_tree(LttvTracefileStats *tfcs)
394 {
395 LttvExecutionState *es = tfcs->parent.process->state;
396
397 find_event_tree(tfcs, tfcs->parent.process->pid_time,
398 tfcs->parent.cpu_name,
399 es->t, es->n, &(tfcs->current_events_tree),
400 &(tfcs->current_event_types_tree));
401 }
402
403
404 static 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);
412 delta = ltt_time_sub(tfcs->parent.parent.timestamp,
413 tfcs->parent.process->state->change);
414 *(cpu_time.v_time) = ltt_time_add(*(cpu_time.v_time), delta);
415 }
416
417
418 static 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);
426 delta = ltt_time_sub(tfcs->parent.parent.timestamp,
427 tfcs->parent.process->state->entry);
428 *(elapsed_time.v_time) = ltt_time_add(*(elapsed_time.v_time), delta);
429
430 lttv_attribute_find(tfcs->current_events_tree, LTTV_STATS_CPU_TIME,
431 LTTV_TIME, &cpu_time);
432 delta = ltt_time_sub(tfcs->parent.parent.timestamp,
433 tfcs->parent.process->state->change);
434 *(cpu_time.v_time) = ltt_time_add(*(cpu_time.v_time), delta);
435 }
436
437
438 static gboolean before_syscall_entry(void *hook_data, void *call_data)
439 {
440 mode_change((LttvTracefileStats *)call_data);
441 return FALSE;
442 }
443
444
445 static gboolean after_syscall_entry(void *hook_data, void *call_data)
446 {
447 update_event_tree((LttvTracefileStats *)call_data);
448 return FALSE;
449 }
450
451
452 gboolean before_syscall_exit(void *hook_data, void *call_data)
453 {
454 mode_end((LttvTracefileStats *)call_data);
455 return FALSE;
456 }
457
458
459 static gboolean after_syscall_exit(void *hook_data, void *call_data)
460 {
461 update_event_tree((LttvTracefileStats *)call_data);
462 return FALSE;
463 }
464
465
466 gboolean before_trap_entry(void *hook_data, void *call_data)
467 {
468 mode_change((LttvTracefileStats *)call_data);
469 return FALSE;
470 }
471
472
473 static gboolean after_trap_entry(void *hook_data, void *call_data)
474 {
475 update_event_tree((LttvTracefileStats *)call_data);
476 return FALSE;
477 }
478
479
480 gboolean before_trap_exit(void *hook_data, void *call_data)
481 {
482 mode_end((LttvTracefileStats *)call_data);
483 return FALSE;
484 }
485
486
487 gboolean after_trap_exit(void *hook_data, void *call_data)
488 {
489 update_event_tree((LttvTracefileStats *)call_data);
490 return FALSE;
491 }
492
493
494 gboolean before_irq_entry(void *hook_data, void *call_data)
495 {
496 mode_change((LttvTracefileStats *)call_data);
497 return FALSE;
498 }
499
500
501 gboolean after_irq_entry(void *hook_data, void *call_data)
502 {
503 update_event_tree((LttvTracefileStats *)call_data);
504 return FALSE;
505 }
506
507
508 gboolean before_irq_exit(void *hook_data, void *call_data)
509 {
510 mode_end((LttvTracefileStats *)call_data);
511 return FALSE;
512 }
513
514
515 gboolean after_irq_exit(void *hook_data, void *call_data)
516 {
517 update_event_tree((LttvTracefileStats *)call_data);
518 return FALSE;
519 }
520
521
522 gboolean before_schedchange(void *hook_data, void *call_data)
523 {
524 LttvTracefileStats *tfcs = (LttvTracefileStats *)call_data;
525
526 LttEvent *e = ltt_tracefile_get_event(tfcs->parent.parent.tf);
527
528 LttvTraceHookByFacility *thf = (LttvTraceHookByFacility *)hook_data;
529
530 guint pid_in, pid_out;
531
532 gint state_out;
533
534 LttvProcessState *process;
535
536 pid_out = ltt_event_get_unsigned(e, thf->f1);
537 pid_in = ltt_event_get_unsigned(e, thf->f2);
538 state_out = ltt_event_get_int(e, thf->f3);
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
546 process = lttv_state_find_process_or_create(&(tfcs->parent), pid_in);
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
559 gboolean process_fork(void *hook_data, void *call_data)
560 {
561 /* nothing to do for now */
562 return FALSE;
563 }
564
565
566 gboolean 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
573 gboolean process_free(void *hook_data, void *call_data)
574 {
575 return FALSE;
576 }
577
578 gboolean every_event(void *hook_data, void *call_data)
579 {
580 LttvTracefileStats *tfcs = (LttvTracefileStats *)call_data;
581
582 LttEvent *e = ltt_tracefile_get_event(tfcs->parent.parent.tf);
583
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,
592 ltt_eventtype_name(ltt_event_eventtype(e)),
593 LTTV_UINT, &v);
594 (*(v.v_uint))++;
595 return FALSE;
596 }
597
598
599 void
600 lttv_stats_sum_trace(LttvTraceStats *self)
601 {
602 LttvAttribute *sum_container = self->stats;
603
604 LttvAttributeType type;
605
606 LttvAttributeValue value;
607
608 LttvAttributeName name;
609
610 unsigned sum;
611
612 int i, j, k, l, m, nb_process, nb_cpu, nb_mode_type, nb_submode,
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,
619 *trace_modes_tree;
620
621 main_tree = sum_container;
622
623 lttv_attribute_find(sum_container,
624 LTTV_STATS_SUMMED,
625 LTTV_UINT, &value);
626 if(*(value.v_uint) != 0) return;
627 *(value.v_uint) = 1;
628
629 processes_tree = lttv_attribute_find_subdir(main_tree,
630 LTTV_STATS_PROCESSES);
631 trace_modes_tree = lttv_attribute_find_subdir(main_tree,
632 LTTV_STATS_MODES);
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);
665
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));
669
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);
673
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);
678 }
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);
683 }
684 lttv_attribute_recursive_add(cpu_events_tree, mode_events_tree);
685 }
686 lttv_attribute_recursive_add(process_modes_tree, cpu_tree);
687 lttv_attribute_recursive_add(trace_cpu_tree, cpu_tree);
688 }
689 lttv_attribute_recursive_add(trace_modes_tree, process_modes_tree);
690 }
691 }
692
693
694 gboolean 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
700 void
701 lttv_stats_sum_traceset(LttvTracesetStats *self)
702 {
703 LttvTraceset *traceset = self->parent.parent.ts;
704 LttvAttribute *sum_container = self->stats;
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
714 lttv_attribute_find(sum_container, LTTV_STATS_SUMMED,
715 LTTV_UINT, &value);
716 if(*(value.v_uint) != 0) return;
717 *(value.v_uint) = 1;
718
719 traceset_modes_tree = lttv_attribute_find_subdir(sum_container,
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);
728 lttv_attribute_recursive_add(traceset_modes_tree, trace_modes_tree);
729 }
730 }
731
732
733 // Hook wrapper. call_data is a traceset context.
734 gboolean lttv_stats_hook_add_event_hooks(void *hook_data, void *call_data)
735 {
736 LttvTracesetStats *tss = (LttvTracesetStats*)call_data;
737
738 lttv_stats_add_event_hooks(tss);
739
740 return 0;
741 }
742
743 void lttv_stats_add_event_hooks(LttvTracesetStats *self)
744 {
745 LttvTraceset *traceset = self->parent.parent.ts;
746
747 guint i, j, k, l, nb_trace, nb_tracefile;
748
749 LttvTraceStats *ts;
750
751 LttvTracefileStats *tfs;
752
753 GArray *hooks, *before_hooks, *after_hooks;
754
755 LttvTraceHook *hook;
756
757 LttvTraceHookByFacility *thf;
758
759 LttvAttributeValue val;
760
761 gint ret;
762
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
770 hooks = g_array_sized_new(FALSE, FALSE, sizeof(LttvTraceHook), 7);
771 g_array_set_size(hooks, 7);
772
773 ret = lttv_trace_find_hook(ts->parent.parent.t,
774 LTT_FACILITY_KERNEL, LTT_EVENT_SYSCALL_ENTRY,
775 LTT_FIELD_SYSCALL_ID, 0, 0,
776 before_syscall_entry,
777 &g_array_index(hooks, LttvTraceHook, 0));
778 g_assert(!ret);
779
780 ret = lttv_trace_find_hook(ts->parent.parent.t,
781 LTT_FACILITY_KERNEL, LTT_EVENT_SYSCALL_EXIT,
782 0, 0, 0,
783 before_syscall_exit,
784 &g_array_index(hooks, LttvTraceHook, 1));
785 g_assert(!ret);
786
787 ret = lttv_trace_find_hook(ts->parent.parent.t,
788 LTT_FACILITY_KERNEL, LTT_EVENT_TRAP_ENTRY,
789 LTT_FIELD_TRAP_ID, 0, 0,
790 before_trap_entry,
791 &g_array_index(hooks, LttvTraceHook, 2));
792 g_assert(!ret);
793
794 ret = lttv_trace_find_hook(ts->parent.parent.t,
795 LTT_FACILITY_KERNEL, LTT_EVENT_TRAP_EXIT,
796 0, 0, 0,
797 before_trap_exit, &g_array_index(hooks, LttvTraceHook, 3));
798 g_assert(!ret);
799
800 ret = lttv_trace_find_hook(ts->parent.parent.t,
801 LTT_FACILITY_KERNEL, LTT_EVENT_IRQ_ENTRY,
802 LTT_FIELD_IRQ_ID, 0, 0,
803 before_irq_entry, &g_array_index(hooks, LttvTraceHook, 4));
804 g_assert(!ret);
805
806 ret = lttv_trace_find_hook(ts->parent.parent.t,
807 LTT_FACILITY_KERNEL, LTT_EVENT_IRQ_EXIT,
808 0, 0, 0,
809 before_irq_exit, &g_array_index(hooks, LttvTraceHook, 5));
810 g_assert(!ret);
811
812 ret = lttv_trace_find_hook(ts->parent.parent.t,
813 LTT_FACILITY_PROCESS, LTT_EVENT_SCHEDCHANGE,
814 LTT_FIELD_OUT, LTT_FIELD_IN, LTT_FIELD_OUT_STATE,
815 before_schedchange,
816 &g_array_index(hooks, LttvTraceHook, 6));
817 g_assert(!ret);
818
819 before_hooks = hooks;
820
821 hooks = g_array_sized_new(FALSE, FALSE, sizeof(LttvTraceHook), 9);
822 g_array_set_size(hooks, 9);
823
824 ret = lttv_trace_find_hook(ts->parent.parent.t,
825 LTT_FACILITY_KERNEL, LTT_EVENT_SYSCALL_ENTRY,
826 LTT_FIELD_SYSCALL_ID, 0, 0,
827 after_syscall_entry,
828 &g_array_index(hooks, LttvTraceHook, 0));
829 g_assert(!ret);
830
831 ret = lttv_trace_find_hook(ts->parent.parent.t,
832 LTT_FACILITY_KERNEL, LTT_EVENT_SYSCALL_EXIT,
833 0, 0, 0,
834 after_syscall_exit,
835 &g_array_index(hooks, LttvTraceHook, 1));
836 g_assert(!ret);
837
838 ret = lttv_trace_find_hook(ts->parent.parent.t,
839 LTT_FACILITY_KERNEL, LTT_EVENT_TRAP_ENTRY,
840 LTT_FIELD_TRAP_ID, 0, 0,
841 after_trap_entry, &g_array_index(hooks, LttvTraceHook, 2));
842 g_assert(!ret);
843
844 ret = lttv_trace_find_hook(ts->parent.parent.t,
845 LTT_FACILITY_KERNEL, LTT_EVENT_TRAP_EXIT,
846 0, 0, 0,
847 after_trap_exit, &g_array_index(hooks, LttvTraceHook, 3));
848 g_assert(!ret);
849
850 ret = lttv_trace_find_hook(ts->parent.parent.t,
851 LTT_FACILITY_KERNEL, LTT_EVENT_IRQ_ENTRY,
852 LTT_FIELD_IRQ_ID, 0, 0,
853 after_irq_entry, &g_array_index(hooks, LttvTraceHook, 4));
854 g_assert(!ret);
855
856 ret = lttv_trace_find_hook(ts->parent.parent.t,
857 LTT_FACILITY_KERNEL, LTT_EVENT_IRQ_EXIT,
858 0, 0, 0,
859 after_irq_exit, &g_array_index(hooks, LttvTraceHook, 5));
860 g_assert(!ret);
861
862
863 ret = lttv_trace_find_hook(ts->parent.parent.t,
864 LTT_FACILITY_PROCESS, LTT_EVENT_FORK,
865 LTT_FIELD_PARENT_PID, LTT_FIELD_CHILD_PID, 0,
866 process_fork,
867 &g_array_index(hooks, LttvTraceHook, 6));
868 g_assert(!ret);
869
870 ret = lttv_trace_find_hook(ts->parent.parent.t,
871 LTT_FACILITY_PROCESS, LTT_EVENT_EXIT,
872 LTT_FIELD_PID, 0, 0,
873 process_exit, &g_array_index(hooks, LttvTraceHook, 7));
874 g_assert(!ret);
875
876 ret = lttv_trace_find_hook(ts->parent.parent.t,
877 LTT_FACILITY_PROCESS, LTT_EVENT_FREE,
878 LTT_FIELD_PID, 0, 0,
879 process_free, &g_array_index(hooks, LttvTraceHook, 8));
880 g_assert(!ret);
881
882
883 after_hooks = hooks;
884
885 /* Add these hooks to each event_by_id hooks list */
886
887 nb_tracefile = ts->parent.parent.tracefiles->len;
888
889 for(j = 0 ; j < nb_tracefile ; j++) {
890 tfs = LTTV_TRACEFILE_STATS(g_array_index(ts->parent.parent.tracefiles,
891 LttvTracefileContext*, j));
892 lttv_hooks_add(tfs->parent.parent.event, every_event, NULL,
893 LTTV_PRIO_DEFAULT);
894
895 for(k = 0 ; k < before_hooks->len ; k++) {
896 hook = &g_array_index(before_hooks, LttvTraceHook, k);
897 for(l = 0; l<hook->fac_list->len;l++) {
898 thf = g_array_index(hook->fac_list, LttvTraceHookByFacility*, l);
899 lttv_hooks_add(
900 lttv_hooks_by_id_find(tfs->parent.parent.event_by_id, thf->id),
901 thf->h,
902 thf,
903 LTTV_PRIO_STATS_BEFORE_STATE);
904 }
905 }
906 for(k = 0 ; k < after_hooks->len ; k++) {
907 hook = &g_array_index(after_hooks, LttvTraceHook, k);
908 for(l = 0; l<hook->fac_list->len;l++) {
909 thf = g_array_index(hook->fac_list, LttvTraceHookByFacility*, l);
910 lttv_hooks_add(
911 lttv_hooks_by_id_find(tfs->parent.parent.event_by_id, thf->id),
912 thf->h,
913 thf,
914 LTTV_PRIO_STATS_AFTER_STATE);
915 }
916 }
917 }
918 lttv_attribute_find(self->parent.parent.a, LTTV_STATS_BEFORE_HOOKS,
919 LTTV_POINTER, &val);
920 *(val.v_pointer) = before_hooks;
921 lttv_attribute_find(self->parent.parent.a, LTTV_STATS_AFTER_HOOKS,
922 LTTV_POINTER, &val);
923 *(val.v_pointer) = after_hooks;
924 }
925 }
926
927 // Hook wrapper. call_data is a traceset context.
928 gboolean lttv_stats_hook_remove_event_hooks(void *hook_data, void *call_data)
929 {
930 LttvTracesetStats *tss = (LttvTracesetStats*)call_data;
931
932 lttv_stats_remove_event_hooks(tss);
933
934 return 0;
935 }
936
937 void lttv_stats_remove_event_hooks(LttvTracesetStats *self)
938 {
939 LttvTraceset *traceset = self->parent.parent.ts;
940
941 guint i, j, k, l, nb_trace, nb_tracefile;
942
943 LttvTraceStats *ts;
944
945 LttvTracefileStats *tfs;
946
947 void *hook_data;
948
949 GArray *before_hooks, *after_hooks;
950
951 LttvTraceHook *hook;
952
953 LttvTraceHookByFacility *thf;
954
955 LttvAttributeValue val;
956
957 nb_trace = lttv_traceset_number(traceset);
958 for(i = 0 ; i < nb_trace ; i++) {
959 ts = (LttvTraceStats*)self->parent.parent.traces[i];
960 lttv_attribute_find(self->parent.parent.a, LTTV_STATS_BEFORE_HOOKS,
961 LTTV_POINTER, &val);
962 before_hooks = *(val.v_pointer);
963 lttv_attribute_find(self->parent.parent.a, LTTV_STATS_AFTER_HOOKS,
964 LTTV_POINTER, &val);
965 after_hooks = *(val.v_pointer);
966
967 /* Remove these hooks from each event_by_id hooks list */
968
969 nb_tracefile = ts->parent.parent.tracefiles->len;
970
971 for(j = 0 ; j < nb_tracefile ; j++) {
972 tfs = LTTV_TRACEFILE_STATS(g_array_index(ts->parent.parent.tracefiles,
973 LttvTracefileContext*, j));
974 lttv_hooks_remove_data(tfs->parent.parent.event, every_event,
975 NULL);
976
977 for(k = 0 ; k < before_hooks->len ; k++) {
978 hook = &g_array_index(before_hooks, LttvTraceHook, k);
979 for(l = 0 ; l < hook->fac_list->len ; l++) {
980 thf = g_array_index(hook->fac_list, LttvTraceHookByFacility*, l);
981 lttv_hooks_remove_data(
982 lttv_hooks_by_id_find(tfs->parent.parent.event_by_id, thf->id),
983 thf->h,
984 thf);
985 }
986 }
987 for(k = 0 ; k < after_hooks->len ; k++) {
988 hook = &g_array_index(after_hooks, LttvTraceHook, k);
989 for(l = 0 ; l < hook->fac_list->len ; l++) {
990 thf = g_array_index(hook->fac_list, LttvTraceHookByFacility*, l);
991 lttv_hooks_remove_data(
992 lttv_hooks_by_id_find(tfs->parent.parent.event_by_id, thf->id),
993 thf->h,
994 thf);
995 }
996 }
997 }
998 g_debug("lttv_stats_remove_event_hooks()");
999 g_array_free(before_hooks, TRUE);
1000 g_array_free(after_hooks, TRUE);
1001 }
1002 }
1003
1004
1005 static void module_init()
1006 {
1007 LTTV_STATS_PROCESS_UNKNOWN = g_quark_from_string("unknown process");
1008 LTTV_STATS_PROCESSES = g_quark_from_string("processes");
1009 LTTV_STATS_CPU = g_quark_from_string("cpu");
1010 LTTV_STATS_MODE_TYPES = g_quark_from_string("mode_types");
1011 LTTV_STATS_MODES = g_quark_from_string("modes");
1012 LTTV_STATS_SUBMODES = g_quark_from_string("submodes");
1013 LTTV_STATS_EVENT_TYPES = g_quark_from_string("event_types");
1014 LTTV_STATS_CPU_TIME = g_quark_from_string("cpu time");
1015 LTTV_STATS_ELAPSED_TIME = g_quark_from_string("elapsed time");
1016 LTTV_STATS_EVENTS = g_quark_from_string("events");
1017 LTTV_STATS_EVENTS_COUNT = g_quark_from_string("events count");
1018 LTTV_STATS_BEFORE_HOOKS = g_quark_from_string("saved stats before hooks");
1019 LTTV_STATS_AFTER_HOOKS = g_quark_from_string("saved stats after hooks");
1020 LTTV_STATS_USE_COUNT = g_quark_from_string("stats_use_count");
1021 LTTV_STATS = g_quark_from_string("statistics");
1022 LTTV_STATS_TRACEFILES = g_quark_from_string("tracefiles statistics");
1023 LTTV_STATS_SUMMED = g_quark_from_string("statistics summed");
1024 }
1025
1026 static void module_destroy()
1027 {
1028 }
1029
1030
1031 LTTV_MODULE("stats", "Compute processes statistics", \
1032 "Accumulate statistics for event types, processes and CPUs", \
1033 module_init, module_destroy, "state");
1034
1035 /* Change the places where stats are called (create/read/write stats)
1036
1037 Check for options in batchtest.c to reduce writing and see what tests are
1038 best candidates for performance analysis. Once OK, commit, move to main
1039 and run tests. Update the gui for statistics. */
This page took 0.049024 seconds and 5 git commands to generate.