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