gobjects referenced in attributes. No more recursive_free
[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(self->parent.parent.ts_a,LTTV_STATS);
84 lttv_attribute_find(self->parent.parent.ts_a, LTTV_STATS_USE_COUNT,
85 LTTV_UINT, &v);
86
87 *(v.v_uint)++;
88 if(*(v.v_uint) == 1) {
89 g_assert(lttv_attribute_get_number(self->stats) == 0);
90 }
91
92 nb_trace = lttv_traceset_number(ts);
93
94 for(i = 0 ; i < nb_trace ; i++) {
95 tc = (LTTV_TRACESET_CONTEXT(self)->traces[i]);
96 tcs = (LttvTraceStats *)tc;
97
98 tcs->stats = lttv_attribute_find_subdir(tcs->parent.parent.t_a,LTTV_STATS);
99 tracefiles_stats = lttv_attribute_find_subdir(tcs->parent.parent.t_a,
100 LTTV_STATS_TRACEFILES);
101 lttv_attribute_find(tcs->parent.parent.t_a, LTTV_STATS_USE_COUNT,
102 LTTV_UINT, &v);
103
104 *(v.v_uint)++;
105 if(*(v.v_uint) == 1) {
106 g_assert(lttv_attribute_get_number(tcs->stats) == 0);
107 }
108
109 nb_tracefile = ltt_trace_control_tracefile_number(tc->t) +
110 ltt_trace_per_cpu_tracefile_number(tc->t);
111
112 for(j = 0 ; j < nb_tracefile ; j++) {
113 tfcs = LTTV_TRACEFILE_STATS(tc->tracefiles[j]);
114 tfcs->stats = lttv_attribute_find_subdir(tracefiles_stats,
115 tfcs->parent.cpu_name);
116 find_event_tree(tfcs, LTTV_STATS_PROCESS_UNKNOWN,
117 tfcs->parent.cpu_name, LTTV_STATE_MODE_UNKNOWN,
118 LTTV_STATE_SUBMODE_UNKNOWN, &tfcs->current_events_tree,
119 &tfcs->current_event_types_tree);
120 }
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 };
255
256 type = g_type_register_static (LTTV_TRACESET_STATE_TYPE, "LttvTracesetStatsType",
257 &info, 0);
258 }
259 return type;
260 }
261
262
263 static void
264 trace_stats_instance_init (GTypeInstance *instance, gpointer g_class)
265 {
266 }
267
268
269 static void
270 trace_stats_finalize (LttvTraceStats *self)
271 {
272 G_OBJECT_CLASS(g_type_class_peek(LTTV_TRACE_STATE_TYPE))->
273 finalize(G_OBJECT(self));
274 }
275
276
277 static void
278 trace_stats_class_init (LttvTraceContextClass *klass)
279 {
280 GObjectClass *gobject_class = G_OBJECT_CLASS(klass);
281
282 gobject_class->finalize = (void (*)(GObject *self)) trace_stats_finalize;
283 }
284
285
286 GType
287 lttv_trace_stats_get_type(void)
288 {
289 static GType type = 0;
290 if (type == 0) {
291 static const GTypeInfo info = {
292 sizeof (LttvTraceStatsClass),
293 NULL, /* base_init */
294 NULL, /* base_finalize */
295 (GClassInitFunc) trace_stats_class_init, /* class_init */
296 NULL, /* class_finalize */
297 NULL, /* class_data */
298 sizeof (LttvTraceStats),
299 0, /* n_preallocs */
300 (GInstanceInitFunc) trace_stats_instance_init /* instance_init */
301 };
302
303 type = g_type_register_static (LTTV_TRACE_STATE_TYPE,
304 "LttvTraceStatsType", &info, 0);
305 }
306 return type;
307 }
308
309
310 static void
311 tracefile_stats_instance_init (GTypeInstance *instance, gpointer g_class)
312 {
313 }
314
315
316 static void
317 tracefile_stats_finalize (LttvTracefileStats *self)
318 {
319 G_OBJECT_CLASS(g_type_class_peek(LTTV_TRACEFILE_STATE_TYPE))->
320 finalize(G_OBJECT(self));
321 }
322
323
324 static void
325 tracefile_stats_class_init (LttvTracefileStatsClass *klass)
326 {
327 GObjectClass *gobject_class = G_OBJECT_CLASS(klass);
328
329 gobject_class->finalize = (void (*)(GObject *self)) tracefile_stats_finalize;
330 }
331
332
333 GType
334 lttv_tracefile_stats_get_type(void)
335 {
336 static GType type = 0;
337 if (type == 0) {
338 static const GTypeInfo info = {
339 sizeof (LttvTracefileStatsClass),
340 NULL, /* base_init */
341 NULL, /* base_finalize */
342 (GClassInitFunc) tracefile_stats_class_init, /* class_init */
343 NULL, /* class_finalize */
344 NULL, /* class_data */
345 sizeof (LttvTracefileStats),
346 0, /* n_preallocs */
347 (GInstanceInitFunc) tracefile_stats_instance_init /* instance_init */
348 };
349
350 type = g_type_register_static (LTTV_TRACEFILE_STATE_TYPE,
351 "LttvTracefileStatsType", &info, 0);
352 }
353 return type;
354 }
355
356
357 static void
358 find_event_tree(LttvTracefileStats *tfcs, GQuark process, GQuark cpu,
359 GQuark mode, GQuark sub_mode, LttvAttribute **events_tree,
360 LttvAttribute **event_types_tree)
361 {
362 LttvAttribute *a;
363
364 LttvTraceStats *tcs = LTTV_TRACE_STATS(tfcs->parent.parent.t_context);
365 a = lttv_attribute_find_subdir(tcs->stats, LTTV_STATS_PROCESSES);
366 a = lttv_attribute_find_subdir(a, tfcs->parent.process->pid_time);
367 a = lttv_attribute_find_subdir(a, LTTV_STATS_CPU);
368 a = lttv_attribute_find_subdir(a, tfcs->parent.cpu_name);
369 a = lttv_attribute_find_subdir(a, LTTV_STATS_MODE_TYPES);
370 a = lttv_attribute_find_subdir(a, tfcs->parent.process->state->t);
371 a = lttv_attribute_find_subdir(a, LTTV_STATS_SUBMODES);
372 a = lttv_attribute_find_subdir(a, tfcs->parent.process->state->n);
373 *events_tree = a;
374 a = lttv_attribute_find_subdir(a, LTTV_STATS_EVENT_TYPES);
375 *event_types_tree = a;
376 }
377
378
379 static void update_event_tree(LttvTracefileStats *tfcs)
380 {
381 LttvExecutionState *es = tfcs->parent.process->state;
382
383 find_event_tree(tfcs, tfcs->parent.process->pid_time, tfcs->parent.cpu_name,
384 es->t, es->n, &(tfcs->current_events_tree),
385 &(tfcs->current_event_types_tree));
386 }
387
388
389 static void mode_change(LttvTracefileStats *tfcs)
390 {
391 LttvAttributeValue cpu_time;
392
393 LttTime delta;
394
395 lttv_attribute_find(tfcs->current_events_tree, LTTV_STATS_CPU_TIME,
396 LTTV_TIME, &cpu_time);
397 delta = ltt_time_sub(tfcs->parent.parent.timestamp,
398 tfcs->parent.process->state->change);
399 *(cpu_time.v_time) = ltt_time_add(*(cpu_time.v_time), delta);
400 }
401
402
403 static void mode_end(LttvTracefileStats *tfcs)
404 {
405 LttvAttributeValue elapsed_time, cpu_time;
406
407 LttTime delta;
408
409 lttv_attribute_find(tfcs->current_events_tree, LTTV_STATS_ELAPSED_TIME,
410 LTTV_TIME, &elapsed_time);
411 delta = ltt_time_sub(tfcs->parent.parent.timestamp,
412 tfcs->parent.process->state->entry);
413 *(elapsed_time.v_time) = ltt_time_add(*(elapsed_time.v_time), delta);
414
415 lttv_attribute_find(tfcs->current_events_tree, LTTV_STATS_CPU_TIME,
416 LTTV_TIME, &cpu_time);
417 delta = ltt_time_sub(tfcs->parent.parent.timestamp,
418 tfcs->parent.process->state->change);
419 *(cpu_time.v_time) = ltt_time_add(*(cpu_time.v_time), delta);
420 }
421
422
423 static gboolean before_syscall_entry(void *hook_data, void *call_data)
424 {
425 mode_change((LttvTracefileStats *)call_data);
426 return FALSE;
427 }
428
429
430 static gboolean after_syscall_entry(void *hook_data, void *call_data)
431 {
432 update_event_tree((LttvTracefileStats *)call_data);
433 return FALSE;
434 }
435
436
437 gboolean before_syscall_exit(void *hook_data, void *call_data)
438 {
439 mode_end((LttvTracefileStats *)call_data);
440 return FALSE;
441 }
442
443
444 static gboolean after_syscall_exit(void *hook_data, void *call_data)
445 {
446 update_event_tree((LttvTracefileStats *)call_data);
447 return FALSE;
448 }
449
450
451 gboolean before_trap_entry(void *hook_data, void *call_data)
452 {
453 mode_change((LttvTracefileStats *)call_data);
454 return FALSE;
455 }
456
457
458 static gboolean after_trap_entry(void *hook_data, void *call_data)
459 {
460 update_event_tree((LttvTracefileStats *)call_data);
461 return FALSE;
462 }
463
464
465 gboolean before_trap_exit(void *hook_data, void *call_data)
466 {
467 mode_end((LttvTracefileStats *)call_data);
468 return FALSE;
469 }
470
471
472 gboolean after_trap_exit(void *hook_data, void *call_data)
473 {
474 update_event_tree((LttvTracefileStats *)call_data);
475 return FALSE;
476 }
477
478
479 gboolean before_irq_entry(void *hook_data, void *call_data)
480 {
481 mode_change((LttvTracefileStats *)call_data);
482 return FALSE;
483 }
484
485
486 gboolean after_irq_entry(void *hook_data, void *call_data)
487 {
488 update_event_tree((LttvTracefileStats *)call_data);
489 return FALSE;
490 }
491
492
493 gboolean before_irq_exit(void *hook_data, void *call_data)
494 {
495 mode_end((LttvTracefileStats *)call_data);
496 return FALSE;
497 }
498
499
500 gboolean after_irq_exit(void *hook_data, void *call_data)
501 {
502 update_event_tree((LttvTracefileStats *)call_data);
503 return FALSE;
504 }
505
506
507 gboolean before_schedchange(void *hook_data, void *call_data)
508 {
509 LttvTraceHook *h = (LttvTraceHook *)hook_data;
510
511 LttvTracefileStats *tfcs = (LttvTracefileStats *)call_data;
512
513 guint pid_in, pid_out, state_out;
514
515 LttvProcessState *process;
516
517 pid_in = ltt_event_get_unsigned(tfcs->parent.parent.e, h->f1);
518 pid_out = ltt_event_get_unsigned(tfcs->parent.parent.e, h->f2);
519 state_out = ltt_event_get_unsigned(tfcs->parent.parent.e, h->f3);
520
521 /* compute the time for the process to schedule out */
522
523 mode_change(tfcs);
524
525 /* get the information for the process scheduled in */
526
527 process = lttv_state_find_process_or_create(&(tfcs->parent), pid_in);
528
529 find_event_tree(tfcs, process->pid_time, tfcs->parent.cpu_name,
530 process->state->t, process->state->n, &(tfcs->current_events_tree),
531 &(tfcs->current_event_types_tree));
532
533 /* compute the time waiting for the process to schedule in */
534
535 mode_change(tfcs);
536 return FALSE;
537 }
538
539
540 gboolean process_fork(void *hook_data, void *call_data)
541 {
542 /* nothing to do for now */
543 return FALSE;
544 }
545
546
547 gboolean process_exit(void *hook_data, void *call_data)
548 {
549 /* We should probably exit all modes here or we could do that at
550 schedule out. */
551 return FALSE;
552 }
553
554
555 gboolean every_event(void *hook_data, void *call_data)
556 {
557 LttvTracefileStats *tfcs = (LttvTracefileStats *)call_data;
558
559 LttvAttributeValue v;
560
561 /* The current branch corresponds to the tracefile/process/interrupt state.
562 Statistics are added within it, to count the number of events of this
563 type occuring in this context. A quark has been pre-allocated for each
564 event type and is used as name. */
565
566 lttv_attribute_find(tfcs->current_event_types_tree,
567 ((LttvTraceState *)(tfcs->parent.parent.t_context))->
568 eventtype_names[ltt_event_eventtype_id(tfcs->parent.parent.e)],
569 LTTV_UINT, &v);
570 (*(v.v_uint))++;
571 return FALSE;
572 }
573
574
575 void
576 lttv_stats_sum_trace(LttvTraceStats *self)
577 {
578 LttvTraceStats *tcs;
579
580 LttvAttributeType type;
581
582 LttvAttributeValue value;
583
584 LttvAttributeName name;
585
586 unsigned sum;
587
588 int i, j, k, l, m, nb_process, nb_cpu, nb_mode_type, nb_submode,
589 nb_event_type;
590
591 LttvAttribute *main_tree, *processes_tree, *process_tree, *cpus_tree,
592 *cpu_tree, *mode_tree, *mode_types_tree, *submodes_tree,
593 *submode_tree, *event_types_tree, *mode_events_tree,
594 *cpu_events_tree, *process_modes_tree, *trace_cpu_tree,
595 *trace_modes_tree;
596
597 main_tree = self->stats;
598
599 lttv_attribute_find(self->parent.parent.t_a, LTTV_STATS_SUMMED,
600 LTTV_UINT, &value);
601 if(*(value.v_uint) != 0) return;
602 *(value.v_uint) = 1;
603
604 processes_tree = lttv_attribute_find_subdir(main_tree,
605 LTTV_STATS_PROCESSES);
606 trace_modes_tree = lttv_attribute_find_subdir(main_tree, LTTV_STATS_MODES);
607 nb_process = lttv_attribute_get_number(processes_tree);
608
609 for(i = 0 ; i < nb_process ; i++) {
610 type = lttv_attribute_get(processes_tree, i, &name, &value);
611 process_tree = LTTV_ATTRIBUTE(*(value.v_gobject));
612
613 cpus_tree = lttv_attribute_find_subdir(process_tree, LTTV_STATS_CPU);
614 process_modes_tree = lttv_attribute_find_subdir(process_tree,
615 LTTV_STATS_MODES);
616 nb_cpu = lttv_attribute_get_number(cpus_tree);
617
618 for(j = 0 ; j < nb_cpu ; j++) {
619 type = lttv_attribute_get(cpus_tree, j, &name, &value);
620 cpu_tree = LTTV_ATTRIBUTE(*(value.v_gobject));
621
622 mode_types_tree = lttv_attribute_find_subdir(cpu_tree,
623 LTTV_STATS_MODE_TYPES);
624 cpu_events_tree = lttv_attribute_find_subdir(cpu_tree,
625 LTTV_STATS_EVENTS);
626 trace_cpu_tree = lttv_attribute_find_subdir(main_tree, LTTV_STATS_CPU);
627 trace_cpu_tree = lttv_attribute_find_subdir(trace_cpu_tree, name);
628 nb_mode_type = lttv_attribute_get_number(mode_types_tree);
629
630 for(k = 0 ; k < nb_mode_type ; k++) {
631 type = lttv_attribute_get(mode_types_tree, k, &name, &value);
632 mode_tree = LTTV_ATTRIBUTE(*(value.v_gobject));
633
634 submodes_tree = lttv_attribute_find_subdir(mode_tree,
635 LTTV_STATS_SUBMODES);
636 mode_events_tree = lttv_attribute_find_subdir(mode_tree,
637 LTTV_STATS_EVENTS);
638 nb_submode = lttv_attribute_get_number(submodes_tree);
639
640 for(l = 0 ; l < nb_submode ; l++) {
641 type = lttv_attribute_get(submodes_tree, l, &name, &value);
642 submode_tree = LTTV_ATTRIBUTE(*(value.v_gobject));
643
644 event_types_tree = lttv_attribute_find_subdir(submode_tree,
645 LTTV_STATS_EVENT_TYPES);
646 nb_event_type = lttv_attribute_get_number(event_types_tree);
647
648 sum = 0;
649 for(m = 0 ; m < nb_event_type ; m++) {
650 type = lttv_attribute_get(event_types_tree, m, &name, &value);
651 sum += *(value.v_uint);
652 }
653 lttv_attribute_find(submode_tree, LTTV_STATS_EVENTS_COUNT,
654 LTTV_UINT, &value);
655 *(value.v_uint) = sum;
656 lttv_attribute_recursive_add(mode_events_tree, submode_tree);
657 }
658 lttv_attribute_recursive_add(cpu_events_tree, mode_events_tree);
659 }
660 lttv_attribute_recursive_add(process_modes_tree, cpu_tree);
661 lttv_attribute_recursive_add(trace_cpu_tree, cpu_tree);
662 }
663 lttv_attribute_recursive_add(trace_modes_tree, process_modes_tree);
664 }
665 }
666
667
668 void
669 lttv_stats_sum_traceset(LttvTracesetStats *self)
670 {
671 LttvTraceset *traceset = self->parent.parent.ts;
672
673 LttvTraceStats *tcs;
674
675 int i, nb_trace;
676
677 LttvAttribute *main_tree, *trace_modes_tree, *traceset_modes_tree;
678
679 LttvAttributeValue value;
680
681 lttv_attribute_find(self->parent.parent.ts_a, LTTV_STATS_SUMMED,
682 LTTV_UINT, &value);
683 if(*(value.v_uint) != 0) return;
684 *(value.v_uint) = 1;
685
686 traceset_modes_tree = lttv_attribute_find_subdir(self->stats,
687 LTTV_STATS_MODES);
688 nb_trace = lttv_traceset_number(traceset);
689
690 for(i = 0 ; i < nb_trace ; i++) {
691 tcs = (LttvTraceStats *)(self->parent.parent.traces[i]);
692 lttv_stats_sum_trace(tcs);
693 main_tree = tcs->stats;
694 trace_modes_tree = lttv_attribute_find_subdir(main_tree, LTTV_STATS_MODES);
695 lttv_attribute_recursive_add(traceset_modes_tree, trace_modes_tree);
696 }
697 }
698
699
700 lttv_stats_add_event_hooks(LttvTracesetStats *self)
701 {
702 LttvTraceset *traceset = self->parent.parent.ts;
703
704 guint i, j, k, nb_trace, nb_tracefile;
705
706 LttFacility *f;
707
708 LttEventType *et;
709
710 LttvTraceStats *ts;
711
712 LttvTracefileStats *tfs;
713
714 void *hook_data;
715
716 GArray *hooks, *before_hooks, *after_hooks;
717
718 LttvTraceHook hook;
719
720 LttvAttributeValue val;
721
722 nb_trace = lttv_traceset_number(traceset);
723 for(i = 0 ; i < nb_trace ; i++) {
724 ts = (LttvTraceStats *)self->parent.parent.traces[i];
725
726 /* Find the eventtype id for the following events and register the
727 associated by id hooks. */
728
729 hooks = g_array_new(FALSE, FALSE, sizeof(LttvTraceHook));
730 g_array_set_size(hooks, 7);
731
732 lttv_trace_find_hook(ts->parent.parent.t, "core","syscall_entry",
733 "syscall_id", NULL, NULL, before_syscall_entry,
734 &g_array_index(hooks, LttvTraceHook, 0));
735
736 lttv_trace_find_hook(ts->parent.parent.t, "core", "syscall_exit", NULL,
737 NULL, NULL, before_syscall_exit,
738 &g_array_index(hooks, LttvTraceHook, 1));
739
740 lttv_trace_find_hook(ts->parent.parent.t, "core", "trap_entry", "trap_id",
741 NULL, NULL, before_trap_entry,
742 &g_array_index(hooks, LttvTraceHook, 2));
743
744 lttv_trace_find_hook(ts->parent.parent.t, "core", "trap_exit", NULL, NULL,
745 NULL, before_trap_exit, &g_array_index(hooks, LttvTraceHook, 3));
746
747 lttv_trace_find_hook(ts->parent.parent.t, "core", "irq_entry", "irq_id",
748 NULL, NULL, before_irq_entry, &g_array_index(hooks, LttvTraceHook, 4));
749
750 lttv_trace_find_hook(ts->parent.parent.t, "core", "irq_exit", NULL, NULL,
751 NULL, before_irq_exit, &g_array_index(hooks, LttvTraceHook, 5));
752
753 lttv_trace_find_hook(ts->parent.parent.t, "core", "schedchange", "in",
754 "out", "out_state", before_schedchange,
755 &g_array_index(hooks, LttvTraceHook, 6));
756
757 before_hooks = hooks;
758
759 hooks = g_array_new(FALSE, FALSE, sizeof(LttvTraceHook));
760 g_array_set_size(hooks, 8);
761
762 lttv_trace_find_hook(ts->parent.parent.t, "core","syscall_entry",
763 "syscall_id", NULL, NULL, after_syscall_entry,
764 &g_array_index(hooks, LttvTraceHook, 0));
765
766 lttv_trace_find_hook(ts->parent.parent.t, "core", "syscall_exit", NULL,
767 NULL, NULL, after_syscall_exit,
768 &g_array_index(hooks, LttvTraceHook, 1));
769
770 lttv_trace_find_hook(ts->parent.parent.t, "core", "trap_entry", "trap_id",
771 NULL, NULL, after_trap_entry, &g_array_index(hooks, LttvTraceHook, 2));
772
773 lttv_trace_find_hook(ts->parent.parent.t, "core", "trap_exit", NULL, NULL,
774 NULL, after_trap_exit, &g_array_index(hooks, LttvTraceHook, 3));
775
776 lttv_trace_find_hook(ts->parent.parent.t, "core", "irq_entry", "irq_id",
777 NULL, NULL, after_irq_entry, &g_array_index(hooks, LttvTraceHook, 4));
778
779 lttv_trace_find_hook(ts->parent.parent.t, "core", "irq_exit", NULL, NULL,
780 NULL, after_irq_exit, &g_array_index(hooks, LttvTraceHook, 5));
781
782 lttv_trace_find_hook(ts->parent.parent.t, "core", "process_fork",
783 "child_pid", NULL, NULL, process_fork,
784 &g_array_index(hooks, LttvTraceHook, 6));
785
786 lttv_trace_find_hook(ts->parent.parent.t, "core", "process_exit", NULL,
787 NULL, NULL, process_exit, &g_array_index(hooks, LttvTraceHook, 7));
788
789 after_hooks = hooks;
790
791 /* Add these hooks to each event_by_id hooks list */
792
793 nb_tracefile = ltt_trace_control_tracefile_number(ts->parent.parent.t) +
794 ltt_trace_per_cpu_tracefile_number(ts->parent.parent.t);
795
796 for(j = 0 ; j < nb_tracefile ; j++) {
797 tfs = LTTV_TRACEFILE_STATS(ts->parent.parent.tracefiles[j]);
798 lttv_hooks_add(tfs->parent.parent.event, every_event, NULL,
799 LTTV_PRIO_DEFAULT);
800
801 for(k = 0 ; k < before_hooks->len ; k++) {
802 hook = g_array_index(before_hooks, LttvTraceHook, k);
803 lttv_hooks_add(lttv_hooks_by_id_find(
804 tfs->parent.parent.event_by_id,
805 hook.id), hook.h, &g_array_index(before_hooks, LttvTraceHook, k),
806 LTTV_PRIO_STATS_BEFORE_STATE);
807 }
808 for(k = 0 ; k < after_hooks->len ; k++) {
809 hook = g_array_index(after_hooks, LttvTraceHook, k);
810 lttv_hooks_add(lttv_hooks_by_id_find(
811 tfs->parent.parent.event_by_id,
812 hook.id), hook.h, &g_array_index(after_hooks, LttvTraceHook, k),
813 LTTV_PRIO_STATS_AFTER_STATE);
814 }
815 }
816 lttv_attribute_find(self->parent.parent.a, LTTV_STATS_BEFORE_HOOKS,
817 LTTV_POINTER, &val);
818 *(val.v_pointer) = before_hooks;
819 lttv_attribute_find(self->parent.parent.a, LTTV_STATS_AFTER_HOOKS,
820 LTTV_POINTER, &val);
821 *(val.v_pointer) = after_hooks;
822 }
823 }
824
825
826 lttv_stats_remove_event_hooks(LttvTracesetStats *self)
827 {
828 LttvTraceset *traceset = self->parent.parent.ts;
829
830 guint i, j, k, nb_trace, nb_tracefile;
831
832 LttvTraceStats *ts;
833
834 LttvTracefileStats *tfs;
835
836 void *hook_data;
837
838 GArray *before_hooks, *after_hooks;
839
840 LttvTraceHook hook;
841
842 LttvAttributeValue val;
843
844 nb_trace = lttv_traceset_number(traceset);
845 for(i = 0 ; i < nb_trace ; i++) {
846 ts = LTTV_TRACE_STATS(self->parent.parent.traces[i]);
847 lttv_attribute_find(self->parent.parent.a, LTTV_STATS_BEFORE_HOOKS,
848 LTTV_POINTER, &val);
849 before_hooks = *(val.v_pointer);
850 lttv_attribute_find(self->parent.parent.a, LTTV_STATS_AFTER_HOOKS,
851 LTTV_POINTER, &val);
852 after_hooks = *(val.v_pointer);
853
854 /* Remove these hooks from each event_by_id hooks list */
855
856 nb_tracefile = ltt_trace_control_tracefile_number(ts->parent.parent.t) +
857 ltt_trace_per_cpu_tracefile_number(ts->parent.parent.t);
858
859 for(j = 0 ; j < nb_tracefile ; j++) {
860 tfs = LTTV_TRACEFILE_STATS(ts->parent.parent.tracefiles[j]);
861 lttv_hooks_remove_data(tfs->parent.parent.event, every_event,
862 NULL);
863
864 for(k = 0 ; k < before_hooks->len ; k++) {
865 hook = g_array_index(before_hooks, LttvTraceHook, k);
866 lttv_hooks_remove_data(
867 lttv_hooks_by_id_find(tfs->parent.parent.event_by_id,
868 hook.id), hook.h, &g_array_index(before_hooks, LttvTraceHook, k));
869 }
870 for(k = 0 ; k < after_hooks->len ; k++) {
871 hook = g_array_index(after_hooks, LttvTraceHook, k);
872 lttv_hooks_remove_data(
873 lttv_hooks_by_id_find(tfs->parent.parent.event_by_id,
874 hook.id), hook.h, &g_array_index(after_hooks, LttvTraceHook, k));
875 }
876 }
877 g_debug("lttv_stats_remove_event_hooks()");
878 g_array_free(before_hooks, TRUE);
879 g_array_free(after_hooks, TRUE);
880 }
881 }
882
883
884 static void module_init()
885 {
886 LTTV_STATS_PROCESS_UNKNOWN = g_quark_from_string("unknown process");
887 LTTV_STATS_PROCESSES = g_quark_from_string("processes");
888 LTTV_STATS_CPU = g_quark_from_string("cpu");
889 LTTV_STATS_MODE_TYPES = g_quark_from_string("mode_types");
890 LTTV_STATS_MODES = g_quark_from_string("modes");
891 LTTV_STATS_SUBMODES = g_quark_from_string("submodes");
892 LTTV_STATS_EVENT_TYPES = g_quark_from_string("event_types");
893 LTTV_STATS_CPU_TIME = g_quark_from_string("cpu time");
894 LTTV_STATS_ELAPSED_TIME = g_quark_from_string("elapsed time");
895 LTTV_STATS_EVENTS = g_quark_from_string("events");
896 LTTV_STATS_EVENTS_COUNT = g_quark_from_string("events count");
897 LTTV_STATS_BEFORE_HOOKS = g_quark_from_string("saved stats before hooks");
898 LTTV_STATS_AFTER_HOOKS = g_quark_from_string("saved stats after hooks");
899 LTTV_STATS_USE_COUNT = g_quark_from_string("stats_use_count");
900 LTTV_STATS = g_quark_from_string("statistics");
901 LTTV_STATS_TRACEFILES = g_quark_from_string("tracefiles statistics");
902 LTTV_STATS_SUMMED = g_quark_from_string("statistics summed");
903 }
904
905 static void module_destroy()
906 {
907 }
908
909
910 LTTV_MODULE("stats", "Compute processes statistics", \
911 "Accumulate statistics for event types, processes and CPUs", \
912 module_init, module_destroy, "state");
913
914 /* Change the places where stats are called (create/read/write stats)
915
916 Check for options in batchtest.c to reduce writing and see what tests are
917 best candidates for performance analysis. Once OK, commit, move to main
918 and run tests. Update the gui for statistics. */
This page took 0.047292 seconds and 4 git commands to generate.