fix smp in control flow view
[lttv.git] / ltt / branches / poly / lttv / lttv / 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
4e4d11b3 19#ifdef HAVE_CONFIG_H
20#include <config.h>
21#endif
b445142a 22
9f797243 23#include <stdio.h>
08b1c66e 24#include <lttv/module.h>
b445142a 25#include <lttv/stats.h>
2a2fa4f0 26#include <lttv/lttv.h>
f95bc830 27#include <lttv/attribute.h>
b445142a 28#include <ltt/facility.h>
29#include <ltt/trace.h>
30#include <ltt/event.h>
826f1ab2 31#include <ltt/type.h>
b445142a 32
9f797243 33#define BUF_SIZE 256
34
b445142a 35GQuark
36 LTTV_STATS_PROCESS_UNKNOWN,
37 LTTV_STATS_PROCESSES,
38 LTTV_STATS_CPU,
39 LTTV_STATS_MODE_TYPES,
40 LTTV_STATS_MODES,
41 LTTV_STATS_SUBMODES,
42 LTTV_STATS_EVENT_TYPES,
43 LTTV_STATS_CPU_TIME,
44 LTTV_STATS_ELAPSED_TIME,
45 LTTV_STATS_EVENTS,
f95bc830 46 LTTV_STATS_EVENTS_COUNT,
47 LTTV_STATS_USE_COUNT,
48 LTTV_STATS,
49 LTTV_STATS_TRACEFILES,
50 LTTV_STATS_SUMMED;
b445142a 51
52static GQuark
53 LTTV_STATS_BEFORE_HOOKS,
54 LTTV_STATS_AFTER_HOOKS;
55
b445142a 56static void
00e74b69 57find_event_tree(LttvTracefileStats *tfcs, GQuark pid_time, GQuark cpu,
b445142a 58 GQuark mode, GQuark sub_mode, LttvAttribute **events_tree,
59 LttvAttribute **event_types_tree);
60
61static void
62init(LttvTracesetStats *self, LttvTraceset *ts)
63{
dbb7bb09 64 guint i, j, nb_trace, nb_tracefile;
b445142a 65
66 LttvTraceContext *tc;
67
68 LttvTraceStats *tcs;
69
70 LttvTracefileContext *tfc;
71
3c9bb8b1 72 LttvTracefileContext **tfs;
b445142a 73 LttvTracefileStats *tfcs;
74
75 LttTime timestamp = {0,0};
76
f95bc830 77 LttvAttributeValue v;
78
79 LttvAttribute
80 *stats_tree,
81 *tracefiles_stats;
82
b445142a 83 LTTV_TRACESET_CONTEXT_CLASS(g_type_class_peek(LTTV_TRACESET_STATE_TYPE))->
84 init((LttvTracesetContext *)self, ts);
85
d3e01c7a 86 self->stats = lttv_attribute_find_subdir(
87 lttv_traceset_attribute(self->parent.parent.ts),
88 LTTV_STATS);
89 lttv_attribute_find(lttv_traceset_attribute(self->parent.parent.ts),
90 LTTV_STATS_USE_COUNT,
91 LTTV_UINT, &v);
f95bc830 92
93 *(v.v_uint)++;
94 if(*(v.v_uint) == 1) {
95 g_assert(lttv_attribute_get_number(self->stats) == 0);
96 }
97
b445142a 98 nb_trace = lttv_traceset_number(ts);
99
100 for(i = 0 ; i < nb_trace ; i++) {
021eeb41 101 tc = self->parent.parent.traces[i];
102 tcs = LTTV_TRACE_STATS(tc);
f95bc830 103
104 tcs->stats = lttv_attribute_find_subdir(tcs->parent.parent.t_a,LTTV_STATS);
105 tracefiles_stats = lttv_attribute_find_subdir(tcs->parent.parent.t_a,
106 LTTV_STATS_TRACEFILES);
107 lttv_attribute_find(tcs->parent.parent.t_a, LTTV_STATS_USE_COUNT,
108 LTTV_UINT, &v);
109
110 *(v.v_uint)++;
111 if(*(v.v_uint) == 1) {
112 g_assert(lttv_attribute_get_number(tcs->stats) == 0);
113 }
b445142a 114
eed2ef37 115 nb_tracefile = tc->tracefiles->len;
b445142a 116
dbb7bb09 117 for(j = 0 ; j < nb_tracefile ; j++) {
3c9bb8b1 118 tfs = &g_array_index(tc->tracefiles,
119 LttvTracefileContext*, j);
120 tfcs = LTTV_TRACEFILE_STATS(*tfs);
f95bc830 121 tfcs->stats = lttv_attribute_find_subdir(tracefiles_stats,
348c6ba8 122 ltt_tracefile_long_name(tfcs->parent.parent.tf));
b445142a 123 find_event_tree(tfcs, LTTV_STATS_PROCESS_UNKNOWN,
348c6ba8 124 ltt_tracefile_long_name(tfcs->parent.parent.tf),
125 LTTV_STATE_MODE_UNKNOWN,
b445142a 126 LTTV_STATE_SUBMODE_UNKNOWN, &tfcs->current_events_tree,
127 &tfcs->current_event_types_tree);
128 }
129 }
130}
131
b445142a 132static void
133fini(LttvTracesetStats *self)
134{
135 guint i, j, nb_trace, nb_tracefile;
136
137 LttvTraceset *ts;
138
139 LttvTraceContext *tc;
140
141 LttvTraceStats *tcs;
142
143 LttvTracefileContext *tfc;
144
145 LttvTracefileStats *tfcs;
146
147 LttTime timestamp = {0,0};
148
f95bc830 149 LttvAttributeValue v;
150
151 LttvAttribute *tracefiles_stats;
152
153 lttv_attribute_find(self->parent.parent.ts_a, LTTV_STATS_USE_COUNT,
154 LTTV_UINT, &v);
155 *(v.v_uint)--;
156
157 if(*(v.v_uint) == 0) {
158 lttv_attribute_remove_by_name(self->parent.parent.ts_a, LTTV_STATS);
f95bc830 159 }
160 self->stats = NULL;
161
b445142a 162 ts = self->parent.parent.ts;
163 nb_trace = lttv_traceset_number(ts);
164
165 for(i = 0 ; i < nb_trace ; i++) {
f95bc830 166 tcs = (LttvTraceStats *)(tc = (LTTV_TRACESET_CONTEXT(self)->traces[i]));
167
168 lttv_attribute_find(tcs->parent.parent.t_a, LTTV_STATS_USE_COUNT,
169 LTTV_UINT, &v);
170 *(v.v_uint)--;
171
172 if(*(v.v_uint) == 0) {
173 lttv_attribute_remove_by_name(tcs->parent.parent.t_a,LTTV_STATS);
f95bc830 174 tracefiles_stats = lttv_attribute_find_subdir(tcs->parent.parent.t_a,
175 LTTV_STATS_TRACEFILES);
176 lttv_attribute_remove_by_name(tcs->parent.parent.t_a,
177 LTTV_STATS_TRACEFILES);
f95bc830 178 }
179 tcs->stats = NULL;
b445142a 180
eed2ef37 181 nb_tracefile = tc->tracefiles->len;
b445142a 182
b445142a 183 for(j = 0 ; j < nb_tracefile ; j++) {
cb03932a 184 tfc = g_array_index(tc->tracefiles,
185 LttvTracefileContext*, j);
359b2948 186 tfcs = (LttvTracefileStats *)tfc;
f95bc830 187 tfcs->stats = NULL;
b445142a 188 tfcs->current_events_tree = NULL;
189 tfcs->current_event_types_tree = NULL;
190 }
191 }
192 LTTV_TRACESET_CONTEXT_CLASS(g_type_class_peek(LTTV_TRACESET_STATE_TYPE))->
193 fini((LttvTracesetContext *)self);
194}
195
196
197static LttvTracesetContext *
198new_traceset_context(LttvTracesetContext *self)
199{
200 return LTTV_TRACESET_CONTEXT(g_object_new(LTTV_TRACESET_STATS_TYPE, NULL));
201}
202
203
204static LttvTraceContext *
205new_trace_context(LttvTracesetContext *self)
206{
207 return LTTV_TRACE_CONTEXT(g_object_new(LTTV_TRACE_STATS_TYPE, NULL));
208}
209
210
211static LttvTracefileContext *
212new_tracefile_context(LttvTracesetContext *self)
213{
214 return LTTV_TRACEFILE_CONTEXT(g_object_new(LTTV_TRACEFILE_STATS_TYPE, NULL));
215}
216
217
218static void
219traceset_stats_instance_init (GTypeInstance *instance, gpointer g_class)
220{
221}
222
223
224static void
225traceset_stats_finalize (LttvTracesetStats *self)
226{
227 G_OBJECT_CLASS(g_type_class_peek(LTTV_TRACESET_STATE_TYPE))->
228 finalize(G_OBJECT(self));
229}
230
231
232static void
233traceset_stats_class_init (LttvTracesetContextClass *klass)
234{
235 GObjectClass *gobject_class = G_OBJECT_CLASS(klass);
236
237 gobject_class->finalize = (void (*)(GObject *self)) traceset_stats_finalize;
238 klass->init = (void (*)(LttvTracesetContext *self, LttvTraceset *ts))init;
239 klass->fini = (void (*)(LttvTracesetContext *self))fini;
240 klass->new_traceset_context = new_traceset_context;
241 klass->new_trace_context = new_trace_context;
242 klass->new_tracefile_context = new_tracefile_context;
243}
244
245
246GType
247lttv_traceset_stats_get_type(void)
248{
249 static GType type = 0;
250 if (type == 0) {
251 static const GTypeInfo info = {
252 sizeof (LttvTracesetStatsClass),
253 NULL, /* base_init */
254 NULL, /* base_finalize */
255 (GClassInitFunc) traceset_stats_class_init, /* class_init */
256 NULL, /* class_finalize */
257 NULL, /* class_data */
dbb7bb09 258 sizeof (LttvTracesetStats),
b445142a 259 0, /* n_preallocs */
00e74b69 260 (GInstanceInitFunc) traceset_stats_instance_init, /* instance_init */
261 NULL /* Value handling */
b445142a 262 };
263
00e74b69 264 type = g_type_register_static (LTTV_TRACESET_STATE_TYPE,
265 "LttvTracesetStatsType",
266 &info, 0);
b445142a 267 }
268 return type;
269}
270
271
272static void
273trace_stats_instance_init (GTypeInstance *instance, gpointer g_class)
274{
275}
276
277
278static void
279trace_stats_finalize (LttvTraceStats *self)
280{
281 G_OBJECT_CLASS(g_type_class_peek(LTTV_TRACE_STATE_TYPE))->
282 finalize(G_OBJECT(self));
283}
284
285
286static void
287trace_stats_class_init (LttvTraceContextClass *klass)
288{
289 GObjectClass *gobject_class = G_OBJECT_CLASS(klass);
290
291 gobject_class->finalize = (void (*)(GObject *self)) trace_stats_finalize;
292}
293
294
295GType
296lttv_trace_stats_get_type(void)
297{
298 static GType type = 0;
299 if (type == 0) {
300 static const GTypeInfo info = {
301 sizeof (LttvTraceStatsClass),
302 NULL, /* base_init */
303 NULL, /* base_finalize */
304 (GClassInitFunc) trace_stats_class_init, /* class_init */
305 NULL, /* class_finalize */
306 NULL, /* class_data */
307 sizeof (LttvTraceStats),
308 0, /* n_preallocs */
00e74b69 309 (GInstanceInitFunc) trace_stats_instance_init, /* instance_init */
310 NULL /* Value handling */
b445142a 311 };
312
313 type = g_type_register_static (LTTV_TRACE_STATE_TYPE,
314 "LttvTraceStatsType", &info, 0);
315 }
316 return type;
317}
318
319
320static void
321tracefile_stats_instance_init (GTypeInstance *instance, gpointer g_class)
322{
323}
324
325
326static void
327tracefile_stats_finalize (LttvTracefileStats *self)
328{
329 G_OBJECT_CLASS(g_type_class_peek(LTTV_TRACEFILE_STATE_TYPE))->
330 finalize(G_OBJECT(self));
331}
332
333
334static void
335tracefile_stats_class_init (LttvTracefileStatsClass *klass)
336{
337 GObjectClass *gobject_class = G_OBJECT_CLASS(klass);
338
339 gobject_class->finalize = (void (*)(GObject *self)) tracefile_stats_finalize;
340}
341
342
343GType
344lttv_tracefile_stats_get_type(void)
345{
346 static GType type = 0;
347 if (type == 0) {
348 static const GTypeInfo info = {
349 sizeof (LttvTracefileStatsClass),
350 NULL, /* base_init */
351 NULL, /* base_finalize */
352 (GClassInitFunc) tracefile_stats_class_init, /* class_init */
353 NULL, /* class_finalize */
354 NULL, /* class_data */
355 sizeof (LttvTracefileStats),
356 0, /* n_preallocs */
00e74b69 357 (GInstanceInitFunc) tracefile_stats_instance_init, /* instance_init */
358 NULL /* Value handling */
b445142a 359 };
360
361 type = g_type_register_static (LTTV_TRACEFILE_STATE_TYPE,
362 "LttvTracefileStatsType", &info, 0);
363 }
364 return type;
365}
366
367
368static void
00e74b69 369find_event_tree(LttvTracefileStats *tfcs,
370 GQuark pid_time,
371 GQuark cpu,
372 GQuark mode,
373 GQuark sub_mode,
374 LttvAttribute **events_tree,
375 LttvAttribute **event_types_tree)
b445142a 376{
377 LttvAttribute *a;
378
3c9bb8b1 379 LttvTraceStats *tcs = (LttvTraceStats*)tfcs->parent.parent.t_context;
b445142a 380 a = lttv_attribute_find_subdir(tcs->stats, LTTV_STATS_PROCESSES);
00e74b69 381 a = lttv_attribute_find_subdir(a, pid_time);
b445142a 382 a = lttv_attribute_find_subdir(a, LTTV_STATS_CPU);
00e74b69 383 a = lttv_attribute_find_subdir(a, cpu);
b445142a 384 a = lttv_attribute_find_subdir(a, LTTV_STATS_MODE_TYPES);
00e74b69 385 a = lttv_attribute_find_subdir(a, mode);
b445142a 386 a = lttv_attribute_find_subdir(a, LTTV_STATS_SUBMODES);
00e74b69 387 a = lttv_attribute_find_subdir(a, sub_mode);
b445142a 388 *events_tree = a;
389 a = lttv_attribute_find_subdir(a, LTTV_STATS_EVENT_TYPES);
390 *event_types_tree = a;
391}
392
393
394static void update_event_tree(LttvTracefileStats *tfcs)
395{
348c6ba8 396 LttvTraceState *ts = (LttvTraceState *)tfcs->parent.parent.t_context;
397 guint cpu = ltt_tracefile_num(tfcs->parent.parent.tf);
398 LttvProcessState *process = ts->running_process[cpu];
399 LttvExecutionState *es = process->state;
b445142a 400
348c6ba8 401 find_event_tree(tfcs, process->pid_time,
402 ltt_tracefile_long_name(tfcs->parent.parent.tf),
b445142a 403 es->t, es->n, &(tfcs->current_events_tree),
404 &(tfcs->current_event_types_tree));
405}
406
407
408static void mode_change(LttvTracefileStats *tfcs)
409{
348c6ba8 410 LttvTraceState *ts = (LttvTraceState *)tfcs->parent.parent.t_context;
411 guint cpu = ltt_tracefile_num(tfcs->parent.parent.tf);
412 LttvProcessState *process = ts->running_process[cpu];
b445142a 413 LttvAttributeValue cpu_time;
414
415 LttTime delta;
416
417 lttv_attribute_find(tfcs->current_events_tree, LTTV_STATS_CPU_TIME,
418 LTTV_TIME, &cpu_time);
308711e5 419 delta = ltt_time_sub(tfcs->parent.parent.timestamp,
348c6ba8 420 process->state->change);
308711e5 421 *(cpu_time.v_time) = ltt_time_add(*(cpu_time.v_time), delta);
b445142a 422}
423
424
425static void mode_end(LttvTracefileStats *tfcs)
426{
348c6ba8 427 LttvTraceState *ts = (LttvTraceState *)tfcs->parent.parent.t_context;
428 guint cpu = ltt_tracefile_num(tfcs->parent.parent.tf);
429 LttvProcessState *process = ts->running_process[cpu];
b445142a 430 LttvAttributeValue elapsed_time, cpu_time;
431
432 LttTime delta;
433
434 lttv_attribute_find(tfcs->current_events_tree, LTTV_STATS_ELAPSED_TIME,
435 LTTV_TIME, &elapsed_time);
308711e5 436 delta = ltt_time_sub(tfcs->parent.parent.timestamp,
348c6ba8 437 process->state->entry);
308711e5 438 *(elapsed_time.v_time) = ltt_time_add(*(elapsed_time.v_time), delta);
b445142a 439
440 lttv_attribute_find(tfcs->current_events_tree, LTTV_STATS_CPU_TIME,
441 LTTV_TIME, &cpu_time);
308711e5 442 delta = ltt_time_sub(tfcs->parent.parent.timestamp,
348c6ba8 443 process->state->change);
308711e5 444 *(cpu_time.v_time) = ltt_time_add(*(cpu_time.v_time), delta);
b445142a 445}
446
447
448static gboolean before_syscall_entry(void *hook_data, void *call_data)
449{
450 mode_change((LttvTracefileStats *)call_data);
451 return FALSE;
452}
453
454
455static gboolean after_syscall_entry(void *hook_data, void *call_data)
456{
457 update_event_tree((LttvTracefileStats *)call_data);
458 return FALSE;
459}
460
461
462gboolean before_syscall_exit(void *hook_data, void *call_data)
463{
464 mode_end((LttvTracefileStats *)call_data);
465 return FALSE;
466}
467
468
469static gboolean after_syscall_exit(void *hook_data, void *call_data)
470{
471 update_event_tree((LttvTracefileStats *)call_data);
472 return FALSE;
473}
474
475
476gboolean before_trap_entry(void *hook_data, void *call_data)
477{
478 mode_change((LttvTracefileStats *)call_data);
479 return FALSE;
480}
481
482
483static gboolean after_trap_entry(void *hook_data, void *call_data)
484{
485 update_event_tree((LttvTracefileStats *)call_data);
486 return FALSE;
487}
488
489
490gboolean before_trap_exit(void *hook_data, void *call_data)
491{
492 mode_end((LttvTracefileStats *)call_data);
493 return FALSE;
494}
495
496
497gboolean after_trap_exit(void *hook_data, void *call_data)
498{
499 update_event_tree((LttvTracefileStats *)call_data);
500 return FALSE;
501}
502
503
504gboolean before_irq_entry(void *hook_data, void *call_data)
505{
506 mode_change((LttvTracefileStats *)call_data);
507 return FALSE;
508}
509
510
511gboolean after_irq_entry(void *hook_data, void *call_data)
512{
513 update_event_tree((LttvTracefileStats *)call_data);
514 return FALSE;
515}
516
517
518gboolean before_irq_exit(void *hook_data, void *call_data)
519{
520 mode_end((LttvTracefileStats *)call_data);
521 return FALSE;
522}
523
524
525gboolean after_irq_exit(void *hook_data, void *call_data)
526{
527 update_event_tree((LttvTracefileStats *)call_data);
528 return FALSE;
529}
530
531
532gboolean before_schedchange(void *hook_data, void *call_data)
533{
b445142a 534 LttvTracefileStats *tfcs = (LttvTracefileStats *)call_data;
535
348c6ba8 536 LttvTraceState *ts = (LttvTraceState*)tfcs->parent.parent.t_context;
537
eed2ef37 538 LttEvent *e = ltt_tracefile_get_event(tfcs->parent.parent.tf);
539
d052ffc3 540 LttvTraceHookByFacility *thf = (LttvTraceHookByFacility *)hook_data;
eed2ef37 541
d7cf605c 542 guint pid_in, pid_out;
543
544 gint state_out;
b445142a 545
546 LttvProcessState *process;
547
eed2ef37 548 pid_out = ltt_event_get_unsigned(e, thf->f1);
549 pid_in = ltt_event_get_unsigned(e, thf->f2);
d7cf605c 550 state_out = ltt_event_get_int(e, thf->f3);
b445142a 551
552 /* compute the time for the process to schedule out */
553
554 mode_change(tfcs);
555
556 /* get the information for the process scheduled in */
557
348c6ba8 558 process = lttv_state_find_process_or_create(ts,
559 ANY_CPU, pid_in, &tfcs->parent.parent.timestamp);
b445142a 560
348c6ba8 561 find_event_tree(tfcs, process->pid_time,
562 ltt_tracefile_long_name(tfcs->parent.parent.tf),
b445142a 563 process->state->t, process->state->n, &(tfcs->current_events_tree),
564 &(tfcs->current_event_types_tree));
565
566 /* compute the time waiting for the process to schedule in */
567
568 mode_change(tfcs);
569 return FALSE;
570}
571
572
573gboolean process_fork(void *hook_data, void *call_data)
574{
575 /* nothing to do for now */
576 return FALSE;
577}
578
579
580gboolean process_exit(void *hook_data, void *call_data)
581{
582 /* We should probably exit all modes here or we could do that at
583 schedule out. */
584 return FALSE;
585}
586
eed2ef37 587gboolean process_free(void *hook_data, void *call_data)
588{
589 return FALSE;
590}
b445142a 591
592gboolean every_event(void *hook_data, void *call_data)
593{
594 LttvTracefileStats *tfcs = (LttvTracefileStats *)call_data;
595
eed2ef37 596 LttEvent *e = ltt_tracefile_get_event(tfcs->parent.parent.tf);
597
b445142a 598 LttvAttributeValue v;
599
600 /* The current branch corresponds to the tracefile/process/interrupt state.
601 Statistics are added within it, to count the number of events of this
602 type occuring in this context. A quark has been pre-allocated for each
603 event type and is used as name. */
604
605 lttv_attribute_find(tfcs->current_event_types_tree,
eed2ef37 606 ltt_eventtype_name(ltt_event_eventtype(e)),
b445142a 607 LTTV_UINT, &v);
608 (*(v.v_uint))++;
609 return FALSE;
610}
611
612
f95bc830 613void
614lttv_stats_sum_trace(LttvTraceStats *self)
b445142a 615{
d3e01c7a 616 LttvAttribute *sum_container = self->stats;
b445142a 617
b445142a 618 LttvAttributeType type;
619
620 LttvAttributeValue value;
621
622 LttvAttributeName name;
623
624 unsigned sum;
625
f95bc830 626 int i, j, k, l, m, nb_process, nb_cpu, nb_mode_type, nb_submode,
b445142a 627 nb_event_type;
628
629 LttvAttribute *main_tree, *processes_tree, *process_tree, *cpus_tree,
630 *cpu_tree, *mode_tree, *mode_types_tree, *submodes_tree,
631 *submode_tree, *event_types_tree, *mode_events_tree,
632 *cpu_events_tree, *process_modes_tree, *trace_cpu_tree,
f95bc830 633 *trace_modes_tree;
634
d3e01c7a 635 main_tree = sum_container;
f95bc830 636
d3e01c7a 637 lttv_attribute_find(sum_container,
638 LTTV_STATS_SUMMED,
639 LTTV_UINT, &value);
f95bc830 640 if(*(value.v_uint) != 0) return;
641 *(value.v_uint) = 1;
642
643 processes_tree = lttv_attribute_find_subdir(main_tree,
d3e01c7a 644 LTTV_STATS_PROCESSES);
645 trace_modes_tree = lttv_attribute_find_subdir(main_tree,
646 LTTV_STATS_MODES);
f95bc830 647 nb_process = lttv_attribute_get_number(processes_tree);
648
649 for(i = 0 ; i < nb_process ; i++) {
650 type = lttv_attribute_get(processes_tree, i, &name, &value);
651 process_tree = LTTV_ATTRIBUTE(*(value.v_gobject));
652
653 cpus_tree = lttv_attribute_find_subdir(process_tree, LTTV_STATS_CPU);
654 process_modes_tree = lttv_attribute_find_subdir(process_tree,
655 LTTV_STATS_MODES);
656 nb_cpu = lttv_attribute_get_number(cpus_tree);
657
658 for(j = 0 ; j < nb_cpu ; j++) {
659 type = lttv_attribute_get(cpus_tree, j, &name, &value);
660 cpu_tree = LTTV_ATTRIBUTE(*(value.v_gobject));
661
662 mode_types_tree = lttv_attribute_find_subdir(cpu_tree,
663 LTTV_STATS_MODE_TYPES);
664 cpu_events_tree = lttv_attribute_find_subdir(cpu_tree,
665 LTTV_STATS_EVENTS);
666 trace_cpu_tree = lttv_attribute_find_subdir(main_tree, LTTV_STATS_CPU);
667 trace_cpu_tree = lttv_attribute_find_subdir(trace_cpu_tree, name);
668 nb_mode_type = lttv_attribute_get_number(mode_types_tree);
669
670 for(k = 0 ; k < nb_mode_type ; k++) {
671 type = lttv_attribute_get(mode_types_tree, k, &name, &value);
672 mode_tree = LTTV_ATTRIBUTE(*(value.v_gobject));
673
674 submodes_tree = lttv_attribute_find_subdir(mode_tree,
675 LTTV_STATS_SUBMODES);
676 mode_events_tree = lttv_attribute_find_subdir(mode_tree,
677 LTTV_STATS_EVENTS);
678 nb_submode = lttv_attribute_get_number(submodes_tree);
b445142a 679
f95bc830 680 for(l = 0 ; l < nb_submode ; l++) {
681 type = lttv_attribute_get(submodes_tree, l, &name, &value);
682 submode_tree = LTTV_ATTRIBUTE(*(value.v_gobject));
b445142a 683
f95bc830 684 event_types_tree = lttv_attribute_find_subdir(submode_tree,
685 LTTV_STATS_EVENT_TYPES);
686 nb_event_type = lttv_attribute_get_number(event_types_tree);
b445142a 687
f95bc830 688 sum = 0;
689 for(m = 0 ; m < nb_event_type ; m++) {
690 type = lttv_attribute_get(event_types_tree, m, &name, &value);
691 sum += *(value.v_uint);
b445142a 692 }
f95bc830 693 lttv_attribute_find(submode_tree, LTTV_STATS_EVENTS_COUNT,
694 LTTV_UINT, &value);
695 *(value.v_uint) = sum;
696 lttv_attribute_recursive_add(mode_events_tree, submode_tree);
b445142a 697 }
f95bc830 698 lttv_attribute_recursive_add(cpu_events_tree, mode_events_tree);
b445142a 699 }
f95bc830 700 lttv_attribute_recursive_add(process_modes_tree, cpu_tree);
701 lttv_attribute_recursive_add(trace_cpu_tree, cpu_tree);
b445142a 702 }
f95bc830 703 lttv_attribute_recursive_add(trace_modes_tree, process_modes_tree);
704 }
705}
706
707
d3e01c7a 708gboolean lttv_stats_sum_traceset_hook(void *hook_data, void *call_data)
709{
710 lttv_stats_sum_traceset((LttvTracesetStats *)call_data);
711 return 0;
712}
713
f95bc830 714void
715lttv_stats_sum_traceset(LttvTracesetStats *self)
716{
717 LttvTraceset *traceset = self->parent.parent.ts;
d3e01c7a 718 LttvAttribute *sum_container = self->stats;
f95bc830 719
720 LttvTraceStats *tcs;
721
722 int i, nb_trace;
723
724 LttvAttribute *main_tree, *trace_modes_tree, *traceset_modes_tree;
725
726 LttvAttributeValue value;
727
d3e01c7a 728 lttv_attribute_find(sum_container, LTTV_STATS_SUMMED,
f95bc830 729 LTTV_UINT, &value);
730 if(*(value.v_uint) != 0) return;
731 *(value.v_uint) = 1;
732
d3e01c7a 733 traceset_modes_tree = lttv_attribute_find_subdir(sum_container,
f95bc830 734 LTTV_STATS_MODES);
735 nb_trace = lttv_traceset_number(traceset);
736
737 for(i = 0 ; i < nb_trace ; i++) {
738 tcs = (LttvTraceStats *)(self->parent.parent.traces[i]);
739 lttv_stats_sum_trace(tcs);
740 main_tree = tcs->stats;
741 trace_modes_tree = lttv_attribute_find_subdir(main_tree, LTTV_STATS_MODES);
b445142a 742 lttv_attribute_recursive_add(traceset_modes_tree, trace_modes_tree);
743 }
b445142a 744}
745
746
d3e01c7a 747// Hook wrapper. call_data is a traceset context.
00e74b69 748gboolean lttv_stats_hook_add_event_hooks(void *hook_data, void *call_data)
d3e01c7a 749{
750 LttvTracesetStats *tss = (LttvTracesetStats*)call_data;
751
752 lttv_stats_add_event_hooks(tss);
753
754 return 0;
755}
756
00e74b69 757void lttv_stats_add_event_hooks(LttvTracesetStats *self)
b445142a 758{
759 LttvTraceset *traceset = self->parent.parent.ts;
760
eed2ef37 761 guint i, j, k, l, nb_trace, nb_tracefile;
b445142a 762
b445142a 763 LttvTraceStats *ts;
764
765 LttvTracefileStats *tfs;
766
b445142a 767 GArray *hooks, *before_hooks, *after_hooks;
768
eed2ef37 769 LttvTraceHook *hook;
770
771 LttvTraceHookByFacility *thf;
b445142a 772
773 LttvAttributeValue val;
774
9d239bd9 775 gint ret;
776
b445142a 777 nb_trace = lttv_traceset_number(traceset);
778 for(i = 0 ; i < nb_trace ; i++) {
779 ts = (LttvTraceStats *)self->parent.parent.traces[i];
780
781 /* Find the eventtype id for the following events and register the
782 associated by id hooks. */
783
eed2ef37 784 hooks = g_array_sized_new(FALSE, FALSE, sizeof(LttvTraceHook), 7);
b445142a 785 g_array_set_size(hooks, 7);
786
9d239bd9 787 ret = lttv_trace_find_hook(ts->parent.parent.t,
eed2ef37 788 LTT_FACILITY_KERNEL, LTT_EVENT_SYSCALL_ENTRY,
789 LTT_FIELD_SYSCALL_ID, 0, 0,
2c82c4dc 790 before_syscall_entry, NULL,
b445142a 791 &g_array_index(hooks, LttvTraceHook, 0));
9d239bd9 792 g_assert(!ret);
b445142a 793
9d239bd9 794 ret = lttv_trace_find_hook(ts->parent.parent.t,
eed2ef37 795 LTT_FACILITY_KERNEL, LTT_EVENT_SYSCALL_EXIT,
796 0, 0, 0,
2c82c4dc 797 before_syscall_exit, NULL,
b445142a 798 &g_array_index(hooks, LttvTraceHook, 1));
9d239bd9 799 g_assert(!ret);
b445142a 800
9d239bd9 801 ret = lttv_trace_find_hook(ts->parent.parent.t,
eed2ef37 802 LTT_FACILITY_KERNEL, LTT_EVENT_TRAP_ENTRY,
803 LTT_FIELD_TRAP_ID, 0, 0,
2c82c4dc 804 before_trap_entry, NULL,
b445142a 805 &g_array_index(hooks, LttvTraceHook, 2));
9d239bd9 806 g_assert(!ret);
b445142a 807
9d239bd9 808 ret = lttv_trace_find_hook(ts->parent.parent.t,
eed2ef37 809 LTT_FACILITY_KERNEL, LTT_EVENT_TRAP_EXIT,
810 0, 0, 0,
2c82c4dc 811 before_trap_exit, NULL,
812 &g_array_index(hooks, LttvTraceHook, 3));
9d239bd9 813 g_assert(!ret);
eed2ef37 814
9d239bd9 815 ret = lttv_trace_find_hook(ts->parent.parent.t,
eed2ef37 816 LTT_FACILITY_KERNEL, LTT_EVENT_IRQ_ENTRY,
817 LTT_FIELD_IRQ_ID, 0, 0,
2c82c4dc 818 before_irq_entry, NULL,
819 &g_array_index(hooks, LttvTraceHook, 4));
9d239bd9 820 g_assert(!ret);
eed2ef37 821
9d239bd9 822 ret = lttv_trace_find_hook(ts->parent.parent.t,
eed2ef37 823 LTT_FACILITY_KERNEL, LTT_EVENT_IRQ_EXIT,
824 0, 0, 0,
2c82c4dc 825 before_irq_exit, NULL,
826 &g_array_index(hooks, LttvTraceHook, 5));
9d239bd9 827 g_assert(!ret);
eed2ef37 828
9d239bd9 829 ret = lttv_trace_find_hook(ts->parent.parent.t,
eed2ef37 830 LTT_FACILITY_PROCESS, LTT_EVENT_SCHEDCHANGE,
831 LTT_FIELD_OUT, LTT_FIELD_IN, LTT_FIELD_OUT_STATE,
2c82c4dc 832 before_schedchange, NULL,
eed2ef37 833 &g_array_index(hooks, LttvTraceHook, 6));
9d239bd9 834 g_assert(!ret);
b445142a 835
836 before_hooks = hooks;
837
eed2ef37 838 hooks = g_array_sized_new(FALSE, FALSE, sizeof(LttvTraceHook), 9);
839 g_array_set_size(hooks, 9);
b445142a 840
9d239bd9 841 ret = lttv_trace_find_hook(ts->parent.parent.t,
eed2ef37 842 LTT_FACILITY_KERNEL, LTT_EVENT_SYSCALL_ENTRY,
843 LTT_FIELD_SYSCALL_ID, 0, 0,
2c82c4dc 844 after_syscall_entry, NULL,
b445142a 845 &g_array_index(hooks, LttvTraceHook, 0));
9d239bd9 846 g_assert(!ret);
b445142a 847
9d239bd9 848 ret = lttv_trace_find_hook(ts->parent.parent.t,
eed2ef37 849 LTT_FACILITY_KERNEL, LTT_EVENT_SYSCALL_EXIT,
850 0, 0, 0,
2c82c4dc 851 after_syscall_exit, NULL,
b445142a 852 &g_array_index(hooks, LttvTraceHook, 1));
9d239bd9 853 g_assert(!ret);
b445142a 854
9d239bd9 855 ret = lttv_trace_find_hook(ts->parent.parent.t,
eed2ef37 856 LTT_FACILITY_KERNEL, LTT_EVENT_TRAP_ENTRY,
857 LTT_FIELD_TRAP_ID, 0, 0,
2c82c4dc 858 after_trap_entry, NULL,
859 &g_array_index(hooks, LttvTraceHook, 2));
9d239bd9 860 g_assert(!ret);
eed2ef37 861
9d239bd9 862 ret = lttv_trace_find_hook(ts->parent.parent.t,
eed2ef37 863 LTT_FACILITY_KERNEL, LTT_EVENT_TRAP_EXIT,
864 0, 0, 0,
2c82c4dc 865 after_trap_exit, NULL,
866 &g_array_index(hooks, LttvTraceHook, 3));
9d239bd9 867 g_assert(!ret);
b445142a 868
9d239bd9 869 ret = lttv_trace_find_hook(ts->parent.parent.t,
eed2ef37 870 LTT_FACILITY_KERNEL, LTT_EVENT_IRQ_ENTRY,
871 LTT_FIELD_IRQ_ID, 0, 0,
2c82c4dc 872 after_irq_entry, NULL,
873 &g_array_index(hooks, LttvTraceHook, 4));
9d239bd9 874 g_assert(!ret);
b445142a 875
9d239bd9 876 ret = lttv_trace_find_hook(ts->parent.parent.t,
eed2ef37 877 LTT_FACILITY_KERNEL, LTT_EVENT_IRQ_EXIT,
878 0, 0, 0,
2c82c4dc 879 after_irq_exit, NULL,
880 &g_array_index(hooks, LttvTraceHook, 5));
9d239bd9 881 g_assert(!ret);
b445142a 882
b445142a 883
9d239bd9 884 ret = lttv_trace_find_hook(ts->parent.parent.t,
eed2ef37 885 LTT_FACILITY_PROCESS, LTT_EVENT_FORK,
886 LTT_FIELD_PARENT_PID, LTT_FIELD_CHILD_PID, 0,
2c82c4dc 887 process_fork, NULL,
b445142a 888 &g_array_index(hooks, LttvTraceHook, 6));
9d239bd9 889 g_assert(!ret);
b445142a 890
9d239bd9 891 ret = lttv_trace_find_hook(ts->parent.parent.t,
eed2ef37 892 LTT_FACILITY_PROCESS, LTT_EVENT_EXIT,
893 LTT_FIELD_PID, 0, 0,
2c82c4dc 894 process_exit, NULL,
895 &g_array_index(hooks, LttvTraceHook, 7));
9d239bd9 896 g_assert(!ret);
eed2ef37 897
9d239bd9 898 ret = lttv_trace_find_hook(ts->parent.parent.t,
eed2ef37 899 LTT_FACILITY_PROCESS, LTT_EVENT_FREE,
900 LTT_FIELD_PID, 0, 0,
2c82c4dc 901 process_free, NULL,
902 &g_array_index(hooks, LttvTraceHook, 8));
9d239bd9 903 g_assert(!ret);
eed2ef37 904
b445142a 905
906 after_hooks = hooks;
907
359b2948 908 /* Add these hooks to each event_by_id hooks list */
b445142a 909
eed2ef37 910 nb_tracefile = ts->parent.parent.tracefiles->len;
b445142a 911
dbb7bb09 912 for(j = 0 ; j < nb_tracefile ; j++) {
d7cf605c 913 tfs = LTTV_TRACEFILE_STATS(g_array_index(ts->parent.parent.tracefiles,
914 LttvTracefileContext*, j));
359b2948 915 lttv_hooks_add(tfs->parent.parent.event, every_event, NULL,
916 LTTV_PRIO_DEFAULT);
b445142a 917
918 for(k = 0 ; k < before_hooks->len ; k++) {
eed2ef37 919 hook = &g_array_index(before_hooks, LttvTraceHook, k);
920 for(l = 0; l<hook->fac_list->len;l++) {
921 thf = g_array_index(hook->fac_list, LttvTraceHookByFacility*, l);
922 lttv_hooks_add(
923 lttv_hooks_by_id_find(tfs->parent.parent.event_by_id, thf->id),
924 thf->h,
d052ffc3 925 thf,
eed2ef37 926 LTTV_PRIO_STATS_BEFORE_STATE);
927 }
b445142a 928 }
929 for(k = 0 ; k < after_hooks->len ; k++) {
eed2ef37 930 hook = &g_array_index(after_hooks, LttvTraceHook, k);
931 for(l = 0; l<hook->fac_list->len;l++) {
932 thf = g_array_index(hook->fac_list, LttvTraceHookByFacility*, l);
933 lttv_hooks_add(
934 lttv_hooks_by_id_find(tfs->parent.parent.event_by_id, thf->id),
935 thf->h,
d052ffc3 936 thf,
eed2ef37 937 LTTV_PRIO_STATS_AFTER_STATE);
938 }
b445142a 939 }
940 }
941 lttv_attribute_find(self->parent.parent.a, LTTV_STATS_BEFORE_HOOKS,
942 LTTV_POINTER, &val);
943 *(val.v_pointer) = before_hooks;
944 lttv_attribute_find(self->parent.parent.a, LTTV_STATS_AFTER_HOOKS,
945 LTTV_POINTER, &val);
946 *(val.v_pointer) = after_hooks;
947 }
b445142a 948}
949
d3e01c7a 950// Hook wrapper. call_data is a traceset context.
00e74b69 951gboolean lttv_stats_hook_remove_event_hooks(void *hook_data, void *call_data)
d3e01c7a 952{
953 LttvTracesetStats *tss = (LttvTracesetStats*)call_data;
954
955 lttv_stats_remove_event_hooks(tss);
956
957 return 0;
958}
b445142a 959
00e74b69 960void lttv_stats_remove_event_hooks(LttvTracesetStats *self)
b445142a 961{
962 LttvTraceset *traceset = self->parent.parent.ts;
963
eed2ef37 964 guint i, j, k, l, nb_trace, nb_tracefile;
b445142a 965
966 LttvTraceStats *ts;
967
968 LttvTracefileStats *tfs;
969
970 void *hook_data;
971
972 GArray *before_hooks, *after_hooks;
973
eed2ef37 974 LttvTraceHook *hook;
975
976 LttvTraceHookByFacility *thf;
b445142a 977
978 LttvAttributeValue val;
979
980 nb_trace = lttv_traceset_number(traceset);
981 for(i = 0 ; i < nb_trace ; i++) {
ae80b609 982 ts = (LttvTraceStats*)self->parent.parent.traces[i];
b445142a 983 lttv_attribute_find(self->parent.parent.a, LTTV_STATS_BEFORE_HOOKS,
984 LTTV_POINTER, &val);
985 before_hooks = *(val.v_pointer);
986 lttv_attribute_find(self->parent.parent.a, LTTV_STATS_AFTER_HOOKS,
987 LTTV_POINTER, &val);
988 after_hooks = *(val.v_pointer);
989
359b2948 990 /* Remove these hooks from each event_by_id hooks list */
b445142a 991
eed2ef37 992 nb_tracefile = ts->parent.parent.tracefiles->len;
b445142a 993
dbb7bb09 994 for(j = 0 ; j < nb_tracefile ; j++) {
cb03932a 995 tfs = LTTV_TRACEFILE_STATS(g_array_index(ts->parent.parent.tracefiles,
996 LttvTracefileContext*, j));
359b2948 997 lttv_hooks_remove_data(tfs->parent.parent.event, every_event,
b445142a 998 NULL);
999
1000 for(k = 0 ; k < before_hooks->len ; k++) {
eed2ef37 1001 hook = &g_array_index(before_hooks, LttvTraceHook, k);
1002 for(l = 0 ; l < hook->fac_list->len ; l++) {
1003 thf = g_array_index(hook->fac_list, LttvTraceHookByFacility*, l);
1004 lttv_hooks_remove_data(
1005 lttv_hooks_by_id_find(tfs->parent.parent.event_by_id, thf->id),
1006 thf->h,
d052ffc3 1007 thf);
eed2ef37 1008 }
b445142a 1009 }
1010 for(k = 0 ; k < after_hooks->len ; k++) {
eed2ef37 1011 hook = &g_array_index(after_hooks, LttvTraceHook, k);
1012 for(l = 0 ; l < hook->fac_list->len ; l++) {
1013 thf = g_array_index(hook->fac_list, LttvTraceHookByFacility*, l);
1014 lttv_hooks_remove_data(
1015 lttv_hooks_by_id_find(tfs->parent.parent.event_by_id, thf->id),
1016 thf->h,
d052ffc3 1017 thf);
eed2ef37 1018 }
b445142a 1019 }
1020 }
2a2fa4f0 1021 g_debug("lttv_stats_remove_event_hooks()");
b445142a 1022 g_array_free(before_hooks, TRUE);
1023 g_array_free(after_hooks, TRUE);
1024 }
9f797243 1025}
08b1c66e 1026
1027
1028static void module_init()
1029{
1030 LTTV_STATS_PROCESS_UNKNOWN = g_quark_from_string("unknown process");
1031 LTTV_STATS_PROCESSES = g_quark_from_string("processes");
1032 LTTV_STATS_CPU = g_quark_from_string("cpu");
1033 LTTV_STATS_MODE_TYPES = g_quark_from_string("mode_types");
1034 LTTV_STATS_MODES = g_quark_from_string("modes");
1035 LTTV_STATS_SUBMODES = g_quark_from_string("submodes");
1036 LTTV_STATS_EVENT_TYPES = g_quark_from_string("event_types");
1037 LTTV_STATS_CPU_TIME = g_quark_from_string("cpu time");
1038 LTTV_STATS_ELAPSED_TIME = g_quark_from_string("elapsed time");
1039 LTTV_STATS_EVENTS = g_quark_from_string("events");
1040 LTTV_STATS_EVENTS_COUNT = g_quark_from_string("events count");
1041 LTTV_STATS_BEFORE_HOOKS = g_quark_from_string("saved stats before hooks");
1042 LTTV_STATS_AFTER_HOOKS = g_quark_from_string("saved stats after hooks");
f95bc830 1043 LTTV_STATS_USE_COUNT = g_quark_from_string("stats_use_count");
1044 LTTV_STATS = g_quark_from_string("statistics");
1045 LTTV_STATS_TRACEFILES = g_quark_from_string("tracefiles statistics");
1046 LTTV_STATS_SUMMED = g_quark_from_string("statistics summed");
08b1c66e 1047}
1048
1049static void module_destroy()
1050{
1051}
1052
1053
1054LTTV_MODULE("stats", "Compute processes statistics", \
1055 "Accumulate statistics for event types, processes and CPUs", \
1056 module_init, module_destroy, "state");
f95bc830 1057
1058/* Change the places where stats are called (create/read/write stats)
1059
1060 Check for options in batchtest.c to reduce writing and see what tests are
1061 best candidates for performance analysis. Once OK, commit, move to main
1062 and run tests. Update the gui for statistics. */
This page took 0.080078 seconds and 4 git commands to generate.