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