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