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