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
501 lttv_attribute_find(tfcs->current_events_tree, LTTV_STATS_CPU_TIME,
502 LTTV_TIME, &cpu_time);
d3670e3d 503
504 /* if it is a running mode, we must count its cpu time */
505 if(process->state->s == LTTV_STATE_RUN &&
506 process->state->t != LTTV_STATE_MODE_UNKNOWN)
507 delta = ltt_time_sub(tfcs->parent.parent.timestamp,
508 process->state->change);
509 else
510 delta = ltt_time_zero;
511
308711e5 512 *(cpu_time.v_time) = ltt_time_add(*(cpu_time.v_time), delta);
b49e54b4 513 process->state->cum_cpu_time = ltt_time_add(process->state->cum_cpu_time,
d3670e3d 514 delta);
b49e54b4 515
516 lttv_attribute_find(tfcs->current_events_tree, LTTV_STATS_CUMULATIVE_CPU_TIME,
517 LTTV_TIME, &cum_cpu_time);
518 *(cum_cpu_time.v_time) = ltt_time_add(*(cum_cpu_time.v_time),
d3670e3d 519 process->state->cum_cpu_time);
b445142a 520}
521
522
b49e54b4 523static void after_mode_end(LttvTracefileStats *tfcs)
524{
525 LttvTraceState *ts = (LttvTraceState *)tfcs->parent.parent.t_context;
526 guint cpu = tfcs->parent.cpu;
527 LttvProcessState *process = ts->running_process[cpu];
528 LttvAttributeValue cum_cpu_time;
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
555gboolean before_syscall_exit(void *hook_data, void *call_data)
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
569gboolean before_trap_entry(void *hook_data, void *call_data)
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
583gboolean before_trap_exit(void *hook_data, void *call_data)
584{
585 mode_end((LttvTracefileStats *)call_data);
586 return FALSE;
587}
588
589
590gboolean after_trap_exit(void *hook_data, void *call_data)
591{
b49e54b4 592 after_mode_end((LttvTracefileStats *)call_data);
b445142a 593 return FALSE;
594}
595
596
597gboolean before_irq_entry(void *hook_data, void *call_data)
598{
599 mode_change((LttvTracefileStats *)call_data);
600 return FALSE;
601}
602
b445142a 603gboolean after_irq_entry(void *hook_data, void *call_data)
604{
605 update_event_tree((LttvTracefileStats *)call_data);
606 return FALSE;
607}
608
609
610gboolean before_irq_exit(void *hook_data, void *call_data)
611{
612 mode_end((LttvTracefileStats *)call_data);
613 return FALSE;
614}
615
616
617gboolean after_irq_exit(void *hook_data, void *call_data)
618{
b49e54b4 619 after_mode_end((LttvTracefileStats *)call_data);
b445142a 620 return FALSE;
621}
622
623
faf074a3 624gboolean before_soft_irq_entry(void *hook_data, void *call_data)
625{
626 mode_change((LttvTracefileStats *)call_data);
627 return FALSE;
628}
629
630gboolean after_soft_irq_entry(void *hook_data, void *call_data)
631{
632 update_event_tree((LttvTracefileStats *)call_data);
633 return FALSE;
634}
635
636
637gboolean before_soft_irq_exit(void *hook_data, void *call_data)
638{
639 mode_end((LttvTracefileStats *)call_data);
640 return FALSE;
641}
642
643
644gboolean after_soft_irq_exit(void *hook_data, void *call_data)
645{
b49e54b4 646 after_mode_end((LttvTracefileStats *)call_data);
faf074a3 647 return FALSE;
648}
649
14236daa 650gboolean before_function_entry(void *hook_data, void *call_data)
651{
b49e54b4 652 mode_change((LttvTracefileStats *)call_data);
14236daa 653 return FALSE;
654}
655
656gboolean after_function_entry(void *hook_data, void *call_data)
657{
658 update_event_tree((LttvTracefileStats *)call_data);
659 return FALSE;
660}
661
662gboolean before_function_exit(void *hook_data, void *call_data)
663{
664 mode_end((LttvTracefileStats *)call_data);
665 return FALSE;
666}
667
668gboolean after_function_exit(void *hook_data, void *call_data)
669{
b49e54b4 670 after_mode_end((LttvTracefileStats *)call_data);
14236daa 671 return FALSE;
672}
673
faf074a3 674
b445142a 675gboolean before_schedchange(void *hook_data, void *call_data)
676{
b445142a 677 LttvTracefileStats *tfcs = (LttvTracefileStats *)call_data;
678
348c6ba8 679 LttvTraceState *ts = (LttvTraceState*)tfcs->parent.parent.t_context;
680
eed2ef37 681 LttEvent *e = ltt_tracefile_get_event(tfcs->parent.parent.tf);
682
d052ffc3 683 LttvTraceHookByFacility *thf = (LttvTraceHookByFacility *)hook_data;
eed2ef37 684
d7cf605c 685 guint pid_in, pid_out;
686
687 gint state_out;
b445142a 688
eed2ef37 689 pid_out = ltt_event_get_unsigned(e, thf->f1);
690 pid_in = ltt_event_get_unsigned(e, thf->f2);
d7cf605c 691 state_out = ltt_event_get_int(e, thf->f3);
b445142a 692
693 /* compute the time for the process to schedule out */
b445142a 694 mode_change(tfcs);
695
b49e54b4 696 return FALSE;
697}
b445142a 698
b49e54b4 699gboolean after_schedchange(void *hook_data, void *call_data)
700{
701 LttvTracefileStats *tfcs = (LttvTracefileStats *)call_data;
702
703 LttvTraceState *ts = (LttvTraceState*)tfcs->parent.parent.t_context;
b445142a 704
b49e54b4 705 LttEvent *e = ltt_tracefile_get_event(tfcs->parent.parent.tf);
706
707 LttvTraceHookByFacility *thf = (LttvTraceHookByFacility *)hook_data;
708
709 guint pid_in, pid_out;
710
711 gint state_out;
712
713 LttvProcessState *process;
714
715 pid_out = ltt_event_get_unsigned(e, thf->f1);
716 pid_in = ltt_event_get_unsigned(e, thf->f2);
717 state_out = ltt_event_get_int(e, thf->f3);
718
719 /* get the information for the process scheduled in */
c0cb4d12 720 guint cpu = tfcs->parent.cpu;
b49e54b4 721 process = ts->running_process[cpu];
c0cb4d12 722
348c6ba8 723 find_event_tree(tfcs, process->pid_time,
c0cb4d12 724 cpu,
d3670e3d 725 process->current_function,
b445142a 726 process->state->t, process->state->n, &(tfcs->current_events_tree),
727 &(tfcs->current_event_types_tree));
728
729 /* compute the time waiting for the process to schedule in */
b445142a 730 mode_change(tfcs);
b445142a 731
d3670e3d 732 return FALSE;
b49e54b4 733}
b445142a 734
735gboolean process_fork(void *hook_data, void *call_data)
736{
737 /* nothing to do for now */
738 return FALSE;
739}
740
741
742gboolean process_exit(void *hook_data, void *call_data)
743{
744 /* We should probably exit all modes here or we could do that at
745 schedule out. */
746 return FALSE;
747}
748
954417fa 749gboolean before_enum_process_state(void *hook_data, void *call_data)
750{
d3670e3d 751#if 0
752 /* Broken : adds up time in the current process doing the dump */
753 LttvTracefileStats *tfcs = (LttvTracefileStats *)call_data;
754 mode_end(tfcs);
755 after_mode_end(tfcs);
756 mode_change(tfcs);
757#endif //0
954417fa 758 return FALSE;
759}
760
761gboolean after_enum_process_state(void *hook_data, void *call_data)
762{
d3670e3d 763 LttvTracefileStats *tfcs = (LttvTracefileStats *)call_data;
764 LttvTracefileContext *tfc = (LttvTracefileContext *)call_data;
765 LttvTraceState *ts = (LttvTraceState*)tfc->t_context;
766 guint nb_cpus, i;
767
768 nb_cpus = ltt_trace_get_num_cpu(ts->parent.t);
769 for(i=0; i<nb_cpus; i++) {
770 update_trace_event_tree(tfcs, i);
771 }
772 return FALSE;
773}
774
775static gboolean after_statedump_end(void *hook_data, void *call_data)
776{
777 LttvTracefileStats *tfcs = (LttvTracefileStats *)call_data;
778 LttvTracefileContext *tfc = (LttvTracefileContext *)call_data;
779 LttvTraceState *ts = (LttvTraceState*)tfc->t_context;
780 guint nb_cpus, i;
781
782 nb_cpus = ltt_trace_get_num_cpu(ts->parent.t);
783 for(i=0; i<nb_cpus; i++) {
784 update_trace_event_tree(tfcs, i);
785 }
954417fa 786 return FALSE;
787}
788
eed2ef37 789gboolean process_free(void *hook_data, void *call_data)
790{
791 return FALSE;
792}
b445142a 793
794gboolean every_event(void *hook_data, void *call_data)
795{
796 LttvTracefileStats *tfcs = (LttvTracefileStats *)call_data;
797
eed2ef37 798 LttEvent *e = ltt_tracefile_get_event(tfcs->parent.parent.tf);
799
b445142a 800 LttvAttributeValue v;
801
802 /* The current branch corresponds to the tracefile/process/interrupt state.
803 Statistics are added within it, to count the number of events of this
804 type occuring in this context. A quark has been pre-allocated for each
805 event type and is used as name. */
806
807 lttv_attribute_find(tfcs->current_event_types_tree,
eed2ef37 808 ltt_eventtype_name(ltt_event_eventtype(e)),
b445142a 809 LTTV_UINT, &v);
810 (*(v.v_uint))++;
811 return FALSE;
812}
813
d3670e3d 814static void lttv_stats_cleanup_process_state(LttvTraceState *ts,
815 LttvProcessState *process)
c4a72569 816{
d3670e3d 817 LttvTraceStats *tcs = (LttvTraceStats *)ts;
c4a72569 818 LttvTracesetContext *tsc = ts->parent.ts_context;
c4a72569 819 int i;
820 LttvTracefileStats **tfs = (LttvTracefileStats **)
821 &g_array_index(ts->parent.tracefiles, LttvTracefileContext*,
822 process->cpu);
823 int cleanup_empty = 0;
824 LttTime nested_delta = ltt_time_zero;
825 /* FIXME : ok, this is a hack. The time is infinite here :( */
826 LttTime save_time = (*tfs)->parent.parent.timestamp;
827 LttTime start, end;
828 ltt_trace_time_span_get(ts->parent.t, &start, &end);
829 (*tfs)->parent.parent.timestamp = end;
830
831 do {
832 if(ltt_time_compare(process->state->cum_cpu_time, ltt_time_zero) != 0) {
833 find_event_tree(*tfs, process->pid_time,
834 process->cpu,
835 process->current_function,
836 process->state->t, process->state->n, &((*tfs)->current_events_tree),
837 &((*tfs)->current_event_types_tree));
d3670e3d 838 mode_end(*tfs);
c4a72569 839 nested_delta = process->state->cum_cpu_time;
840 }
841 cleanup_empty = lttv_state_pop_state_cleanup(process,
842 (LttvTracefileState *)*tfs);
843 process->state->cum_cpu_time = ltt_time_add(process->state->cum_cpu_time,
844 nested_delta);
845
846 } while(cleanup_empty != 1);
847
848 (*tfs)->parent.parent.timestamp = save_time;
b49e54b4 849}
850
d3670e3d 851/* For each cpu, for each of their stacked states,
b49e54b4 852 * perform sum of needed values. */
853static void lttv_stats_cleanup_state(LttvTraceStats *tcs)
854{
855 LttvTraceState *ts = (LttvTraceState *)tcs;
d3670e3d 856 guint nb_cpus, i;
857
858 nb_cpus = ltt_trace_get_num_cpu(ts->parent.t);
c4a72569 859
d3670e3d 860 for(i=0; i<nb_cpus; i++) {
861 lttv_stats_cleanup_process_state(ts, ts->running_process[i]);
862 }
b49e54b4 863}
b445142a 864
f95bc830 865void
69374af5 866lttv_stats_sum_trace(LttvTraceStats *self, LttvAttribute *ts_stats)
b445142a 867{
d3e01c7a 868 LttvAttribute *sum_container = self->stats;
b445142a 869
b445142a 870 LttvAttributeType type;
871
872 LttvAttributeValue value;
873
874 LttvAttributeName name;
875
d3670e3d 876 gboolean is_named;
c0cb4d12 877
b445142a 878 unsigned sum;
879
d3670e3d 880 int trace_is_summed;
69374af5 881
f95bc830 882 int i, j, k, l, m, nb_process, nb_cpu, nb_mode_type, nb_submode,
3813c77b 883 nb_event_type, nf, nb_functions;
b445142a 884
885 LttvAttribute *main_tree, *processes_tree, *process_tree, *cpus_tree,
886 *cpu_tree, *mode_tree, *mode_types_tree, *submodes_tree,
887 *submode_tree, *event_types_tree, *mode_events_tree,
3813c77b 888 *cpu_functions_tree,
d3670e3d 889 *function_tree,
890 *function_mode_types_tree,
891 *trace_cpu_tree;
f95bc830 892
b49e54b4 893
d3e01c7a 894 main_tree = sum_container;
f95bc830 895
d3e01c7a 896 lttv_attribute_find(sum_container,
897 LTTV_STATS_SUMMED,
898 LTTV_UINT, &value);
d3670e3d 899 trace_is_summed = *(value.v_uint);
f95bc830 900 *(value.v_uint) = 1;
901
d3670e3d 902 /* First cleanup the state : sum all stalled information (never ending
903 * states). */
904 if(!trace_is_summed)
905 lttv_stats_cleanup_state(self);
906
f95bc830 907 processes_tree = lttv_attribute_find_subdir(main_tree,
d3e01c7a 908 LTTV_STATS_PROCESSES);
f95bc830 909 nb_process = lttv_attribute_get_number(processes_tree);
910
911 for(i = 0 ; i < nb_process ; i++) {
c0cb4d12 912 type = lttv_attribute_get(processes_tree, i, &name, &value, &is_named);
f95bc830 913 process_tree = LTTV_ATTRIBUTE(*(value.v_gobject));
914
915 cpus_tree = lttv_attribute_find_subdir(process_tree, LTTV_STATS_CPU);
f95bc830 916 nb_cpu = lttv_attribute_get_number(cpus_tree);
917
918 for(j = 0 ; j < nb_cpu ; j++) {
c0cb4d12 919 type = lttv_attribute_get(cpus_tree, j, &name, &value, &is_named);
f95bc830 920 cpu_tree = LTTV_ATTRIBUTE(*(value.v_gobject));
921
f95bc830 922 trace_cpu_tree = lttv_attribute_find_subdir(main_tree, LTTV_STATS_CPU);
c0cb4d12 923 trace_cpu_tree = lttv_attribute_find_subdir_unnamed(trace_cpu_tree, name);
d3670e3d 924 cpu_functions_tree = lttv_attribute_find_subdir(cpu_tree,
925 LTTV_STATS_FUNCTIONS);
926 nb_functions = lttv_attribute_get_number(cpu_functions_tree);
927
928 for(nf=0; nf < nb_functions; nf++) {
929 type = lttv_attribute_get(cpu_functions_tree, nf, &name, &value,
930 &is_named);
931 function_tree = LTTV_ATTRIBUTE(*(value.v_gobject));
932 function_mode_types_tree = lttv_attribute_find_subdir(function_tree,
933 LTTV_STATS_MODE_TYPES);
934 nb_mode_type = lttv_attribute_get_number(function_mode_types_tree);
935 for(k = 0 ; k < nb_mode_type ; k++) {
936 type = lttv_attribute_get(function_mode_types_tree, k, &name, &value,
937 &is_named);
938 mode_tree = LTTV_ATTRIBUTE(*(value.v_gobject));
939
940 submodes_tree = lttv_attribute_find_subdir(mode_tree,
941 LTTV_STATS_SUBMODES);
942 mode_events_tree = lttv_attribute_find_subdir(mode_tree,
943 LTTV_STATS_EVENTS);
944 mode_types_tree = lttv_attribute_find_subdir(mode_tree,
945 LTTV_STATS_MODE_TYPES);
946
947 nb_submode = lttv_attribute_get_number(submodes_tree);
948
949 for(l = 0 ; l < nb_submode ; l++) {
950 type = lttv_attribute_get(submodes_tree, l, &name, &value,
951 &is_named);
952 submode_tree = LTTV_ATTRIBUTE(*(value.v_gobject));
953
954 event_types_tree = lttv_attribute_find_subdir(submode_tree,
955 LTTV_STATS_EVENT_TYPES);
956 nb_event_type = lttv_attribute_get_number(event_types_tree);
957
958 sum = 0;
959 for(m = 0 ; m < nb_event_type ; m++) {
960 type = lttv_attribute_get(event_types_tree, m, &name, &value,
961 &is_named);
962 sum += *(value.v_uint);
963 }
964 lttv_attribute_find(submode_tree, LTTV_STATS_EVENTS_COUNT,
965 LTTV_UINT, &value);
966 *(value.v_uint) = sum;
967
968 type = lttv_attribute_get(submodes_tree, l, &name, &value,
969 &is_named);
970 submode_tree = LTTV_ATTRIBUTE(*(value.v_gobject));
971 if(!trace_is_summed) {
972 lttv_attribute_recursive_add(mode_events_tree, event_types_tree);
973 lttv_attribute_recursive_add(mode_types_tree, submode_tree);
974 }
975 }
976 if(!trace_is_summed) {
977 lttv_attribute_recursive_add(function_tree, mode_types_tree);
978 }
979 }
980 if(!trace_is_summed) {
981 lttv_attribute_recursive_add(cpu_tree, function_tree);
982 lttv_attribute_recursive_add(process_tree, function_tree);
983 lttv_attribute_recursive_add(trace_cpu_tree, function_tree);
984 lttv_attribute_recursive_add(main_tree, function_tree);
985 }
986 lttv_attribute_recursive_add(ts_stats, function_tree);
987 }
b445142a 988 }
f95bc830 989 }
990}
991
992
d3e01c7a 993gboolean lttv_stats_sum_traceset_hook(void *hook_data, void *call_data)
994{
995 lttv_stats_sum_traceset((LttvTracesetStats *)call_data);
996 return 0;
997}
998
f95bc830 999void
1000lttv_stats_sum_traceset(LttvTracesetStats *self)
1001{
1002 LttvTraceset *traceset = self->parent.parent.ts;
d3e01c7a 1003 LttvAttribute *sum_container = self->stats;
f95bc830 1004
1005 LttvTraceStats *tcs;
1006
1007 int i, nb_trace;
1008
3813c77b 1009 LttvAttribute *main_tree;
f95bc830 1010
1011 LttvAttributeValue value;
1012
d3e01c7a 1013 lttv_attribute_find(sum_container, LTTV_STATS_SUMMED,
f95bc830 1014 LTTV_UINT, &value);
1015 if(*(value.v_uint) != 0) return;
1016 *(value.v_uint) = 1;
1017
f95bc830 1018 nb_trace = lttv_traceset_number(traceset);
1019
1020 for(i = 0 ; i < nb_trace ; i++) {
1021 tcs = (LttvTraceStats *)(self->parent.parent.traces[i]);
69374af5 1022 lttv_stats_sum_trace(tcs, self->stats);
d3670e3d 1023 // lttv_attribute_recursive_add(sum_container, tcs->stats);
b445142a 1024 }
b445142a 1025}
1026
1027
d3e01c7a 1028// Hook wrapper. call_data is a traceset context.
00e74b69 1029gboolean lttv_stats_hook_add_event_hooks(void *hook_data, void *call_data)
d3e01c7a 1030{
1031 LttvTracesetStats *tss = (LttvTracesetStats*)call_data;
1032
1033 lttv_stats_add_event_hooks(tss);
1034
1035 return 0;
1036}
1037
00e74b69 1038void lttv_stats_add_event_hooks(LttvTracesetStats *self)
b445142a 1039{
1040 LttvTraceset *traceset = self->parent.parent.ts;
1041
eed2ef37 1042 guint i, j, k, l, nb_trace, nb_tracefile;
b445142a 1043
b445142a 1044 LttvTraceStats *ts;
1045
1046 LttvTracefileStats *tfs;
1047
b445142a 1048 GArray *hooks, *before_hooks, *after_hooks;
1049
eed2ef37 1050 LttvTraceHook *hook;
1051
1052 LttvTraceHookByFacility *thf;
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,
f5d7967f 1071 LTT_FACILITY_KERNEL_ARCH, 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,
f5d7967f 1078 LTT_FACILITY_KERNEL_ARCH, 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,
eed2ef37 1085 LTT_FACILITY_KERNEL, LTT_EVENT_TRAP_ENTRY,
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,
eed2ef37 1092 LTT_FACILITY_KERNEL, LTT_EVENT_TRAP_EXIT,
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,
eed2ef37 1099 LTT_FACILITY_KERNEL, LTT_EVENT_IRQ_ENTRY,
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,
eed2ef37 1106 LTT_FACILITY_KERNEL, LTT_EVENT_IRQ_EXIT,
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,
1113 LTT_FACILITY_KERNEL, LTT_EVENT_SOFT_IRQ_ENTRY,
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,
1120 LTT_FACILITY_KERNEL, LTT_EVENT_SOFT_IRQ_EXIT,
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,
eed2ef37 1127 LTT_FACILITY_PROCESS, LTT_EVENT_SCHEDCHANGE,
1128 LTT_FIELD_OUT, LTT_FIELD_IN, LTT_FIELD_OUT_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,
1134 LTT_FACILITY_USER_GENERIC, LTT_EVENT_FUNCTION_ENTRY,
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,
1141 LTT_FACILITY_USER_GENERIC, LTT_EVENT_FUNCTION_EXIT,
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,
1149 LTT_FACILITY_STATEDUMP, LTT_EVENT_ENUM_PROCESS_STATE,
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,
f5d7967f 1164 LTT_FACILITY_KERNEL_ARCH, 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,
f5d7967f 1171 LTT_FACILITY_KERNEL_ARCH, 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,
eed2ef37 1178 LTT_FACILITY_KERNEL, LTT_EVENT_TRAP_ENTRY,
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,
eed2ef37 1185 LTT_FACILITY_KERNEL, LTT_EVENT_TRAP_EXIT,
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,
eed2ef37 1192 LTT_FACILITY_KERNEL, LTT_EVENT_IRQ_ENTRY,
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,
eed2ef37 1199 LTT_FACILITY_KERNEL, LTT_EVENT_IRQ_EXIT,
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,
1206 LTT_FACILITY_KERNEL, LTT_EVENT_SOFT_IRQ_ENTRY,
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,
1213 LTT_FACILITY_KERNEL, LTT_EVENT_SOFT_IRQ_EXIT,
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,
1220 LTT_FACILITY_PROCESS, LTT_EVENT_SCHEDCHANGE,
1221 LTT_FIELD_OUT, LTT_FIELD_IN, LTT_FIELD_OUT_STATE,
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,
eed2ef37 1227 LTT_FACILITY_PROCESS, LTT_EVENT_FORK,
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,
eed2ef37 1234 LTT_FACILITY_PROCESS, LTT_EVENT_EXIT,
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,
eed2ef37 1241 LTT_FACILITY_PROCESS, LTT_EVENT_FREE,
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,
1248 LTT_FACILITY_USER_GENERIC, LTT_EVENT_FUNCTION_ENTRY,
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,
1255 LTT_FACILITY_USER_GENERIC, LTT_EVENT_FUNCTION_EXIT,
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,
1263 LTT_FACILITY_STATEDUMP, LTT_EVENT_ENUM_PROCESS_STATE,
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,
1270 LTT_FACILITY_STATEDUMP, LTT_EVENT_STATEDUMP_END,
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++) {
eed2ef37 1291 hook = &g_array_index(before_hooks, LttvTraceHook, k);
1292 for(l = 0; l<hook->fac_list->len;l++) {
1293 thf = g_array_index(hook->fac_list, LttvTraceHookByFacility*, l);
1294 lttv_hooks_add(
1295 lttv_hooks_by_id_find(tfs->parent.parent.event_by_id, thf->id),
1296 thf->h,
d052ffc3 1297 thf,
eed2ef37 1298 LTTV_PRIO_STATS_BEFORE_STATE);
1299 }
b445142a 1300 }
1301 for(k = 0 ; k < after_hooks->len ; k++) {
eed2ef37 1302 hook = &g_array_index(after_hooks, LttvTraceHook, k);
1303 for(l = 0; l<hook->fac_list->len;l++) {
1304 thf = g_array_index(hook->fac_list, LttvTraceHookByFacility*, l);
1305 lttv_hooks_add(
1306 lttv_hooks_by_id_find(tfs->parent.parent.event_by_id, thf->id),
1307 thf->h,
d052ffc3 1308 thf,
eed2ef37 1309 LTTV_PRIO_STATS_AFTER_STATE);
1310 }
b445142a 1311 }
1312 }
1313 lttv_attribute_find(self->parent.parent.a, LTTV_STATS_BEFORE_HOOKS,
1314 LTTV_POINTER, &val);
1315 *(val.v_pointer) = before_hooks;
1316 lttv_attribute_find(self->parent.parent.a, LTTV_STATS_AFTER_HOOKS,
1317 LTTV_POINTER, &val);
1318 *(val.v_pointer) = after_hooks;
1319 }
b445142a 1320}
1321
d3e01c7a 1322// Hook wrapper. call_data is a traceset context.
00e74b69 1323gboolean lttv_stats_hook_remove_event_hooks(void *hook_data, void *call_data)
d3e01c7a 1324{
1325 LttvTracesetStats *tss = (LttvTracesetStats*)call_data;
1326
1327 lttv_stats_remove_event_hooks(tss);
1328
1329 return 0;
1330}
b445142a 1331
00e74b69 1332void lttv_stats_remove_event_hooks(LttvTracesetStats *self)
b445142a 1333{
1334 LttvTraceset *traceset = self->parent.parent.ts;
1335
eed2ef37 1336 guint i, j, k, l, nb_trace, nb_tracefile;
b445142a 1337
1338 LttvTraceStats *ts;
1339
1340 LttvTracefileStats *tfs;
1341
1342 void *hook_data;
1343
1344 GArray *before_hooks, *after_hooks;
1345
eed2ef37 1346 LttvTraceHook *hook;
1347
1348 LttvTraceHookByFacility *thf;
b445142a 1349
1350 LttvAttributeValue val;
1351
1352 nb_trace = lttv_traceset_number(traceset);
1353 for(i = 0 ; i < nb_trace ; i++) {
ae80b609 1354 ts = (LttvTraceStats*)self->parent.parent.traces[i];
b445142a 1355 lttv_attribute_find(self->parent.parent.a, LTTV_STATS_BEFORE_HOOKS,
1356 LTTV_POINTER, &val);
1357 before_hooks = *(val.v_pointer);
1358 lttv_attribute_find(self->parent.parent.a, LTTV_STATS_AFTER_HOOKS,
1359 LTTV_POINTER, &val);
1360 after_hooks = *(val.v_pointer);
1361
359b2948 1362 /* Remove these hooks from each event_by_id hooks list */
b445142a 1363
eed2ef37 1364 nb_tracefile = ts->parent.parent.tracefiles->len;
b445142a 1365
dbb7bb09 1366 for(j = 0 ; j < nb_tracefile ; j++) {
cb03932a 1367 tfs = LTTV_TRACEFILE_STATS(g_array_index(ts->parent.parent.tracefiles,
1368 LttvTracefileContext*, j));
359b2948 1369 lttv_hooks_remove_data(tfs->parent.parent.event, every_event,
b445142a 1370 NULL);
1371
1372 for(k = 0 ; k < before_hooks->len ; k++) {
eed2ef37 1373 hook = &g_array_index(before_hooks, LttvTraceHook, k);
1374 for(l = 0 ; l < hook->fac_list->len ; l++) {
1375 thf = g_array_index(hook->fac_list, LttvTraceHookByFacility*, l);
1376 lttv_hooks_remove_data(
1377 lttv_hooks_by_id_find(tfs->parent.parent.event_by_id, thf->id),
1378 thf->h,
d052ffc3 1379 thf);
eed2ef37 1380 }
b445142a 1381 }
1382 for(k = 0 ; k < after_hooks->len ; k++) {
eed2ef37 1383 hook = &g_array_index(after_hooks, LttvTraceHook, k);
1384 for(l = 0 ; l < hook->fac_list->len ; l++) {
1385 thf = g_array_index(hook->fac_list, LttvTraceHookByFacility*, l);
1386 lttv_hooks_remove_data(
1387 lttv_hooks_by_id_find(tfs->parent.parent.event_by_id, thf->id),
1388 thf->h,
d052ffc3 1389 thf);
eed2ef37 1390 }
b445142a 1391 }
1392 }
2a2fa4f0 1393 g_debug("lttv_stats_remove_event_hooks()");
b445142a 1394 g_array_free(before_hooks, TRUE);
1395 g_array_free(after_hooks, TRUE);
1396 }
9f797243 1397}
08b1c66e 1398
1399
1400static void module_init()
1401{
1402 LTTV_STATS_PROCESS_UNKNOWN = g_quark_from_string("unknown process");
1403 LTTV_STATS_PROCESSES = g_quark_from_string("processes");
1404 LTTV_STATS_CPU = g_quark_from_string("cpu");
1405 LTTV_STATS_MODE_TYPES = g_quark_from_string("mode_types");
1406 LTTV_STATS_MODES = g_quark_from_string("modes");
1407 LTTV_STATS_SUBMODES = g_quark_from_string("submodes");
14236daa 1408 LTTV_STATS_FUNCTIONS = g_quark_from_string("functions");
08b1c66e 1409 LTTV_STATS_EVENT_TYPES = g_quark_from_string("event_types");
1410 LTTV_STATS_CPU_TIME = g_quark_from_string("cpu time");
b49e54b4 1411 LTTV_STATS_CUMULATIVE_CPU_TIME = g_quark_from_string("cumulative cpu time (includes nested routines and modes)");
1412 LTTV_STATS_ELAPSED_TIME = g_quark_from_string("elapsed time (includes per process waiting time)");
08b1c66e 1413 LTTV_STATS_EVENTS = g_quark_from_string("events");
1414 LTTV_STATS_EVENTS_COUNT = g_quark_from_string("events count");
1415 LTTV_STATS_BEFORE_HOOKS = g_quark_from_string("saved stats before hooks");
1416 LTTV_STATS_AFTER_HOOKS = g_quark_from_string("saved stats after hooks");
f95bc830 1417 LTTV_STATS_USE_COUNT = g_quark_from_string("stats_use_count");
1418 LTTV_STATS = g_quark_from_string("statistics");
1419 LTTV_STATS_TRACEFILES = g_quark_from_string("tracefiles statistics");
1420 LTTV_STATS_SUMMED = g_quark_from_string("statistics summed");
08b1c66e 1421}
1422
1423static void module_destroy()
1424{
1425}
1426
1427
1428LTTV_MODULE("stats", "Compute processes statistics", \
1429 "Accumulate statistics for event types, processes and CPUs", \
1430 module_init, module_destroy, "state");
f95bc830 1431
1432/* Change the places where stats are called (create/read/write stats)
1433
1434 Check for options in batchtest.c to reduce writing and see what tests are
1435 best candidates for performance analysis. Once OK, commit, move to main
1436 and run tests. Update the gui for statistics. */
This page took 0.107863 seconds and 4 git commands to generate.