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