b56eb36fda3a9107785a86fe42109cf9cd7d9b2b
[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 nb_trace = lttv_traceset_number(traceset);
744 for(i = 0 ; i < nb_trace ; i++) {
745 ts = (LttvTraceStats *)self->parent.parent.traces[i];
746
747 /* Find the eventtype id for the following events and register the
748 associated by id hooks. */
749
750 hooks = g_array_new(FALSE, FALSE, sizeof(LttvTraceHook));
751 g_array_set_size(hooks, 7);
752
753 lttv_trace_find_hook(ts->parent.parent.t, "core","syscall_entry",
754 "syscall_id", NULL, NULL, before_syscall_entry,
755 &g_array_index(hooks, LttvTraceHook, 0));
756
757 lttv_trace_find_hook(ts->parent.parent.t, "core", "syscall_exit", NULL,
758 NULL, NULL, before_syscall_exit,
759 &g_array_index(hooks, LttvTraceHook, 1));
760
761 lttv_trace_find_hook(ts->parent.parent.t, "core", "trap_entry", "trap_id",
762 NULL, NULL, before_trap_entry,
763 &g_array_index(hooks, LttvTraceHook, 2));
764
765 lttv_trace_find_hook(ts->parent.parent.t, "core", "trap_exit", NULL, NULL,
766 NULL, before_trap_exit, &g_array_index(hooks, LttvTraceHook, 3));
767
768 lttv_trace_find_hook(ts->parent.parent.t, "core", "irq_entry", "irq_id",
769 NULL, NULL, before_irq_entry, &g_array_index(hooks, LttvTraceHook, 4));
770
771 lttv_trace_find_hook(ts->parent.parent.t, "core", "irq_exit", NULL, NULL,
772 NULL, before_irq_exit, &g_array_index(hooks, LttvTraceHook, 5));
773
774 lttv_trace_find_hook(ts->parent.parent.t, "core", "schedchange", "in",
775 "out", "out_state", before_schedchange,
776 &g_array_index(hooks, LttvTraceHook, 6));
777
778 before_hooks = hooks;
779
780 hooks = g_array_new(FALSE, FALSE, sizeof(LttvTraceHook));
781 g_array_set_size(hooks, 8);
782
783 lttv_trace_find_hook(ts->parent.parent.t, "core","syscall_entry",
784 "syscall_id", NULL, NULL, after_syscall_entry,
785 &g_array_index(hooks, LttvTraceHook, 0));
786
787 lttv_trace_find_hook(ts->parent.parent.t, "core", "syscall_exit", NULL,
788 NULL, NULL, after_syscall_exit,
789 &g_array_index(hooks, LttvTraceHook, 1));
790
791 lttv_trace_find_hook(ts->parent.parent.t, "core", "trap_entry", "trap_id",
792 NULL, NULL, after_trap_entry, &g_array_index(hooks, LttvTraceHook, 2));
793
794 lttv_trace_find_hook(ts->parent.parent.t, "core", "trap_exit", NULL, NULL,
795 NULL, after_trap_exit, &g_array_index(hooks, LttvTraceHook, 3));
796
797 lttv_trace_find_hook(ts->parent.parent.t, "core", "irq_entry", "irq_id",
798 NULL, NULL, after_irq_entry, &g_array_index(hooks, LttvTraceHook, 4));
799
800 lttv_trace_find_hook(ts->parent.parent.t, "core", "irq_exit", NULL, NULL,
801 NULL, after_irq_exit, &g_array_index(hooks, LttvTraceHook, 5));
802
803 lttv_trace_find_hook(ts->parent.parent.t, "core", "process_fork",
804 "child_pid", NULL, NULL, process_fork,
805 &g_array_index(hooks, LttvTraceHook, 6));
806
807 lttv_trace_find_hook(ts->parent.parent.t, "core", "process_exit", NULL,
808 NULL, NULL, process_exit, &g_array_index(hooks, LttvTraceHook, 7));
809
810 after_hooks = hooks;
811
812 /* Add these hooks to each event_by_id hooks list */
813
814 nb_tracefile = ltt_trace_control_tracefile_number(ts->parent.parent.t) +
815 ltt_trace_per_cpu_tracefile_number(ts->parent.parent.t);
816
817 for(j = 0 ; j < nb_tracefile ; j++) {
818 tfs = LTTV_TRACEFILE_STATS(ts->parent.parent.tracefiles[j]);
819 lttv_hooks_add(tfs->parent.parent.event, every_event, NULL,
820 LTTV_PRIO_DEFAULT);
821
822 for(k = 0 ; k < before_hooks->len ; k++) {
823 hook = g_array_index(before_hooks, LttvTraceHook, k);
824 lttv_hooks_add(lttv_hooks_by_id_find(
825 tfs->parent.parent.event_by_id,
826 hook.id), hook.h, &g_array_index(before_hooks, LttvTraceHook, k),
827 LTTV_PRIO_STATS_BEFORE_STATE);
828 }
829 for(k = 0 ; k < after_hooks->len ; k++) {
830 hook = g_array_index(after_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(after_hooks, LttvTraceHook, k),
834 LTTV_PRIO_STATS_AFTER_STATE);
835 }
836 }
837 lttv_attribute_find(self->parent.parent.a, LTTV_STATS_BEFORE_HOOKS,
838 LTTV_POINTER, &val);
839 *(val.v_pointer) = before_hooks;
840 lttv_attribute_find(self->parent.parent.a, LTTV_STATS_AFTER_HOOKS,
841 LTTV_POINTER, &val);
842 *(val.v_pointer) = after_hooks;
843 }
844 }
845
846 // Hook wrapper. call_data is a traceset context.
847 gint lttv_stats_hook_remove_event_hooks(void *hook_data, void *call_data)
848 {
849 LttvTracesetStats *tss = (LttvTracesetStats*)call_data;
850
851 lttv_stats_remove_event_hooks(tss);
852
853 return 0;
854 }
855
856 lttv_stats_remove_event_hooks(LttvTracesetStats *self)
857 {
858 LttvTraceset *traceset = self->parent.parent.ts;
859
860 guint i, j, k, nb_trace, nb_tracefile;
861
862 LttvTraceStats *ts;
863
864 LttvTracefileStats *tfs;
865
866 void *hook_data;
867
868 GArray *before_hooks, *after_hooks;
869
870 LttvTraceHook hook;
871
872 LttvAttributeValue val;
873
874 nb_trace = lttv_traceset_number(traceset);
875 for(i = 0 ; i < nb_trace ; i++) {
876 ts = LTTV_TRACE_STATS(self->parent.parent.traces[i]);
877 lttv_attribute_find(self->parent.parent.a, LTTV_STATS_BEFORE_HOOKS,
878 LTTV_POINTER, &val);
879 before_hooks = *(val.v_pointer);
880 lttv_attribute_find(self->parent.parent.a, LTTV_STATS_AFTER_HOOKS,
881 LTTV_POINTER, &val);
882 after_hooks = *(val.v_pointer);
883
884 /* Remove these hooks from each event_by_id hooks list */
885
886 nb_tracefile = ltt_trace_control_tracefile_number(ts->parent.parent.t) +
887 ltt_trace_per_cpu_tracefile_number(ts->parent.parent.t);
888
889 for(j = 0 ; j < nb_tracefile ; j++) {
890 tfs = LTTV_TRACEFILE_STATS(ts->parent.parent.tracefiles[j]);
891 lttv_hooks_remove_data(tfs->parent.parent.event, every_event,
892 NULL);
893
894 for(k = 0 ; k < before_hooks->len ; k++) {
895 hook = g_array_index(before_hooks, LttvTraceHook, k);
896 lttv_hooks_remove_data(
897 lttv_hooks_by_id_find(tfs->parent.parent.event_by_id,
898 hook.id), hook.h, &g_array_index(before_hooks, LttvTraceHook, k));
899 }
900 for(k = 0 ; k < after_hooks->len ; k++) {
901 hook = g_array_index(after_hooks, LttvTraceHook, k);
902 lttv_hooks_remove_data(
903 lttv_hooks_by_id_find(tfs->parent.parent.event_by_id,
904 hook.id), hook.h, &g_array_index(after_hooks, LttvTraceHook, k));
905 }
906 }
907 g_debug("lttv_stats_remove_event_hooks()");
908 g_array_free(before_hooks, TRUE);
909 g_array_free(after_hooks, TRUE);
910 }
911 }
912
913
914 static void module_init()
915 {
916 LTTV_STATS_PROCESS_UNKNOWN = g_quark_from_string("unknown process");
917 LTTV_STATS_PROCESSES = g_quark_from_string("processes");
918 LTTV_STATS_CPU = g_quark_from_string("cpu");
919 LTTV_STATS_MODE_TYPES = g_quark_from_string("mode_types");
920 LTTV_STATS_MODES = g_quark_from_string("modes");
921 LTTV_STATS_SUBMODES = g_quark_from_string("submodes");
922 LTTV_STATS_EVENT_TYPES = g_quark_from_string("event_types");
923 LTTV_STATS_CPU_TIME = g_quark_from_string("cpu time");
924 LTTV_STATS_ELAPSED_TIME = g_quark_from_string("elapsed time");
925 LTTV_STATS_EVENTS = g_quark_from_string("events");
926 LTTV_STATS_EVENTS_COUNT = g_quark_from_string("events count");
927 LTTV_STATS_BEFORE_HOOKS = g_quark_from_string("saved stats before hooks");
928 LTTV_STATS_AFTER_HOOKS = g_quark_from_string("saved stats after hooks");
929 LTTV_STATS_USE_COUNT = g_quark_from_string("stats_use_count");
930 LTTV_STATS = g_quark_from_string("statistics");
931 LTTV_STATS_TRACEFILES = g_quark_from_string("tracefiles statistics");
932 LTTV_STATS_SUMMED = g_quark_from_string("statistics summed");
933 }
934
935 static void module_destroy()
936 {
937 }
938
939
940 LTTV_MODULE("stats", "Compute processes statistics", \
941 "Accumulate statistics for event types, processes and CPUs", \
942 module_init, module_destroy, "state");
943
944 /* Change the places where stats are called (create/read/write stats)
945
946 Check for options in batchtest.c to reduce writing and see what tests are
947 best candidates for performance analysis. Once OK, commit, move to main
948 and run tests. Update the gui for statistics. */
This page took 0.08588 seconds and 4 git commands to generate.