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