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