update compat
[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
b445142a 396static void
00e74b69 397find_event_tree(LttvTracefileStats *tfcs,
398 GQuark pid_time,
c0cb4d12 399 guint cpu,
d3670e3d 400 guint64 function,
00e74b69 401 GQuark mode,
402 GQuark sub_mode,
403 LttvAttribute **events_tree,
404 LttvAttribute **event_types_tree)
b445142a 405{
c0cb4d12 406 LttvAttribute *a, *prev_a;
d3670e3d 407 gchar fstring[MAX_64_HEX_STRING_LEN];
408 gint ret;
14236daa 409
d3670e3d 410 ret = snprintf(fstring, MAX_64_HEX_STRING_LEN-1,
411 "0x%llX", function) > 0;
412 g_assert(ret > 0);
413 fstring[MAX_64_HEX_STRING_LEN-1] = '\0';
b445142a 414
3c9bb8b1 415 LttvTraceStats *tcs = (LttvTraceStats*)tfcs->parent.parent.t_context;
b445142a 416 a = lttv_attribute_find_subdir(tcs->stats, LTTV_STATS_PROCESSES);
00e74b69 417 a = lttv_attribute_find_subdir(a, pid_time);
b445142a 418 a = lttv_attribute_find_subdir(a, LTTV_STATS_CPU);
c0cb4d12 419 a = lttv_attribute_find_subdir_unnamed(a, cpu);
14236daa 420 a = lttv_attribute_find_subdir(a, LTTV_STATS_FUNCTIONS);
421 a = lttv_attribute_find_subdir(a, g_quark_from_string(fstring));
b445142a 422 a = lttv_attribute_find_subdir(a, LTTV_STATS_MODE_TYPES);
00e74b69 423 a = lttv_attribute_find_subdir(a, mode);
b445142a 424 a = lttv_attribute_find_subdir(a, LTTV_STATS_SUBMODES);
00e74b69 425 a = lttv_attribute_find_subdir(a, sub_mode);
b445142a 426 *events_tree = a;
427 a = lttv_attribute_find_subdir(a, LTTV_STATS_EVENT_TYPES);
428 *event_types_tree = a;
429}
430
89f8741a 431static void update_event_tree(LttvTracefileStats *tfcs)
b445142a 432{
89f8741a 433 guint cpu = tfcs->parent.cpu;
348c6ba8 434 LttvTraceState *ts = (LttvTraceState *)tfcs->parent.parent.t_context;
348c6ba8 435 LttvProcessState *process = ts->running_process[cpu];
436 LttvExecutionState *es = process->state;
b445142a 437
348c6ba8 438 find_event_tree(tfcs, process->pid_time,
c0cb4d12 439 cpu,
d3670e3d 440 process->current_function,
b445142a 441 es->t, es->n, &(tfcs->current_events_tree),
442 &(tfcs->current_event_types_tree));
443}
444
89f8741a 445
446/* Update the trace event tree for the specified cpu */
447static void update_trace_event_tree(LttvTraceStats *tcs)
d3670e3d 448{
89f8741a 449 LttvTracefileStats *tfcs;
450 LttvTraceContext *tc = (LttvTraceContext*)tcs;
451 guint j, nb_tracefile;
452
453 /* For each tracefile, update the event tree */
454 nb_tracefile = tc->tracefiles->len;
455 for(j = 0; j < nb_tracefile; j++) {
456 tfcs = LTTV_TRACEFILE_STATS(g_array_index(tc->tracefiles,
457 LttvTracefileContext*, j));
458 update_event_tree(tfcs);
459 }
d3670e3d 460}
b445142a 461
462static void mode_change(LttvTracefileStats *tfcs)
463{
348c6ba8 464 LttvTraceState *ts = (LttvTraceState *)tfcs->parent.parent.t_context;
ae3d0f50 465 guint cpu = tfcs->parent.cpu;
348c6ba8 466 LttvProcessState *process = ts->running_process[cpu];
b49e54b4 467 LttvAttributeValue cpu_time, cum_cpu_time;
b445142a 468
469 LttTime delta;
470
d3670e3d 471 if(process->state->s == LTTV_STATE_RUN &&
472 process->state->t != LTTV_STATE_MODE_UNKNOWN)
473 delta = ltt_time_sub(tfcs->parent.parent.timestamp,
474 process->state->change);
475 else
476 delta = ltt_time_zero;
b49e54b4 477
478 lttv_attribute_find(tfcs->current_events_tree, LTTV_STATS_CPU_TIME,
479 LTTV_TIME, &cpu_time);
308711e5 480 *(cpu_time.v_time) = ltt_time_add(*(cpu_time.v_time), delta);
b445142a 481
b49e54b4 482 process->state->cum_cpu_time = ltt_time_add(process->state->cum_cpu_time,
d3670e3d 483 delta);
b49e54b4 484}
b445142a 485
b49e54b4 486/* Note : every mode_end must come with a cumulative cpu time update in the
d3670e3d 487 * after hook. */
b445142a 488static void mode_end(LttvTracefileStats *tfcs)
489{
348c6ba8 490 LttvTraceState *ts = (LttvTraceState *)tfcs->parent.parent.t_context;
ae3d0f50 491 guint cpu = tfcs->parent.cpu;
348c6ba8 492 LttvProcessState *process = ts->running_process[cpu];
b49e54b4 493 LttvAttributeValue elapsed_time, cpu_time, cum_cpu_time;
b445142a 494
495 LttTime delta;
496
15f3a340 497 /* FIXME put there in case of a missing update after a state modification */
89f8741a 498 //void *lasttree = tfcs->current_events_tree;
15f3a340 499 //update_event_tree(tfcs);
89f8741a 500 //g_assert (lasttree == tfcs->current_events_tree);
b445142a 501 lttv_attribute_find(tfcs->current_events_tree, LTTV_STATS_ELAPSED_TIME,
502 LTTV_TIME, &elapsed_time);
d3670e3d 503
89f8741a 504 if(process->state->t != LTTV_STATE_MODE_UNKNOWN) {
d3670e3d 505 delta = ltt_time_sub(tfcs->parent.parent.timestamp,
506 process->state->entry);
89f8741a 507 } else
d3670e3d 508 delta = ltt_time_zero;
509
308711e5 510 *(elapsed_time.v_time) = ltt_time_add(*(elapsed_time.v_time), delta);
b445142a 511
512 lttv_attribute_find(tfcs->current_events_tree, LTTV_STATS_CPU_TIME,
513 LTTV_TIME, &cpu_time);
d3670e3d 514
515 /* if it is a running mode, we must count its cpu time */
516 if(process->state->s == LTTV_STATE_RUN &&
517 process->state->t != LTTV_STATE_MODE_UNKNOWN)
518 delta = ltt_time_sub(tfcs->parent.parent.timestamp,
519 process->state->change);
520 else
521 delta = ltt_time_zero;
522
308711e5 523 *(cpu_time.v_time) = ltt_time_add(*(cpu_time.v_time), delta);
b49e54b4 524 process->state->cum_cpu_time = ltt_time_add(process->state->cum_cpu_time,
d3670e3d 525 delta);
b49e54b4 526
527 lttv_attribute_find(tfcs->current_events_tree, LTTV_STATS_CUMULATIVE_CPU_TIME,
528 LTTV_TIME, &cum_cpu_time);
529 *(cum_cpu_time.v_time) = ltt_time_add(*(cum_cpu_time.v_time),
d3670e3d 530 process->state->cum_cpu_time);
b445142a 531}
532
533
b49e54b4 534static void after_mode_end(LttvTracefileStats *tfcs)
535{
536 LttvTraceState *ts = (LttvTraceState *)tfcs->parent.parent.t_context;
537 guint cpu = tfcs->parent.cpu;
538 LttvProcessState *process = ts->running_process[cpu];
539 LttvAttributeValue cum_cpu_time;
540
541 LttTime nested_delta;
542
543 nested_delta = process->state->cum_cpu_time;
d3670e3d 544 process->state->cum_cpu_time = ltt_time_zero; /* For after traceset hook */
b49e54b4 545
546 update_event_tree(tfcs);
547
548 process->state->cum_cpu_time = ltt_time_add(process->state->cum_cpu_time,
d3670e3d 549 nested_delta);
b49e54b4 550}
551
b445142a 552static gboolean before_syscall_entry(void *hook_data, void *call_data)
553{
554 mode_change((LttvTracefileStats *)call_data);
555 return FALSE;
556}
557
558
559static gboolean after_syscall_entry(void *hook_data, void *call_data)
560{
561 update_event_tree((LttvTracefileStats *)call_data);
562 return FALSE;
563}
564
565
89f8741a 566static gboolean before_syscall_exit(void *hook_data, void *call_data)
b445142a 567{
568 mode_end((LttvTracefileStats *)call_data);
569 return FALSE;
570}
571
572
573static gboolean after_syscall_exit(void *hook_data, void *call_data)
574{
b49e54b4 575 after_mode_end((LttvTracefileStats *)call_data);
b445142a 576 return FALSE;
577}
578
579
89f8741a 580static gboolean before_trap_entry(void *hook_data, void *call_data)
b445142a 581{
582 mode_change((LttvTracefileStats *)call_data);
583 return FALSE;
584}
585
586
587static gboolean after_trap_entry(void *hook_data, void *call_data)
588{
589 update_event_tree((LttvTracefileStats *)call_data);
590 return FALSE;
591}
592
593
89f8741a 594static gboolean before_trap_exit(void *hook_data, void *call_data)
b445142a 595{
596 mode_end((LttvTracefileStats *)call_data);
597 return FALSE;
598}
599
600
89f8741a 601static gboolean after_trap_exit(void *hook_data, void *call_data)
b445142a 602{
b49e54b4 603 after_mode_end((LttvTracefileStats *)call_data);
b445142a 604 return FALSE;
605}
606
607
89f8741a 608static gboolean before_irq_entry(void *hook_data, void *call_data)
b445142a 609{
610 mode_change((LttvTracefileStats *)call_data);
611 return FALSE;
612}
613
89f8741a 614static gboolean after_irq_entry(void *hook_data, void *call_data)
b445142a 615{
616 update_event_tree((LttvTracefileStats *)call_data);
617 return FALSE;
618}
619
620
89f8741a 621static gboolean before_irq_exit(void *hook_data, void *call_data)
b445142a 622{
623 mode_end((LttvTracefileStats *)call_data);
624 return FALSE;
625}
626
627
89f8741a 628static gboolean after_irq_exit(void *hook_data, void *call_data)
b445142a 629{
b49e54b4 630 after_mode_end((LttvTracefileStats *)call_data);
b445142a 631 return FALSE;
632}
633
634
89f8741a 635static gboolean before_soft_irq_entry(void *hook_data, void *call_data)
faf074a3 636{
637 mode_change((LttvTracefileStats *)call_data);
638 return FALSE;
639}
640
89f8741a 641static gboolean after_soft_irq_entry(void *hook_data, void *call_data)
faf074a3 642{
643 update_event_tree((LttvTracefileStats *)call_data);
644 return FALSE;
645}
646
89f8741a 647static gboolean before_soft_irq_exit(void *hook_data, void *call_data)
faf074a3 648{
649 mode_end((LttvTracefileStats *)call_data);
650 return FALSE;
651}
652
653
89f8741a 654static gboolean after_soft_irq_exit(void *hook_data, void *call_data)
faf074a3 655{
b49e54b4 656 after_mode_end((LttvTracefileStats *)call_data);
faf074a3 657 return FALSE;
658}
659
89f8741a 660static gboolean before_function_entry(void *hook_data, void *call_data)
14236daa 661{
b49e54b4 662 mode_change((LttvTracefileStats *)call_data);
14236daa 663 return FALSE;
664}
665
89f8741a 666static gboolean after_function_entry(void *hook_data, void *call_data)
14236daa 667{
668 update_event_tree((LttvTracefileStats *)call_data);
669 return FALSE;
670}
671
89f8741a 672static gboolean before_function_exit(void *hook_data, void *call_data)
14236daa 673{
674 mode_end((LttvTracefileStats *)call_data);
675 return FALSE;
676}
677
89f8741a 678static gboolean after_function_exit(void *hook_data, void *call_data)
14236daa 679{
b49e54b4 680 after_mode_end((LttvTracefileStats *)call_data);
14236daa 681 return FALSE;
682}
683
faf074a3 684
89f8741a 685static gboolean before_schedchange(void *hook_data, void *call_data)
b445142a 686{
b445142a 687 LttvTracefileStats *tfcs = (LttvTracefileStats *)call_data;
688
348c6ba8 689 LttvTraceState *ts = (LttvTraceState*)tfcs->parent.parent.t_context;
690
eed2ef37 691 LttEvent *e = ltt_tracefile_get_event(tfcs->parent.parent.tf);
692
d052ffc3 693 LttvTraceHookByFacility *thf = (LttvTraceHookByFacility *)hook_data;
eed2ef37 694
d7cf605c 695 guint pid_in, pid_out;
696
697 gint state_out;
b445142a 698
eed2ef37 699 pid_out = ltt_event_get_unsigned(e, thf->f1);
700 pid_in = ltt_event_get_unsigned(e, thf->f2);
d7cf605c 701 state_out = ltt_event_get_int(e, thf->f3);
b445142a 702
703 /* compute the time for the process to schedule out */
b445142a 704 mode_change(tfcs);
705
b49e54b4 706 return FALSE;
707}
b445142a 708
89f8741a 709static gboolean after_schedchange(void *hook_data, void *call_data)
b49e54b4 710{
711 LttvTracefileStats *tfcs = (LttvTracefileStats *)call_data;
712
713 LttvTraceState *ts = (LttvTraceState*)tfcs->parent.parent.t_context;
b445142a 714
b49e54b4 715 LttEvent *e = ltt_tracefile_get_event(tfcs->parent.parent.tf);
716
717 LttvTraceHookByFacility *thf = (LttvTraceHookByFacility *)hook_data;
718
719 guint pid_in, pid_out;
720
721 gint state_out;
722
723 LttvProcessState *process;
724
725 pid_out = ltt_event_get_unsigned(e, thf->f1);
726 pid_in = ltt_event_get_unsigned(e, thf->f2);
727 state_out = ltt_event_get_int(e, thf->f3);
728
729 /* get the information for the process scheduled in */
c0cb4d12 730 guint cpu = tfcs->parent.cpu;
b49e54b4 731 process = ts->running_process[cpu];
c0cb4d12 732
348c6ba8 733 find_event_tree(tfcs, process->pid_time,
c0cb4d12 734 cpu,
d3670e3d 735 process->current_function,
b445142a 736 process->state->t, process->state->n, &(tfcs->current_events_tree),
737 &(tfcs->current_event_types_tree));
738
739 /* compute the time waiting for the process to schedule in */
b445142a 740 mode_change(tfcs);
b445142a 741
d3670e3d 742 return FALSE;
b49e54b4 743}
b445142a 744
89f8741a 745static gboolean process_fork(void *hook_data, void *call_data)
b445142a 746{
b445142a 747 return FALSE;
748}
749
89f8741a 750static gboolean process_exit(void *hook_data, void *call_data)
b445142a 751{
89f8741a 752 update_event_tree((LttvTracefileStats *)call_data);
b445142a 753 return FALSE;
754}
755
89f8741a 756static gboolean before_enum_process_state(void *hook_data, void *call_data)
954417fa 757{
d3670e3d 758#if 0
759 /* Broken : adds up time in the current process doing the dump */
760 LttvTracefileStats *tfcs = (LttvTracefileStats *)call_data;
761 mode_end(tfcs);
762 after_mode_end(tfcs);
763 mode_change(tfcs);
764#endif //0
954417fa 765 return FALSE;
766}
767
89f8741a 768static gboolean after_enum_process_state(void *hook_data, void *call_data)
954417fa 769{
d3670e3d 770 LttvTracefileContext *tfc = (LttvTracefileContext *)call_data;
89f8741a 771 LttvTraceStats *tcs = (LttvTraceStats*)tfc->t_context;
772 update_trace_event_tree(tcs);
d3670e3d 773 return FALSE;
774}
775
776static gboolean after_statedump_end(void *hook_data, void *call_data)
777{
d3670e3d 778 LttvTracefileContext *tfc = (LttvTracefileContext *)call_data;
89f8741a 779 LttvTraceStats *tcs = (LttvTraceStats*)tfc->t_context;
780 update_trace_event_tree(tcs);
954417fa 781 return FALSE;
782}
783
89f8741a 784static gboolean process_free(void *hook_data, void *call_data)
eed2ef37 785{
786 return FALSE;
787}
b445142a 788
89f8741a 789static gboolean every_event(void *hook_data, void *call_data)
b445142a 790{
791 LttvTracefileStats *tfcs = (LttvTracefileStats *)call_data;
792
eed2ef37 793 LttEvent *e = ltt_tracefile_get_event(tfcs->parent.parent.tf);
794
b445142a 795 LttvAttributeValue v;
796
797 /* The current branch corresponds to the tracefile/process/interrupt state.
798 Statistics are added within it, to count the number of events of this
799 type occuring in this context. A quark has been pre-allocated for each
800 event type and is used as name. */
801
802 lttv_attribute_find(tfcs->current_event_types_tree,
eed2ef37 803 ltt_eventtype_name(ltt_event_eventtype(e)),
b445142a 804 LTTV_UINT, &v);
805 (*(v.v_uint))++;
806 return FALSE;
807}
808
d3670e3d 809static void lttv_stats_cleanup_process_state(LttvTraceState *ts,
810 LttvProcessState *process)
c4a72569 811{
d3670e3d 812 LttvTraceStats *tcs = (LttvTraceStats *)ts;
c4a72569 813 LttvTracesetContext *tsc = ts->parent.ts_context;
c4a72569 814 int i;
815 LttvTracefileStats **tfs = (LttvTracefileStats **)
816 &g_array_index(ts->parent.tracefiles, LttvTracefileContext*,
817 process->cpu);
818 int cleanup_empty = 0;
819 LttTime nested_delta = ltt_time_zero;
820 /* FIXME : ok, this is a hack. The time is infinite here :( */
821 LttTime save_time = (*tfs)->parent.parent.timestamp;
822 LttTime start, end;
823 ltt_trace_time_span_get(ts->parent.t, &start, &end);
824 (*tfs)->parent.parent.timestamp = end;
825
826 do {
827 if(ltt_time_compare(process->state->cum_cpu_time, ltt_time_zero) != 0) {
828 find_event_tree(*tfs, process->pid_time,
829 process->cpu,
830 process->current_function,
831 process->state->t, process->state->n, &((*tfs)->current_events_tree),
832 &((*tfs)->current_event_types_tree));
d3670e3d 833 mode_end(*tfs);
c4a72569 834 nested_delta = process->state->cum_cpu_time;
835 }
836 cleanup_empty = lttv_state_pop_state_cleanup(process,
837 (LttvTracefileState *)*tfs);
838 process->state->cum_cpu_time = ltt_time_add(process->state->cum_cpu_time,
839 nested_delta);
840
841 } while(cleanup_empty != 1);
842
843 (*tfs)->parent.parent.timestamp = save_time;
b49e54b4 844}
845
d3670e3d 846/* For each cpu, for each of their stacked states,
b49e54b4 847 * perform sum of needed values. */
848static void lttv_stats_cleanup_state(LttvTraceStats *tcs)
849{
850 LttvTraceState *ts = (LttvTraceState *)tcs;
d3670e3d 851 guint nb_cpus, i;
852
853 nb_cpus = ltt_trace_get_num_cpu(ts->parent.t);
c4a72569 854
d3670e3d 855 for(i=0; i<nb_cpus; i++) {
856 lttv_stats_cleanup_process_state(ts, ts->running_process[i]);
857 }
b49e54b4 858}
b445142a 859
f95bc830 860void
69374af5 861lttv_stats_sum_trace(LttvTraceStats *self, LttvAttribute *ts_stats)
b445142a 862{
d3e01c7a 863 LttvAttribute *sum_container = self->stats;
b445142a 864
b445142a 865 LttvAttributeType type;
866
867 LttvAttributeValue value;
868
869 LttvAttributeName name;
870
d3670e3d 871 gboolean is_named;
c0cb4d12 872
b445142a 873 unsigned sum;
874
d3670e3d 875 int trace_is_summed;
69374af5 876
f95bc830 877 int i, j, k, l, m, nb_process, nb_cpu, nb_mode_type, nb_submode,
3813c77b 878 nb_event_type, nf, nb_functions;
b445142a 879
880 LttvAttribute *main_tree, *processes_tree, *process_tree, *cpus_tree,
881 *cpu_tree, *mode_tree, *mode_types_tree, *submodes_tree,
882 *submode_tree, *event_types_tree, *mode_events_tree,
3813c77b 883 *cpu_functions_tree,
d3670e3d 884 *function_tree,
885 *function_mode_types_tree,
886 *trace_cpu_tree;
f95bc830 887
b49e54b4 888
d3e01c7a 889 main_tree = sum_container;
f95bc830 890
d3e01c7a 891 lttv_attribute_find(sum_container,
892 LTTV_STATS_SUMMED,
893 LTTV_UINT, &value);
d3670e3d 894 trace_is_summed = *(value.v_uint);
f95bc830 895 *(value.v_uint) = 1;
896
d3670e3d 897 /* First cleanup the state : sum all stalled information (never ending
898 * states). */
899 if(!trace_is_summed)
900 lttv_stats_cleanup_state(self);
901
f95bc830 902 processes_tree = lttv_attribute_find_subdir(main_tree,
d3e01c7a 903 LTTV_STATS_PROCESSES);
f95bc830 904 nb_process = lttv_attribute_get_number(processes_tree);
905
906 for(i = 0 ; i < nb_process ; i++) {
c0cb4d12 907 type = lttv_attribute_get(processes_tree, i, &name, &value, &is_named);
f95bc830 908 process_tree = LTTV_ATTRIBUTE(*(value.v_gobject));
909
910 cpus_tree = lttv_attribute_find_subdir(process_tree, LTTV_STATS_CPU);
f95bc830 911 nb_cpu = lttv_attribute_get_number(cpus_tree);
912
913 for(j = 0 ; j < nb_cpu ; j++) {
c0cb4d12 914 type = lttv_attribute_get(cpus_tree, j, &name, &value, &is_named);
f95bc830 915 cpu_tree = LTTV_ATTRIBUTE(*(value.v_gobject));
916
f95bc830 917 trace_cpu_tree = lttv_attribute_find_subdir(main_tree, LTTV_STATS_CPU);
c0cb4d12 918 trace_cpu_tree = lttv_attribute_find_subdir_unnamed(trace_cpu_tree, name);
d3670e3d 919 cpu_functions_tree = lttv_attribute_find_subdir(cpu_tree,
920 LTTV_STATS_FUNCTIONS);
921 nb_functions = lttv_attribute_get_number(cpu_functions_tree);
922
923 for(nf=0; nf < nb_functions; nf++) {
924 type = lttv_attribute_get(cpu_functions_tree, nf, &name, &value,
925 &is_named);
926 function_tree = LTTV_ATTRIBUTE(*(value.v_gobject));
927 function_mode_types_tree = lttv_attribute_find_subdir(function_tree,
928 LTTV_STATS_MODE_TYPES);
929 nb_mode_type = lttv_attribute_get_number(function_mode_types_tree);
930 for(k = 0 ; k < nb_mode_type ; k++) {
931 type = lttv_attribute_get(function_mode_types_tree, k, &name, &value,
932 &is_named);
933 mode_tree = LTTV_ATTRIBUTE(*(value.v_gobject));
934
935 submodes_tree = lttv_attribute_find_subdir(mode_tree,
936 LTTV_STATS_SUBMODES);
937 mode_events_tree = lttv_attribute_find_subdir(mode_tree,
938 LTTV_STATS_EVENTS);
939 mode_types_tree = lttv_attribute_find_subdir(mode_tree,
940 LTTV_STATS_MODE_TYPES);
941
942 nb_submode = lttv_attribute_get_number(submodes_tree);
943
944 for(l = 0 ; l < nb_submode ; l++) {
945 type = lttv_attribute_get(submodes_tree, l, &name, &value,
946 &is_named);
947 submode_tree = LTTV_ATTRIBUTE(*(value.v_gobject));
948
949 event_types_tree = lttv_attribute_find_subdir(submode_tree,
950 LTTV_STATS_EVENT_TYPES);
951 nb_event_type = lttv_attribute_get_number(event_types_tree);
952
953 sum = 0;
954 for(m = 0 ; m < nb_event_type ; m++) {
955 type = lttv_attribute_get(event_types_tree, m, &name, &value,
956 &is_named);
957 sum += *(value.v_uint);
958 }
959 lttv_attribute_find(submode_tree, LTTV_STATS_EVENTS_COUNT,
960 LTTV_UINT, &value);
961 *(value.v_uint) = sum;
962
963 type = lttv_attribute_get(submodes_tree, l, &name, &value,
964 &is_named);
965 submode_tree = LTTV_ATTRIBUTE(*(value.v_gobject));
966 if(!trace_is_summed) {
967 lttv_attribute_recursive_add(mode_events_tree, event_types_tree);
968 lttv_attribute_recursive_add(mode_types_tree, submode_tree);
969 }
970 }
971 if(!trace_is_summed) {
972 lttv_attribute_recursive_add(function_tree, mode_types_tree);
973 }
974 }
975 if(!trace_is_summed) {
976 lttv_attribute_recursive_add(cpu_tree, function_tree);
977 lttv_attribute_recursive_add(process_tree, function_tree);
978 lttv_attribute_recursive_add(trace_cpu_tree, function_tree);
979 lttv_attribute_recursive_add(main_tree, function_tree);
980 }
981 lttv_attribute_recursive_add(ts_stats, function_tree);
982 }
b445142a 983 }
f95bc830 984 }
985}
986
987
d3e01c7a 988gboolean lttv_stats_sum_traceset_hook(void *hook_data, void *call_data)
989{
990 lttv_stats_sum_traceset((LttvTracesetStats *)call_data);
991 return 0;
992}
993
f95bc830 994void
995lttv_stats_sum_traceset(LttvTracesetStats *self)
996{
997 LttvTraceset *traceset = self->parent.parent.ts;
d3e01c7a 998 LttvAttribute *sum_container = self->stats;
f95bc830 999
1000 LttvTraceStats *tcs;
1001
1002 int i, nb_trace;
1003
3813c77b 1004 LttvAttribute *main_tree;
f95bc830 1005
1006 LttvAttributeValue value;
1007
d3e01c7a 1008 lttv_attribute_find(sum_container, LTTV_STATS_SUMMED,
f95bc830 1009 LTTV_UINT, &value);
1010 if(*(value.v_uint) != 0) return;
1011 *(value.v_uint) = 1;
1012
f95bc830 1013 nb_trace = lttv_traceset_number(traceset);
1014
1015 for(i = 0 ; i < nb_trace ; i++) {
1016 tcs = (LttvTraceStats *)(self->parent.parent.traces[i]);
69374af5 1017 lttv_stats_sum_trace(tcs, self->stats);
d3670e3d 1018 // lttv_attribute_recursive_add(sum_container, tcs->stats);
b445142a 1019 }
b445142a 1020}
1021
1022
d3e01c7a 1023// Hook wrapper. call_data is a traceset context.
00e74b69 1024gboolean lttv_stats_hook_add_event_hooks(void *hook_data, void *call_data)
d3e01c7a 1025{
1026 LttvTracesetStats *tss = (LttvTracesetStats*)call_data;
1027
1028 lttv_stats_add_event_hooks(tss);
1029
1030 return 0;
1031}
1032
00e74b69 1033void lttv_stats_add_event_hooks(LttvTracesetStats *self)
b445142a 1034{
1035 LttvTraceset *traceset = self->parent.parent.ts;
1036
eed2ef37 1037 guint i, j, k, l, nb_trace, nb_tracefile;
b445142a 1038
b445142a 1039 LttvTraceStats *ts;
1040
1041 LttvTracefileStats *tfs;
1042
b445142a 1043 GArray *hooks, *before_hooks, *after_hooks;
1044
eed2ef37 1045 LttvTraceHook *hook;
1046
1047 LttvTraceHookByFacility *thf;
b445142a 1048
1049 LttvAttributeValue val;
1050
9d239bd9 1051 gint ret;
d3670e3d 1052 gint hn;
9d239bd9 1053
b445142a 1054 nb_trace = lttv_traceset_number(traceset);
1055 for(i = 0 ; i < nb_trace ; i++) {
1056 ts = (LttvTraceStats *)self->parent.parent.traces[i];
1057
1058 /* Find the eventtype id for the following events and register the
1059 associated by id hooks. */
1060
954417fa 1061 hooks = g_array_sized_new(FALSE, FALSE, sizeof(LttvTraceHook), 12);
1062 g_array_set_size(hooks, 12);
1063 hn=0;
b445142a 1064
9d239bd9 1065 ret = lttv_trace_find_hook(ts->parent.parent.t,
f5d7967f 1066 LTT_FACILITY_KERNEL_ARCH, LTT_EVENT_SYSCALL_ENTRY,
eed2ef37 1067 LTT_FIELD_SYSCALL_ID, 0, 0,
2c82c4dc 1068 before_syscall_entry, NULL,
2501204d 1069 &g_array_index(hooks, LttvTraceHook, hn++));
1070 if(ret) hn--;
b445142a 1071
9d239bd9 1072 ret = lttv_trace_find_hook(ts->parent.parent.t,
f5d7967f 1073 LTT_FACILITY_KERNEL_ARCH, LTT_EVENT_SYSCALL_EXIT,
eed2ef37 1074 0, 0, 0,
2c82c4dc 1075 before_syscall_exit, NULL,
2501204d 1076 &g_array_index(hooks, LttvTraceHook, hn++));
1077 if(ret) hn--;
b445142a 1078
9d239bd9 1079 ret = lttv_trace_find_hook(ts->parent.parent.t,
eed2ef37 1080 LTT_FACILITY_KERNEL, LTT_EVENT_TRAP_ENTRY,
1081 LTT_FIELD_TRAP_ID, 0, 0,
2c82c4dc 1082 before_trap_entry, NULL,
2501204d 1083 &g_array_index(hooks, LttvTraceHook, hn++));
1084 if(ret) hn--;
b445142a 1085
9d239bd9 1086 ret = lttv_trace_find_hook(ts->parent.parent.t,
eed2ef37 1087 LTT_FACILITY_KERNEL, LTT_EVENT_TRAP_EXIT,
1088 0, 0, 0,
2c82c4dc 1089 before_trap_exit, NULL,
2501204d 1090 &g_array_index(hooks, LttvTraceHook, hn++));
1091 if(ret) hn--;
eed2ef37 1092
9d239bd9 1093 ret = lttv_trace_find_hook(ts->parent.parent.t,
eed2ef37 1094 LTT_FACILITY_KERNEL, LTT_EVENT_IRQ_ENTRY,
1095 LTT_FIELD_IRQ_ID, 0, 0,
2c82c4dc 1096 before_irq_entry, NULL,
2501204d 1097 &g_array_index(hooks, LttvTraceHook, hn++));
1098 if(ret) hn--;
eed2ef37 1099
9d239bd9 1100 ret = lttv_trace_find_hook(ts->parent.parent.t,
eed2ef37 1101 LTT_FACILITY_KERNEL, LTT_EVENT_IRQ_EXIT,
1102 0, 0, 0,
2c82c4dc 1103 before_irq_exit, NULL,
2501204d 1104 &g_array_index(hooks, LttvTraceHook, hn++));
1105 if(ret) hn--;
eed2ef37 1106
faf074a3 1107 ret = lttv_trace_find_hook(ts->parent.parent.t,
1108 LTT_FACILITY_KERNEL, LTT_EVENT_SOFT_IRQ_ENTRY,
1109 LTT_FIELD_SOFT_IRQ_ID, 0, 0,
1110 before_soft_irq_entry, NULL,
2501204d 1111 &g_array_index(hooks, LttvTraceHook, hn++));
1112 if(ret) hn--;
faf074a3 1113
1114 ret = lttv_trace_find_hook(ts->parent.parent.t,
1115 LTT_FACILITY_KERNEL, LTT_EVENT_SOFT_IRQ_EXIT,
1116 0, 0, 0,
1117 before_soft_irq_exit, NULL,
2501204d 1118 &g_array_index(hooks, LttvTraceHook, hn++));
1119 if(ret) hn--;
faf074a3 1120
9d239bd9 1121 ret = lttv_trace_find_hook(ts->parent.parent.t,
eed2ef37 1122 LTT_FACILITY_PROCESS, LTT_EVENT_SCHEDCHANGE,
1123 LTT_FIELD_OUT, LTT_FIELD_IN, LTT_FIELD_OUT_STATE,
2c82c4dc 1124 before_schedchange, NULL,
2501204d 1125 &g_array_index(hooks, LttvTraceHook, hn++));
1126 if(ret) hn--;
14236daa 1127
1128 ret = lttv_trace_find_hook(ts->parent.parent.t,
1129 LTT_FACILITY_USER_GENERIC, LTT_EVENT_FUNCTION_ENTRY,
1130 LTT_FIELD_THIS_FN, LTT_FIELD_CALL_SITE, 0,
1131 before_function_entry, NULL,
1132 &g_array_index(hooks, LttvTraceHook, hn++));
1133 if(ret) hn--;
1134
1135 ret = lttv_trace_find_hook(ts->parent.parent.t,
1136 LTT_FACILITY_USER_GENERIC, LTT_EVENT_FUNCTION_EXIT,
1137 LTT_FIELD_THIS_FN, LTT_FIELD_CALL_SITE, 0,
1138 before_function_exit, NULL,
1139 &g_array_index(hooks, LttvTraceHook, hn++));
1140 if(ret) hn--;
954417fa 1141
1142 /* statedump-related hooks */
1143 ret = lttv_trace_find_hook(ts->parent.parent.t,
1144 LTT_FACILITY_STATEDUMP, LTT_EVENT_ENUM_PROCESS_STATE,
1145 LTT_FIELD_PID, LTT_FIELD_PARENT_PID, LTT_FIELD_NAME,
1146 before_enum_process_state, NULL,
1147 &g_array_index(hooks, LttvTraceHook, hn++));
1148 if(ret) hn--;
1149
2501204d 1150 g_array_set_size(hooks, hn);
b445142a 1151
1152 before_hooks = hooks;
1153
d3670e3d 1154 hooks = g_array_sized_new(FALSE, FALSE, sizeof(LttvTraceHook), 16);
1155 g_array_set_size(hooks, 16);
954417fa 1156 hn=0;
b445142a 1157
9d239bd9 1158 ret = lttv_trace_find_hook(ts->parent.parent.t,
f5d7967f 1159 LTT_FACILITY_KERNEL_ARCH, LTT_EVENT_SYSCALL_ENTRY,
eed2ef37 1160 LTT_FIELD_SYSCALL_ID, 0, 0,
2c82c4dc 1161 after_syscall_entry, NULL,
2501204d 1162 &g_array_index(hooks, LttvTraceHook, hn++));
1163 if(ret) hn--;
b445142a 1164
9d239bd9 1165 ret = lttv_trace_find_hook(ts->parent.parent.t,
f5d7967f 1166 LTT_FACILITY_KERNEL_ARCH, LTT_EVENT_SYSCALL_EXIT,
eed2ef37 1167 0, 0, 0,
2c82c4dc 1168 after_syscall_exit, NULL,
2501204d 1169 &g_array_index(hooks, LttvTraceHook, hn++));
1170 if(ret) hn--;
b445142a 1171
9d239bd9 1172 ret = lttv_trace_find_hook(ts->parent.parent.t,
eed2ef37 1173 LTT_FACILITY_KERNEL, LTT_EVENT_TRAP_ENTRY,
1174 LTT_FIELD_TRAP_ID, 0, 0,
2c82c4dc 1175 after_trap_entry, NULL,
2501204d 1176 &g_array_index(hooks, LttvTraceHook, hn++));
1177 if(ret) hn--;
eed2ef37 1178
9d239bd9 1179 ret = lttv_trace_find_hook(ts->parent.parent.t,
eed2ef37 1180 LTT_FACILITY_KERNEL, LTT_EVENT_TRAP_EXIT,
1181 0, 0, 0,
2c82c4dc 1182 after_trap_exit, NULL,
2501204d 1183 &g_array_index(hooks, LttvTraceHook, hn++));
1184 if(ret) hn--;
b445142a 1185
9d239bd9 1186 ret = lttv_trace_find_hook(ts->parent.parent.t,
eed2ef37 1187 LTT_FACILITY_KERNEL, LTT_EVENT_IRQ_ENTRY,
1188 LTT_FIELD_IRQ_ID, 0, 0,
2c82c4dc 1189 after_irq_entry, NULL,
2501204d 1190 &g_array_index(hooks, LttvTraceHook, hn++));
1191 if(ret) hn--;
b445142a 1192
9d239bd9 1193 ret = lttv_trace_find_hook(ts->parent.parent.t,
eed2ef37 1194 LTT_FACILITY_KERNEL, LTT_EVENT_IRQ_EXIT,
1195 0, 0, 0,
2c82c4dc 1196 after_irq_exit, NULL,
2501204d 1197 &g_array_index(hooks, LttvTraceHook, hn++));
1198 if(ret) hn--;
b445142a 1199
faf074a3 1200 ret = lttv_trace_find_hook(ts->parent.parent.t,
1201 LTT_FACILITY_KERNEL, LTT_EVENT_SOFT_IRQ_ENTRY,
1202 LTT_FIELD_SOFT_IRQ_ID, 0, 0,
1203 after_irq_entry, NULL,
2501204d 1204 &g_array_index(hooks, LttvTraceHook, hn++));
1205 if(ret) hn--;
faf074a3 1206
1207 ret = lttv_trace_find_hook(ts->parent.parent.t,
1208 LTT_FACILITY_KERNEL, LTT_EVENT_SOFT_IRQ_EXIT,
1209 0, 0, 0,
1210 after_soft_irq_exit, NULL,
2501204d 1211 &g_array_index(hooks, LttvTraceHook, hn++));
1212 if(ret) hn--;
b445142a 1213
b49e54b4 1214 ret = lttv_trace_find_hook(ts->parent.parent.t,
1215 LTT_FACILITY_PROCESS, LTT_EVENT_SCHEDCHANGE,
1216 LTT_FIELD_OUT, LTT_FIELD_IN, LTT_FIELD_OUT_STATE,
1217 after_schedchange, NULL,
1218 &g_array_index(hooks, LttvTraceHook, hn++));
1219 if(ret) hn--;
1220
9d239bd9 1221 ret = lttv_trace_find_hook(ts->parent.parent.t,
eed2ef37 1222 LTT_FACILITY_PROCESS, LTT_EVENT_FORK,
1223 LTT_FIELD_PARENT_PID, LTT_FIELD_CHILD_PID, 0,
2c82c4dc 1224 process_fork, NULL,
2501204d 1225 &g_array_index(hooks, LttvTraceHook, hn++));
1226 if(ret) hn--;
b445142a 1227
9d239bd9 1228 ret = lttv_trace_find_hook(ts->parent.parent.t,
eed2ef37 1229 LTT_FACILITY_PROCESS, LTT_EVENT_EXIT,
1230 LTT_FIELD_PID, 0, 0,
2c82c4dc 1231 process_exit, NULL,
2501204d 1232 &g_array_index(hooks, LttvTraceHook, hn++));
1233 if(ret) hn--;
eed2ef37 1234
9d239bd9 1235 ret = lttv_trace_find_hook(ts->parent.parent.t,
eed2ef37 1236 LTT_FACILITY_PROCESS, LTT_EVENT_FREE,
1237 LTT_FIELD_PID, 0, 0,
2c82c4dc 1238 process_free, NULL,
2501204d 1239 &g_array_index(hooks, LttvTraceHook, hn++));
1240 if(ret) hn--;
eed2ef37 1241
14236daa 1242 ret = lttv_trace_find_hook(ts->parent.parent.t,
1243 LTT_FACILITY_USER_GENERIC, LTT_EVENT_FUNCTION_ENTRY,
1244 LTT_FIELD_THIS_FN, LTT_FIELD_CALL_SITE, 0,
1245 after_function_entry, NULL,
1246 &g_array_index(hooks, LttvTraceHook, hn++));
1247 if(ret) hn--;
1248
1249 ret = lttv_trace_find_hook(ts->parent.parent.t,
1250 LTT_FACILITY_USER_GENERIC, LTT_EVENT_FUNCTION_EXIT,
1251 LTT_FIELD_THIS_FN, LTT_FIELD_CALL_SITE, 0,
1252 after_function_exit, NULL,
1253 &g_array_index(hooks, LttvTraceHook, hn++));
1254 if(ret) hn--;
954417fa 1255
1256 /* statedump-related hooks */
1257 ret = lttv_trace_find_hook(ts->parent.parent.t,
1258 LTT_FACILITY_STATEDUMP, LTT_EVENT_ENUM_PROCESS_STATE,
1259 LTT_FIELD_PID, LTT_FIELD_PARENT_PID, LTT_FIELD_NAME,
1260 after_enum_process_state, NULL,
1261 &g_array_index(hooks, LttvTraceHook, hn++));
1262 if(ret) hn--;
1263
d3670e3d 1264 ret = lttv_trace_find_hook(ts->parent.parent.t,
1265 LTT_FACILITY_STATEDUMP, LTT_EVENT_STATEDUMP_END,
1266 0, 0, 0,
1267 after_statedump_end, NULL,
1268 &g_array_index(hooks, LttvTraceHook, hn++));
1269 if(ret) hn--;
1270
2501204d 1271 g_array_set_size(hooks, hn);
b445142a 1272
1273 after_hooks = hooks;
1274
359b2948 1275 /* Add these hooks to each event_by_id hooks list */
b445142a 1276
eed2ef37 1277 nb_tracefile = ts->parent.parent.tracefiles->len;
b445142a 1278
dbb7bb09 1279 for(j = 0 ; j < nb_tracefile ; j++) {
d7cf605c 1280 tfs = LTTV_TRACEFILE_STATS(g_array_index(ts->parent.parent.tracefiles,
1281 LttvTracefileContext*, j));
359b2948 1282 lttv_hooks_add(tfs->parent.parent.event, every_event, NULL,
1283 LTTV_PRIO_DEFAULT);
b445142a 1284
1285 for(k = 0 ; k < before_hooks->len ; k++) {
eed2ef37 1286 hook = &g_array_index(before_hooks, LttvTraceHook, k);
1287 for(l = 0; l<hook->fac_list->len;l++) {
1288 thf = g_array_index(hook->fac_list, LttvTraceHookByFacility*, l);
1289 lttv_hooks_add(
1290 lttv_hooks_by_id_find(tfs->parent.parent.event_by_id, thf->id),
1291 thf->h,
d052ffc3 1292 thf,
eed2ef37 1293 LTTV_PRIO_STATS_BEFORE_STATE);
1294 }
b445142a 1295 }
1296 for(k = 0 ; k < after_hooks->len ; k++) {
eed2ef37 1297 hook = &g_array_index(after_hooks, LttvTraceHook, k);
1298 for(l = 0; l<hook->fac_list->len;l++) {
1299 thf = g_array_index(hook->fac_list, LttvTraceHookByFacility*, l);
1300 lttv_hooks_add(
1301 lttv_hooks_by_id_find(tfs->parent.parent.event_by_id, thf->id),
1302 thf->h,
d052ffc3 1303 thf,
eed2ef37 1304 LTTV_PRIO_STATS_AFTER_STATE);
1305 }
b445142a 1306 }
1307 }
1308 lttv_attribute_find(self->parent.parent.a, LTTV_STATS_BEFORE_HOOKS,
1309 LTTV_POINTER, &val);
1310 *(val.v_pointer) = before_hooks;
1311 lttv_attribute_find(self->parent.parent.a, LTTV_STATS_AFTER_HOOKS,
1312 LTTV_POINTER, &val);
1313 *(val.v_pointer) = after_hooks;
1314 }
b445142a 1315}
1316
d3e01c7a 1317// Hook wrapper. call_data is a traceset context.
00e74b69 1318gboolean lttv_stats_hook_remove_event_hooks(void *hook_data, void *call_data)
d3e01c7a 1319{
1320 LttvTracesetStats *tss = (LttvTracesetStats*)call_data;
1321
1322 lttv_stats_remove_event_hooks(tss);
1323
1324 return 0;
1325}
b445142a 1326
00e74b69 1327void lttv_stats_remove_event_hooks(LttvTracesetStats *self)
b445142a 1328{
1329 LttvTraceset *traceset = self->parent.parent.ts;
1330
eed2ef37 1331 guint i, j, k, l, nb_trace, nb_tracefile;
b445142a 1332
1333 LttvTraceStats *ts;
1334
1335 LttvTracefileStats *tfs;
1336
1337 void *hook_data;
1338
1339 GArray *before_hooks, *after_hooks;
1340
eed2ef37 1341 LttvTraceHook *hook;
1342
1343 LttvTraceHookByFacility *thf;
b445142a 1344
1345 LttvAttributeValue val;
1346
1347 nb_trace = lttv_traceset_number(traceset);
1348 for(i = 0 ; i < nb_trace ; i++) {
ae80b609 1349 ts = (LttvTraceStats*)self->parent.parent.traces[i];
b445142a 1350 lttv_attribute_find(self->parent.parent.a, LTTV_STATS_BEFORE_HOOKS,
1351 LTTV_POINTER, &val);
1352 before_hooks = *(val.v_pointer);
1353 lttv_attribute_find(self->parent.parent.a, LTTV_STATS_AFTER_HOOKS,
1354 LTTV_POINTER, &val);
1355 after_hooks = *(val.v_pointer);
1356
359b2948 1357 /* Remove these hooks from each event_by_id hooks list */
b445142a 1358
eed2ef37 1359 nb_tracefile = ts->parent.parent.tracefiles->len;
b445142a 1360
dbb7bb09 1361 for(j = 0 ; j < nb_tracefile ; j++) {
cb03932a 1362 tfs = LTTV_TRACEFILE_STATS(g_array_index(ts->parent.parent.tracefiles,
1363 LttvTracefileContext*, j));
359b2948 1364 lttv_hooks_remove_data(tfs->parent.parent.event, every_event,
b445142a 1365 NULL);
1366
1367 for(k = 0 ; k < before_hooks->len ; k++) {
eed2ef37 1368 hook = &g_array_index(before_hooks, LttvTraceHook, k);
1369 for(l = 0 ; l < hook->fac_list->len ; l++) {
1370 thf = g_array_index(hook->fac_list, LttvTraceHookByFacility*, l);
1371 lttv_hooks_remove_data(
1372 lttv_hooks_by_id_find(tfs->parent.parent.event_by_id, thf->id),
1373 thf->h,
d052ffc3 1374 thf);
eed2ef37 1375 }
b445142a 1376 }
1377 for(k = 0 ; k < after_hooks->len ; k++) {
eed2ef37 1378 hook = &g_array_index(after_hooks, LttvTraceHook, k);
1379 for(l = 0 ; l < hook->fac_list->len ; l++) {
1380 thf = g_array_index(hook->fac_list, LttvTraceHookByFacility*, l);
1381 lttv_hooks_remove_data(
1382 lttv_hooks_by_id_find(tfs->parent.parent.event_by_id, thf->id),
1383 thf->h,
d052ffc3 1384 thf);
eed2ef37 1385 }
b445142a 1386 }
1387 }
2a2fa4f0 1388 g_debug("lttv_stats_remove_event_hooks()");
b445142a 1389 g_array_free(before_hooks, TRUE);
1390 g_array_free(after_hooks, TRUE);
1391 }
9f797243 1392}
08b1c66e 1393
1394
1395static void module_init()
1396{
1397 LTTV_STATS_PROCESS_UNKNOWN = g_quark_from_string("unknown process");
1398 LTTV_STATS_PROCESSES = g_quark_from_string("processes");
1399 LTTV_STATS_CPU = g_quark_from_string("cpu");
1400 LTTV_STATS_MODE_TYPES = g_quark_from_string("mode_types");
1401 LTTV_STATS_MODES = g_quark_from_string("modes");
1402 LTTV_STATS_SUBMODES = g_quark_from_string("submodes");
14236daa 1403 LTTV_STATS_FUNCTIONS = g_quark_from_string("functions");
08b1c66e 1404 LTTV_STATS_EVENT_TYPES = g_quark_from_string("event_types");
1405 LTTV_STATS_CPU_TIME = g_quark_from_string("cpu time");
b49e54b4 1406 LTTV_STATS_CUMULATIVE_CPU_TIME = g_quark_from_string("cumulative cpu time (includes nested routines and modes)");
1407 LTTV_STATS_ELAPSED_TIME = g_quark_from_string("elapsed time (includes per process waiting time)");
08b1c66e 1408 LTTV_STATS_EVENTS = g_quark_from_string("events");
1409 LTTV_STATS_EVENTS_COUNT = g_quark_from_string("events count");
1410 LTTV_STATS_BEFORE_HOOKS = g_quark_from_string("saved stats before hooks");
1411 LTTV_STATS_AFTER_HOOKS = g_quark_from_string("saved stats after hooks");
f95bc830 1412 LTTV_STATS_USE_COUNT = g_quark_from_string("stats_use_count");
1413 LTTV_STATS = g_quark_from_string("statistics");
1414 LTTV_STATS_TRACEFILES = g_quark_from_string("tracefiles statistics");
1415 LTTV_STATS_SUMMED = g_quark_from_string("statistics summed");
08b1c66e 1416}
1417
1418static void module_destroy()
1419{
1420}
1421
1422
1423LTTV_MODULE("stats", "Compute processes statistics", \
1424 "Accumulate statistics for event types, processes and CPUs", \
1425 module_init, module_destroy, "state");
f95bc830 1426
1427/* Change the places where stats are called (create/read/write stats)
1428
1429 Check for options in batchtest.c to reduce writing and see what tests are
1430 best candidates for performance analysis. Once OK, commit, move to main
1431 and run tests. Update the gui for statistics. */
This page took 0.111669 seconds and 4 git commands to generate.