Add reference counts to state and stats saved attributes. This way, the
[lttv.git] / ltt / branches / poly / lttv / main / stats.c
CommitLineData
9c312311 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
b445142a 19
9f797243 20#include <stdio.h>
08b1c66e 21#include <lttv/module.h>
b445142a 22#include <lttv/stats.h>
2a2fa4f0 23#include <lttv/lttv.h>
f95bc830 24#include <lttv/attribute.h>
b445142a 25#include <ltt/facility.h>
26#include <ltt/trace.h>
27#include <ltt/event.h>
28
9f797243 29#define BUF_SIZE 256
30
b445142a 31GQuark
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,
f95bc830 42 LTTV_STATS_EVENTS_COUNT,
43 LTTV_STATS_USE_COUNT,
44 LTTV_STATS,
45 LTTV_STATS_TRACEFILES,
46 LTTV_STATS_SUMMED;
b445142a 47
48static GQuark
49 LTTV_STATS_BEFORE_HOOKS,
50 LTTV_STATS_AFTER_HOOKS;
51
52static void remove_all_processes(GHashTable *processes);
53
54static void
55find_event_tree(LttvTracefileStats *tfcs, GQuark process, GQuark cpu,
56 GQuark mode, GQuark sub_mode, LttvAttribute **events_tree,
57 LttvAttribute **event_types_tree);
58
59static void
60init(LttvTracesetStats *self, LttvTraceset *ts)
61{
dbb7bb09 62 guint i, j, nb_trace, nb_tracefile;
b445142a 63
64 LttvTraceContext *tc;
65
66 LttvTraceStats *tcs;
67
68 LttvTracefileContext *tfc;
69
70 LttvTracefileStats *tfcs;
71
72 LttTime timestamp = {0,0};
73
f95bc830 74 LttvAttributeValue v;
75
76 LttvAttribute
77 *stats_tree,
78 *tracefiles_stats;
79
b445142a 80 LTTV_TRACESET_CONTEXT_CLASS(g_type_class_peek(LTTV_TRACESET_STATE_TYPE))->
81 init((LttvTracesetContext *)self, ts);
82
f95bc830 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
b445142a 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]);
f95bc830 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 }
b445142a 107
dbb7bb09 108 nb_tracefile = ltt_trace_control_tracefile_number(tc->t) +
109 ltt_trace_per_cpu_tracefile_number(tc->t);
b445142a 110
dbb7bb09 111 for(j = 0 ; j < nb_tracefile ; j++) {
112 tfcs = LTTV_TRACEFILE_STATS(tc->tracefiles[j]);
f95bc830 113 tfcs->stats = lttv_attribute_find_subdir(tracefiles_stats,
114 tfcs->parent.cpu_name);
b445142a 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
124static void
125fini(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
f95bc830 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
b445142a 155 ts = self->parent.parent.ts;
156 nb_trace = lttv_traceset_number(ts);
157
158 for(i = 0 ; i < nb_trace ; i++) {
f95bc830 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;
b445142a 175
dbb7bb09 176 nb_tracefile = ltt_trace_control_tracefile_number(tc->t) +
177 ltt_trace_per_cpu_tracefile_number(tc->t);
b445142a 178
b445142a 179 for(j = 0 ; j < nb_tracefile ; j++) {
f95bc830 180 tfcs = ((LttvTracefileStats *)tfc = tc->tracefiles[j]);
181 tfcs->stats = NULL;
b445142a 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
191static LttvTracesetContext *
192new_traceset_context(LttvTracesetContext *self)
193{
194 return LTTV_TRACESET_CONTEXT(g_object_new(LTTV_TRACESET_STATS_TYPE, NULL));
195}
196
197
198static LttvTraceContext *
199new_trace_context(LttvTracesetContext *self)
200{
201 return LTTV_TRACE_CONTEXT(g_object_new(LTTV_TRACE_STATS_TYPE, NULL));
202}
203
204
205static LttvTracefileContext *
206new_tracefile_context(LttvTracesetContext *self)
207{
208 return LTTV_TRACEFILE_CONTEXT(g_object_new(LTTV_TRACEFILE_STATS_TYPE, NULL));
209}
210
211
212static void
213traceset_stats_instance_init (GTypeInstance *instance, gpointer g_class)
214{
215}
216
217
218static void
219traceset_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
226static void
227traceset_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
240GType
241lttv_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 */
dbb7bb09 252 sizeof (LttvTracesetStats),
b445142a 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
264static void
265trace_stats_instance_init (GTypeInstance *instance, gpointer g_class)
266{
267}
268
269
270static void
271trace_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
278static void
279trace_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
287GType
288lttv_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
311static void
312tracefile_stats_instance_init (GTypeInstance *instance, gpointer g_class)
313{
314}
315
316
317static void
318tracefile_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
325static void
326tracefile_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
334GType
335lttv_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
358static void
359find_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
380static 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
390static 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);
308711e5 398 delta = ltt_time_sub(tfcs->parent.parent.timestamp,
b445142a 399 tfcs->parent.process->state->change);
308711e5 400 *(cpu_time.v_time) = ltt_time_add(*(cpu_time.v_time), delta);
b445142a 401}
402
403
404static 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);
308711e5 412 delta = ltt_time_sub(tfcs->parent.parent.timestamp,
b445142a 413 tfcs->parent.process->state->entry);
308711e5 414 *(elapsed_time.v_time) = ltt_time_add(*(elapsed_time.v_time), delta);
b445142a 415
416 lttv_attribute_find(tfcs->current_events_tree, LTTV_STATS_CPU_TIME,
417 LTTV_TIME, &cpu_time);
308711e5 418 delta = ltt_time_sub(tfcs->parent.parent.timestamp,
b445142a 419 tfcs->parent.process->state->change);
308711e5 420 *(cpu_time.v_time) = ltt_time_add(*(cpu_time.v_time), delta);
b445142a 421}
422
423
424static gboolean before_syscall_entry(void *hook_data, void *call_data)
425{
426 mode_change((LttvTracefileStats *)call_data);
427 return FALSE;
428}
429
430
431static gboolean after_syscall_entry(void *hook_data, void *call_data)
432{
433 update_event_tree((LttvTracefileStats *)call_data);
434 return FALSE;
435}
436
437
438gboolean before_syscall_exit(void *hook_data, void *call_data)
439{
440 mode_end((LttvTracefileStats *)call_data);
441 return FALSE;
442}
443
444
445static gboolean after_syscall_exit(void *hook_data, void *call_data)
446{
447 update_event_tree((LttvTracefileStats *)call_data);
448 return FALSE;
449}
450
451
452gboolean before_trap_entry(void *hook_data, void *call_data)
453{
454 mode_change((LttvTracefileStats *)call_data);
455 return FALSE;
456}
457
458
459static gboolean after_trap_entry(void *hook_data, void *call_data)
460{
461 update_event_tree((LttvTracefileStats *)call_data);
462 return FALSE;
463}
464
465
466gboolean before_trap_exit(void *hook_data, void *call_data)
467{
468 mode_end((LttvTracefileStats *)call_data);
469 return FALSE;
470}
471
472
473gboolean after_trap_exit(void *hook_data, void *call_data)
474{
475 update_event_tree((LttvTracefileStats *)call_data);
476 return FALSE;
477}
478
479
480gboolean before_irq_entry(void *hook_data, void *call_data)
481{
482 mode_change((LttvTracefileStats *)call_data);
483 return FALSE;
484}
485
486
487gboolean after_irq_entry(void *hook_data, void *call_data)
488{
489 update_event_tree((LttvTracefileStats *)call_data);
490 return FALSE;
491}
492
493
494gboolean before_irq_exit(void *hook_data, void *call_data)
495{
496 mode_end((LttvTracefileStats *)call_data);
497 return FALSE;
498}
499
500
501gboolean after_irq_exit(void *hook_data, void *call_data)
502{
503 update_event_tree((LttvTracefileStats *)call_data);
504 return FALSE;
505}
506
507
508gboolean 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
2a2fa4f0 528 process = lttv_state_find_process_or_create(&(tfcs->parent), pid_in);
b445142a 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
541gboolean process_fork(void *hook_data, void *call_data)
542{
543 /* nothing to do for now */
544 return FALSE;
545}
546
547
548gboolean 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
556gboolean 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
f95bc830 576void
577lttv_stats_sum_trace(LttvTraceStats *self)
b445142a 578{
b445142a 579 LttvTraceStats *tcs;
580
b445142a 581 LttvAttributeType type;
582
583 LttvAttributeValue value;
584
585 LttvAttributeName name;
586
587 unsigned sum;
588
f95bc830 589 int i, j, k, l, m, nb_process, nb_cpu, nb_mode_type, nb_submode,
b445142a 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,
f95bc830 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);
b445142a 640
f95bc830 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));
b445142a 644
f95bc830 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);
b445142a 648
f95bc830 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);
b445142a 653 }
f95bc830 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);
b445142a 658 }
f95bc830 659 lttv_attribute_recursive_add(cpu_events_tree, mode_events_tree);
b445142a 660 }
f95bc830 661 lttv_attribute_recursive_add(process_modes_tree, cpu_tree);
662 lttv_attribute_recursive_add(trace_cpu_tree, cpu_tree);
b445142a 663 }
f95bc830 664 lttv_attribute_recursive_add(trace_modes_tree, process_modes_tree);
665 }
666}
667
668
669void
670lttv_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);
b445142a 696 lttv_attribute_recursive_add(traceset_modes_tree, trace_modes_tree);
697 }
b445142a 698}
699
700
701lttv_stats_add_event_hooks(LttvTracesetStats *self)
702{
703 LttvTraceset *traceset = self->parent.parent.ts;
704
dbb7bb09 705 guint i, j, k, nb_trace, nb_tracefile;
b445142a 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
dbb7bb09 794 nb_tracefile = ltt_trace_control_tracefile_number(ts->parent.parent.t) +
795 ltt_trace_per_cpu_tracefile_number(ts->parent.parent.t);
b445142a 796
dbb7bb09 797 for(j = 0 ; j < nb_tracefile ; j++) {
798 tfs = LTTV_TRACEFILE_STATS(ts->parent.parent.tracefiles[j]);
b445142a 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 }
b445142a 821}
822
823
824lttv_stats_remove_event_hooks(LttvTracesetStats *self)
825{
826 LttvTraceset *traceset = self->parent.parent.ts;
827
dbb7bb09 828 guint i, j, k, nb_trace, nb_tracefile;
b445142a 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
dbb7bb09 854 nb_tracefile = ltt_trace_control_tracefile_number(ts->parent.parent.t) +
855 ltt_trace_per_cpu_tracefile_number(ts->parent.parent.t);
b445142a 856
dbb7bb09 857 for(j = 0 ; j < nb_tracefile ; j++) {
858 tfs = LTTV_TRACEFILE_STATS(ts->parent.parent.tracefiles[j]);
b445142a 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 }
2a2fa4f0 875 g_debug("lttv_stats_remove_event_hooks()");
b445142a 876 g_array_free(before_hooks, TRUE);
877 g_array_free(after_hooks, TRUE);
878 }
9f797243 879}
08b1c66e 880
881
882static 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");
f95bc830 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");
08b1c66e 901}
902
903static void module_destroy()
904{
905}
906
907
908LTTV_MODULE("stats", "Compute processes statistics", \
909 "Accumulate statistics for event types, processes and CPUs", \
910 module_init, module_destroy, "state");
f95bc830 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.063572 seconds and 4 git commands to generate.