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