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