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