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