Fix statistics: take into account many tracefiles per cpu
[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,
90e19f82
AM
51 LTTV_STATS_SUMMED,
52 LTTV_STATS_BEFORE_HOOKS,
53 LTTV_STATS_AFTER_HOOKS;
54
516a8712 55static void find_event_tree(LttvCPUStats *cpu_stats, GQuark pid_time,
90e19f82
AM
56 guint cpu, guint64 function,
57 GQuark mode, GQuark sub_mode, LttvAttribute **events_tree,
58 LttvAttribute **event_types_tree);
b445142a 59
d730b5c8 60
61static void lttv_stats_init(LttvTracesetStats *self)
b445142a 62{
516a8712 63 guint i, j, nb_trace, nb_cpu, nb_tracefile;
b445142a 64
90e19f82 65 LttvTraceContext *tc;
b445142a 66
90e19f82 67 LttvTraceStats *tcs;
b445142a 68
90e19f82
AM
69 LttvTracefileContext **tfs;
70 LttvTracefileStats *tfcs;
516a8712 71 LttvCPUStats *cpu_stats;
f95bc830 72
90e19f82 73 LttvAttributeValue v;
f95bc830 74
90e19f82 75 LttvTraceset *ts = self->parent.parent.ts;
f95bc830 76
90e19f82
AM
77 self->stats = lttv_attribute_find_subdir(
78 lttv_traceset_attribute(self->parent.parent.ts), LTTV_STATS);
79 lttv_attribute_find(lttv_traceset_attribute(self->parent.parent.ts),
80 LTTV_STATS_USE_COUNT,
81 LTTV_UINT, &v);
f95bc830 82
90e19f82
AM
83 (*(v.v_uint))++;
84 if(*(v.v_uint) == 1) {
85 g_assert(lttv_attribute_get_number(self->stats) == 0);
86 }
b445142a 87
90e19f82 88 nb_trace = lttv_traceset_number(ts);
f95bc830 89
90e19f82
AM
90 for(i = 0 ; i < nb_trace ; i++) {
91 tc = self->parent.parent.traces[i];
92 tcs = LTTV_TRACE_STATS(tc);
f95bc830 93
90e19f82
AM
94 tcs->stats = lttv_attribute_find_subdir(tcs->parent.parent.t_a,
95 LTTV_STATS);
90e19f82
AM
96 lttv_attribute_find(tcs->parent.parent.t_a, LTTV_STATS_USE_COUNT,
97 LTTV_UINT, &v);
b445142a 98
90e19f82
AM
99 (*(v.v_uint))++;
100 if(*(v.v_uint) == 1) {
101 g_assert(lttv_attribute_get_number(tcs->stats) == 0);
102 }
b445142a 103
516a8712
MD
104 nb_cpu = ltt_trace_get_num_cpu(tc->t);
105 tcs->cpu_stats = g_new(LttvCPUStats, nb_cpu);
106 for(j = 0 ; j < nb_cpu; j++) {
107 cpu_stats = &tcs->cpu_stats[j];
108 cpu_stats->cpu = j;
109 cpu_stats->tcs = tcs;
110 find_event_tree(cpu_stats, LTTV_STATS_PROCESS_UNKNOWN,
111 cpu_stats->cpu,
112 0x0ULL,
113 LTTV_STATE_MODE_UNKNOWN,
114 LTTV_STATE_SUBMODE_UNKNOWN, &cpu_stats->current_events_tree,
115 &cpu_stats->current_event_types_tree);
116 }
90e19f82 117 nb_tracefile = tc->tracefiles->len;
516a8712 118 for (j = 0; j < nb_tracefile; j++) {
90e19f82
AM
119 tfs = &g_array_index(tc->tracefiles, LttvTracefileContext*, j);
120 tfcs = LTTV_TRACEFILE_STATS(*tfs);
516a8712 121 tfcs->cpu_stats = &tcs->cpu_stats[tfcs->parent.cpu];
90e19f82
AM
122 }
123 }
d730b5c8 124
b445142a 125}
126
d730b5c8 127static void lttv_stats_fini(LttvTracesetStats *self)
b445142a 128{
516a8712 129 guint i, j, nb_trace, nb_cpu, nb_tracefile;
90e19f82
AM
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
516a8712 141 LttvCPUStats *cpu_stats;
f95bc830 142
516a8712 143 LttvAttributeValue v;
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
516a8712
MD
164 if(*(v.v_uint) == 0)
165 lttv_attribute_remove_by_name(tcs->parent.parent.t_a, LTTV_STATS);
90e19f82 166 tcs->stats = NULL;
b445142a 167
90e19f82 168 nb_tracefile = tc->tracefiles->len;
516a8712 169 for (j = 0; j < nb_tracefile; j++) {
90e19f82 170 tfc = g_array_index(tc->tracefiles, LttvTracefileContext*, j);
516a8712
MD
171 tfcs = LTTV_TRACEFILE_STATS(tfc);
172 tfcs->cpu_stats = NULL;
173 }
174
175 nb_cpu = ltt_trace_get_num_cpu(tc->t);
176
177 for(j = 0 ; j < nb_cpu; j++) {
178 cpu_stats = &tcs->cpu_stats[j];
179 cpu_stats->current_events_tree = NULL;
180 cpu_stats->current_event_types_tree = NULL;
90e19f82 181 }
516a8712 182 g_free(tcs->cpu_stats);
90e19f82 183 }
d730b5c8 184}
185
186
187void lttv_stats_reset(LttvTracesetStats *self)
188{
90e19f82
AM
189 lttv_stats_fini(self);
190 lttv_stats_init(self);
d730b5c8 191}
192
193
194
90e19f82 195static void init(LttvTracesetStats *self, LttvTraceset *ts)
d730b5c8 196{
90e19f82
AM
197 LTTV_TRACESET_CONTEXT_CLASS(g_type_class_peek(LTTV_TRACESET_STATE_TYPE))->
198 init((LttvTracesetContext *)self, ts);
199
200 lttv_stats_init(self);
d730b5c8 201}
202
203
90e19f82 204static void fini(LttvTracesetStats *self)
d730b5c8 205{
90e19f82 206 lttv_stats_fini(self);
d730b5c8 207
90e19f82
AM
208 LTTV_TRACESET_CONTEXT_CLASS(g_type_class_peek(LTTV_TRACESET_STATE_TYPE))->
209 fini((LttvTracesetContext *)self);
b445142a 210}
211
212
90e19f82 213static LttvTracesetContext *new_traceset_context(LttvTracesetContext *self)
b445142a 214{
90e19f82 215 return LTTV_TRACESET_CONTEXT(g_object_new(LTTV_TRACESET_STATS_TYPE, NULL));
b445142a 216}
217
218
90e19f82 219static LttvTraceContext *new_trace_context(LttvTracesetContext *self)
b445142a 220{
90e19f82 221 return LTTV_TRACE_CONTEXT(g_object_new(LTTV_TRACE_STATS_TYPE, NULL));
b445142a 222}
223
224
90e19f82 225static LttvTracefileContext *new_tracefile_context(LttvTracesetContext *self)
b445142a 226{
90e19f82 227 return LTTV_TRACEFILE_CONTEXT(g_object_new(LTTV_TRACEFILE_STATS_TYPE, NULL));
b445142a 228}
229
230
90e19f82
AM
231static void traceset_stats_instance_init (GTypeInstance *instance,
232 gpointer g_class)
b445142a 233{
234}
235
236
90e19f82 237static void traceset_stats_finalize (LttvTracesetStats *self)
b445142a 238{
90e19f82
AM
239 G_OBJECT_CLASS(g_type_class_peek(LTTV_TRACESET_STATE_TYPE))->
240 finalize(G_OBJECT(self));
b445142a 241}
242
243
90e19f82 244static void traceset_stats_class_init (LttvTracesetContextClass *klass)
b445142a 245{
90e19f82 246 GObjectClass *gobject_class = G_OBJECT_CLASS(klass);
b445142a 247
90e19f82
AM
248 gobject_class->finalize = (void (*)(GObject *self)) traceset_stats_finalize;
249 klass->init = (void (*)(LttvTracesetContext *self, LttvTraceset *ts))init;
250 klass->fini = (void (*)(LttvTracesetContext *self))fini;
251 klass->new_traceset_context = new_traceset_context;
252 klass->new_trace_context = new_trace_context;
253 klass->new_tracefile_context = new_tracefile_context;
b445142a 254}
255
256
90e19f82 257GType lttv_traceset_stats_get_type(void)
b445142a 258{
90e19f82
AM
259 static GType type = 0;
260 if (type == 0) {
261 static const GTypeInfo info = {
262 sizeof (LttvTracesetStatsClass),
263 NULL, /* base_init */
264 NULL, /* base_finalize */
265 (GClassInitFunc) traceset_stats_class_init, /* class_init */
266 NULL, /* class_finalize */
267 NULL, /* class_data */
268 sizeof (LttvTracesetStats),
269 0, /* n_preallocs */
270 (GInstanceInitFunc) traceset_stats_instance_init, /* instance_init */
271 NULL /* Value handling */
272 };
b445142a 273
90e19f82
AM
274 type = g_type_register_static (LTTV_TRACESET_STATE_TYPE,
275 "LttvTracesetStatsType", &info, 0);
276 }
277 return type;
b445142a 278}
279
280
90e19f82
AM
281static void trace_stats_instance_init (GTypeInstance *instance,
282 gpointer g_class)
b445142a 283{
284}
285
286
90e19f82 287static void trace_stats_finalize (LttvTraceStats *self)
b445142a 288{
90e19f82
AM
289 G_OBJECT_CLASS(g_type_class_peek(LTTV_TRACE_STATE_TYPE))->
290 finalize(G_OBJECT(self));
b445142a 291}
292
293
90e19f82 294static void trace_stats_class_init (LttvTraceContextClass *klass)
b445142a 295{
90e19f82 296 GObjectClass *gobject_class = G_OBJECT_CLASS(klass);
b445142a 297
90e19f82 298 gobject_class->finalize = (void (*)(GObject *self)) trace_stats_finalize;
b445142a 299}
300
301
90e19f82 302GType lttv_trace_stats_get_type(void)
b445142a 303{
90e19f82
AM
304 static GType type = 0;
305 if (type == 0) {
306 static const GTypeInfo info = {
307 sizeof (LttvTraceStatsClass),
308 NULL, /* base_init */
309 NULL, /* base_finalize */
310 (GClassInitFunc) trace_stats_class_init, /* class_init */
311 NULL, /* class_finalize */
312 NULL, /* class_data */
313 sizeof (LttvTraceStats),
314 0, /* n_preallocs */
315 (GInstanceInitFunc) trace_stats_instance_init, /* instance_init */
316 NULL /* Value handling */
317 };
b445142a 318
90e19f82
AM
319 type = g_type_register_static (LTTV_TRACE_STATE_TYPE,
320 "LttvTraceStatsType", &info, 0);
321 }
322 return type;
b445142a 323}
324
325
90e19f82
AM
326static void tracefile_stats_instance_init (GTypeInstance *instance,
327 gpointer g_class)
b445142a 328{
329}
330
331
90e19f82 332static void tracefile_stats_finalize (LttvTracefileStats *self)
b445142a 333{
90e19f82
AM
334 G_OBJECT_CLASS(g_type_class_peek(LTTV_TRACEFILE_STATE_TYPE))->
335 finalize(G_OBJECT(self));
b445142a 336}
337
338
90e19f82 339static void tracefile_stats_class_init (LttvTracefileStatsClass *klass)
b445142a 340{
90e19f82 341 GObjectClass *gobject_class = G_OBJECT_CLASS(klass);
b445142a 342
90e19f82 343 gobject_class->finalize = (void (*)(GObject *self)) tracefile_stats_finalize;
b445142a 344}
345
346
90e19f82 347GType lttv_tracefile_stats_get_type(void)
b445142a 348{
90e19f82
AM
349 static GType type = 0;
350 if (type == 0) {
351 static const GTypeInfo info = {
352 sizeof (LttvTracefileStatsClass),
353 NULL, /* base_init */
354 NULL, /* base_finalize */
355 (GClassInitFunc) tracefile_stats_class_init, /* class_init */
356 NULL, /* class_finalize */
357 NULL, /* class_data */
358 sizeof (LttvTracefileStats),
359 0, /* n_preallocs */
360 (GInstanceInitFunc) tracefile_stats_instance_init, /* instance_init */
361 NULL /* Value handling */
362 };
b445142a 363
90e19f82
AM
364 type = g_type_register_static (LTTV_TRACEFILE_STATE_TYPE,
365 "LttvTracefileStatsType", &info, 0);
366 }
367 return type;
b445142a 368}
369
516a8712 370static void find_event_tree(LttvCPUStats *cpu_stats,
90e19f82
AM
371 GQuark pid_time,
372 guint cpu,
373 guint64 function,
374 GQuark mode,
375 GQuark sub_mode,
376 LttvAttribute **events_tree,
377 LttvAttribute **event_types_tree)
b445142a 378{
90e19f82
AM
379 LttvAttribute *a;
380 gchar fstring[MAX_64_HEX_STRING_LEN];
381 gint ret;
14236daa 382
90e19f82
AM
383 ret = snprintf(fstring, MAX_64_HEX_STRING_LEN-1,
384 "0x%" PRIX64, function) > 0;
385 g_assert(ret > 0);
386 fstring[MAX_64_HEX_STRING_LEN-1] = '\0';
b445142a 387
516a8712 388 LttvTraceStats *tcs = cpu_stats->tcs;
90e19f82
AM
389 a = lttv_attribute_find_subdir(tcs->stats, LTTV_STATS_PROCESSES);
390 a = lttv_attribute_find_subdir(a, pid_time);
391 a = lttv_attribute_find_subdir(a, LTTV_STATS_CPU);
392 a = lttv_attribute_find_subdir_unnamed(a, cpu);
393 a = lttv_attribute_find_subdir(a, LTTV_STATS_FUNCTIONS);
394 a = lttv_attribute_find_subdir(a, g_quark_from_string(fstring));
395 a = lttv_attribute_find_subdir(a, LTTV_STATS_MODE_TYPES);
396 a = lttv_attribute_find_subdir(a, mode);
397 a = lttv_attribute_find_subdir(a, LTTV_STATS_SUBMODES);
398 a = lttv_attribute_find_subdir(a, sub_mode);
399 *events_tree = a;
400 a = lttv_attribute_find_subdir(a, LTTV_STATS_EVENT_TYPES);
401 *event_types_tree = a;
b445142a 402}
403
516a8712 404static void update_event_tree(LttvCPUStats *cpu_stats)
b445142a 405{
516a8712
MD
406 LttvTraceStats *tcs = cpu_stats->tcs;
407 guint cpu = cpu_stats->cpu;
408 LttvTraceState *ts = &tcs->parent;
90e19f82
AM
409 LttvProcessState *process = ts->running_process[cpu];
410 LttvExecutionState *es = process->state;
b445142a 411
516a8712 412 find_event_tree(cpu_stats, process->pid_time,
90e19f82
AM
413 cpu,
414 process->current_function,
516a8712
MD
415 es->t, es->n, &(cpu_stats->current_events_tree),
416 &(cpu_stats->current_event_types_tree));
b445142a 417}
418
516a8712 419/* Update the trace event tree each cpu */
89f8741a 420static void update_trace_event_tree(LttvTraceStats *tcs)
d3670e3d 421{
516a8712 422 LttvCPUStats *cpu_stats;
90e19f82 423 LttvTraceContext *tc = (LttvTraceContext*)tcs;
516a8712
MD
424 guint j, nb_cpu;
425
426 /* For each cpu, update the event tree */
427 nb_cpu = ltt_trace_get_num_cpu(tc->t);
428 for(j = 0; j < nb_cpu; j++) {
429 cpu_stats = &tcs->cpu_stats[j];
430 update_event_tree(cpu_stats);
90e19f82 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
516a8712 450 lttv_attribute_find(tfcs->cpu_stats->current_events_tree, LTTV_STATS_CPU_TIME,
90e19f82
AM
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 469 /* FIXME put there in case of a missing update after a state modification */
516a8712 470 //void *lasttree = tfcs->cpu_stats->current_events_tree;
90e19f82 471 //update_event_tree(tfcs);
516a8712
MD
472 //g_assert (lasttree == tfcs->cpu_stats->current_events_tree);
473 lttv_attribute_find(tfcs->cpu_stats->current_events_tree, LTTV_STATS_ELAPSED_TIME,
90e19f82 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
516a8712 484 lttv_attribute_find(tfcs->cpu_stats->current_events_tree, LTTV_STATS_CPU_TIME,
90e19f82 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
516a8712 499 lttv_attribute_find(tfcs->cpu_stats->current_events_tree, LTTV_STATS_CUMULATIVE_CPU_TIME,
90e19f82
AM
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
516a8712 517 update_event_tree(tfcs->cpu_stats);
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{
516a8712 532 update_event_tree(((LttvTracefileStats *)call_data)->cpu_stats);
90e19f82 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{
516a8712 560 update_event_tree(((LttvTracefileStats *)call_data)->cpu_stats);
90e19f82 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{
516a8712 587 update_event_tree(((LttvTracefileStats *)call_data)->cpu_stats);
90e19f82 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{
516a8712 614 update_event_tree(((LttvTracefileStats *)call_data)->cpu_stats);
90e19f82 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{
516a8712 639 update_event_tree(((LttvTracefileStats *)call_data)->cpu_stats);
90e19f82 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
516a8712 702 find_event_tree(tfcs->cpu_stats, process->pid_time,
90e19f82
AM
703 cpu,
704 process->current_function,
516a8712
MD
705 process->state->t, process->state->n,
706 &(tfcs->cpu_stats->current_events_tree),
707 &(tfcs->cpu_stats->current_event_types_tree));
b445142a 708
90e19f82
AM
709 /* compute the time waiting for the process to schedule in */
710 mode_change(tfcs);
b445142a 711
90e19f82 712 return FALSE;
b49e54b4 713}
b445142a 714
89f8741a 715static gboolean process_fork(void *hook_data, void *call_data)
b445142a 716{
90e19f82 717 return FALSE;
b445142a 718}
719
89f8741a 720static gboolean process_exit(void *hook_data, void *call_data)
b445142a 721{
516a8712 722 update_event_tree(((LttvTracefileStats *)call_data)->cpu_stats);
90e19f82 723 return FALSE;
b445142a 724}
725
89f8741a 726static gboolean before_enum_process_state(void *hook_data, void *call_data)
954417fa 727{
d3670e3d 728#if 0
90e19f82
AM
729 /* Broken : adds up time in the current process doing the dump */
730 LttvTracefileStats *tfcs = (LttvTracefileStats *)call_data;
731 mode_end(tfcs);
732 after_mode_end(tfcs);
733 mode_change(tfcs);
d3670e3d 734#endif //0
90e19f82 735 return FALSE;
954417fa 736}
737
89f8741a 738static gboolean after_enum_process_state(void *hook_data, void *call_data)
954417fa 739{
90e19f82
AM
740 LttvTracefileContext *tfc = (LttvTracefileContext *)call_data;
741 LttvTraceStats *tcs = (LttvTraceStats*)tfc->t_context;
742 update_trace_event_tree(tcs);
743 return FALSE;
d3670e3d 744}
745
746static gboolean after_statedump_end(void *hook_data, void *call_data)
747{
90e19f82
AM
748 LttvTracefileContext *tfc = (LttvTracefileContext *)call_data;
749 LttvTraceStats *tcs = (LttvTraceStats*)tfc->t_context;
750 update_trace_event_tree(tcs);
751 return FALSE;
954417fa 752}
753
89f8741a 754static gboolean process_free(void *hook_data, void *call_data)
eed2ef37 755{
90e19f82 756 return FALSE;
eed2ef37 757}
b445142a 758
89f8741a 759static gboolean every_event(void *hook_data, void *call_data)
b445142a 760{
90e19f82 761 LttvTracefileStats *tfcs = (LttvTracefileStats *)call_data;
b445142a 762
90e19f82 763 LttEvent *e = ltt_tracefile_get_event(tfcs->parent.parent.tf);
eed2ef37 764
90e19f82 765 LttvAttributeValue v;
b445142a 766
90e19f82 767 struct marker_info *info;
68003874 768
90e19f82
AM
769 /* The current branch corresponds to the tracefile/process/interrupt state.
770 Statistics are added within it, to count the number of events of this
771 type occuring in this context. A quark has been pre-allocated for each
772 event type and is used as name. */
b445142a 773
90e19f82 774 info = marker_get_info_from_id(tfcs->parent.parent.tf->mdata, e->event_id);
68003874 775
516a8712 776 lttv_attribute_find(tfcs->cpu_stats->current_event_types_tree,
90e19f82
AM
777 info->name, LTTV_UINT, &v);
778 (*(v.v_uint))++;
779 return FALSE;
b445142a 780}
781
b91e751b 782struct cleanup_state_struct {
90e19f82
AM
783 LttvTraceState *ts;
784 LttTime current_time;
b91e751b 785};
786
787//static void lttv_stats_cleanup_process_state(LttvTraceState *ts,
90e19f82 788// LttvProcessState *process, LttTime current_time)
b91e751b 789static void lttv_stats_cleanup_process_state(gpointer key, gpointer value,
90e19f82
AM
790 gpointer user_data)
791{
792 struct cleanup_state_struct *cleanup_closure =
793 (struct cleanup_state_struct *)user_data;
794 LttvTraceState *ts = cleanup_closure->ts;
795 LttvProcessState *process = (LttvProcessState *)value;
796 LttTime current_time = cleanup_closure->current_time;
797 LttvTracefileStats **tfs = (LttvTracefileStats **)
798 &g_array_index(ts->parent.tracefiles, LttvTracefileContext*,
799 process->cpu);
800 int cleanup_empty = 0;
801 LttTime nested_delta = ltt_time_zero;
802
803 /* FIXME : ok, this is a hack. The time is infinite here :( */
804 //LttTime save_time = (*tfs)->parent.parent.timestamp;
805 //LttTime start, end;
806 //ltt_trace_time_span_get(ts->parent.t, &start, &end);
807 //(*tfs)->parent.parent.timestamp = end;
808
809 do {
810 if(ltt_time_compare(process->state->cum_cpu_time, ltt_time_zero) != 0) {
516a8712 811 find_event_tree((*tfs)->cpu_stats, process->pid_time,
90e19f82
AM
812 process->cpu,
813 process->current_function,
516a8712
MD
814 process->state->t, process->state->n,
815 &((*tfs)->cpu_stats->current_events_tree),
816 &((*tfs)->cpu_stats->current_event_types_tree));
90e19f82
AM
817 /* Call mode_end only if not at end of trace */
818 if(ltt_time_compare(current_time, ltt_time_infinite) != 0)
819 mode_end(*tfs);
820 nested_delta = process->state->cum_cpu_time;
821 }
822 cleanup_empty = lttv_state_pop_state_cleanup(process,
823 (LttvTracefileState *)*tfs);
824 process->state->cum_cpu_time = ltt_time_add(process->state->cum_cpu_time,
825 nested_delta);
826
827 } while(cleanup_empty != 1);
828
829 //(*tfs)->parent.parent.timestamp = save_time;
b49e54b4 830}
831
d3670e3d 832/* For each cpu, for each of their stacked states,
b49e54b4 833 * perform sum of needed values. */
b91e751b 834static void lttv_stats_cleanup_state(LttvTraceStats *tcs, LttTime current_time)
b49e54b4 835{
90e19f82
AM
836 LttvTraceState *ts = (LttvTraceState *)tcs;
837 struct cleanup_state_struct cleanup_closure;
b91e751b 838#if 0
90e19f82 839 guint nb_cpus, i;
d3670e3d 840
90e19f82
AM
841 nb_cpus = ltt_trace_get_num_cpu(ts->parent.t);
842
843 for(i=0; i<nb_cpus; i++) {
844 lttv_stats_cleanup_process_state(ts, ts->running_process[i], current_time);
845 }
b91e751b 846#endif //0
90e19f82
AM
847 cleanup_closure.ts = ts;
848 cleanup_closure.current_time = current_time;
849 g_hash_table_foreach(ts->processes, lttv_stats_cleanup_process_state,
850 &cleanup_closure);
851}
852
853void lttv_stats_sum_trace(LttvTraceStats *self, LttvAttribute *ts_stats,
854 LttTime current_time)
855{
856 LttvAttribute *sum_container = self->stats;
857
858 LttvAttributeType type;
859
860 LttvAttributeValue value;
861
862 LttvAttributeName name;
863
864 gboolean is_named;
865
866 unsigned sum;
867
868 int trace_is_summed;
869
870 int i, j, k, l, m, nb_process, nb_cpu, nb_mode_type, nb_submode,
871 nb_event_type, nf, nb_functions;
872
873 LttvAttribute *main_tree, *processes_tree, *process_tree, *cpus_tree,
874 *cpu_tree, *mode_tree, *mode_types_tree, *submodes_tree,
875 *submode_tree, *event_types_tree, *mode_events_tree,
876 *cpu_functions_tree,
877 *function_tree,
878 *function_mode_types_tree,
879 *trace_cpu_tree;
880
881
882 main_tree = sum_container;
883
884 lttv_attribute_find(sum_container,
885 LTTV_STATS_SUMMED,
886 LTTV_UINT, &value);
887 trace_is_summed = *(value.v_uint);
888 *(value.v_uint) = 1;
889
890 /* First cleanup the state : sum all stalled information (never ending
891 * states). */
892 if(!trace_is_summed)
893 lttv_stats_cleanup_state(self, current_time);
894
895 processes_tree = lttv_attribute_find_subdir(main_tree,
896 LTTV_STATS_PROCESSES);
897 nb_process = lttv_attribute_get_number(processes_tree);
898
899 for(i = 0 ; i < nb_process ; i++) {
900 type = lttv_attribute_get(processes_tree, i, &name, &value, &is_named);
901 process_tree = LTTV_ATTRIBUTE(*(value.v_gobject));
902
903 cpus_tree = lttv_attribute_find_subdir(process_tree, LTTV_STATS_CPU);
904 nb_cpu = lttv_attribute_get_number(cpus_tree);
905
906 for(j = 0 ; j < nb_cpu ; j++) {
907 type = lttv_attribute_get(cpus_tree, j, &name, &value, &is_named);
908 cpu_tree = LTTV_ATTRIBUTE(*(value.v_gobject));
909
910 trace_cpu_tree = lttv_attribute_find_subdir(main_tree,
911 LTTV_STATS_CPU);
912 trace_cpu_tree = lttv_attribute_find_subdir_unnamed(trace_cpu_tree, name);
913 cpu_functions_tree = lttv_attribute_find_subdir(cpu_tree,
914 LTTV_STATS_FUNCTIONS);
915 nb_functions = lttv_attribute_get_number(cpu_functions_tree);
916
917 for(nf=0; nf < nb_functions; nf++) {
918 type = lttv_attribute_get(cpu_functions_tree, nf, &name, &value,
919 &is_named);
920 function_tree = LTTV_ATTRIBUTE(*(value.v_gobject));
921 function_mode_types_tree = lttv_attribute_find_subdir(function_tree,
922 LTTV_STATS_MODE_TYPES);
923 nb_mode_type = lttv_attribute_get_number(function_mode_types_tree);
924 for(k = 0 ; k < nb_mode_type ; k++) {
925 type = lttv_attribute_get(function_mode_types_tree, k, &name,
926 &value, &is_named);
927 mode_tree = LTTV_ATTRIBUTE(*(value.v_gobject));
928
929 submodes_tree = lttv_attribute_find_subdir(mode_tree,
930 LTTV_STATS_SUBMODES);
931 mode_events_tree = lttv_attribute_find_subdir(mode_tree,
932 LTTV_STATS_EVENTS);
933 mode_types_tree = lttv_attribute_find_subdir(mode_tree,
934 LTTV_STATS_MODE_TYPES);
935
936 nb_submode = lttv_attribute_get_number(submodes_tree);
937
938 for(l = 0 ; l < nb_submode ; l++) {
939 type = lttv_attribute_get(submodes_tree, l, &name, &value,
940 &is_named);
941 submode_tree = LTTV_ATTRIBUTE(*(value.v_gobject));
942
943 event_types_tree = lttv_attribute_find_subdir(submode_tree,
944 LTTV_STATS_EVENT_TYPES);
945 nb_event_type = lttv_attribute_get_number(event_types_tree);
946
947 sum = 0;
948 for(m = 0 ; m < nb_event_type ; m++) {
949 type = lttv_attribute_get(event_types_tree, m, &name,
950 &value, &is_named);
951 sum += *(value.v_uint);
952 }
953 lttv_attribute_find(submode_tree, LTTV_STATS_EVENTS_COUNT,
954 LTTV_UINT, &value);
955 *(value.v_uint) = sum;
956
957 type = lttv_attribute_get(submodes_tree, l, &name, &value,
958 &is_named);
959 submode_tree = LTTV_ATTRIBUTE(*(value.v_gobject));
960 if(!trace_is_summed) {
961 lttv_attribute_recursive_add(mode_events_tree, event_types_tree);
962 lttv_attribute_recursive_add(mode_types_tree, submode_tree);
963 }
964 }
965 if(!trace_is_summed) {
966 lttv_attribute_recursive_add(function_tree, mode_types_tree);
967 }
968 }
969 if(!trace_is_summed) {
970 lttv_attribute_recursive_add(cpu_tree, function_tree);
971 lttv_attribute_recursive_add(process_tree, function_tree);
972 lttv_attribute_recursive_add(trace_cpu_tree, function_tree);
973 lttv_attribute_recursive_add(main_tree, function_tree);
974 }
975 lttv_attribute_recursive_add(ts_stats, function_tree);
976 }
977 }
978 }
f95bc830 979}
980
981
d3e01c7a 982gboolean lttv_stats_sum_traceset_hook(void *hook_data, void *call_data)
983{
90e19f82
AM
984 struct sum_traceset_closure *closure =
985 (struct sum_traceset_closure *)call_data;
986 lttv_stats_sum_traceset(closure->tss, closure->current_time);
987 return 0;
d3e01c7a 988}
989
90e19f82 990void lttv_stats_sum_traceset(LttvTracesetStats *self, LttTime current_time)
f95bc830 991{
90e19f82
AM
992 LttvTraceset *traceset = self->parent.parent.ts;
993 LttvAttribute *sum_container = self->stats;
f95bc830 994
90e19f82 995 LttvTraceStats *tcs;
f95bc830 996
90e19f82 997 int i, nb_trace;
f95bc830 998
90e19f82 999 LttvAttributeValue value;
f95bc830 1000
90e19f82
AM
1001 lttv_attribute_find(sum_container, LTTV_STATS_SUMMED,
1002 LTTV_UINT, &value);
1003 if(*(value.v_uint) != 0) return;
1004 *(value.v_uint) = 1;
f95bc830 1005
90e19f82 1006 nb_trace = lttv_traceset_number(traceset);
f95bc830 1007
90e19f82
AM
1008 for(i = 0 ; i < nb_trace ; i++) {
1009 tcs = (LttvTraceStats *)(self->parent.parent.traces[i]);
1010 lttv_stats_sum_trace(tcs, self->stats, current_time);
1011 // lttv_attribute_recursive_add(sum_container, tcs->stats);
1012 }
b445142a 1013}
1014
1015
d3e01c7a 1016// Hook wrapper. call_data is a traceset context.
00e74b69 1017gboolean lttv_stats_hook_add_event_hooks(void *hook_data, void *call_data)
d3e01c7a 1018{
90e19f82 1019 LttvTracesetStats *tss = (LttvTracesetStats*)call_data;
d3e01c7a 1020
90e19f82 1021 lttv_stats_add_event_hooks(tss);
d3e01c7a 1022
90e19f82 1023 return 0;
d3e01c7a 1024}
1025
00e74b69 1026void lttv_stats_add_event_hooks(LttvTracesetStats *self)
b445142a 1027{
90e19f82
AM
1028 LttvTraceset *traceset = self->parent.parent.ts;
1029
1030 guint i, j, k, nb_trace, nb_tracefile;
1031
1032 LttvTraceStats *ts;
1033
1034 LttvTracefileStats *tfs;
1035
1036 GArray *hooks, *before_hooks, *after_hooks;
1037
1038 LttvTraceHook *th;
1039
1040 LttvAttributeValue val;
1041
1042 nb_trace = lttv_traceset_number(traceset);
1043 for(i = 0 ; i < nb_trace ; i++) {
1044 ts = (LttvTraceStats *)self->parent.parent.traces[i];
1045
1046 /* Find the eventtype id for the following events and register the
1047 associated by id hooks. */
1048
1049 hooks = g_array_sized_new(FALSE, FALSE, sizeof(LttvTraceHook), 12);
1050
1051 lttv_trace_find_hook(ts->parent.parent.t,
1052 LTT_CHANNEL_KERNEL,
1053 LTT_EVENT_SYSCALL_ENTRY,
1054 FIELD_ARRAY(LTT_FIELD_SYSCALL_ID),
1055 before_syscall_entry, NULL,
1056 &hooks);
1057
1058 lttv_trace_find_hook(ts->parent.parent.t,
1059 LTT_CHANNEL_KERNEL,
1060 LTT_EVENT_SYSCALL_EXIT,
1061 NULL,
1062 before_syscall_exit, NULL,
1063 &hooks);
1064
1065 lttv_trace_find_hook(ts->parent.parent.t,
1066 LTT_CHANNEL_KERNEL,
1067 LTT_EVENT_TRAP_ENTRY,
1068 FIELD_ARRAY(LTT_FIELD_TRAP_ID),
1069 before_trap_entry, NULL,
1070 &hooks);
1071
1072 lttv_trace_find_hook(ts->parent.parent.t,
1073 LTT_CHANNEL_KERNEL,
1074 LTT_EVENT_TRAP_EXIT,
1075 NULL,
1076 before_trap_exit, NULL,
1077 &hooks);
1078
1079 lttv_trace_find_hook(ts->parent.parent.t,
1080 LTT_CHANNEL_KERNEL,
1081 LTT_EVENT_IRQ_ENTRY,
1082 FIELD_ARRAY(LTT_FIELD_IRQ_ID),
1083 before_irq_entry, NULL,
1084 &hooks);
1085
1086 lttv_trace_find_hook(ts->parent.parent.t,
1087 LTT_CHANNEL_KERNEL,
1088 LTT_EVENT_IRQ_EXIT,
1089 NULL,
1090 before_irq_exit, NULL,
1091 &hooks);
1092
1093 lttv_trace_find_hook(ts->parent.parent.t,
1094 LTT_CHANNEL_KERNEL,
1095 LTT_EVENT_SOFT_IRQ_ENTRY,
1096 FIELD_ARRAY(LTT_FIELD_SOFT_IRQ_ID),
1097 before_soft_irq_entry, NULL,
1098 &hooks);
1099
1100 lttv_trace_find_hook(ts->parent.parent.t,
1101 LTT_CHANNEL_KERNEL,
1102 LTT_EVENT_SOFT_IRQ_EXIT,
1103 NULL,
1104 before_soft_irq_exit, NULL,
1105 &hooks);
1106
1107 lttv_trace_find_hook(ts->parent.parent.t,
1108 LTT_CHANNEL_KERNEL,
1109 LTT_EVENT_SCHED_SCHEDULE,
1110 FIELD_ARRAY(LTT_FIELD_PREV_PID, LTT_FIELD_NEXT_PID, LTT_FIELD_PREV_STATE),
1111 before_schedchange, NULL,
1112 &hooks);
1113
1114 lttv_trace_find_hook(ts->parent.parent.t,
1115 LTT_CHANNEL_USERSPACE,
1116 LTT_EVENT_FUNCTION_ENTRY,
1117 FIELD_ARRAY(LTT_FIELD_THIS_FN, LTT_FIELD_CALL_SITE),
1118 before_function_entry, NULL,
1119 &hooks);
1120
1121 lttv_trace_find_hook(ts->parent.parent.t,
1122 LTT_CHANNEL_USERSPACE,
1123 LTT_EVENT_FUNCTION_EXIT,
1124 FIELD_ARRAY(LTT_FIELD_THIS_FN, LTT_FIELD_CALL_SITE),
1125 before_function_exit, NULL,
1126 &hooks);
1127
1128 /* statedump-related hooks */
1129 lttv_trace_find_hook(ts->parent.parent.t,
1130 LTT_CHANNEL_TASK_STATE,
1131 LTT_EVENT_PROCESS_STATE,
1132 FIELD_ARRAY(LTT_FIELD_PID, LTT_FIELD_PARENT_PID, LTT_FIELD_NAME),
1133 before_enum_process_state, NULL,
1134 &hooks);
1135
1136 before_hooks = hooks;
1137
1138 hooks = g_array_sized_new(FALSE, FALSE, sizeof(LttvTraceHook), 16);
1139
1140 lttv_trace_find_hook(ts->parent.parent.t,
1141 LTT_CHANNEL_KERNEL,
1142 LTT_EVENT_SYSCALL_ENTRY,
1143 FIELD_ARRAY(LTT_FIELD_SYSCALL_ID),
1144 after_syscall_entry, NULL,
1145 &hooks);
1146
1147 lttv_trace_find_hook(ts->parent.parent.t,
1148 LTT_CHANNEL_KERNEL,
1149 LTT_EVENT_SYSCALL_EXIT,
1150 NULL,
1151 after_syscall_exit, NULL,
1152 &hooks);
1153
1154 lttv_trace_find_hook(ts->parent.parent.t,
1155 LTT_CHANNEL_KERNEL,
1156 LTT_EVENT_TRAP_ENTRY,
1157 FIELD_ARRAY(LTT_FIELD_TRAP_ID),
1158 after_trap_entry, NULL,
1159 &hooks);
1160
1161 lttv_trace_find_hook(ts->parent.parent.t,
1162 LTT_CHANNEL_KERNEL,
1163 LTT_EVENT_TRAP_EXIT,
1164 NULL,
1165 after_trap_exit, NULL,
1166 &hooks);
1167
1168 lttv_trace_find_hook(ts->parent.parent.t,
1169 LTT_CHANNEL_KERNEL,
1170 LTT_EVENT_IRQ_ENTRY,
1171 FIELD_ARRAY(LTT_FIELD_IRQ_ID),
1172 after_irq_entry, NULL,
1173 &hooks);
1174
1175 lttv_trace_find_hook(ts->parent.parent.t,
1176 LTT_CHANNEL_KERNEL,
1177 LTT_EVENT_IRQ_EXIT,
1178 NULL,
1179 after_irq_exit, NULL,
1180 &hooks);
1181
1182 lttv_trace_find_hook(ts->parent.parent.t,
1183 LTT_CHANNEL_KERNEL,
1184 LTT_EVENT_SOFT_IRQ_ENTRY,
1185 FIELD_ARRAY(LTT_FIELD_SOFT_IRQ_ID),
1186 after_soft_irq_entry, NULL,
1187 &hooks);
1188
1189 lttv_trace_find_hook(ts->parent.parent.t,
1190 LTT_CHANNEL_KERNEL,
1191 LTT_EVENT_SOFT_IRQ_EXIT,
1192 NULL,
1193 after_soft_irq_exit, NULL,
1194 &hooks);
1195
1196 lttv_trace_find_hook(ts->parent.parent.t,
1197 LTT_CHANNEL_KERNEL,
1198 LTT_EVENT_SCHED_SCHEDULE,
1199 FIELD_ARRAY(LTT_FIELD_PREV_PID, LTT_FIELD_NEXT_PID, LTT_FIELD_PREV_STATE),
1200 after_schedchange, NULL,
1201 &hooks);
1202
1203 lttv_trace_find_hook(ts->parent.parent.t,
1204 LTT_CHANNEL_KERNEL,
1205 LTT_EVENT_PROCESS_FORK,
1206 FIELD_ARRAY(LTT_FIELD_PARENT_PID, LTT_FIELD_CHILD_PID),
1207 process_fork, NULL,
1208 &hooks);
1209
1210 lttv_trace_find_hook(ts->parent.parent.t,
1211 LTT_CHANNEL_KERNEL,
1212 LTT_EVENT_PROCESS_EXIT,
1213 FIELD_ARRAY(LTT_FIELD_PID),
1214 process_exit, NULL,
1215 &hooks);
1216
1217 lttv_trace_find_hook(ts->parent.parent.t,
1218 LTT_CHANNEL_KERNEL,
1219 LTT_EVENT_PROCESS_FREE,
1220 FIELD_ARRAY(LTT_FIELD_PID),
1221 process_free, NULL,
1222 &hooks);
1223
1224 lttv_trace_find_hook(ts->parent.parent.t,
1225 LTT_CHANNEL_USERSPACE,
1226 LTT_EVENT_FUNCTION_ENTRY,
1227 FIELD_ARRAY(LTT_FIELD_THIS_FN, LTT_FIELD_CALL_SITE),
1228 after_function_entry, NULL,
1229 &hooks);
1230
1231 lttv_trace_find_hook(ts->parent.parent.t,
1232 LTT_CHANNEL_USERSPACE,
1233 LTT_EVENT_FUNCTION_EXIT,
1234 FIELD_ARRAY(LTT_FIELD_THIS_FN, LTT_FIELD_CALL_SITE),
1235 after_function_exit, NULL,
1236 &hooks);
1237
1238 /* statedump-related hooks */
1239 lttv_trace_find_hook(ts->parent.parent.t,
1240 LTT_CHANNEL_TASK_STATE,
1241 LTT_EVENT_PROCESS_STATE,
1242 FIELD_ARRAY(LTT_FIELD_PID, LTT_FIELD_PARENT_PID, LTT_FIELD_NAME),
1243 after_enum_process_state, NULL,
1244 &hooks);
1245
1246 lttv_trace_find_hook(ts->parent.parent.t,
1247 LTT_CHANNEL_GLOBAL_STATE,
1248 LTT_EVENT_STATEDUMP_END,
1249 NULL,
1250 after_statedump_end, NULL,
1251 &hooks);
1252
1253 after_hooks = hooks;
1254
1255 /* Add these hooks to each event_by_id hooks list */
1256
1257 nb_tracefile = ts->parent.parent.tracefiles->len;
1258
1259 for(j = 0 ; j < nb_tracefile ; j++) {
1260 tfs = LTTV_TRACEFILE_STATS(g_array_index(ts->parent.parent.tracefiles,
1261 LttvTracefileContext*, j));
1262 lttv_hooks_add(tfs->parent.parent.event, every_event, NULL,
1263 LTTV_PRIO_DEFAULT);
1264
1265 for(k = 0 ; k < before_hooks->len ; k++) {
1266 th = &g_array_index(before_hooks, LttvTraceHook, k);
1267 if (th->mdata == tfs->parent.parent.tf->mdata)
1268 lttv_hooks_add(
1269 lttv_hooks_by_id_find(tfs->parent.parent.event_by_id, th->id),
1270 th->h,
1271 th,
1272 LTTV_PRIO_STATS_BEFORE_STATE);
1273 }
1274 for(k = 0 ; k < after_hooks->len ; k++) {
1275 th = &g_array_index(after_hooks, LttvTraceHook, k);
1276 if (th->mdata == tfs->parent.parent.tf->mdata)
1277 lttv_hooks_add(
1278 lttv_hooks_by_id_find(tfs->parent.parent.event_by_id, th->id),
1279 th->h,
1280 th,
1281 LTTV_PRIO_STATS_AFTER_STATE);
1282 }
1283 }
1284 lttv_attribute_find(self->parent.parent.a, LTTV_STATS_BEFORE_HOOKS,
1285 LTTV_POINTER, &val);
1286 *(val.v_pointer) = before_hooks;
1287 lttv_attribute_find(self->parent.parent.a, LTTV_STATS_AFTER_HOOKS,
1288 LTTV_POINTER, &val);
1289 *(val.v_pointer) = after_hooks;
1290 }
b445142a 1291}
1292
d3e01c7a 1293// Hook wrapper. call_data is a traceset context.
00e74b69 1294gboolean lttv_stats_hook_remove_event_hooks(void *hook_data, void *call_data)
d3e01c7a 1295{
90e19f82 1296 LttvTracesetStats *tss = (LttvTracesetStats*)call_data;
d3e01c7a 1297
90e19f82 1298 lttv_stats_remove_event_hooks(tss);
d3e01c7a 1299
90e19f82 1300 return 0;
d3e01c7a 1301}
b445142a 1302
00e74b69 1303void lttv_stats_remove_event_hooks(LttvTracesetStats *self)
b445142a 1304{
90e19f82
AM
1305 LttvTraceset *traceset = self->parent.parent.ts;
1306
1307 guint i, j, k, nb_trace, nb_tracefile;
b445142a 1308
90e19f82 1309 LttvTraceStats *ts;
b445142a 1310
90e19f82 1311 LttvTracefileStats *tfs;
b445142a 1312
90e19f82 1313 GArray *before_hooks, *after_hooks;
b445142a 1314
90e19f82 1315 LttvTraceHook *th;
b445142a 1316
90e19f82 1317 LttvAttributeValue val;
b445142a 1318
90e19f82
AM
1319 nb_trace = lttv_traceset_number(traceset);
1320 for(i = 0 ; i < nb_trace ; i++) {
1321 ts = (LttvTraceStats*)self->parent.parent.traces[i];
1322 lttv_attribute_find(self->parent.parent.a, LTTV_STATS_BEFORE_HOOKS,
1323 LTTV_POINTER, &val);
1324 before_hooks = *(val.v_pointer);
1325 lttv_attribute_find(self->parent.parent.a, LTTV_STATS_AFTER_HOOKS,
1326 LTTV_POINTER, &val);
1327 after_hooks = *(val.v_pointer);
b445142a 1328
90e19f82 1329 /* Remove these hooks from each event_by_id hooks list */
b445142a 1330
90e19f82 1331 nb_tracefile = ts->parent.parent.tracefiles->len;
b445142a 1332
90e19f82
AM
1333 for(j = 0 ; j < nb_tracefile ; j++) {
1334 tfs = LTTV_TRACEFILE_STATS(g_array_index(ts->parent.parent.tracefiles,
1335 LttvTracefileContext*, j));
1336 lttv_hooks_remove_data(tfs->parent.parent.event, every_event,
1337 NULL);
b445142a 1338
90e19f82
AM
1339 for(k = 0 ; k < before_hooks->len ; k++) {
1340 th = &g_array_index(before_hooks, LttvTraceHook, k);
1341 if (th->mdata == tfs->parent.parent.tf->mdata)
1342 lttv_hooks_remove_data(
1343 lttv_hooks_by_id_find(tfs->parent.parent.event_by_id, th->id),
1344 th->h,
1345 th);
1346 }
1347 for(k = 0 ; k < after_hooks->len ; k++) {
1348 th = &g_array_index(after_hooks, LttvTraceHook, k);
1349 if (th->mdata == tfs->parent.parent.tf->mdata)
1350 lttv_hooks_remove_data(
1351 lttv_hooks_by_id_find(tfs->parent.parent.event_by_id, th->id),
1352 th->h,
1353 th);
b445142a 1354
90e19f82
AM
1355 }
1356 }
1357 g_debug("lttv_stats_remove_event_hooks()");
1358 lttv_trace_hook_remove_all(&before_hooks);
1359 lttv_trace_hook_remove_all(&after_hooks);
1360 g_array_free(before_hooks, TRUE);
1361 g_array_free(after_hooks, TRUE);
1362 }
9f797243 1363}
08b1c66e 1364
1365
1366static void module_init()
1367{
90e19f82
AM
1368 LTTV_STATS_PROCESS_UNKNOWN = g_quark_from_string("unknown process");
1369 LTTV_STATS_PROCESSES = g_quark_from_string("processes");
1370 LTTV_STATS_CPU = g_quark_from_string("cpu");
1371 LTTV_STATS_MODE_TYPES = g_quark_from_string("mode_types");
1372 LTTV_STATS_MODES = g_quark_from_string("modes");
1373 LTTV_STATS_SUBMODES = g_quark_from_string("submodes");
1374 LTTV_STATS_FUNCTIONS = g_quark_from_string("functions");
1375 LTTV_STATS_EVENT_TYPES = g_quark_from_string("event_types");
1376 LTTV_STATS_CPU_TIME = g_quark_from_string("cpu time");
1377 LTTV_STATS_CUMULATIVE_CPU_TIME = g_quark_from_string("cumulative cpu time (includes nested routines and modes)");
1378 LTTV_STATS_ELAPSED_TIME = g_quark_from_string("elapsed time (includes per process waiting time)");
1379 LTTV_STATS_EVENTS = g_quark_from_string("events");
1380 LTTV_STATS_EVENTS_COUNT = g_quark_from_string("events count");
1381 LTTV_STATS_BEFORE_HOOKS = g_quark_from_string("saved stats before hooks");
1382 LTTV_STATS_AFTER_HOOKS = g_quark_from_string("saved stats after hooks");
1383 LTTV_STATS_USE_COUNT = g_quark_from_string("stats_use_count");
1384 LTTV_STATS = g_quark_from_string("statistics");
90e19f82 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.17442 seconds and 4 git commands to generate.