update
[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
14236daa 34#define MAX_64_HEX_STRING_LEN 19
9f797243 35
b445142a 36GQuark
37 LTTV_STATS_PROCESS_UNKNOWN,
38 LTTV_STATS_PROCESSES,
39 LTTV_STATS_CPU,
40 LTTV_STATS_MODE_TYPES,
41 LTTV_STATS_MODES,
42 LTTV_STATS_SUBMODES,
d3670e3d 43 LTTV_STATS_FUNCTIONS,
b445142a 44 LTTV_STATS_EVENT_TYPES,
45 LTTV_STATS_CPU_TIME,
b49e54b4 46 LTTV_STATS_CUMULATIVE_CPU_TIME,
b445142a 47 LTTV_STATS_ELAPSED_TIME,
48 LTTV_STATS_EVENTS,
f95bc830 49 LTTV_STATS_EVENTS_COUNT,
50 LTTV_STATS_USE_COUNT,
51 LTTV_STATS,
52 LTTV_STATS_TRACEFILES,
22b165e9 53 LTTV_STATS_SUMMED,
b445142a 54 LTTV_STATS_BEFORE_HOOKS,
55 LTTV_STATS_AFTER_HOOKS;
56
b445142a 57static void
c0cb4d12 58find_event_tree(LttvTracefileStats *tfcs, GQuark pid_time, guint cpu,
d3670e3d 59 guint64 function,
b445142a 60 GQuark mode, GQuark sub_mode, LttvAttribute **events_tree,
61 LttvAttribute **event_types_tree);
62
d730b5c8 63
64static void lttv_stats_init(LttvTracesetStats *self)
b445142a 65{
dbb7bb09 66 guint i, j, nb_trace, nb_tracefile;
b445142a 67
68 LttvTraceContext *tc;
69
70 LttvTraceStats *tcs;
71
72 LttvTracefileContext *tfc;
73
3c9bb8b1 74 LttvTracefileContext **tfs;
b445142a 75 LttvTracefileStats *tfcs;
76
77 LttTime timestamp = {0,0};
78
f95bc830 79 LttvAttributeValue v;
80
81 LttvAttribute
82 *stats_tree,
83 *tracefiles_stats;
84
d730b5c8 85 LttvTraceset *ts = self->parent.parent.ts;
b445142a 86
d3e01c7a 87 self->stats = lttv_attribute_find_subdir(
88 lttv_traceset_attribute(self->parent.parent.ts),
89 LTTV_STATS);
90 lttv_attribute_find(lttv_traceset_attribute(self->parent.parent.ts),
91 LTTV_STATS_USE_COUNT,
92 LTTV_UINT, &v);
f95bc830 93
0bd2f89c 94 (*(v.v_uint))++;
f95bc830 95 if(*(v.v_uint) == 1) {
96 g_assert(lttv_attribute_get_number(self->stats) == 0);
97 }
98
b445142a 99 nb_trace = lttv_traceset_number(ts);
100
101 for(i = 0 ; i < nb_trace ; i++) {
021eeb41 102 tc = self->parent.parent.traces[i];
103 tcs = LTTV_TRACE_STATS(tc);
f95bc830 104
105 tcs->stats = lttv_attribute_find_subdir(tcs->parent.parent.t_a,LTTV_STATS);
106 tracefiles_stats = lttv_attribute_find_subdir(tcs->parent.parent.t_a,
107 LTTV_STATS_TRACEFILES);
108 lttv_attribute_find(tcs->parent.parent.t_a, LTTV_STATS_USE_COUNT,
109 LTTV_UINT, &v);
110
0bd2f89c 111 (*(v.v_uint))++;
f95bc830 112 if(*(v.v_uint) == 1) {
113 g_assert(lttv_attribute_get_number(tcs->stats) == 0);
114 }
b445142a 115
eed2ef37 116 nb_tracefile = tc->tracefiles->len;
b445142a 117
dbb7bb09 118 for(j = 0 ; j < nb_tracefile ; j++) {
3c9bb8b1 119 tfs = &g_array_index(tc->tracefiles,
120 LttvTracefileContext*, j);
121 tfcs = LTTV_TRACEFILE_STATS(*tfs);
f95bc830 122 tfcs->stats = lttv_attribute_find_subdir(tracefiles_stats,
348c6ba8 123 ltt_tracefile_long_name(tfcs->parent.parent.tf));
d3670e3d 124 guint cpu = tfcs->parent.cpu;
b445142a 125 find_event_tree(tfcs, LTTV_STATS_PROCESS_UNKNOWN,
d3670e3d 126 cpu,
127 0x0ULL,
348c6ba8 128 LTTV_STATE_MODE_UNKNOWN,
b445142a 129 LTTV_STATE_SUBMODE_UNKNOWN, &tfcs->current_events_tree,
130 &tfcs->current_event_types_tree);
131 }
132 }
d730b5c8 133
b445142a 134}
135
d730b5c8 136static void lttv_stats_fini(LttvTracesetStats *self)
b445142a 137{
138 guint i, j, nb_trace, nb_tracefile;
139
140 LttvTraceset *ts;
141
142 LttvTraceContext *tc;
143
144 LttvTraceStats *tcs;
145
146 LttvTracefileContext *tfc;
147
148 LttvTracefileStats *tfcs;
149
150 LttTime timestamp = {0,0};
151
f95bc830 152 LttvAttributeValue v;
153
154 LttvAttribute *tracefiles_stats;
155
156 lttv_attribute_find(self->parent.parent.ts_a, LTTV_STATS_USE_COUNT,
157 LTTV_UINT, &v);
0bd2f89c 158 (*(v.v_uint))--;
f95bc830 159
160 if(*(v.v_uint) == 0) {
161 lttv_attribute_remove_by_name(self->parent.parent.ts_a, LTTV_STATS);
f95bc830 162 }
163 self->stats = NULL;
164
b445142a 165 ts = self->parent.parent.ts;
166 nb_trace = lttv_traceset_number(ts);
167
168 for(i = 0 ; i < nb_trace ; i++) {
f95bc830 169 tcs = (LttvTraceStats *)(tc = (LTTV_TRACESET_CONTEXT(self)->traces[i]));
170
171 lttv_attribute_find(tcs->parent.parent.t_a, LTTV_STATS_USE_COUNT,
172 LTTV_UINT, &v);
0bd2f89c 173 (*(v.v_uint))--;
f95bc830 174
175 if(*(v.v_uint) == 0) {
176 lttv_attribute_remove_by_name(tcs->parent.parent.t_a,LTTV_STATS);
f95bc830 177 tracefiles_stats = lttv_attribute_find_subdir(tcs->parent.parent.t_a,
178 LTTV_STATS_TRACEFILES);
179 lttv_attribute_remove_by_name(tcs->parent.parent.t_a,
180 LTTV_STATS_TRACEFILES);
f95bc830 181 }
182 tcs->stats = NULL;
b445142a 183
eed2ef37 184 nb_tracefile = tc->tracefiles->len;
b445142a 185
b445142a 186 for(j = 0 ; j < nb_tracefile ; j++) {
cb03932a 187 tfc = g_array_index(tc->tracefiles,
188 LttvTracefileContext*, j);
359b2948 189 tfcs = (LttvTracefileStats *)tfc;
f95bc830 190 tfcs->stats = NULL;
b445142a 191 tfcs->current_events_tree = NULL;
192 tfcs->current_event_types_tree = NULL;
193 }
194 }
d730b5c8 195}
196
197
198void lttv_stats_reset(LttvTracesetStats *self)
199{
200 lttv_stats_fini(self);
201 lttv_stats_init(self);
202}
203
204
205
206static void
207init(LttvTracesetStats *self, LttvTraceset *ts)
208{
209 LTTV_TRACESET_CONTEXT_CLASS(g_type_class_peek(LTTV_TRACESET_STATE_TYPE))->
210 init((LttvTracesetContext *)self, ts);
211
212 lttv_stats_init(self);
213}
214
215
216static void
217fini(LttvTracesetStats *self)
218{
219 lttv_stats_fini(self);
220
b445142a 221 LTTV_TRACESET_CONTEXT_CLASS(g_type_class_peek(LTTV_TRACESET_STATE_TYPE))->
222 fini((LttvTracesetContext *)self);
223}
224
225
226static LttvTracesetContext *
227new_traceset_context(LttvTracesetContext *self)
228{
229 return LTTV_TRACESET_CONTEXT(g_object_new(LTTV_TRACESET_STATS_TYPE, NULL));
230}
231
232
233static LttvTraceContext *
234new_trace_context(LttvTracesetContext *self)
235{
236 return LTTV_TRACE_CONTEXT(g_object_new(LTTV_TRACE_STATS_TYPE, NULL));
237}
238
239
240static LttvTracefileContext *
241new_tracefile_context(LttvTracesetContext *self)
242{
243 return LTTV_TRACEFILE_CONTEXT(g_object_new(LTTV_TRACEFILE_STATS_TYPE, NULL));
244}
245
246
247static void
248traceset_stats_instance_init (GTypeInstance *instance, gpointer g_class)
249{
250}
251
252
253static void
254traceset_stats_finalize (LttvTracesetStats *self)
255{
256 G_OBJECT_CLASS(g_type_class_peek(LTTV_TRACESET_STATE_TYPE))->
257 finalize(G_OBJECT(self));
258}
259
260
261static void
262traceset_stats_class_init (LttvTracesetContextClass *klass)
263{
264 GObjectClass *gobject_class = G_OBJECT_CLASS(klass);
265
266 gobject_class->finalize = (void (*)(GObject *self)) traceset_stats_finalize;
267 klass->init = (void (*)(LttvTracesetContext *self, LttvTraceset *ts))init;
268 klass->fini = (void (*)(LttvTracesetContext *self))fini;
269 klass->new_traceset_context = new_traceset_context;
270 klass->new_trace_context = new_trace_context;
271 klass->new_tracefile_context = new_tracefile_context;
272}
273
274
275GType
276lttv_traceset_stats_get_type(void)
277{
278 static GType type = 0;
279 if (type == 0) {
280 static const GTypeInfo info = {
281 sizeof (LttvTracesetStatsClass),
282 NULL, /* base_init */
283 NULL, /* base_finalize */
284 (GClassInitFunc) traceset_stats_class_init, /* class_init */
285 NULL, /* class_finalize */
286 NULL, /* class_data */
dbb7bb09 287 sizeof (LttvTracesetStats),
b445142a 288 0, /* n_preallocs */
00e74b69 289 (GInstanceInitFunc) traceset_stats_instance_init, /* instance_init */
290 NULL /* Value handling */
b445142a 291 };
292
00e74b69 293 type = g_type_register_static (LTTV_TRACESET_STATE_TYPE,
294 "LttvTracesetStatsType",
295 &info, 0);
b445142a 296 }
297 return type;
298}
299
300
301static void
302trace_stats_instance_init (GTypeInstance *instance, gpointer g_class)
303{
304}
305
306
307static void
308trace_stats_finalize (LttvTraceStats *self)
309{
310 G_OBJECT_CLASS(g_type_class_peek(LTTV_TRACE_STATE_TYPE))->
311 finalize(G_OBJECT(self));
312}
313
314
315static void
316trace_stats_class_init (LttvTraceContextClass *klass)
317{
318 GObjectClass *gobject_class = G_OBJECT_CLASS(klass);
319
320 gobject_class->finalize = (void (*)(GObject *self)) trace_stats_finalize;
321}
322
323
324GType
325lttv_trace_stats_get_type(void)
326{
327 static GType type = 0;
328 if (type == 0) {
329 static const GTypeInfo info = {
330 sizeof (LttvTraceStatsClass),
331 NULL, /* base_init */
332 NULL, /* base_finalize */
333 (GClassInitFunc) trace_stats_class_init, /* class_init */
334 NULL, /* class_finalize */
335 NULL, /* class_data */
336 sizeof (LttvTraceStats),
337 0, /* n_preallocs */
00e74b69 338 (GInstanceInitFunc) trace_stats_instance_init, /* instance_init */
339 NULL /* Value handling */
b445142a 340 };
341
342 type = g_type_register_static (LTTV_TRACE_STATE_TYPE,
343 "LttvTraceStatsType", &info, 0);
344 }
345 return type;
346}
347
348
349static void
350tracefile_stats_instance_init (GTypeInstance *instance, gpointer g_class)
351{
352}
353
354
355static void
356tracefile_stats_finalize (LttvTracefileStats *self)
357{
358 G_OBJECT_CLASS(g_type_class_peek(LTTV_TRACEFILE_STATE_TYPE))->
359 finalize(G_OBJECT(self));
360}
361
362
363static void
364tracefile_stats_class_init (LttvTracefileStatsClass *klass)
365{
366 GObjectClass *gobject_class = G_OBJECT_CLASS(klass);
367
368 gobject_class->finalize = (void (*)(GObject *self)) tracefile_stats_finalize;
369}
370
371
372GType
373lttv_tracefile_stats_get_type(void)
374{
375 static GType type = 0;
376 if (type == 0) {
377 static const GTypeInfo info = {
378 sizeof (LttvTracefileStatsClass),
379 NULL, /* base_init */
380 NULL, /* base_finalize */
381 (GClassInitFunc) tracefile_stats_class_init, /* class_init */
382 NULL, /* class_finalize */
383 NULL, /* class_data */
384 sizeof (LttvTracefileStats),
385 0, /* n_preallocs */
00e74b69 386 (GInstanceInitFunc) tracefile_stats_instance_init, /* instance_init */
387 NULL /* Value handling */
b445142a 388 };
389
390 type = g_type_register_static (LTTV_TRACEFILE_STATE_TYPE,
391 "LttvTracefileStatsType", &info, 0);
392 }
393 return type;
394}
395
396
397static void
00e74b69 398find_event_tree(LttvTracefileStats *tfcs,
399 GQuark pid_time,
c0cb4d12 400 guint cpu,
d3670e3d 401 guint64 function,
00e74b69 402 GQuark mode,
403 GQuark sub_mode,
404 LttvAttribute **events_tree,
405 LttvAttribute **event_types_tree)
b445142a 406{
c0cb4d12 407 LttvAttribute *a, *prev_a;
d3670e3d 408 gchar fstring[MAX_64_HEX_STRING_LEN];
409 gint ret;
14236daa 410
d3670e3d 411 ret = snprintf(fstring, MAX_64_HEX_STRING_LEN-1,
412 "0x%llX", function) > 0;
413 g_assert(ret > 0);
414 fstring[MAX_64_HEX_STRING_LEN-1] = '\0';
b445142a 415
3c9bb8b1 416 LttvTraceStats *tcs = (LttvTraceStats*)tfcs->parent.parent.t_context;
b445142a 417 a = lttv_attribute_find_subdir(tcs->stats, LTTV_STATS_PROCESSES);
00e74b69 418 a = lttv_attribute_find_subdir(a, pid_time);
b445142a 419 a = lttv_attribute_find_subdir(a, LTTV_STATS_CPU);
c0cb4d12 420 a = lttv_attribute_find_subdir_unnamed(a, cpu);
14236daa 421 a = lttv_attribute_find_subdir(a, LTTV_STATS_FUNCTIONS);
422 a = lttv_attribute_find_subdir(a, g_quark_from_string(fstring));
b445142a 423 a = lttv_attribute_find_subdir(a, LTTV_STATS_MODE_TYPES);
00e74b69 424 a = lttv_attribute_find_subdir(a, mode);
b445142a 425 a = lttv_attribute_find_subdir(a, LTTV_STATS_SUBMODES);
00e74b69 426 a = lttv_attribute_find_subdir(a, sub_mode);
b445142a 427 *events_tree = a;
428 a = lttv_attribute_find_subdir(a, LTTV_STATS_EVENT_TYPES);
429 *event_types_tree = a;
430}
431
432
d3670e3d 433/* Update the trace event tree for the specified cpu */
434static void update_trace_event_tree(LttvTracefileStats *tfcs, guint cpu)
b445142a 435{
348c6ba8 436 LttvTraceState *ts = (LttvTraceState *)tfcs->parent.parent.t_context;
348c6ba8 437 LttvProcessState *process = ts->running_process[cpu];
438 LttvExecutionState *es = process->state;
b445142a 439
348c6ba8 440 find_event_tree(tfcs, process->pid_time,
c0cb4d12 441 cpu,
d3670e3d 442 process->current_function,
b445142a 443 es->t, es->n, &(tfcs->current_events_tree),
444 &(tfcs->current_event_types_tree));
445}
446
d3670e3d 447static void update_event_tree(LttvTracefileStats *tfcs)
448{
449 update_trace_event_tree(tfcs, tfcs->parent.cpu);
450}
b445142a 451
452static void mode_change(LttvTracefileStats *tfcs)
453{
348c6ba8 454 LttvTraceState *ts = (LttvTraceState *)tfcs->parent.parent.t_context;
ae3d0f50 455 guint cpu = tfcs->parent.cpu;
348c6ba8 456 LttvProcessState *process = ts->running_process[cpu];
b49e54b4 457 LttvAttributeValue cpu_time, cum_cpu_time;
b445142a 458
459 LttTime delta;
460
d3670e3d 461 if(process->state->s == LTTV_STATE_RUN &&
462 process->state->t != LTTV_STATE_MODE_UNKNOWN)
463 delta = ltt_time_sub(tfcs->parent.parent.timestamp,
464 process->state->change);
465 else
466 delta = ltt_time_zero;
b49e54b4 467
468 lttv_attribute_find(tfcs->current_events_tree, LTTV_STATS_CPU_TIME,
469 LTTV_TIME, &cpu_time);
308711e5 470 *(cpu_time.v_time) = ltt_time_add(*(cpu_time.v_time), delta);
b445142a 471
b49e54b4 472 process->state->cum_cpu_time = ltt_time_add(process->state->cum_cpu_time,
d3670e3d 473 delta);
b49e54b4 474}
b445142a 475
b49e54b4 476/* Note : every mode_end must come with a cumulative cpu time update in the
d3670e3d 477 * after hook. */
b445142a 478static void mode_end(LttvTracefileStats *tfcs)
479{
348c6ba8 480 LttvTraceState *ts = (LttvTraceState *)tfcs->parent.parent.t_context;
ae3d0f50 481 guint cpu = tfcs->parent.cpu;
348c6ba8 482 LttvProcessState *process = ts->running_process[cpu];
b49e54b4 483 LttvAttributeValue elapsed_time, cpu_time, cum_cpu_time;
b445142a 484
485 LttTime delta;
486
487 lttv_attribute_find(tfcs->current_events_tree, LTTV_STATS_ELAPSED_TIME,
488 LTTV_TIME, &elapsed_time);
d3670e3d 489
490 if(process->state->t != LTTV_STATE_MODE_UNKNOWN)
491 delta = ltt_time_sub(tfcs->parent.parent.timestamp,
492 process->state->entry);
493 else
494 delta = ltt_time_zero;
495
308711e5 496 *(elapsed_time.v_time) = ltt_time_add(*(elapsed_time.v_time), delta);
b445142a 497
498 lttv_attribute_find(tfcs->current_events_tree, LTTV_STATS_CPU_TIME,
499 LTTV_TIME, &cpu_time);
d3670e3d 500
501 /* if it is a running mode, we must count its cpu time */
502 if(process->state->s == LTTV_STATE_RUN &&
503 process->state->t != LTTV_STATE_MODE_UNKNOWN)
504 delta = ltt_time_sub(tfcs->parent.parent.timestamp,
505 process->state->change);
506 else
507 delta = ltt_time_zero;
508
308711e5 509 *(cpu_time.v_time) = ltt_time_add(*(cpu_time.v_time), delta);
b49e54b4 510 process->state->cum_cpu_time = ltt_time_add(process->state->cum_cpu_time,
d3670e3d 511 delta);
b49e54b4 512
513 lttv_attribute_find(tfcs->current_events_tree, LTTV_STATS_CUMULATIVE_CPU_TIME,
514 LTTV_TIME, &cum_cpu_time);
515 *(cum_cpu_time.v_time) = ltt_time_add(*(cum_cpu_time.v_time),
d3670e3d 516 process->state->cum_cpu_time);
b445142a 517}
518
519
b49e54b4 520static void after_mode_end(LttvTracefileStats *tfcs)
521{
522 LttvTraceState *ts = (LttvTraceState *)tfcs->parent.parent.t_context;
523 guint cpu = tfcs->parent.cpu;
524 LttvProcessState *process = ts->running_process[cpu];
525 LttvAttributeValue cum_cpu_time;
526
527 LttTime nested_delta;
528
529 nested_delta = process->state->cum_cpu_time;
d3670e3d 530 process->state->cum_cpu_time = ltt_time_zero; /* For after traceset hook */
b49e54b4 531
532 update_event_tree(tfcs);
533
534 process->state->cum_cpu_time = ltt_time_add(process->state->cum_cpu_time,
d3670e3d 535 nested_delta);
b49e54b4 536}
537
b445142a 538static gboolean before_syscall_entry(void *hook_data, void *call_data)
539{
540 mode_change((LttvTracefileStats *)call_data);
541 return FALSE;
542}
543
544
545static gboolean after_syscall_entry(void *hook_data, void *call_data)
546{
547 update_event_tree((LttvTracefileStats *)call_data);
548 return FALSE;
549}
550
551
552gboolean before_syscall_exit(void *hook_data, void *call_data)
553{
554 mode_end((LttvTracefileStats *)call_data);
555 return FALSE;
556}
557
558
559static gboolean after_syscall_exit(void *hook_data, void *call_data)
560{
b49e54b4 561 after_mode_end((LttvTracefileStats *)call_data);
b445142a 562 return FALSE;
563}
564
565
566gboolean before_trap_entry(void *hook_data, void *call_data)
567{
568 mode_change((LttvTracefileStats *)call_data);
569 return FALSE;
570}
571
572
573static gboolean after_trap_entry(void *hook_data, void *call_data)
574{
575 update_event_tree((LttvTracefileStats *)call_data);
576 return FALSE;
577}
578
579
580gboolean before_trap_exit(void *hook_data, void *call_data)
581{
582 mode_end((LttvTracefileStats *)call_data);
583 return FALSE;
584}
585
586
587gboolean after_trap_exit(void *hook_data, void *call_data)
588{
b49e54b4 589 after_mode_end((LttvTracefileStats *)call_data);
b445142a 590 return FALSE;
591}
592
593
594gboolean before_irq_entry(void *hook_data, void *call_data)
595{
596 mode_change((LttvTracefileStats *)call_data);
597 return FALSE;
598}
599
b445142a 600gboolean after_irq_entry(void *hook_data, void *call_data)
601{
602 update_event_tree((LttvTracefileStats *)call_data);
603 return FALSE;
604}
605
606
607gboolean before_irq_exit(void *hook_data, void *call_data)
608{
609 mode_end((LttvTracefileStats *)call_data);
610 return FALSE;
611}
612
613
614gboolean after_irq_exit(void *hook_data, void *call_data)
615{
b49e54b4 616 after_mode_end((LttvTracefileStats *)call_data);
b445142a 617 return FALSE;
618}
619
620
faf074a3 621gboolean before_soft_irq_entry(void *hook_data, void *call_data)
622{
623 mode_change((LttvTracefileStats *)call_data);
624 return FALSE;
625}
626
627gboolean after_soft_irq_entry(void *hook_data, void *call_data)
628{
629 update_event_tree((LttvTracefileStats *)call_data);
630 return FALSE;
631}
632
633
634gboolean before_soft_irq_exit(void *hook_data, void *call_data)
635{
636 mode_end((LttvTracefileStats *)call_data);
637 return FALSE;
638}
639
640
641gboolean after_soft_irq_exit(void *hook_data, void *call_data)
642{
b49e54b4 643 after_mode_end((LttvTracefileStats *)call_data);
faf074a3 644 return FALSE;
645}
646
14236daa 647gboolean before_function_entry(void *hook_data, void *call_data)
648{
b49e54b4 649 mode_change((LttvTracefileStats *)call_data);
14236daa 650 return FALSE;
651}
652
653gboolean after_function_entry(void *hook_data, void *call_data)
654{
655 update_event_tree((LttvTracefileStats *)call_data);
656 return FALSE;
657}
658
659gboolean before_function_exit(void *hook_data, void *call_data)
660{
661 mode_end((LttvTracefileStats *)call_data);
662 return FALSE;
663}
664
665gboolean after_function_exit(void *hook_data, void *call_data)
666{
b49e54b4 667 after_mode_end((LttvTracefileStats *)call_data);
14236daa 668 return FALSE;
669}
670
faf074a3 671
b445142a 672gboolean before_schedchange(void *hook_data, void *call_data)
673{
b445142a 674 LttvTracefileStats *tfcs = (LttvTracefileStats *)call_data;
675
348c6ba8 676 LttvTraceState *ts = (LttvTraceState*)tfcs->parent.parent.t_context;
677
eed2ef37 678 LttEvent *e = ltt_tracefile_get_event(tfcs->parent.parent.tf);
679
d052ffc3 680 LttvTraceHookByFacility *thf = (LttvTraceHookByFacility *)hook_data;
eed2ef37 681
d7cf605c 682 guint pid_in, pid_out;
683
684 gint state_out;
b445142a 685
eed2ef37 686 pid_out = ltt_event_get_unsigned(e, thf->f1);
687 pid_in = ltt_event_get_unsigned(e, thf->f2);
d7cf605c 688 state_out = ltt_event_get_int(e, thf->f3);
b445142a 689
690 /* compute the time for the process to schedule out */
691
692 mode_change(tfcs);
693
b49e54b4 694 return FALSE;
695}
b445142a 696
b49e54b4 697gboolean after_schedchange(void *hook_data, void *call_data)
698{
699 LttvTracefileStats *tfcs = (LttvTracefileStats *)call_data;
700
701 LttvTraceState *ts = (LttvTraceState*)tfcs->parent.parent.t_context;
b445142a 702
b49e54b4 703 LttEvent *e = ltt_tracefile_get_event(tfcs->parent.parent.tf);
704
705 LttvTraceHookByFacility *thf = (LttvTraceHookByFacility *)hook_data;
706
707 guint pid_in, pid_out;
708
709 gint state_out;
710
711 LttvProcessState *process;
712
713 pid_out = ltt_event_get_unsigned(e, thf->f1);
714 pid_in = ltt_event_get_unsigned(e, thf->f2);
715 state_out = ltt_event_get_int(e, thf->f3);
716
717 /* get the information for the process scheduled in */
c0cb4d12 718 guint cpu = tfcs->parent.cpu;
b49e54b4 719 process = ts->running_process[cpu];
c0cb4d12 720
348c6ba8 721 find_event_tree(tfcs, process->pid_time,
c0cb4d12 722 cpu,
d3670e3d 723 process->current_function,
b445142a 724 process->state->t, process->state->n, &(tfcs->current_events_tree),
725 &(tfcs->current_event_types_tree));
726
727 /* compute the time waiting for the process to schedule in */
b445142a 728 mode_change(tfcs);
b445142a 729
d3670e3d 730 return FALSE;
b49e54b4 731}
b445142a 732
733gboolean process_fork(void *hook_data, void *call_data)
734{
735 /* nothing to do for now */
736 return FALSE;
737}
738
739
740gboolean process_exit(void *hook_data, void *call_data)
741{
742 /* We should probably exit all modes here or we could do that at
743 schedule out. */
744 return FALSE;
745}
746
954417fa 747gboolean before_enum_process_state(void *hook_data, void *call_data)
748{
d3670e3d 749#if 0
750 /* Broken : adds up time in the current process doing the dump */
751 LttvTracefileStats *tfcs = (LttvTracefileStats *)call_data;
752 mode_end(tfcs);
753 after_mode_end(tfcs);
754 mode_change(tfcs);
755#endif //0
954417fa 756 return FALSE;
757}
758
759gboolean after_enum_process_state(void *hook_data, void *call_data)
760{
d3670e3d 761 LttvTracefileStats *tfcs = (LttvTracefileStats *)call_data;
762 LttvTracefileContext *tfc = (LttvTracefileContext *)call_data;
763 LttvTraceState *ts = (LttvTraceState*)tfc->t_context;
764 guint nb_cpus, i;
765
766 nb_cpus = ltt_trace_get_num_cpu(ts->parent.t);
767 for(i=0; i<nb_cpus; i++) {
768 update_trace_event_tree(tfcs, i);
769 }
770 return FALSE;
771}
772
773static gboolean after_statedump_end(void *hook_data, void *call_data)
774{
775 LttvTracefileStats *tfcs = (LttvTracefileStats *)call_data;
776 LttvTracefileContext *tfc = (LttvTracefileContext *)call_data;
777 LttvTraceState *ts = (LttvTraceState*)tfc->t_context;
778 guint nb_cpus, i;
779
780 nb_cpus = ltt_trace_get_num_cpu(ts->parent.t);
781 for(i=0; i<nb_cpus; i++) {
782 update_trace_event_tree(tfcs, i);
783 }
954417fa 784 return FALSE;
785}
786
eed2ef37 787gboolean process_free(void *hook_data, void *call_data)
788{
789 return FALSE;
790}
b445142a 791
792gboolean every_event(void *hook_data, void *call_data)
793{
794 LttvTracefileStats *tfcs = (LttvTracefileStats *)call_data;
795
eed2ef37 796 LttEvent *e = ltt_tracefile_get_event(tfcs->parent.parent.tf);
797
b445142a 798 LttvAttributeValue v;
799
800 /* The current branch corresponds to the tracefile/process/interrupt state.
801 Statistics are added within it, to count the number of events of this
802 type occuring in this context. A quark has been pre-allocated for each
803 event type and is used as name. */
804
805 lttv_attribute_find(tfcs->current_event_types_tree,
eed2ef37 806 ltt_eventtype_name(ltt_event_eventtype(e)),
b445142a 807 LTTV_UINT, &v);
808 (*(v.v_uint))++;
809 return FALSE;
810}
811
d3670e3d 812static void lttv_stats_cleanup_process_state(LttvTraceState *ts,
813 LttvProcessState *process)
c4a72569 814{
d3670e3d 815 LttvTraceStats *tcs = (LttvTraceStats *)ts;
c4a72569 816 LttvTracesetContext *tsc = ts->parent.ts_context;
c4a72569 817 int i;
818 LttvTracefileStats **tfs = (LttvTracefileStats **)
819 &g_array_index(ts->parent.tracefiles, LttvTracefileContext*,
820 process->cpu);
821 int cleanup_empty = 0;
822 LttTime nested_delta = ltt_time_zero;
823 /* FIXME : ok, this is a hack. The time is infinite here :( */
824 LttTime save_time = (*tfs)->parent.parent.timestamp;
825 LttTime start, end;
826 ltt_trace_time_span_get(ts->parent.t, &start, &end);
827 (*tfs)->parent.parent.timestamp = end;
828
829 do {
830 if(ltt_time_compare(process->state->cum_cpu_time, ltt_time_zero) != 0) {
831 find_event_tree(*tfs, process->pid_time,
832 process->cpu,
833 process->current_function,
834 process->state->t, process->state->n, &((*tfs)->current_events_tree),
835 &((*tfs)->current_event_types_tree));
d3670e3d 836 mode_end(*tfs);
c4a72569 837 nested_delta = process->state->cum_cpu_time;
838 }
839 cleanup_empty = lttv_state_pop_state_cleanup(process,
840 (LttvTracefileState *)*tfs);
841 process->state->cum_cpu_time = ltt_time_add(process->state->cum_cpu_time,
842 nested_delta);
843
844 } while(cleanup_empty != 1);
845
846 (*tfs)->parent.parent.timestamp = save_time;
b49e54b4 847}
848
d3670e3d 849/* For each cpu, for each of their stacked states,
b49e54b4 850 * perform sum of needed values. */
851static void lttv_stats_cleanup_state(LttvTraceStats *tcs)
852{
853 LttvTraceState *ts = (LttvTraceState *)tcs;
d3670e3d 854 guint nb_cpus, i;
855
856 nb_cpus = ltt_trace_get_num_cpu(ts->parent.t);
c4a72569 857
d3670e3d 858 for(i=0; i<nb_cpus; i++) {
859 lttv_stats_cleanup_process_state(ts, ts->running_process[i]);
860 }
c4a72569 861 /* Does not work correctly FIXME. */
d3670e3d 862 //g_hash_table_foreach(ts->processes, lttv_stats_cleanup_process_state,
863 // tcs);
b49e54b4 864}
b445142a 865
f95bc830 866void
69374af5 867lttv_stats_sum_trace(LttvTraceStats *self, LttvAttribute *ts_stats)
b445142a 868{
d3e01c7a 869 LttvAttribute *sum_container = self->stats;
b445142a 870
b445142a 871 LttvAttributeType type;
872
873 LttvAttributeValue value;
874
875 LttvAttributeName name;
876
d3670e3d 877 gboolean is_named;
c0cb4d12 878
b445142a 879 unsigned sum;
880
d3670e3d 881 int trace_is_summed;
69374af5 882
f95bc830 883 int i, j, k, l, m, nb_process, nb_cpu, nb_mode_type, nb_submode,
3813c77b 884 nb_event_type, nf, nb_functions;
b445142a 885
886 LttvAttribute *main_tree, *processes_tree, *process_tree, *cpus_tree,
887 *cpu_tree, *mode_tree, *mode_types_tree, *submodes_tree,
888 *submode_tree, *event_types_tree, *mode_events_tree,
3813c77b 889 *cpu_functions_tree,
d3670e3d 890 *function_tree,
891 *function_mode_types_tree,
892 *trace_cpu_tree;
f95bc830 893
b49e54b4 894
d3e01c7a 895 main_tree = sum_container;
f95bc830 896
d3e01c7a 897 lttv_attribute_find(sum_container,
898 LTTV_STATS_SUMMED,
899 LTTV_UINT, &value);
d3670e3d 900 trace_is_summed = *(value.v_uint);
f95bc830 901 *(value.v_uint) = 1;
902
d3670e3d 903 /* First cleanup the state : sum all stalled information (never ending
904 * states). */
905 if(!trace_is_summed)
906 lttv_stats_cleanup_state(self);
907
f95bc830 908 processes_tree = lttv_attribute_find_subdir(main_tree,
d3e01c7a 909 LTTV_STATS_PROCESSES);
f95bc830 910 nb_process = lttv_attribute_get_number(processes_tree);
911
912 for(i = 0 ; i < nb_process ; i++) {
c0cb4d12 913 type = lttv_attribute_get(processes_tree, i, &name, &value, &is_named);
f95bc830 914 process_tree = LTTV_ATTRIBUTE(*(value.v_gobject));
915
916 cpus_tree = lttv_attribute_find_subdir(process_tree, LTTV_STATS_CPU);
f95bc830 917 nb_cpu = lttv_attribute_get_number(cpus_tree);
918
919 for(j = 0 ; j < nb_cpu ; j++) {
c0cb4d12 920 type = lttv_attribute_get(cpus_tree, j, &name, &value, &is_named);
f95bc830 921 cpu_tree = LTTV_ATTRIBUTE(*(value.v_gobject));
922
f95bc830 923 trace_cpu_tree = lttv_attribute_find_subdir(main_tree, LTTV_STATS_CPU);
c0cb4d12 924 trace_cpu_tree = lttv_attribute_find_subdir_unnamed(trace_cpu_tree, name);
d3670e3d 925 cpu_functions_tree = lttv_attribute_find_subdir(cpu_tree,
926 LTTV_STATS_FUNCTIONS);
927 nb_functions = lttv_attribute_get_number(cpu_functions_tree);
928
929 for(nf=0; nf < nb_functions; nf++) {
930 type = lttv_attribute_get(cpu_functions_tree, nf, &name, &value,
931 &is_named);
932 function_tree = LTTV_ATTRIBUTE(*(value.v_gobject));
933 function_mode_types_tree = lttv_attribute_find_subdir(function_tree,
934 LTTV_STATS_MODE_TYPES);
935 nb_mode_type = lttv_attribute_get_number(function_mode_types_tree);
936 for(k = 0 ; k < nb_mode_type ; k++) {
937 type = lttv_attribute_get(function_mode_types_tree, k, &name, &value,
938 &is_named);
939 mode_tree = LTTV_ATTRIBUTE(*(value.v_gobject));
940
941 submodes_tree = lttv_attribute_find_subdir(mode_tree,
942 LTTV_STATS_SUBMODES);
943 mode_events_tree = lttv_attribute_find_subdir(mode_tree,
944 LTTV_STATS_EVENTS);
945 mode_types_tree = lttv_attribute_find_subdir(mode_tree,
946 LTTV_STATS_MODE_TYPES);
947
948 nb_submode = lttv_attribute_get_number(submodes_tree);
949
950 for(l = 0 ; l < nb_submode ; l++) {
951 type = lttv_attribute_get(submodes_tree, l, &name, &value,
952 &is_named);
953 submode_tree = LTTV_ATTRIBUTE(*(value.v_gobject));
954
955 event_types_tree = lttv_attribute_find_subdir(submode_tree,
956 LTTV_STATS_EVENT_TYPES);
957 nb_event_type = lttv_attribute_get_number(event_types_tree);
958
959 sum = 0;
960 for(m = 0 ; m < nb_event_type ; m++) {
961 type = lttv_attribute_get(event_types_tree, m, &name, &value,
962 &is_named);
963 sum += *(value.v_uint);
964 }
965 lttv_attribute_find(submode_tree, LTTV_STATS_EVENTS_COUNT,
966 LTTV_UINT, &value);
967 *(value.v_uint) = sum;
968
969 type = lttv_attribute_get(submodes_tree, l, &name, &value,
970 &is_named);
971 submode_tree = LTTV_ATTRIBUTE(*(value.v_gobject));
972 if(!trace_is_summed) {
973 lttv_attribute_recursive_add(mode_events_tree, event_types_tree);
974 lttv_attribute_recursive_add(mode_types_tree, submode_tree);
975 }
976 }
977 if(!trace_is_summed) {
978 lttv_attribute_recursive_add(function_tree, mode_types_tree);
979 }
980 }
981 if(!trace_is_summed) {
982 lttv_attribute_recursive_add(cpu_tree, function_tree);
983 lttv_attribute_recursive_add(process_tree, function_tree);
984 lttv_attribute_recursive_add(trace_cpu_tree, function_tree);
985 lttv_attribute_recursive_add(main_tree, function_tree);
986 }
987 lttv_attribute_recursive_add(ts_stats, function_tree);
988 }
b445142a 989 }
f95bc830 990 }
991}
992
993
d3e01c7a 994gboolean lttv_stats_sum_traceset_hook(void *hook_data, void *call_data)
995{
996 lttv_stats_sum_traceset((LttvTracesetStats *)call_data);
997 return 0;
998}
999
f95bc830 1000void
1001lttv_stats_sum_traceset(LttvTracesetStats *self)
1002{
1003 LttvTraceset *traceset = self->parent.parent.ts;
d3e01c7a 1004 LttvAttribute *sum_container = self->stats;
f95bc830 1005
1006 LttvTraceStats *tcs;
1007
1008 int i, nb_trace;
1009
3813c77b 1010 LttvAttribute *main_tree;
f95bc830 1011
1012 LttvAttributeValue value;
1013
d3e01c7a 1014 lttv_attribute_find(sum_container, LTTV_STATS_SUMMED,
f95bc830 1015 LTTV_UINT, &value);
1016 if(*(value.v_uint) != 0) return;
1017 *(value.v_uint) = 1;
1018
f95bc830 1019 nb_trace = lttv_traceset_number(traceset);
1020
1021 for(i = 0 ; i < nb_trace ; i++) {
1022 tcs = (LttvTraceStats *)(self->parent.parent.traces[i]);
69374af5 1023 lttv_stats_sum_trace(tcs, self->stats);
d3670e3d 1024 // lttv_attribute_recursive_add(sum_container, tcs->stats);
b445142a 1025 }
b445142a 1026}
1027
1028
d3e01c7a 1029// Hook wrapper. call_data is a traceset context.
00e74b69 1030gboolean lttv_stats_hook_add_event_hooks(void *hook_data, void *call_data)
d3e01c7a 1031{
1032 LttvTracesetStats *tss = (LttvTracesetStats*)call_data;
1033
1034 lttv_stats_add_event_hooks(tss);
1035
1036 return 0;
1037}
1038
00e74b69 1039void lttv_stats_add_event_hooks(LttvTracesetStats *self)
b445142a 1040{
1041 LttvTraceset *traceset = self->parent.parent.ts;
1042
eed2ef37 1043 guint i, j, k, l, nb_trace, nb_tracefile;
b445142a 1044
b445142a 1045 LttvTraceStats *ts;
1046
1047 LttvTracefileStats *tfs;
1048
b445142a 1049 GArray *hooks, *before_hooks, *after_hooks;
1050
eed2ef37 1051 LttvTraceHook *hook;
1052
1053 LttvTraceHookByFacility *thf;
b445142a 1054
1055 LttvAttributeValue val;
1056
9d239bd9 1057 gint ret;
d3670e3d 1058 gint hn;
9d239bd9 1059
b445142a 1060 nb_trace = lttv_traceset_number(traceset);
1061 for(i = 0 ; i < nb_trace ; i++) {
1062 ts = (LttvTraceStats *)self->parent.parent.traces[i];
1063
1064 /* Find the eventtype id for the following events and register the
1065 associated by id hooks. */
1066
954417fa 1067 hooks = g_array_sized_new(FALSE, FALSE, sizeof(LttvTraceHook), 12);
1068 g_array_set_size(hooks, 12);
1069 hn=0;
b445142a 1070
9d239bd9 1071 ret = lttv_trace_find_hook(ts->parent.parent.t,
f5d7967f 1072 LTT_FACILITY_KERNEL_ARCH, LTT_EVENT_SYSCALL_ENTRY,
eed2ef37 1073 LTT_FIELD_SYSCALL_ID, 0, 0,
2c82c4dc 1074 before_syscall_entry, NULL,
2501204d 1075 &g_array_index(hooks, LttvTraceHook, hn++));
1076 if(ret) hn--;
b445142a 1077
9d239bd9 1078 ret = lttv_trace_find_hook(ts->parent.parent.t,
f5d7967f 1079 LTT_FACILITY_KERNEL_ARCH, LTT_EVENT_SYSCALL_EXIT,
eed2ef37 1080 0, 0, 0,
2c82c4dc 1081 before_syscall_exit, NULL,
2501204d 1082 &g_array_index(hooks, LttvTraceHook, hn++));
1083 if(ret) hn--;
b445142a 1084
9d239bd9 1085 ret = lttv_trace_find_hook(ts->parent.parent.t,
eed2ef37 1086 LTT_FACILITY_KERNEL, LTT_EVENT_TRAP_ENTRY,
1087 LTT_FIELD_TRAP_ID, 0, 0,
2c82c4dc 1088 before_trap_entry, NULL,
2501204d 1089 &g_array_index(hooks, LttvTraceHook, hn++));
1090 if(ret) hn--;
b445142a 1091
9d239bd9 1092 ret = lttv_trace_find_hook(ts->parent.parent.t,
eed2ef37 1093 LTT_FACILITY_KERNEL, LTT_EVENT_TRAP_EXIT,
1094 0, 0, 0,
2c82c4dc 1095 before_trap_exit, NULL,
2501204d 1096 &g_array_index(hooks, LttvTraceHook, hn++));
1097 if(ret) hn--;
eed2ef37 1098
9d239bd9 1099 ret = lttv_trace_find_hook(ts->parent.parent.t,
eed2ef37 1100 LTT_FACILITY_KERNEL, LTT_EVENT_IRQ_ENTRY,
1101 LTT_FIELD_IRQ_ID, 0, 0,
2c82c4dc 1102 before_irq_entry, NULL,
2501204d 1103 &g_array_index(hooks, LttvTraceHook, hn++));
1104 if(ret) hn--;
eed2ef37 1105
9d239bd9 1106 ret = lttv_trace_find_hook(ts->parent.parent.t,
eed2ef37 1107 LTT_FACILITY_KERNEL, LTT_EVENT_IRQ_EXIT,
1108 0, 0, 0,
2c82c4dc 1109 before_irq_exit, NULL,
2501204d 1110 &g_array_index(hooks, LttvTraceHook, hn++));
1111 if(ret) hn--;
eed2ef37 1112
faf074a3 1113 ret = lttv_trace_find_hook(ts->parent.parent.t,
1114 LTT_FACILITY_KERNEL, LTT_EVENT_SOFT_IRQ_ENTRY,
1115 LTT_FIELD_SOFT_IRQ_ID, 0, 0,
1116 before_soft_irq_entry, NULL,
2501204d 1117 &g_array_index(hooks, LttvTraceHook, hn++));
1118 if(ret) hn--;
faf074a3 1119
1120 ret = lttv_trace_find_hook(ts->parent.parent.t,
1121 LTT_FACILITY_KERNEL, LTT_EVENT_SOFT_IRQ_EXIT,
1122 0, 0, 0,
1123 before_soft_irq_exit, NULL,
2501204d 1124 &g_array_index(hooks, LttvTraceHook, hn++));
1125 if(ret) hn--;
faf074a3 1126
9d239bd9 1127 ret = lttv_trace_find_hook(ts->parent.parent.t,
eed2ef37 1128 LTT_FACILITY_PROCESS, LTT_EVENT_SCHEDCHANGE,
1129 LTT_FIELD_OUT, LTT_FIELD_IN, LTT_FIELD_OUT_STATE,
2c82c4dc 1130 before_schedchange, NULL,
2501204d 1131 &g_array_index(hooks, LttvTraceHook, hn++));
1132 if(ret) hn--;
14236daa 1133
1134 ret = lttv_trace_find_hook(ts->parent.parent.t,
1135 LTT_FACILITY_USER_GENERIC, LTT_EVENT_FUNCTION_ENTRY,
1136 LTT_FIELD_THIS_FN, LTT_FIELD_CALL_SITE, 0,
1137 before_function_entry, NULL,
1138 &g_array_index(hooks, LttvTraceHook, hn++));
1139 if(ret) hn--;
1140
1141 ret = lttv_trace_find_hook(ts->parent.parent.t,
1142 LTT_FACILITY_USER_GENERIC, LTT_EVENT_FUNCTION_EXIT,
1143 LTT_FIELD_THIS_FN, LTT_FIELD_CALL_SITE, 0,
1144 before_function_exit, NULL,
1145 &g_array_index(hooks, LttvTraceHook, hn++));
1146 if(ret) hn--;
954417fa 1147
1148 /* statedump-related hooks */
1149 ret = lttv_trace_find_hook(ts->parent.parent.t,
1150 LTT_FACILITY_STATEDUMP, LTT_EVENT_ENUM_PROCESS_STATE,
1151 LTT_FIELD_PID, LTT_FIELD_PARENT_PID, LTT_FIELD_NAME,
1152 before_enum_process_state, NULL,
1153 &g_array_index(hooks, LttvTraceHook, hn++));
1154 if(ret) hn--;
1155
2501204d 1156 g_array_set_size(hooks, hn);
b445142a 1157
1158 before_hooks = hooks;
1159
d3670e3d 1160 hooks = g_array_sized_new(FALSE, FALSE, sizeof(LttvTraceHook), 16);
1161 g_array_set_size(hooks, 16);
954417fa 1162 hn=0;
b445142a 1163
9d239bd9 1164 ret = lttv_trace_find_hook(ts->parent.parent.t,
f5d7967f 1165 LTT_FACILITY_KERNEL_ARCH, LTT_EVENT_SYSCALL_ENTRY,
eed2ef37 1166 LTT_FIELD_SYSCALL_ID, 0, 0,
2c82c4dc 1167 after_syscall_entry, NULL,
2501204d 1168 &g_array_index(hooks, LttvTraceHook, hn++));
1169 if(ret) hn--;
b445142a 1170
9d239bd9 1171 ret = lttv_trace_find_hook(ts->parent.parent.t,
f5d7967f 1172 LTT_FACILITY_KERNEL_ARCH, LTT_EVENT_SYSCALL_EXIT,
eed2ef37 1173 0, 0, 0,
2c82c4dc 1174 after_syscall_exit, NULL,
2501204d 1175 &g_array_index(hooks, LttvTraceHook, hn++));
1176 if(ret) hn--;
b445142a 1177
9d239bd9 1178 ret = lttv_trace_find_hook(ts->parent.parent.t,
eed2ef37 1179 LTT_FACILITY_KERNEL, LTT_EVENT_TRAP_ENTRY,
1180 LTT_FIELD_TRAP_ID, 0, 0,
2c82c4dc 1181 after_trap_entry, NULL,
2501204d 1182 &g_array_index(hooks, LttvTraceHook, hn++));
1183 if(ret) hn--;
eed2ef37 1184
9d239bd9 1185 ret = lttv_trace_find_hook(ts->parent.parent.t,
eed2ef37 1186 LTT_FACILITY_KERNEL, LTT_EVENT_TRAP_EXIT,
1187 0, 0, 0,
2c82c4dc 1188 after_trap_exit, NULL,
2501204d 1189 &g_array_index(hooks, LttvTraceHook, hn++));
1190 if(ret) hn--;
b445142a 1191
9d239bd9 1192 ret = lttv_trace_find_hook(ts->parent.parent.t,
eed2ef37 1193 LTT_FACILITY_KERNEL, LTT_EVENT_IRQ_ENTRY,
1194 LTT_FIELD_IRQ_ID, 0, 0,
2c82c4dc 1195 after_irq_entry, NULL,
2501204d 1196 &g_array_index(hooks, LttvTraceHook, hn++));
1197 if(ret) hn--;
b445142a 1198
9d239bd9 1199 ret = lttv_trace_find_hook(ts->parent.parent.t,
eed2ef37 1200 LTT_FACILITY_KERNEL, LTT_EVENT_IRQ_EXIT,
1201 0, 0, 0,
2c82c4dc 1202 after_irq_exit, NULL,
2501204d 1203 &g_array_index(hooks, LttvTraceHook, hn++));
1204 if(ret) hn--;
b445142a 1205
faf074a3 1206 ret = lttv_trace_find_hook(ts->parent.parent.t,
1207 LTT_FACILITY_KERNEL, LTT_EVENT_SOFT_IRQ_ENTRY,
1208 LTT_FIELD_SOFT_IRQ_ID, 0, 0,
1209 after_irq_entry, NULL,
2501204d 1210 &g_array_index(hooks, LttvTraceHook, hn++));
1211 if(ret) hn--;
faf074a3 1212
1213 ret = lttv_trace_find_hook(ts->parent.parent.t,
1214 LTT_FACILITY_KERNEL, LTT_EVENT_SOFT_IRQ_EXIT,
1215 0, 0, 0,
1216 after_soft_irq_exit, NULL,
2501204d 1217 &g_array_index(hooks, LttvTraceHook, hn++));
1218 if(ret) hn--;
b445142a 1219
b49e54b4 1220 ret = lttv_trace_find_hook(ts->parent.parent.t,
1221 LTT_FACILITY_PROCESS, LTT_EVENT_SCHEDCHANGE,
1222 LTT_FIELD_OUT, LTT_FIELD_IN, LTT_FIELD_OUT_STATE,
1223 after_schedchange, NULL,
1224 &g_array_index(hooks, LttvTraceHook, hn++));
1225 if(ret) hn--;
1226
9d239bd9 1227 ret = lttv_trace_find_hook(ts->parent.parent.t,
eed2ef37 1228 LTT_FACILITY_PROCESS, LTT_EVENT_FORK,
1229 LTT_FIELD_PARENT_PID, LTT_FIELD_CHILD_PID, 0,
2c82c4dc 1230 process_fork, NULL,
2501204d 1231 &g_array_index(hooks, LttvTraceHook, hn++));
1232 if(ret) hn--;
b445142a 1233
9d239bd9 1234 ret = lttv_trace_find_hook(ts->parent.parent.t,
eed2ef37 1235 LTT_FACILITY_PROCESS, LTT_EVENT_EXIT,
1236 LTT_FIELD_PID, 0, 0,
2c82c4dc 1237 process_exit, NULL,
2501204d 1238 &g_array_index(hooks, LttvTraceHook, hn++));
1239 if(ret) hn--;
eed2ef37 1240
9d239bd9 1241 ret = lttv_trace_find_hook(ts->parent.parent.t,
eed2ef37 1242 LTT_FACILITY_PROCESS, LTT_EVENT_FREE,
1243 LTT_FIELD_PID, 0, 0,
2c82c4dc 1244 process_free, NULL,
2501204d 1245 &g_array_index(hooks, LttvTraceHook, hn++));
1246 if(ret) hn--;
eed2ef37 1247
14236daa 1248 ret = lttv_trace_find_hook(ts->parent.parent.t,
1249 LTT_FACILITY_USER_GENERIC, LTT_EVENT_FUNCTION_ENTRY,
1250 LTT_FIELD_THIS_FN, LTT_FIELD_CALL_SITE, 0,
1251 after_function_entry, NULL,
1252 &g_array_index(hooks, LttvTraceHook, hn++));
1253 if(ret) hn--;
1254
1255 ret = lttv_trace_find_hook(ts->parent.parent.t,
1256 LTT_FACILITY_USER_GENERIC, LTT_EVENT_FUNCTION_EXIT,
1257 LTT_FIELD_THIS_FN, LTT_FIELD_CALL_SITE, 0,
1258 after_function_exit, NULL,
1259 &g_array_index(hooks, LttvTraceHook, hn++));
1260 if(ret) hn--;
954417fa 1261
1262 /* statedump-related hooks */
1263 ret = lttv_trace_find_hook(ts->parent.parent.t,
1264 LTT_FACILITY_STATEDUMP, LTT_EVENT_ENUM_PROCESS_STATE,
1265 LTT_FIELD_PID, LTT_FIELD_PARENT_PID, LTT_FIELD_NAME,
1266 after_enum_process_state, NULL,
1267 &g_array_index(hooks, LttvTraceHook, hn++));
1268 if(ret) hn--;
1269
d3670e3d 1270 ret = lttv_trace_find_hook(ts->parent.parent.t,
1271 LTT_FACILITY_STATEDUMP, LTT_EVENT_STATEDUMP_END,
1272 0, 0, 0,
1273 after_statedump_end, NULL,
1274 &g_array_index(hooks, LttvTraceHook, hn++));
1275 if(ret) hn--;
1276
2501204d 1277 g_array_set_size(hooks, hn);
b445142a 1278
1279 after_hooks = hooks;
1280
359b2948 1281 /* Add these hooks to each event_by_id hooks list */
b445142a 1282
eed2ef37 1283 nb_tracefile = ts->parent.parent.tracefiles->len;
b445142a 1284
dbb7bb09 1285 for(j = 0 ; j < nb_tracefile ; j++) {
d7cf605c 1286 tfs = LTTV_TRACEFILE_STATS(g_array_index(ts->parent.parent.tracefiles,
1287 LttvTracefileContext*, j));
359b2948 1288 lttv_hooks_add(tfs->parent.parent.event, every_event, NULL,
1289 LTTV_PRIO_DEFAULT);
b445142a 1290
1291 for(k = 0 ; k < before_hooks->len ; k++) {
eed2ef37 1292 hook = &g_array_index(before_hooks, LttvTraceHook, k);
1293 for(l = 0; l<hook->fac_list->len;l++) {
1294 thf = g_array_index(hook->fac_list, LttvTraceHookByFacility*, l);
1295 lttv_hooks_add(
1296 lttv_hooks_by_id_find(tfs->parent.parent.event_by_id, thf->id),
1297 thf->h,
d052ffc3 1298 thf,
eed2ef37 1299 LTTV_PRIO_STATS_BEFORE_STATE);
1300 }
b445142a 1301 }
1302 for(k = 0 ; k < after_hooks->len ; k++) {
eed2ef37 1303 hook = &g_array_index(after_hooks, LttvTraceHook, k);
1304 for(l = 0; l<hook->fac_list->len;l++) {
1305 thf = g_array_index(hook->fac_list, LttvTraceHookByFacility*, l);
1306 lttv_hooks_add(
1307 lttv_hooks_by_id_find(tfs->parent.parent.event_by_id, thf->id),
1308 thf->h,
d052ffc3 1309 thf,
eed2ef37 1310 LTTV_PRIO_STATS_AFTER_STATE);
1311 }
b445142a 1312 }
1313 }
1314 lttv_attribute_find(self->parent.parent.a, LTTV_STATS_BEFORE_HOOKS,
1315 LTTV_POINTER, &val);
1316 *(val.v_pointer) = before_hooks;
1317 lttv_attribute_find(self->parent.parent.a, LTTV_STATS_AFTER_HOOKS,
1318 LTTV_POINTER, &val);
1319 *(val.v_pointer) = after_hooks;
1320 }
b445142a 1321}
1322
d3e01c7a 1323// Hook wrapper. call_data is a traceset context.
00e74b69 1324gboolean lttv_stats_hook_remove_event_hooks(void *hook_data, void *call_data)
d3e01c7a 1325{
1326 LttvTracesetStats *tss = (LttvTracesetStats*)call_data;
1327
1328 lttv_stats_remove_event_hooks(tss);
1329
1330 return 0;
1331}
b445142a 1332
00e74b69 1333void lttv_stats_remove_event_hooks(LttvTracesetStats *self)
b445142a 1334{
1335 LttvTraceset *traceset = self->parent.parent.ts;
1336
eed2ef37 1337 guint i, j, k, l, nb_trace, nb_tracefile;
b445142a 1338
1339 LttvTraceStats *ts;
1340
1341 LttvTracefileStats *tfs;
1342
1343 void *hook_data;
1344
1345 GArray *before_hooks, *after_hooks;
1346
eed2ef37 1347 LttvTraceHook *hook;
1348
1349 LttvTraceHookByFacility *thf;
b445142a 1350
1351 LttvAttributeValue val;
1352
1353 nb_trace = lttv_traceset_number(traceset);
1354 for(i = 0 ; i < nb_trace ; i++) {
ae80b609 1355 ts = (LttvTraceStats*)self->parent.parent.traces[i];
b445142a 1356 lttv_attribute_find(self->parent.parent.a, LTTV_STATS_BEFORE_HOOKS,
1357 LTTV_POINTER, &val);
1358 before_hooks = *(val.v_pointer);
1359 lttv_attribute_find(self->parent.parent.a, LTTV_STATS_AFTER_HOOKS,
1360 LTTV_POINTER, &val);
1361 after_hooks = *(val.v_pointer);
1362
359b2948 1363 /* Remove these hooks from each event_by_id hooks list */
b445142a 1364
eed2ef37 1365 nb_tracefile = ts->parent.parent.tracefiles->len;
b445142a 1366
dbb7bb09 1367 for(j = 0 ; j < nb_tracefile ; j++) {
cb03932a 1368 tfs = LTTV_TRACEFILE_STATS(g_array_index(ts->parent.parent.tracefiles,
1369 LttvTracefileContext*, j));
359b2948 1370 lttv_hooks_remove_data(tfs->parent.parent.event, every_event,
b445142a 1371 NULL);
1372
1373 for(k = 0 ; k < before_hooks->len ; k++) {
eed2ef37 1374 hook = &g_array_index(before_hooks, LttvTraceHook, k);
1375 for(l = 0 ; l < hook->fac_list->len ; l++) {
1376 thf = g_array_index(hook->fac_list, LttvTraceHookByFacility*, l);
1377 lttv_hooks_remove_data(
1378 lttv_hooks_by_id_find(tfs->parent.parent.event_by_id, thf->id),
1379 thf->h,
d052ffc3 1380 thf);
eed2ef37 1381 }
b445142a 1382 }
1383 for(k = 0 ; k < after_hooks->len ; k++) {
eed2ef37 1384 hook = &g_array_index(after_hooks, LttvTraceHook, k);
1385 for(l = 0 ; l < hook->fac_list->len ; l++) {
1386 thf = g_array_index(hook->fac_list, LttvTraceHookByFacility*, l);
1387 lttv_hooks_remove_data(
1388 lttv_hooks_by_id_find(tfs->parent.parent.event_by_id, thf->id),
1389 thf->h,
d052ffc3 1390 thf);
eed2ef37 1391 }
b445142a 1392 }
1393 }
2a2fa4f0 1394 g_debug("lttv_stats_remove_event_hooks()");
b445142a 1395 g_array_free(before_hooks, TRUE);
1396 g_array_free(after_hooks, TRUE);
1397 }
9f797243 1398}
08b1c66e 1399
1400
1401static void module_init()
1402{
1403 LTTV_STATS_PROCESS_UNKNOWN = g_quark_from_string("unknown process");
1404 LTTV_STATS_PROCESSES = g_quark_from_string("processes");
1405 LTTV_STATS_CPU = g_quark_from_string("cpu");
1406 LTTV_STATS_MODE_TYPES = g_quark_from_string("mode_types");
1407 LTTV_STATS_MODES = g_quark_from_string("modes");
1408 LTTV_STATS_SUBMODES = g_quark_from_string("submodes");
14236daa 1409 LTTV_STATS_FUNCTIONS = g_quark_from_string("functions");
08b1c66e 1410 LTTV_STATS_EVENT_TYPES = g_quark_from_string("event_types");
1411 LTTV_STATS_CPU_TIME = g_quark_from_string("cpu time");
b49e54b4 1412 LTTV_STATS_CUMULATIVE_CPU_TIME = g_quark_from_string("cumulative cpu time (includes nested routines and modes)");
1413 LTTV_STATS_ELAPSED_TIME = g_quark_from_string("elapsed time (includes per process waiting time)");
08b1c66e 1414 LTTV_STATS_EVENTS = g_quark_from_string("events");
1415 LTTV_STATS_EVENTS_COUNT = g_quark_from_string("events count");
1416 LTTV_STATS_BEFORE_HOOKS = g_quark_from_string("saved stats before hooks");
1417 LTTV_STATS_AFTER_HOOKS = g_quark_from_string("saved stats after hooks");
f95bc830 1418 LTTV_STATS_USE_COUNT = g_quark_from_string("stats_use_count");
1419 LTTV_STATS = g_quark_from_string("statistics");
1420 LTTV_STATS_TRACEFILES = g_quark_from_string("tracefiles statistics");
1421 LTTV_STATS_SUMMED = g_quark_from_string("statistics summed");
08b1c66e 1422}
1423
1424static void module_destroy()
1425{
1426}
1427
1428
1429LTTV_MODULE("stats", "Compute processes statistics", \
1430 "Accumulate statistics for event types, processes and CPUs", \
1431 module_init, module_destroy, "state");
f95bc830 1432
1433/* Change the places where stats are called (create/read/write stats)
1434
1435 Check for options in batchtest.c to reduce writing and see what tests are
1436 best candidates for performance analysis. Once OK, commit, move to main
1437 and run tests. Update the gui for statistics. */
This page took 0.113635 seconds and 4 git commands to generate.