pid 0 fix
[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,
302efbad 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,
14236daa 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));
c0cb4d12 124 guint cpu = tfcs->parent.cpu;
b445142a 125 find_event_tree(tfcs, LTTV_STATS_PROCESS_UNKNOWN,
c0cb4d12 126 cpu,
14236daa 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,
14236daa 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;
14236daa 408 gchar fstring[MAX_64_HEX_STRING_LEN];
b49e54b4 409 gint ret;
14236daa 410
b49e54b4 411 ret = snprintf(fstring, MAX_64_HEX_STRING_LEN-1,
412 "0x%llX", function) > 0;
413 g_assert(ret > 0);
14236daa 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
433static void update_event_tree(LttvTracefileStats *tfcs)
434{
348c6ba8 435 LttvTraceState *ts = (LttvTraceState *)tfcs->parent.parent.t_context;
ae3d0f50 436 guint cpu = tfcs->parent.cpu;
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,
14236daa 442 process->current_function,
b445142a 443 es->t, es->n, &(tfcs->current_events_tree),
444 &(tfcs->current_event_types_tree));
445}
446
447
448static void mode_change(LttvTracefileStats *tfcs)
449{
348c6ba8 450 LttvTraceState *ts = (LttvTraceState *)tfcs->parent.parent.t_context;
ae3d0f50 451 guint cpu = tfcs->parent.cpu;
348c6ba8 452 LttvProcessState *process = ts->running_process[cpu];
b49e54b4 453 LttvAttributeValue cpu_time, cum_cpu_time;
b445142a 454
455 LttTime delta;
456
308711e5 457 delta = ltt_time_sub(tfcs->parent.parent.timestamp,
348c6ba8 458 process->state->change);
b49e54b4 459
460 lttv_attribute_find(tfcs->current_events_tree, LTTV_STATS_CPU_TIME,
461 LTTV_TIME, &cpu_time);
308711e5 462 *(cpu_time.v_time) = ltt_time_add(*(cpu_time.v_time), delta);
b445142a 463
b49e54b4 464 process->state->cum_cpu_time = ltt_time_add(process->state->cum_cpu_time,
465 delta);
466}
b445142a 467
b49e54b4 468/* Note : every mode_end must come with a cumulative cpu time update in the
469 * after hook */
b445142a 470static void mode_end(LttvTracefileStats *tfcs)
471{
348c6ba8 472 LttvTraceState *ts = (LttvTraceState *)tfcs->parent.parent.t_context;
ae3d0f50 473 guint cpu = tfcs->parent.cpu;
348c6ba8 474 LttvProcessState *process = ts->running_process[cpu];
b49e54b4 475 LttvAttributeValue elapsed_time, cpu_time, cum_cpu_time;
b445142a 476
477 LttTime delta;
478
479 lttv_attribute_find(tfcs->current_events_tree, LTTV_STATS_ELAPSED_TIME,
480 LTTV_TIME, &elapsed_time);
308711e5 481 delta = ltt_time_sub(tfcs->parent.parent.timestamp,
348c6ba8 482 process->state->entry);
308711e5 483 *(elapsed_time.v_time) = ltt_time_add(*(elapsed_time.v_time), delta);
b445142a 484
485 lttv_attribute_find(tfcs->current_events_tree, LTTV_STATS_CPU_TIME,
486 LTTV_TIME, &cpu_time);
308711e5 487 delta = ltt_time_sub(tfcs->parent.parent.timestamp,
348c6ba8 488 process->state->change);
308711e5 489 *(cpu_time.v_time) = ltt_time_add(*(cpu_time.v_time), delta);
b49e54b4 490 process->state->cum_cpu_time = ltt_time_add(process->state->cum_cpu_time,
491 delta);
492
493 lttv_attribute_find(tfcs->current_events_tree, LTTV_STATS_CUMULATIVE_CPU_TIME,
494 LTTV_TIME, &cum_cpu_time);
495 *(cum_cpu_time.v_time) = ltt_time_add(*(cum_cpu_time.v_time),
496 process->state->cum_cpu_time);
b445142a 497}
498
499
b49e54b4 500static void after_mode_end(LttvTracefileStats *tfcs)
501{
502 LttvTraceState *ts = (LttvTraceState *)tfcs->parent.parent.t_context;
503 guint cpu = tfcs->parent.cpu;
504 LttvProcessState *process = ts->running_process[cpu];
505 LttvAttributeValue cum_cpu_time;
506
507 LttTime nested_delta;
508
509 nested_delta = process->state->cum_cpu_time;
510 process->state->cum_cpu_time = ltt_time_zero; /* For after traceset hook */
511
512 update_event_tree(tfcs);
513
514 process->state->cum_cpu_time = ltt_time_add(process->state->cum_cpu_time,
515 nested_delta);
516}
517
b445142a 518static gboolean before_syscall_entry(void *hook_data, void *call_data)
519{
520 mode_change((LttvTracefileStats *)call_data);
521 return FALSE;
522}
523
524
525static gboolean after_syscall_entry(void *hook_data, void *call_data)
526{
527 update_event_tree((LttvTracefileStats *)call_data);
528 return FALSE;
529}
530
531
532gboolean before_syscall_exit(void *hook_data, void *call_data)
533{
534 mode_end((LttvTracefileStats *)call_data);
535 return FALSE;
536}
537
538
539static gboolean after_syscall_exit(void *hook_data, void *call_data)
540{
b49e54b4 541 after_mode_end((LttvTracefileStats *)call_data);
b445142a 542 return FALSE;
543}
544
545
546gboolean before_trap_entry(void *hook_data, void *call_data)
547{
548 mode_change((LttvTracefileStats *)call_data);
549 return FALSE;
550}
551
552
553static gboolean after_trap_entry(void *hook_data, void *call_data)
554{
555 update_event_tree((LttvTracefileStats *)call_data);
556 return FALSE;
557}
558
559
560gboolean before_trap_exit(void *hook_data, void *call_data)
561{
562 mode_end((LttvTracefileStats *)call_data);
563 return FALSE;
564}
565
566
567gboolean after_trap_exit(void *hook_data, void *call_data)
568{
b49e54b4 569 after_mode_end((LttvTracefileStats *)call_data);
b445142a 570 return FALSE;
571}
572
573
574gboolean before_irq_entry(void *hook_data, void *call_data)
575{
576 mode_change((LttvTracefileStats *)call_data);
577 return FALSE;
578}
579
b445142a 580gboolean after_irq_entry(void *hook_data, void *call_data)
581{
582 update_event_tree((LttvTracefileStats *)call_data);
583 return FALSE;
584}
585
586
587gboolean before_irq_exit(void *hook_data, void *call_data)
588{
589 mode_end((LttvTracefileStats *)call_data);
590 return FALSE;
591}
592
593
594gboolean after_irq_exit(void *hook_data, void *call_data)
595{
b49e54b4 596 after_mode_end((LttvTracefileStats *)call_data);
b445142a 597 return FALSE;
598}
599
600
faf074a3 601gboolean before_soft_irq_entry(void *hook_data, void *call_data)
602{
603 mode_change((LttvTracefileStats *)call_data);
604 return FALSE;
605}
606
607gboolean after_soft_irq_entry(void *hook_data, void *call_data)
608{
609 update_event_tree((LttvTracefileStats *)call_data);
610 return FALSE;
611}
612
613
614gboolean before_soft_irq_exit(void *hook_data, void *call_data)
615{
616 mode_end((LttvTracefileStats *)call_data);
617 return FALSE;
618}
619
620
621gboolean after_soft_irq_exit(void *hook_data, void *call_data)
622{
b49e54b4 623 after_mode_end((LttvTracefileStats *)call_data);
faf074a3 624 return FALSE;
625}
626
14236daa 627gboolean before_function_entry(void *hook_data, void *call_data)
628{
b49e54b4 629 mode_change((LttvTracefileStats *)call_data);
14236daa 630 return FALSE;
631}
632
633gboolean after_function_entry(void *hook_data, void *call_data)
634{
635 update_event_tree((LttvTracefileStats *)call_data);
636 return FALSE;
637}
638
639gboolean before_function_exit(void *hook_data, void *call_data)
640{
641 mode_end((LttvTracefileStats *)call_data);
642 return FALSE;
643}
644
645gboolean after_function_exit(void *hook_data, void *call_data)
646{
b49e54b4 647 after_mode_end((LttvTracefileStats *)call_data);
14236daa 648 return FALSE;
649}
650
faf074a3 651
b445142a 652gboolean before_schedchange(void *hook_data, void *call_data)
653{
b445142a 654 LttvTracefileStats *tfcs = (LttvTracefileStats *)call_data;
655
348c6ba8 656 LttvTraceState *ts = (LttvTraceState*)tfcs->parent.parent.t_context;
657
eed2ef37 658 LttEvent *e = ltt_tracefile_get_event(tfcs->parent.parent.tf);
659
d052ffc3 660 LttvTraceHookByFacility *thf = (LttvTraceHookByFacility *)hook_data;
eed2ef37 661
d7cf605c 662 guint pid_in, pid_out;
663
664 gint state_out;
b445142a 665
eed2ef37 666 pid_out = ltt_event_get_unsigned(e, thf->f1);
667 pid_in = ltt_event_get_unsigned(e, thf->f2);
d7cf605c 668 state_out = ltt_event_get_int(e, thf->f3);
b445142a 669
670 /* compute the time for the process to schedule out */
671
672 mode_change(tfcs);
673
b49e54b4 674 return FALSE;
675}
b445142a 676
b49e54b4 677gboolean after_schedchange(void *hook_data, void *call_data)
678{
679 LttvTracefileStats *tfcs = (LttvTracefileStats *)call_data;
680
681 LttvTraceState *ts = (LttvTraceState*)tfcs->parent.parent.t_context;
b445142a 682
b49e54b4 683 LttEvent *e = ltt_tracefile_get_event(tfcs->parent.parent.tf);
684
685 LttvTraceHookByFacility *thf = (LttvTraceHookByFacility *)hook_data;
686
687 guint pid_in, pid_out;
688
689 gint state_out;
690
691 LttvProcessState *process;
692
693 pid_out = ltt_event_get_unsigned(e, thf->f1);
694 pid_in = ltt_event_get_unsigned(e, thf->f2);
695 state_out = ltt_event_get_int(e, thf->f3);
696
697 /* get the information for the process scheduled in */
c0cb4d12 698 guint cpu = tfcs->parent.cpu;
b49e54b4 699 process = ts->running_process[cpu];
c0cb4d12 700
348c6ba8 701 find_event_tree(tfcs, process->pid_time,
c0cb4d12 702 cpu,
14236daa 703 process->current_function,
b445142a 704 process->state->t, process->state->n, &(tfcs->current_events_tree),
705 &(tfcs->current_event_types_tree));
706
707 /* compute the time waiting for the process to schedule in */
b445142a 708 mode_change(tfcs);
b445142a 709
b49e54b4 710 return FALSE;
711}
b445142a 712
713gboolean process_fork(void *hook_data, void *call_data)
714{
715 /* nothing to do for now */
716 return FALSE;
717}
718
719
720gboolean process_exit(void *hook_data, void *call_data)
721{
722 /* We should probably exit all modes here or we could do that at
723 schedule out. */
724 return FALSE;
725}
726
954417fa 727gboolean before_enum_process_state(void *hook_data, void *call_data)
728{
729 mode_end((LttvTracefileStats *)call_data);
730 after_mode_end((LttvTracefileStats *)call_data);
731 mode_change((LttvTracefileStats *)call_data);
732 return FALSE;
733}
734
735gboolean after_enum_process_state(void *hook_data, void *call_data)
736{
737 update_event_tree((LttvTracefileStats *)call_data);
738 return FALSE;
739}
740
eed2ef37 741gboolean process_free(void *hook_data, void *call_data)
742{
743 return FALSE;
744}
b445142a 745
746gboolean every_event(void *hook_data, void *call_data)
747{
748 LttvTracefileStats *tfcs = (LttvTracefileStats *)call_data;
749
eed2ef37 750 LttEvent *e = ltt_tracefile_get_event(tfcs->parent.parent.tf);
751
b445142a 752 LttvAttributeValue v;
753
754 /* The current branch corresponds to the tracefile/process/interrupt state.
755 Statistics are added within it, to count the number of events of this
756 type occuring in this context. A quark has been pre-allocated for each
757 event type and is used as name. */
758
759 lttv_attribute_find(tfcs->current_event_types_tree,
eed2ef37 760 ltt_eventtype_name(ltt_event_eventtype(e)),
b445142a 761 LTTV_UINT, &v);
762 (*(v.v_uint))++;
763 return FALSE;
764}
765
b49e54b4 766static void lttv_stats_cleanup_process_state(gpointer key, gpointer value,
c4a72569 767 gpointer user_data)
768{
769 LttvTraceStats *tcs = (LttvTraceStats *)user_data;
770 LttvTraceState *ts = (LttvTraceState *)user_data;
771 LttvTracesetContext *tsc = ts->parent.ts_context;
772 LttvProcessState *process = (LttvProcessState *)value;
773 int i;
774 LttvTracefileStats **tfs = (LttvTracefileStats **)
775 &g_array_index(ts->parent.tracefiles, LttvTracefileContext*,
776 process->cpu);
777 int cleanup_empty = 0;
778 LttTime nested_delta = ltt_time_zero;
779 /* FIXME : ok, this is a hack. The time is infinite here :( */
780 LttTime save_time = (*tfs)->parent.parent.timestamp;
781 LttTime start, end;
782 ltt_trace_time_span_get(ts->parent.t, &start, &end);
783 (*tfs)->parent.parent.timestamp = end;
784
785 do {
786 if(ltt_time_compare(process->state->cum_cpu_time, ltt_time_zero) != 0) {
787 find_event_tree(*tfs, process->pid_time,
788 process->cpu,
789 process->current_function,
790 process->state->t, process->state->n, &((*tfs)->current_events_tree),
791 &((*tfs)->current_event_types_tree));
792 /* if it is a running mode, we must count its cpu time */
793 if(process->state->s == LTTV_STATE_RUN)
794 mode_end(*tfs);
795 nested_delta = process->state->cum_cpu_time;
796 }
797 cleanup_empty = lttv_state_pop_state_cleanup(process,
798 (LttvTracefileState *)*tfs);
799 process->state->cum_cpu_time = ltt_time_add(process->state->cum_cpu_time,
800 nested_delta);
801
802 } while(cleanup_empty != 1);
803
804 (*tfs)->parent.parent.timestamp = save_time;
b49e54b4 805}
806
807/* For each process in the state, for each of their stacked states,
808 * perform sum of needed values. */
809static void lttv_stats_cleanup_state(LttvTraceStats *tcs)
810{
811 LttvTraceState *ts = (LttvTraceState *)tcs;
c4a72569 812
813 /* Does not work correctly FIXME. */
814 g_hash_table_foreach(ts->processes, lttv_stats_cleanup_process_state,
815 tcs);
b49e54b4 816}
b445142a 817
f95bc830 818void
69374af5 819lttv_stats_sum_trace(LttvTraceStats *self, LttvAttribute *ts_stats)
b445142a 820{
d3e01c7a 821 LttvAttribute *sum_container = self->stats;
b445142a 822
b445142a 823 LttvAttributeType type;
824
825 LttvAttributeValue value;
826
827 LttvAttributeName name;
828
c0cb4d12 829 gboolean is_named;
830
b445142a 831 unsigned sum;
832
69374af5 833 int trace_is_summed;
834
f95bc830 835 int i, j, k, l, m, nb_process, nb_cpu, nb_mode_type, nb_submode,
3813c77b 836 nb_event_type, nf, nb_functions;
b445142a 837
838 LttvAttribute *main_tree, *processes_tree, *process_tree, *cpus_tree,
839 *cpu_tree, *mode_tree, *mode_types_tree, *submodes_tree,
840 *submode_tree, *event_types_tree, *mode_events_tree,
3813c77b 841 *cpu_functions_tree,
842 *function_tree,
843 *function_mode_types_tree,
844 *trace_cpu_tree;
f95bc830 845
b49e54b4 846
d3e01c7a 847 main_tree = sum_container;
f95bc830 848
d3e01c7a 849 lttv_attribute_find(sum_container,
850 LTTV_STATS_SUMMED,
851 LTTV_UINT, &value);
69374af5 852 trace_is_summed = *(value.v_uint);
f95bc830 853 *(value.v_uint) = 1;
854
b49e54b4 855 /* First cleanup the state : sum all stalled information (never ending
856 * states). */
857 if(!trace_is_summed)
858 lttv_stats_cleanup_state(self);
859
f95bc830 860 processes_tree = lttv_attribute_find_subdir(main_tree,
d3e01c7a 861 LTTV_STATS_PROCESSES);
f95bc830 862 nb_process = lttv_attribute_get_number(processes_tree);
863
864 for(i = 0 ; i < nb_process ; i++) {
c0cb4d12 865 type = lttv_attribute_get(processes_tree, i, &name, &value, &is_named);
f95bc830 866 process_tree = LTTV_ATTRIBUTE(*(value.v_gobject));
867
868 cpus_tree = lttv_attribute_find_subdir(process_tree, LTTV_STATS_CPU);
f95bc830 869 nb_cpu = lttv_attribute_get_number(cpus_tree);
870
871 for(j = 0 ; j < nb_cpu ; j++) {
c0cb4d12 872 type = lttv_attribute_get(cpus_tree, j, &name, &value, &is_named);
f95bc830 873 cpu_tree = LTTV_ATTRIBUTE(*(value.v_gobject));
874
f95bc830 875 trace_cpu_tree = lttv_attribute_find_subdir(main_tree, LTTV_STATS_CPU);
c0cb4d12 876 trace_cpu_tree = lttv_attribute_find_subdir_unnamed(trace_cpu_tree, name);
3813c77b 877 cpu_functions_tree = lttv_attribute_find_subdir(cpu_tree,
878 LTTV_STATS_FUNCTIONS);
879 nb_functions = lttv_attribute_get_number(cpu_functions_tree);
880
881 for(nf=0; nf < nb_functions; nf++) {
c0cb4d12 882 type = lttv_attribute_get(cpu_functions_tree, nf, &name, &value,
883 &is_named);
3813c77b 884 function_tree = LTTV_ATTRIBUTE(*(value.v_gobject));
885 function_mode_types_tree = lttv_attribute_find_subdir(function_tree,
886 LTTV_STATS_MODE_TYPES);
887 nb_mode_type = lttv_attribute_get_number(function_mode_types_tree);
888 for(k = 0 ; k < nb_mode_type ; k++) {
c0cb4d12 889 type = lttv_attribute_get(function_mode_types_tree, k, &name, &value,
890 &is_named);
3813c77b 891 mode_tree = LTTV_ATTRIBUTE(*(value.v_gobject));
892
893 submodes_tree = lttv_attribute_find_subdir(mode_tree,
894 LTTV_STATS_SUBMODES);
895 mode_events_tree = lttv_attribute_find_subdir(mode_tree,
896 LTTV_STATS_EVENTS);
897 mode_types_tree = lttv_attribute_find_subdir(mode_tree,
898 LTTV_STATS_MODE_TYPES);
899
900 nb_submode = lttv_attribute_get_number(submodes_tree);
901
902 for(l = 0 ; l < nb_submode ; l++) {
c0cb4d12 903 type = lttv_attribute_get(submodes_tree, l, &name, &value,
904 &is_named);
3813c77b 905 submode_tree = LTTV_ATTRIBUTE(*(value.v_gobject));
906
907 event_types_tree = lttv_attribute_find_subdir(submode_tree,
908 LTTV_STATS_EVENT_TYPES);
909 nb_event_type = lttv_attribute_get_number(event_types_tree);
910
911 sum = 0;
912 for(m = 0 ; m < nb_event_type ; m++) {
c0cb4d12 913 type = lttv_attribute_get(event_types_tree, m, &name, &value,
914 &is_named);
3813c77b 915 sum += *(value.v_uint);
916 }
917 lttv_attribute_find(submode_tree, LTTV_STATS_EVENTS_COUNT,
918 LTTV_UINT, &value);
919 *(value.v_uint) = sum;
920
c0cb4d12 921 type = lttv_attribute_get(submodes_tree, l, &name, &value,
922 &is_named);
3813c77b 923 submode_tree = LTTV_ATTRIBUTE(*(value.v_gobject));
69374af5 924 if(!trace_is_summed) {
925 lttv_attribute_recursive_add(mode_events_tree, event_types_tree);
926 lttv_attribute_recursive_add(mode_types_tree, submode_tree);
927 }
3813c77b 928 }
69374af5 929 if(!trace_is_summed) {
e3523819 930 lttv_attribute_recursive_add(function_tree, mode_types_tree);
69374af5 931 }
3813c77b 932 }
65c2c8a0 933 if(!trace_is_summed) {
e3523819 934 lttv_attribute_recursive_add(cpu_tree, function_tree);
935 lttv_attribute_recursive_add(process_tree, function_tree);
936 lttv_attribute_recursive_add(trace_cpu_tree, function_tree);
937 lttv_attribute_recursive_add(main_tree, function_tree);
65c2c8a0 938 }
e3523819 939 lttv_attribute_recursive_add(ts_stats, function_tree);
69374af5 940 }
b445142a 941 }
f95bc830 942 }
943}
944
945
d3e01c7a 946gboolean lttv_stats_sum_traceset_hook(void *hook_data, void *call_data)
947{
948 lttv_stats_sum_traceset((LttvTracesetStats *)call_data);
949 return 0;
950}
951
f95bc830 952void
953lttv_stats_sum_traceset(LttvTracesetStats *self)
954{
955 LttvTraceset *traceset = self->parent.parent.ts;
d3e01c7a 956 LttvAttribute *sum_container = self->stats;
f95bc830 957
958 LttvTraceStats *tcs;
959
960 int i, nb_trace;
961
3813c77b 962 LttvAttribute *main_tree;
f95bc830 963
964 LttvAttributeValue value;
965
d3e01c7a 966 lttv_attribute_find(sum_container, LTTV_STATS_SUMMED,
f95bc830 967 LTTV_UINT, &value);
968 if(*(value.v_uint) != 0) return;
969 *(value.v_uint) = 1;
970
f95bc830 971 nb_trace = lttv_traceset_number(traceset);
972
973 for(i = 0 ; i < nb_trace ; i++) {
974 tcs = (LttvTraceStats *)(self->parent.parent.traces[i]);
69374af5 975 lttv_stats_sum_trace(tcs, self->stats);
976 // lttv_attribute_recursive_add(sum_container, tcs->stats);
b445142a 977 }
b445142a 978}
979
980
d3e01c7a 981// Hook wrapper. call_data is a traceset context.
00e74b69 982gboolean lttv_stats_hook_add_event_hooks(void *hook_data, void *call_data)
d3e01c7a 983{
984 LttvTracesetStats *tss = (LttvTracesetStats*)call_data;
985
986 lttv_stats_add_event_hooks(tss);
987
988 return 0;
989}
990
00e74b69 991void lttv_stats_add_event_hooks(LttvTracesetStats *self)
b445142a 992{
993 LttvTraceset *traceset = self->parent.parent.ts;
994
eed2ef37 995 guint i, j, k, l, nb_trace, nb_tracefile;
b445142a 996
b445142a 997 LttvTraceStats *ts;
998
999 LttvTracefileStats *tfs;
1000
b445142a 1001 GArray *hooks, *before_hooks, *after_hooks;
1002
eed2ef37 1003 LttvTraceHook *hook;
1004
1005 LttvTraceHookByFacility *thf;
b445142a 1006
1007 LttvAttributeValue val;
1008
9d239bd9 1009 gint ret;
2501204d 1010 gint hn;
9d239bd9 1011
b445142a 1012 nb_trace = lttv_traceset_number(traceset);
1013 for(i = 0 ; i < nb_trace ; i++) {
1014 ts = (LttvTraceStats *)self->parent.parent.traces[i];
1015
1016 /* Find the eventtype id for the following events and register the
1017 associated by id hooks. */
1018
954417fa 1019 hooks = g_array_sized_new(FALSE, FALSE, sizeof(LttvTraceHook), 12);
1020 g_array_set_size(hooks, 12);
1021 hn=0;
b445142a 1022
9d239bd9 1023 ret = lttv_trace_find_hook(ts->parent.parent.t,
f5d7967f 1024 LTT_FACILITY_KERNEL_ARCH, LTT_EVENT_SYSCALL_ENTRY,
eed2ef37 1025 LTT_FIELD_SYSCALL_ID, 0, 0,
2c82c4dc 1026 before_syscall_entry, NULL,
2501204d 1027 &g_array_index(hooks, LttvTraceHook, hn++));
1028 if(ret) hn--;
b445142a 1029
9d239bd9 1030 ret = lttv_trace_find_hook(ts->parent.parent.t,
f5d7967f 1031 LTT_FACILITY_KERNEL_ARCH, LTT_EVENT_SYSCALL_EXIT,
eed2ef37 1032 0, 0, 0,
2c82c4dc 1033 before_syscall_exit, NULL,
2501204d 1034 &g_array_index(hooks, LttvTraceHook, hn++));
1035 if(ret) hn--;
b445142a 1036
9d239bd9 1037 ret = lttv_trace_find_hook(ts->parent.parent.t,
eed2ef37 1038 LTT_FACILITY_KERNEL, LTT_EVENT_TRAP_ENTRY,
1039 LTT_FIELD_TRAP_ID, 0, 0,
2c82c4dc 1040 before_trap_entry, NULL,
2501204d 1041 &g_array_index(hooks, LttvTraceHook, hn++));
1042 if(ret) hn--;
b445142a 1043
9d239bd9 1044 ret = lttv_trace_find_hook(ts->parent.parent.t,
eed2ef37 1045 LTT_FACILITY_KERNEL, LTT_EVENT_TRAP_EXIT,
1046 0, 0, 0,
2c82c4dc 1047 before_trap_exit, NULL,
2501204d 1048 &g_array_index(hooks, LttvTraceHook, hn++));
1049 if(ret) hn--;
eed2ef37 1050
9d239bd9 1051 ret = lttv_trace_find_hook(ts->parent.parent.t,
eed2ef37 1052 LTT_FACILITY_KERNEL, LTT_EVENT_IRQ_ENTRY,
1053 LTT_FIELD_IRQ_ID, 0, 0,
2c82c4dc 1054 before_irq_entry, NULL,
2501204d 1055 &g_array_index(hooks, LttvTraceHook, hn++));
1056 if(ret) hn--;
eed2ef37 1057
9d239bd9 1058 ret = lttv_trace_find_hook(ts->parent.parent.t,
eed2ef37 1059 LTT_FACILITY_KERNEL, LTT_EVENT_IRQ_EXIT,
1060 0, 0, 0,
2c82c4dc 1061 before_irq_exit, NULL,
2501204d 1062 &g_array_index(hooks, LttvTraceHook, hn++));
1063 if(ret) hn--;
eed2ef37 1064
faf074a3 1065 ret = lttv_trace_find_hook(ts->parent.parent.t,
1066 LTT_FACILITY_KERNEL, LTT_EVENT_SOFT_IRQ_ENTRY,
1067 LTT_FIELD_SOFT_IRQ_ID, 0, 0,
1068 before_soft_irq_entry, NULL,
2501204d 1069 &g_array_index(hooks, LttvTraceHook, hn++));
1070 if(ret) hn--;
faf074a3 1071
1072 ret = lttv_trace_find_hook(ts->parent.parent.t,
1073 LTT_FACILITY_KERNEL, LTT_EVENT_SOFT_IRQ_EXIT,
1074 0, 0, 0,
1075 before_soft_irq_exit, NULL,
2501204d 1076 &g_array_index(hooks, LttvTraceHook, hn++));
1077 if(ret) hn--;
faf074a3 1078
9d239bd9 1079 ret = lttv_trace_find_hook(ts->parent.parent.t,
eed2ef37 1080 LTT_FACILITY_PROCESS, LTT_EVENT_SCHEDCHANGE,
1081 LTT_FIELD_OUT, LTT_FIELD_IN, LTT_FIELD_OUT_STATE,
2c82c4dc 1082 before_schedchange, NULL,
2501204d 1083 &g_array_index(hooks, LttvTraceHook, hn++));
1084 if(ret) hn--;
14236daa 1085
1086 ret = lttv_trace_find_hook(ts->parent.parent.t,
1087 LTT_FACILITY_USER_GENERIC, LTT_EVENT_FUNCTION_ENTRY,
1088 LTT_FIELD_THIS_FN, LTT_FIELD_CALL_SITE, 0,
1089 before_function_entry, NULL,
1090 &g_array_index(hooks, LttvTraceHook, hn++));
1091 if(ret) hn--;
1092
1093 ret = lttv_trace_find_hook(ts->parent.parent.t,
1094 LTT_FACILITY_USER_GENERIC, LTT_EVENT_FUNCTION_EXIT,
1095 LTT_FIELD_THIS_FN, LTT_FIELD_CALL_SITE, 0,
1096 before_function_exit, NULL,
1097 &g_array_index(hooks, LttvTraceHook, hn++));
1098 if(ret) hn--;
954417fa 1099
1100 /* statedump-related hooks */
1101 ret = lttv_trace_find_hook(ts->parent.parent.t,
1102 LTT_FACILITY_STATEDUMP, LTT_EVENT_ENUM_PROCESS_STATE,
1103 LTT_FIELD_PID, LTT_FIELD_PARENT_PID, LTT_FIELD_NAME,
1104 before_enum_process_state, NULL,
1105 &g_array_index(hooks, LttvTraceHook, hn++));
1106 if(ret) hn--;
1107
2501204d 1108 g_array_set_size(hooks, hn);
b445142a 1109
1110 before_hooks = hooks;
1111
954417fa 1112 hooks = g_array_sized_new(FALSE, FALSE, sizeof(LttvTraceHook), 15);
1113 g_array_set_size(hooks, 15);
1114 hn=0;
b445142a 1115
9d239bd9 1116 ret = lttv_trace_find_hook(ts->parent.parent.t,
f5d7967f 1117 LTT_FACILITY_KERNEL_ARCH, LTT_EVENT_SYSCALL_ENTRY,
eed2ef37 1118 LTT_FIELD_SYSCALL_ID, 0, 0,
2c82c4dc 1119 after_syscall_entry, NULL,
2501204d 1120 &g_array_index(hooks, LttvTraceHook, hn++));
1121 if(ret) hn--;
b445142a 1122
9d239bd9 1123 ret = lttv_trace_find_hook(ts->parent.parent.t,
f5d7967f 1124 LTT_FACILITY_KERNEL_ARCH, LTT_EVENT_SYSCALL_EXIT,
eed2ef37 1125 0, 0, 0,
2c82c4dc 1126 after_syscall_exit, NULL,
2501204d 1127 &g_array_index(hooks, LttvTraceHook, hn++));
1128 if(ret) hn--;
b445142a 1129
9d239bd9 1130 ret = lttv_trace_find_hook(ts->parent.parent.t,
eed2ef37 1131 LTT_FACILITY_KERNEL, LTT_EVENT_TRAP_ENTRY,
1132 LTT_FIELD_TRAP_ID, 0, 0,
2c82c4dc 1133 after_trap_entry, NULL,
2501204d 1134 &g_array_index(hooks, LttvTraceHook, hn++));
1135 if(ret) hn--;
eed2ef37 1136
9d239bd9 1137 ret = lttv_trace_find_hook(ts->parent.parent.t,
eed2ef37 1138 LTT_FACILITY_KERNEL, LTT_EVENT_TRAP_EXIT,
1139 0, 0, 0,
2c82c4dc 1140 after_trap_exit, NULL,
2501204d 1141 &g_array_index(hooks, LttvTraceHook, hn++));
1142 if(ret) hn--;
b445142a 1143
9d239bd9 1144 ret = lttv_trace_find_hook(ts->parent.parent.t,
eed2ef37 1145 LTT_FACILITY_KERNEL, LTT_EVENT_IRQ_ENTRY,
1146 LTT_FIELD_IRQ_ID, 0, 0,
2c82c4dc 1147 after_irq_entry, NULL,
2501204d 1148 &g_array_index(hooks, LttvTraceHook, hn++));
1149 if(ret) hn--;
b445142a 1150
9d239bd9 1151 ret = lttv_trace_find_hook(ts->parent.parent.t,
eed2ef37 1152 LTT_FACILITY_KERNEL, LTT_EVENT_IRQ_EXIT,
1153 0, 0, 0,
2c82c4dc 1154 after_irq_exit, NULL,
2501204d 1155 &g_array_index(hooks, LttvTraceHook, hn++));
1156 if(ret) hn--;
b445142a 1157
faf074a3 1158 ret = lttv_trace_find_hook(ts->parent.parent.t,
1159 LTT_FACILITY_KERNEL, LTT_EVENT_SOFT_IRQ_ENTRY,
1160 LTT_FIELD_SOFT_IRQ_ID, 0, 0,
1161 after_irq_entry, NULL,
2501204d 1162 &g_array_index(hooks, LttvTraceHook, hn++));
1163 if(ret) hn--;
faf074a3 1164
1165 ret = lttv_trace_find_hook(ts->parent.parent.t,
1166 LTT_FACILITY_KERNEL, LTT_EVENT_SOFT_IRQ_EXIT,
1167 0, 0, 0,
1168 after_soft_irq_exit, NULL,
2501204d 1169 &g_array_index(hooks, LttvTraceHook, hn++));
1170 if(ret) hn--;
b445142a 1171
b49e54b4 1172 ret = lttv_trace_find_hook(ts->parent.parent.t,
1173 LTT_FACILITY_PROCESS, LTT_EVENT_SCHEDCHANGE,
1174 LTT_FIELD_OUT, LTT_FIELD_IN, LTT_FIELD_OUT_STATE,
1175 after_schedchange, NULL,
1176 &g_array_index(hooks, LttvTraceHook, hn++));
1177 if(ret) hn--;
1178
9d239bd9 1179 ret = lttv_trace_find_hook(ts->parent.parent.t,
eed2ef37 1180 LTT_FACILITY_PROCESS, LTT_EVENT_FORK,
1181 LTT_FIELD_PARENT_PID, LTT_FIELD_CHILD_PID, 0,
2c82c4dc 1182 process_fork, NULL,
2501204d 1183 &g_array_index(hooks, LttvTraceHook, hn++));
1184 if(ret) hn--;
b445142a 1185
9d239bd9 1186 ret = lttv_trace_find_hook(ts->parent.parent.t,
eed2ef37 1187 LTT_FACILITY_PROCESS, LTT_EVENT_EXIT,
1188 LTT_FIELD_PID, 0, 0,
2c82c4dc 1189 process_exit, NULL,
2501204d 1190 &g_array_index(hooks, LttvTraceHook, hn++));
1191 if(ret) hn--;
eed2ef37 1192
9d239bd9 1193 ret = lttv_trace_find_hook(ts->parent.parent.t,
eed2ef37 1194 LTT_FACILITY_PROCESS, LTT_EVENT_FREE,
1195 LTT_FIELD_PID, 0, 0,
2c82c4dc 1196 process_free, NULL,
2501204d 1197 &g_array_index(hooks, LttvTraceHook, hn++));
1198 if(ret) hn--;
eed2ef37 1199
14236daa 1200 ret = lttv_trace_find_hook(ts->parent.parent.t,
1201 LTT_FACILITY_USER_GENERIC, LTT_EVENT_FUNCTION_ENTRY,
1202 LTT_FIELD_THIS_FN, LTT_FIELD_CALL_SITE, 0,
1203 after_function_entry, NULL,
1204 &g_array_index(hooks, LttvTraceHook, hn++));
1205 if(ret) hn--;
1206
1207 ret = lttv_trace_find_hook(ts->parent.parent.t,
1208 LTT_FACILITY_USER_GENERIC, LTT_EVENT_FUNCTION_EXIT,
1209 LTT_FIELD_THIS_FN, LTT_FIELD_CALL_SITE, 0,
1210 after_function_exit, NULL,
1211 &g_array_index(hooks, LttvTraceHook, hn++));
1212 if(ret) hn--;
954417fa 1213
1214 /* statedump-related hooks */
1215 ret = lttv_trace_find_hook(ts->parent.parent.t,
1216 LTT_FACILITY_STATEDUMP, LTT_EVENT_ENUM_PROCESS_STATE,
1217 LTT_FIELD_PID, LTT_FIELD_PARENT_PID, LTT_FIELD_NAME,
1218 after_enum_process_state, NULL,
1219 &g_array_index(hooks, LttvTraceHook, hn++));
1220 if(ret) hn--;
1221
2501204d 1222 g_array_set_size(hooks, hn);
b445142a 1223
1224 after_hooks = hooks;
1225
359b2948 1226 /* Add these hooks to each event_by_id hooks list */
b445142a 1227
eed2ef37 1228 nb_tracefile = ts->parent.parent.tracefiles->len;
b445142a 1229
dbb7bb09 1230 for(j = 0 ; j < nb_tracefile ; j++) {
d7cf605c 1231 tfs = LTTV_TRACEFILE_STATS(g_array_index(ts->parent.parent.tracefiles,
1232 LttvTracefileContext*, j));
359b2948 1233 lttv_hooks_add(tfs->parent.parent.event, every_event, NULL,
1234 LTTV_PRIO_DEFAULT);
b445142a 1235
1236 for(k = 0 ; k < before_hooks->len ; k++) {
eed2ef37 1237 hook = &g_array_index(before_hooks, LttvTraceHook, k);
1238 for(l = 0; l<hook->fac_list->len;l++) {
1239 thf = g_array_index(hook->fac_list, LttvTraceHookByFacility*, l);
1240 lttv_hooks_add(
1241 lttv_hooks_by_id_find(tfs->parent.parent.event_by_id, thf->id),
1242 thf->h,
d052ffc3 1243 thf,
eed2ef37 1244 LTTV_PRIO_STATS_BEFORE_STATE);
1245 }
b445142a 1246 }
1247 for(k = 0 ; k < after_hooks->len ; k++) {
eed2ef37 1248 hook = &g_array_index(after_hooks, LttvTraceHook, k);
1249 for(l = 0; l<hook->fac_list->len;l++) {
1250 thf = g_array_index(hook->fac_list, LttvTraceHookByFacility*, l);
1251 lttv_hooks_add(
1252 lttv_hooks_by_id_find(tfs->parent.parent.event_by_id, thf->id),
1253 thf->h,
d052ffc3 1254 thf,
eed2ef37 1255 LTTV_PRIO_STATS_AFTER_STATE);
1256 }
b445142a 1257 }
1258 }
1259 lttv_attribute_find(self->parent.parent.a, LTTV_STATS_BEFORE_HOOKS,
1260 LTTV_POINTER, &val);
1261 *(val.v_pointer) = before_hooks;
1262 lttv_attribute_find(self->parent.parent.a, LTTV_STATS_AFTER_HOOKS,
1263 LTTV_POINTER, &val);
1264 *(val.v_pointer) = after_hooks;
1265 }
b445142a 1266}
1267
d3e01c7a 1268// Hook wrapper. call_data is a traceset context.
00e74b69 1269gboolean lttv_stats_hook_remove_event_hooks(void *hook_data, void *call_data)
d3e01c7a 1270{
1271 LttvTracesetStats *tss = (LttvTracesetStats*)call_data;
1272
1273 lttv_stats_remove_event_hooks(tss);
1274
1275 return 0;
1276}
b445142a 1277
00e74b69 1278void lttv_stats_remove_event_hooks(LttvTracesetStats *self)
b445142a 1279{
1280 LttvTraceset *traceset = self->parent.parent.ts;
1281
eed2ef37 1282 guint i, j, k, l, nb_trace, nb_tracefile;
b445142a 1283
1284 LttvTraceStats *ts;
1285
1286 LttvTracefileStats *tfs;
1287
1288 void *hook_data;
1289
1290 GArray *before_hooks, *after_hooks;
1291
eed2ef37 1292 LttvTraceHook *hook;
1293
1294 LttvTraceHookByFacility *thf;
b445142a 1295
1296 LttvAttributeValue val;
1297
1298 nb_trace = lttv_traceset_number(traceset);
1299 for(i = 0 ; i < nb_trace ; i++) {
ae80b609 1300 ts = (LttvTraceStats*)self->parent.parent.traces[i];
b445142a 1301 lttv_attribute_find(self->parent.parent.a, LTTV_STATS_BEFORE_HOOKS,
1302 LTTV_POINTER, &val);
1303 before_hooks = *(val.v_pointer);
1304 lttv_attribute_find(self->parent.parent.a, LTTV_STATS_AFTER_HOOKS,
1305 LTTV_POINTER, &val);
1306 after_hooks = *(val.v_pointer);
1307
359b2948 1308 /* Remove these hooks from each event_by_id hooks list */
b445142a 1309
eed2ef37 1310 nb_tracefile = ts->parent.parent.tracefiles->len;
b445142a 1311
dbb7bb09 1312 for(j = 0 ; j < nb_tracefile ; j++) {
cb03932a 1313 tfs = LTTV_TRACEFILE_STATS(g_array_index(ts->parent.parent.tracefiles,
1314 LttvTracefileContext*, j));
359b2948 1315 lttv_hooks_remove_data(tfs->parent.parent.event, every_event,
b445142a 1316 NULL);
1317
1318 for(k = 0 ; k < before_hooks->len ; k++) {
eed2ef37 1319 hook = &g_array_index(before_hooks, LttvTraceHook, k);
1320 for(l = 0 ; l < hook->fac_list->len ; l++) {
1321 thf = g_array_index(hook->fac_list, LttvTraceHookByFacility*, l);
1322 lttv_hooks_remove_data(
1323 lttv_hooks_by_id_find(tfs->parent.parent.event_by_id, thf->id),
1324 thf->h,
d052ffc3 1325 thf);
eed2ef37 1326 }
b445142a 1327 }
1328 for(k = 0 ; k < after_hooks->len ; k++) {
eed2ef37 1329 hook = &g_array_index(after_hooks, LttvTraceHook, k);
1330 for(l = 0 ; l < hook->fac_list->len ; l++) {
1331 thf = g_array_index(hook->fac_list, LttvTraceHookByFacility*, l);
1332 lttv_hooks_remove_data(
1333 lttv_hooks_by_id_find(tfs->parent.parent.event_by_id, thf->id),
1334 thf->h,
d052ffc3 1335 thf);
eed2ef37 1336 }
b445142a 1337 }
1338 }
2a2fa4f0 1339 g_debug("lttv_stats_remove_event_hooks()");
b445142a 1340 g_array_free(before_hooks, TRUE);
1341 g_array_free(after_hooks, TRUE);
1342 }
9f797243 1343}
08b1c66e 1344
1345
1346static void module_init()
1347{
1348 LTTV_STATS_PROCESS_UNKNOWN = g_quark_from_string("unknown process");
1349 LTTV_STATS_PROCESSES = g_quark_from_string("processes");
1350 LTTV_STATS_CPU = g_quark_from_string("cpu");
1351 LTTV_STATS_MODE_TYPES = g_quark_from_string("mode_types");
1352 LTTV_STATS_MODES = g_quark_from_string("modes");
1353 LTTV_STATS_SUBMODES = g_quark_from_string("submodes");
14236daa 1354 LTTV_STATS_FUNCTIONS = g_quark_from_string("functions");
08b1c66e 1355 LTTV_STATS_EVENT_TYPES = g_quark_from_string("event_types");
1356 LTTV_STATS_CPU_TIME = g_quark_from_string("cpu time");
b49e54b4 1357 LTTV_STATS_CUMULATIVE_CPU_TIME = g_quark_from_string("cumulative cpu time (includes nested routines and modes)");
1358 LTTV_STATS_ELAPSED_TIME = g_quark_from_string("elapsed time (includes per process waiting time)");
08b1c66e 1359 LTTV_STATS_EVENTS = g_quark_from_string("events");
1360 LTTV_STATS_EVENTS_COUNT = g_quark_from_string("events count");
1361 LTTV_STATS_BEFORE_HOOKS = g_quark_from_string("saved stats before hooks");
1362 LTTV_STATS_AFTER_HOOKS = g_quark_from_string("saved stats after hooks");
f95bc830 1363 LTTV_STATS_USE_COUNT = g_quark_from_string("stats_use_count");
1364 LTTV_STATS = g_quark_from_string("statistics");
1365 LTTV_STATS_TRACEFILES = g_quark_from_string("tracefiles statistics");
1366 LTTV_STATS_SUMMED = g_quark_from_string("statistics summed");
08b1c66e 1367}
1368
1369static void module_destroy()
1370{
1371}
1372
1373
1374LTTV_MODULE("stats", "Compute processes statistics", \
1375 "Accumulate statistics for event types, processes and CPUs", \
1376 module_init, module_destroy, "state");
f95bc830 1377
1378/* Change the places where stats are called (create/read/write stats)
1379
1380 Check for options in batchtest.c to reduce writing and see what tests are
1381 best candidates for performance analysis. Once OK, commit, move to main
1382 and run tests. Update the gui for statistics. */
This page took 0.108206 seconds and 4 git commands to generate.