1 /* This file is part of the Linux Trace Toolkit viewer
2 * Copyright (C) 2003-2004 Michel Dagenais
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;
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.
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,
24 #include <lttv/module.h>
25 #include <lttv/stats.h>
26 #include <lttv/lttv.h>
27 #include <lttv/attribute.h>
28 #include <ltt/facility.h>
29 #include <ltt/trace.h>
30 #include <ltt/event.h>
34 #define MAX_64_HEX_STRING_LEN 19
37 LTTV_STATS_PROCESS_UNKNOWN,
40 LTTV_STATS_MODE_TYPES,
44 LTTV_STATS_EVENT_TYPES,
46 LTTV_STATS_CUMULATIVE_CPU_TIME,
47 LTTV_STATS_ELAPSED_TIME,
49 LTTV_STATS_EVENTS_COUNT,
52 LTTV_STATS_TRACEFILES,
54 LTTV_STATS_BEFORE_HOOKS,
55 LTTV_STATS_AFTER_HOOKS,
56 /***********************************************************/
57 LTTV_XENO_STATS_THREADS,
58 LTTV_XENO_STATS_THREAD_ADDRESS,
59 LTTV_XENO_STATS_THREAD_PERIOD,
60 LTTV_XENO_STATS_THREAD_PRIO,
61 LTTV_XENO_STATS_STATE,
62 LTTV_XENO_STATS_SYNCH,
63 LTTV_XENO_STATS_PERIOD,
64 LTTV_XENO_STATS_PERIOD_OVERRUNS,
65 LTTV_XENO_STATS_TEXT_OVERRUNS,
66 LTTV_XENO_STATS_TEXT_TICKS,
67 LTTV_XENO_STATS_TEXT_TOTAL,
68 LTTV_XENO_STATS_TEXT_OWNER,
69 LTTV_XENO_STATS_TEXT_WAITING,
70 LTTV_XENO_STATS_TEXT_OWNER_TOTAL,
71 LTTV_XENO_STATS_TEXT_OWNER_MAX,
72 LTTV_XENO_STATS_TEXT_OWNER_MIN,
73 LTTV_XENO_STATS_TEXT_OWNER_AVG,
74 LTTV_XENO_STATS_TEXT_WAITING,
75 LTTV_XENO_STATS_TEXT_WAITING_TOTAL,
76 LTTV_XENO_STATS_TEXT_WAITING_MAX,
77 LTTV_XENO_STATS_TEXT_WAITING_MIN,
78 LTTV_XENO_STATS_TEXT_WAITING_AVG,
79 LTTV_XENO_STATS_TEXT_READY_MAX,
80 LTTV_XENO_STATS_TEXT_READY_MIN,
81 LTTV_XENO_STATS_TEXT_READY_AVG,
82 LTTV_XENO_STATS_TEXT_RUNNING_MAX,
83 LTTV_XENO_STATS_TEXT_RUNNING_MIN,
84 LTTV_XENO_STATS_TEXT_RUNNING_AVG,
85 LTTV_XENO_STATS_TEXT_SUSPEND_MAX,
86 LTTV_XENO_STATS_TEXT_SUSPEND_MIN,
87 LTTV_XENO_STATS_TEXT_SUSPEND_AVG,
88 LTTV_XENO_STATS_NB_PERIOD;
89 /***********************************************************/
91 /****************************************************************************************************************************/
92 static void xeno_find_task_tree(LttvTracefileStats *tfcs, GQuark name, gulong address, guint cpu,
93 /*GQuark mode, GQuark sub_mode,*/ LttvAttribute **events_tree, LttvAttribute **event_types_tree);
94 gboolean xenoltt_thread_init(void *hook_data, void *call_data);
95 gboolean xenoltt_thread_set_period(void *hook_data, void *call_data);
96 gboolean xenoltt_thread_renice(void *hook_data, void *call_data);
97 gboolean xenoltt_before_change_state(void *hook_data, void *call_data);
98 gboolean xenoltt_after_change_state(void *hook_data, void *call_data);
99 gboolean xenoltt_thread_overruns(void *hook_data, void *call_data);
100 gboolean xenoltt_synch_owner(void *hook_data, void *call_data);
101 gboolean xenoltt_synch_wait(void *hook_data, void *call_data);
102 gboolean xenoltt_synch_unblock(void *hook_data, void *call_data);
103 gboolean xenoltt_synch_wakeup(void *hook_data, void *call_data);
104 gboolean xenoltt_synch_flush(void *hook_data, void *call_data);
105 /****************************************************************************************************************************/
107 find_event_tree(LttvTracefileStats *tfcs, GQuark pid_time, guint cpu,
109 GQuark mode, GQuark sub_mode, LttvAttribute **events_tree,
110 LttvAttribute **event_types_tree);
113 static void lttv_stats_init(LttvTracesetStats *self)
115 guint i, j, nb_trace, nb_tracefile;
117 LttvTraceContext *tc;
121 LttvTracefileContext *tfc;
123 LttvTracefileContext **tfs;
124 LttvTracefileStats *tfcs;
126 LttTime timestamp = {0,0};
128 LttvAttributeValue v;
134 LttvTraceset *ts = self->parent.parent.ts;
136 self->stats = lttv_attribute_find_subdir(
137 lttv_traceset_attribute(self->parent.parent.ts),
139 lttv_attribute_find(lttv_traceset_attribute(self->parent.parent.ts),
140 LTTV_STATS_USE_COUNT,
143 self->xenoltt_stats = lttv_attribute_find_subdir(
144 lttv_traceset_attribute(self->parent.parent.ts),
148 if(*(v.v_uint) == 1) {
149 g_assert(lttv_attribute_get_number(self->stats) == 0);
152 nb_trace = lttv_traceset_number(ts);
154 for(i = 0 ; i < nb_trace ; i++) {
155 tc = self->parent.parent.traces[i];
156 tcs = LTTV_TRACE_STATS(tc);
158 tcs->stats = lttv_attribute_find_subdir(tcs->parent.parent.t_a,LTTV_STATS);
160 tcs->xenoltt_stats = lttv_attribute_find_subdir(tcs->parent.parent.t_a,LTTV_STATS);
162 tracefiles_stats = lttv_attribute_find_subdir(tcs->parent.parent.t_a,
163 LTTV_STATS_TRACEFILES);
164 lttv_attribute_find(tcs->parent.parent.t_a, LTTV_STATS_USE_COUNT,
168 if(*(v.v_uint) == 1) {
169 g_assert(lttv_attribute_get_number(tcs->stats) == 0);
172 nb_tracefile = tc->tracefiles->len;
174 for(j = 0 ; j < nb_tracefile ; j++) {
175 tfs = &g_array_index(tc->tracefiles,
176 LttvTracefileContext*, j);
177 tfcs = LTTV_TRACEFILE_STATS(*tfs);
178 tfcs->stats = lttv_attribute_find_subdir(tracefiles_stats,
179 ltt_tracefile_long_name(tfcs->parent.parent.tf));
180 guint cpu = tfcs->parent.cpu;
181 find_event_tree(tfcs, LTTV_STATS_PROCESS_UNKNOWN,
184 LTTV_STATE_MODE_UNKNOWN,
185 LTTV_STATE_SUBMODE_UNKNOWN, &tfcs->current_events_tree,
186 &tfcs->current_event_types_tree);
191 static void lttv_stats_fini(LttvTracesetStats *self)
193 guint i, j, nb_trace, nb_tracefile;
197 LttvTraceContext *tc;
201 LttvTracefileContext *tfc;
203 LttvTracefileStats *tfcs;
205 LttTime timestamp = {0,0};
207 LttvAttributeValue v;
209 LttvAttribute *tracefiles_stats;
211 lttv_attribute_find(self->parent.parent.ts_a, LTTV_STATS_USE_COUNT,
215 if(*(v.v_uint) == 0) {
216 lttv_attribute_remove_by_name(self->parent.parent.ts_a, LTTV_STATS);
220 ts = self->parent.parent.ts;
221 nb_trace = lttv_traceset_number(ts);
223 for(i = 0 ; i < nb_trace ; i++) {
224 tcs = (LttvTraceStats *)(tc = (LTTV_TRACESET_CONTEXT(self)->traces[i]));
226 lttv_attribute_find(tcs->parent.parent.t_a, LTTV_STATS_USE_COUNT,
230 if(*(v.v_uint) == 0) {
231 lttv_attribute_remove_by_name(tcs->parent.parent.t_a,LTTV_STATS);
232 tracefiles_stats = lttv_attribute_find_subdir(tcs->parent.parent.t_a,
233 LTTV_STATS_TRACEFILES);
234 lttv_attribute_remove_by_name(tcs->parent.parent.t_a,
235 LTTV_STATS_TRACEFILES);
239 nb_tracefile = tc->tracefiles->len;
241 for(j = 0 ; j < nb_tracefile ; j++) {
242 tfc = g_array_index(tc->tracefiles,
243 LttvTracefileContext*, j);
244 tfcs = (LttvTracefileStats *)tfc;
246 tfcs->current_events_tree = NULL;
247 tfcs->current_event_types_tree = NULL;
253 void lttv_stats_reset(LttvTracesetStats *self)
255 lttv_stats_fini(self);
256 lttv_stats_init(self);
262 init(LttvTracesetStats *self, LttvTraceset *ts)
264 LTTV_TRACESET_CONTEXT_CLASS(g_type_class_peek(LTTV_TRACESET_STATE_TYPE))->
265 init((LttvTracesetContext *)self, ts);
267 lttv_stats_init(self);
272 fini(LttvTracesetStats *self)
274 lttv_stats_fini(self);
276 LTTV_TRACESET_CONTEXT_CLASS(g_type_class_peek(LTTV_TRACESET_STATE_TYPE))->
277 fini((LttvTracesetContext *)self);
281 static LttvTracesetContext *
282 new_traceset_context(LttvTracesetContext *self)
284 return LTTV_TRACESET_CONTEXT(g_object_new(LTTV_TRACESET_STATS_TYPE, NULL));
288 static LttvTraceContext *
289 new_trace_context(LttvTracesetContext *self)
291 return LTTV_TRACE_CONTEXT(g_object_new(LTTV_TRACE_STATS_TYPE, NULL));
295 static LttvTracefileContext *
296 new_tracefile_context(LttvTracesetContext *self)
298 return LTTV_TRACEFILE_CONTEXT(g_object_new(LTTV_TRACEFILE_STATS_TYPE, NULL));
303 traceset_stats_instance_init (GTypeInstance *instance, gpointer g_class)
309 traceset_stats_finalize (LttvTracesetStats *self)
311 G_OBJECT_CLASS(g_type_class_peek(LTTV_TRACESET_STATE_TYPE))->
312 finalize(G_OBJECT(self));
317 traceset_stats_class_init (LttvTracesetContextClass *klass)
319 GObjectClass *gobject_class = G_OBJECT_CLASS(klass);
321 gobject_class->finalize = (void (*)(GObject *self)) traceset_stats_finalize;
322 klass->init = (void (*)(LttvTracesetContext *self, LttvTraceset *ts))init;
323 klass->fini = (void (*)(LttvTracesetContext *self))fini;
324 klass->new_traceset_context = new_traceset_context;
325 klass->new_trace_context = new_trace_context;
326 klass->new_tracefile_context = new_tracefile_context;
331 lttv_traceset_stats_get_type(void)
333 static GType type = 0;
335 static const GTypeInfo info = {
336 sizeof (LttvTracesetStatsClass),
337 NULL, /* base_init */
338 NULL, /* base_finalize */
339 (GClassInitFunc) traceset_stats_class_init, /* class_init */
340 NULL, /* class_finalize */
341 NULL, /* class_data */
342 sizeof (LttvTracesetStats),
344 (GInstanceInitFunc) traceset_stats_instance_init, /* instance_init */
345 NULL /* Value handling */
348 type = g_type_register_static (LTTV_TRACESET_STATE_TYPE,
349 "LttvTracesetStatsType",
357 trace_stats_instance_init (GTypeInstance *instance, gpointer g_class)
363 trace_stats_finalize (LttvTraceStats *self)
365 G_OBJECT_CLASS(g_type_class_peek(LTTV_TRACE_STATE_TYPE))->
366 finalize(G_OBJECT(self));
371 trace_stats_class_init (LttvTraceContextClass *klass)
373 GObjectClass *gobject_class = G_OBJECT_CLASS(klass);
375 gobject_class->finalize = (void (*)(GObject *self)) trace_stats_finalize;
380 lttv_trace_stats_get_type(void)
382 static GType type = 0;
384 static const GTypeInfo info = {
385 sizeof (LttvTraceStatsClass),
386 NULL, /* base_init */
387 NULL, /* base_finalize */
388 (GClassInitFunc) trace_stats_class_init, /* class_init */
389 NULL, /* class_finalize */
390 NULL, /* class_data */
391 sizeof (LttvTraceStats),
393 (GInstanceInitFunc) trace_stats_instance_init, /* instance_init */
394 NULL /* Value handling */
397 type = g_type_register_static (LTTV_TRACE_STATE_TYPE,
398 "LttvTraceStatsType", &info, 0);
405 tracefile_stats_instance_init (GTypeInstance *instance, gpointer g_class)
411 tracefile_stats_finalize (LttvTracefileStats *self)
413 G_OBJECT_CLASS(g_type_class_peek(LTTV_TRACEFILE_STATE_TYPE))->
414 finalize(G_OBJECT(self));
419 tracefile_stats_class_init (LttvTracefileStatsClass *klass)
421 GObjectClass *gobject_class = G_OBJECT_CLASS(klass);
423 gobject_class->finalize = (void (*)(GObject *self)) tracefile_stats_finalize;
428 lttv_tracefile_stats_get_type(void)
430 static GType type = 0;
432 static const GTypeInfo info = {
433 sizeof (LttvTracefileStatsClass),
434 NULL, /* base_init */
435 NULL, /* base_finalize */
436 (GClassInitFunc) tracefile_stats_class_init, /* class_init */
437 NULL, /* class_finalize */
438 NULL, /* class_data */
439 sizeof (LttvTracefileStats),
441 (GInstanceInitFunc) tracefile_stats_instance_init, /* instance_init */
442 NULL /* Value handling */
445 type = g_type_register_static (LTTV_TRACEFILE_STATE_TYPE,
446 "LttvTracefileStatsType", &info, 0);
453 find_event_tree(LttvTracefileStats *tfcs,
459 LttvAttribute **events_tree,
460 LttvAttribute **event_types_tree)
462 LttvAttribute *a, *prev_a;
463 gchar fstring[MAX_64_HEX_STRING_LEN];
466 ret = snprintf(fstring, MAX_64_HEX_STRING_LEN-1,
467 "0x%llX", function) > 0;
469 fstring[MAX_64_HEX_STRING_LEN-1] = '\0';
471 LttvTraceStats *tcs = (LttvTraceStats*)tfcs->parent.parent.t_context;
472 a = lttv_attribute_find_subdir(tcs->stats, LTTV_STATS_PROCESSES);
473 a = lttv_attribute_find_subdir(a, pid_time);
474 a = lttv_attribute_find_subdir(a, LTTV_STATS_CPU);
475 a = lttv_attribute_find_subdir_unnamed(a, cpu);
476 a = lttv_attribute_find_subdir(a, LTTV_STATS_FUNCTIONS);
477 a = lttv_attribute_find_subdir(a, g_quark_from_string(fstring));
478 a = lttv_attribute_find_subdir(a, LTTV_STATS_MODE_TYPES);
479 a = lttv_attribute_find_subdir(a, mode);
480 a = lttv_attribute_find_subdir(a, LTTV_STATS_SUBMODES);
481 a = lttv_attribute_find_subdir(a, sub_mode);
483 a = lttv_attribute_find_subdir(a, LTTV_STATS_EVENT_TYPES);
484 *event_types_tree = a;
488 static void update_event_tree(LttvTracefileStats *tfcs)
490 LttvTraceState *ts = (LttvTraceState *)tfcs->parent.parent.t_context;
491 guint cpu = tfcs->parent.cpu;
492 LttvProcessState *process = ts->running_process[cpu];
493 LttvExecutionState *es = process->state;
495 find_event_tree(tfcs, process->pid_time,
497 process->current_function,
498 es->t, es->n, &(tfcs->current_events_tree),
499 &(tfcs->current_event_types_tree));
503 static void mode_change(LttvTracefileStats *tfcs)
505 LttvTraceState *ts = (LttvTraceState *)tfcs->parent.parent.t_context;
506 guint cpu = tfcs->parent.cpu;
507 LttvProcessState *process = ts->running_process[cpu];
508 LttvAttributeValue cpu_time, cum_cpu_time;
512 delta = ltt_time_sub(tfcs->parent.parent.timestamp,
513 process->state->change);
515 lttv_attribute_find(tfcs->current_events_tree, LTTV_STATS_CPU_TIME,
516 LTTV_TIME, &cpu_time);
517 *(cpu_time.v_time) = ltt_time_add(*(cpu_time.v_time), delta);
519 process->state->cum_cpu_time = ltt_time_add(process->state->cum_cpu_time,
523 /* Note : every mode_end must come with a cumulative cpu time update in the
525 static void mode_end(LttvTracefileStats *tfcs)
527 LttvTraceState *ts = (LttvTraceState *)tfcs->parent.parent.t_context;
528 guint cpu = tfcs->parent.cpu;
529 LttvProcessState *process = ts->running_process[cpu];
530 LttvAttributeValue elapsed_time, cpu_time, cum_cpu_time;
534 lttv_attribute_find(tfcs->current_events_tree, LTTV_STATS_ELAPSED_TIME,
535 LTTV_TIME, &elapsed_time);
536 delta = ltt_time_sub(tfcs->parent.parent.timestamp,
537 process->state->entry);
538 *(elapsed_time.v_time) = ltt_time_add(*(elapsed_time.v_time), delta);
540 lttv_attribute_find(tfcs->current_events_tree, LTTV_STATS_CPU_TIME,
541 LTTV_TIME, &cpu_time);
542 delta = ltt_time_sub(tfcs->parent.parent.timestamp,
543 process->state->change);
544 *(cpu_time.v_time) = ltt_time_add(*(cpu_time.v_time), delta);
545 process->state->cum_cpu_time = ltt_time_add(process->state->cum_cpu_time,
548 lttv_attribute_find(tfcs->current_events_tree, LTTV_STATS_CUMULATIVE_CPU_TIME,
549 LTTV_TIME, &cum_cpu_time);
550 *(cum_cpu_time.v_time) = ltt_time_add(*(cum_cpu_time.v_time),
551 process->state->cum_cpu_time);
555 static void after_mode_end(LttvTracefileStats *tfcs)
557 LttvTraceState *ts = (LttvTraceState *)tfcs->parent.parent.t_context;
558 guint cpu = tfcs->parent.cpu;
559 LttvProcessState *process = ts->running_process[cpu];
560 LttvAttributeValue cum_cpu_time;
562 LttTime nested_delta;
564 nested_delta = process->state->cum_cpu_time;
565 process->state->cum_cpu_time = ltt_time_zero; /* For after traceset hook */
567 update_event_tree(tfcs);
569 process->state->cum_cpu_time = ltt_time_add(process->state->cum_cpu_time,
573 static gboolean before_syscall_entry(void *hook_data, void *call_data)
575 mode_change((LttvTracefileStats *)call_data);
580 static gboolean after_syscall_entry(void *hook_data, void *call_data)
582 update_event_tree((LttvTracefileStats *)call_data);
587 gboolean before_syscall_exit(void *hook_data, void *call_data)
589 mode_end((LttvTracefileStats *)call_data);
594 static gboolean after_syscall_exit(void *hook_data, void *call_data)
596 after_mode_end((LttvTracefileStats *)call_data);
601 gboolean before_trap_entry(void *hook_data, void *call_data)
603 mode_change((LttvTracefileStats *)call_data);
608 static gboolean after_trap_entry(void *hook_data, void *call_data)
610 update_event_tree((LttvTracefileStats *)call_data);
615 gboolean before_trap_exit(void *hook_data, void *call_data)
617 mode_end((LttvTracefileStats *)call_data);
622 gboolean after_trap_exit(void *hook_data, void *call_data)
624 after_mode_end((LttvTracefileStats *)call_data);
629 gboolean before_irq_entry(void *hook_data, void *call_data)
631 mode_change((LttvTracefileStats *)call_data);
635 gboolean after_irq_entry(void *hook_data, void *call_data)
637 update_event_tree((LttvTracefileStats *)call_data);
642 gboolean before_irq_exit(void *hook_data, void *call_data)
644 mode_end((LttvTracefileStats *)call_data);
649 gboolean after_irq_exit(void *hook_data, void *call_data)
651 after_mode_end((LttvTracefileStats *)call_data);
656 gboolean before_soft_irq_entry(void *hook_data, void *call_data)
658 mode_change((LttvTracefileStats *)call_data);
662 gboolean after_soft_irq_entry(void *hook_data, void *call_data)
664 update_event_tree((LttvTracefileStats *)call_data);
669 gboolean before_soft_irq_exit(void *hook_data, void *call_data)
671 mode_end((LttvTracefileStats *)call_data);
676 gboolean after_soft_irq_exit(void *hook_data, void *call_data)
678 after_mode_end((LttvTracefileStats *)call_data);
682 gboolean before_function_entry(void *hook_data, void *call_data)
684 mode_change((LttvTracefileStats *)call_data);
688 gboolean after_function_entry(void *hook_data, void *call_data)
690 update_event_tree((LttvTracefileStats *)call_data);
694 gboolean before_function_exit(void *hook_data, void *call_data)
696 mode_end((LttvTracefileStats *)call_data);
700 gboolean after_function_exit(void *hook_data, void *call_data)
702 after_mode_end((LttvTracefileStats *)call_data);
707 gboolean before_schedchange(void *hook_data, void *call_data)
709 LttvTracefileStats *tfcs = (LttvTracefileStats *)call_data;
711 LttvTraceState *ts = (LttvTraceState*)tfcs->parent.parent.t_context;
713 LttEvent *e = ltt_tracefile_get_event(tfcs->parent.parent.tf);
715 LttvTraceHookByFacility *thf = (LttvTraceHookByFacility *)hook_data;
717 guint pid_in, pid_out;
721 pid_out = ltt_event_get_unsigned(e, thf->f1);
722 pid_in = ltt_event_get_unsigned(e, thf->f2);
723 state_out = ltt_event_get_int(e, thf->f3);
725 /* compute the time for the process to schedule out */
732 gboolean after_schedchange(void *hook_data, void *call_data)
734 LttvTracefileStats *tfcs = (LttvTracefileStats *)call_data;
736 LttvTraceState *ts = (LttvTraceState*)tfcs->parent.parent.t_context;
738 LttEvent *e = ltt_tracefile_get_event(tfcs->parent.parent.tf);
740 LttvTraceHookByFacility *thf = (LttvTraceHookByFacility *)hook_data;
742 guint pid_in, pid_out;
746 LttvProcessState *process;
748 pid_out = ltt_event_get_unsigned(e, thf->f1);
749 pid_in = ltt_event_get_unsigned(e, thf->f2);
750 state_out = ltt_event_get_int(e, thf->f3);
752 /* get the information for the process scheduled in */
753 guint cpu = tfcs->parent.cpu;
754 process = ts->running_process[cpu];
756 find_event_tree(tfcs, process->pid_time,
758 process->current_function,
759 process->state->t, process->state->n, &(tfcs->current_events_tree),
760 &(tfcs->current_event_types_tree));
762 /* compute the time waiting for the process to schedule in */
768 gboolean process_fork(void *hook_data, void *call_data)
770 /* nothing to do for now */
775 gboolean process_exit(void *hook_data, void *call_data)
777 /* We should probably exit all modes here or we could do that at
782 gboolean before_enum_process_state(void *hook_data, void *call_data)
784 mode_end((LttvTracefileStats *)call_data);
785 after_mode_end((LttvTracefileStats *)call_data);
786 mode_change((LttvTracefileStats *)call_data);
790 gboolean after_enum_process_state(void *hook_data, void *call_data)
792 update_event_tree((LttvTracefileStats *)call_data);
796 gboolean process_free(void *hook_data, void *call_data)
801 gboolean every_event(void *hook_data, void *call_data)
803 LttvTracefileStats *tfcs = (LttvTracefileStats *)call_data;
805 LttEvent *e = ltt_tracefile_get_event(tfcs->parent.parent.tf);
807 LttvAttributeValue v;
809 /* The current branch corresponds to the tracefile/process/interrupt state.
810 Statistics are added within it, to count the number of events of this
811 type occuring in this context. A quark has been pre-allocated for each
812 event type and is used as name. */
814 lttv_attribute_find(tfcs->current_event_types_tree,
815 ltt_eventtype_name(ltt_event_eventtype(e)),
821 static void lttv_stats_cleanup_process_state(gpointer key, gpointer value,
824 LttvTraceStats *tcs = (LttvTraceStats *)user_data;
825 LttvTraceState *ts = (LttvTraceState *)user_data;
826 LttvTracesetContext *tsc = ts->parent.ts_context;
827 LttvProcessState *process = (LttvProcessState *)value;
829 LttvTracefileStats **tfs = (LttvTracefileStats **)
830 &g_array_index(ts->parent.tracefiles, LttvTracefileContext*,
832 int cleanup_empty = 0;
833 LttTime nested_delta = ltt_time_zero;
834 /* FIXME : ok, this is a hack. The time is infinite here :( */
835 LttTime save_time = (*tfs)->parent.parent.timestamp;
837 ltt_trace_time_span_get(ts->parent.t, &start, &end);
838 (*tfs)->parent.parent.timestamp = end;
841 if(ltt_time_compare(process->state->cum_cpu_time, ltt_time_zero) != 0) {
842 find_event_tree(*tfs, process->pid_time,
844 process->current_function,
845 process->state->t, process->state->n, &((*tfs)->current_events_tree),
846 &((*tfs)->current_event_types_tree));
848 nested_delta = process->state->cum_cpu_time;
850 cleanup_empty = lttv_state_pop_state_cleanup(process,
851 (LttvTracefileState *)*tfs);
852 process->state->cum_cpu_time = ltt_time_add(process->state->cum_cpu_time,
855 } while(cleanup_empty != 1);
857 (*tfs)->parent.parent.timestamp = save_time;
860 /* For each process in the state, for each of their stacked states,
861 * perform sum of needed values. */
862 static void lttv_stats_cleanup_state(LttvTraceStats *tcs)
864 LttvTraceState *ts = (LttvTraceState *)tcs;
866 /* Does not work correctly FIXME. */
867 g_hash_table_foreach(ts->processes, lttv_stats_cleanup_process_state,
872 lttv_stats_sum_trace(LttvTraceStats *self, LttvAttribute *ts_stats)
874 LttvAttribute *sum_container = self->stats;
876 LttvAttributeType type;
878 LttvAttributeValue value;
880 LttvAttributeName name;
888 int i, j, k, l, m, nb_process, nb_cpu, nb_mode_type, nb_submode,
889 nb_event_type, nf, nb_functions;
891 LttvAttribute *main_tree, *processes_tree, *process_tree, *cpus_tree,
892 *cpu_tree, *mode_tree, *mode_types_tree, *submodes_tree,
893 *submode_tree, *event_types_tree, *mode_events_tree,
896 *function_mode_types_tree,
900 main_tree = sum_container;
902 lttv_attribute_find(sum_container,
905 trace_is_summed = *(value.v_uint);
908 /* First cleanup the state : sum all stalled information (never ending
911 lttv_stats_cleanup_state(self);
913 processes_tree = lttv_attribute_find_subdir(main_tree,
914 LTTV_STATS_PROCESSES);
915 nb_process = lttv_attribute_get_number(processes_tree);
917 for(i = 0 ; i < nb_process ; i++) {
918 type = lttv_attribute_get(processes_tree, i, &name, &value, &is_named);
919 process_tree = LTTV_ATTRIBUTE(*(value.v_gobject));
921 cpus_tree = lttv_attribute_find_subdir(process_tree, LTTV_STATS_CPU);
922 nb_cpu = lttv_attribute_get_number(cpus_tree);
924 for(j = 0 ; j < nb_cpu ; j++) {
925 type = lttv_attribute_get(cpus_tree, j, &name, &value, &is_named);
926 cpu_tree = LTTV_ATTRIBUTE(*(value.v_gobject));
928 trace_cpu_tree = lttv_attribute_find_subdir(main_tree, LTTV_STATS_CPU);
929 trace_cpu_tree = lttv_attribute_find_subdir_unnamed(trace_cpu_tree, name);
930 cpu_functions_tree = lttv_attribute_find_subdir(cpu_tree,
931 LTTV_STATS_FUNCTIONS);
932 nb_functions = lttv_attribute_get_number(cpu_functions_tree);
934 for(nf=0; nf < nb_functions; nf++) {
935 type = lttv_attribute_get(cpu_functions_tree, nf, &name, &value,
937 function_tree = LTTV_ATTRIBUTE(*(value.v_gobject));
938 function_mode_types_tree = lttv_attribute_find_subdir(function_tree,
939 LTTV_STATS_MODE_TYPES);
940 nb_mode_type = lttv_attribute_get_number(function_mode_types_tree);
941 for(k = 0 ; k < nb_mode_type ; k++) {
942 type = lttv_attribute_get(function_mode_types_tree, k, &name, &value,
944 mode_tree = LTTV_ATTRIBUTE(*(value.v_gobject));
946 submodes_tree = lttv_attribute_find_subdir(mode_tree,
947 LTTV_STATS_SUBMODES);
948 mode_events_tree = lttv_attribute_find_subdir(mode_tree,
950 mode_types_tree = lttv_attribute_find_subdir(mode_tree,
951 LTTV_STATS_MODE_TYPES);
953 nb_submode = lttv_attribute_get_number(submodes_tree);
955 for(l = 0 ; l < nb_submode ; l++) {
956 type = lttv_attribute_get(submodes_tree, l, &name, &value,
958 submode_tree = LTTV_ATTRIBUTE(*(value.v_gobject));
960 event_types_tree = lttv_attribute_find_subdir(submode_tree,
961 LTTV_STATS_EVENT_TYPES);
962 nb_event_type = lttv_attribute_get_number(event_types_tree);
965 for(m = 0 ; m < nb_event_type ; m++) {
966 type = lttv_attribute_get(event_types_tree, m, &name, &value,
968 sum += *(value.v_uint);
970 lttv_attribute_find(submode_tree, LTTV_STATS_EVENTS_COUNT,
972 *(value.v_uint) = sum;
974 type = lttv_attribute_get(submodes_tree, l, &name, &value,
976 submode_tree = LTTV_ATTRIBUTE(*(value.v_gobject));
977 if(!trace_is_summed) {
978 lttv_attribute_recursive_add(mode_events_tree, event_types_tree);
979 lttv_attribute_recursive_add(mode_types_tree, submode_tree);
982 if(!trace_is_summed) {
983 lttv_attribute_recursive_add(function_tree, mode_types_tree);
986 if(!trace_is_summed) {
987 lttv_attribute_recursive_add(cpu_tree, function_tree);
988 lttv_attribute_recursive_add(process_tree, function_tree);
989 lttv_attribute_recursive_add(trace_cpu_tree, function_tree);
990 lttv_attribute_recursive_add(main_tree, function_tree);
992 lttv_attribute_recursive_add(ts_stats, function_tree);
999 gboolean lttv_stats_sum_traceset_hook(void *hook_data, void *call_data)
1001 lttv_stats_sum_traceset((LttvTracesetStats *)call_data);
1006 lttv_stats_sum_traceset(LttvTracesetStats *self)
1008 LttvTraceset *traceset = self->parent.parent.ts;
1009 LttvAttribute *sum_container = self->stats;
1011 LttvTraceStats *tcs;
1015 LttvAttribute *main_tree;
1017 LttvAttributeValue value;
1019 lttv_attribute_find(sum_container, LTTV_STATS_SUMMED,
1021 if(*(value.v_uint) != 0) return;
1022 *(value.v_uint) = 1;
1024 nb_trace = lttv_traceset_number(traceset);
1026 for(i = 0 ; i < nb_trace ; i++) {
1027 tcs = (LttvTraceStats *)(self->parent.parent.traces[i]);
1028 lttv_stats_sum_trace(tcs, self->stats);
1029 // lttv_attribute_recursive_add(sum_container, tcs->stats);
1034 // Hook wrapper. call_data is a traceset context.
1035 gboolean lttv_stats_hook_add_event_hooks(void *hook_data, void *call_data)
1037 LttvTracesetStats *tss = (LttvTracesetStats*)call_data;
1039 lttv_stats_add_event_hooks(tss);
1044 void lttv_stats_add_event_hooks(LttvTracesetStats *self)
1046 LttvTraceset *traceset = self->parent.parent.ts;
1048 guint i, j, k, l, nb_trace, nb_tracefile;
1052 LttvTracefileStats *tfs;
1054 GArray *hooks, *before_hooks, *after_hooks;
1056 LttvTraceHook *hook;
1058 LttvTraceHookByFacility *thf;
1060 LttvAttributeValue val;
1065 nb_trace = lttv_traceset_number(traceset);
1066 for(i = 0 ; i < nb_trace ; i++) {
1067 ts = (LttvTraceStats *)self->parent.parent.traces[i];
1069 /* Find the eventtype id for the following events and register the
1070 associated by id hooks. */
1072 hooks = g_array_sized_new(FALSE, FALSE, sizeof(LttvTraceHook), 16);
1073 g_array_set_size(hooks, 16);
1076 ret = lttv_trace_find_hook(ts->parent.parent.t,
1077 LTT_FACILITY_KERNEL_ARCH, LTT_EVENT_SYSCALL_ENTRY,
1078 LTT_FIELD_SYSCALL_ID, 0, 0,
1079 before_syscall_entry, NULL,
1080 &g_array_index(hooks, LttvTraceHook, hn++));
1083 ret = lttv_trace_find_hook(ts->parent.parent.t,
1084 LTT_FACILITY_KERNEL_ARCH, LTT_EVENT_SYSCALL_EXIT,
1086 before_syscall_exit, NULL,
1087 &g_array_index(hooks, LttvTraceHook, hn++));
1090 ret = lttv_trace_find_hook(ts->parent.parent.t,
1091 LTT_FACILITY_KERNEL, LTT_EVENT_TRAP_ENTRY,
1092 LTT_FIELD_TRAP_ID, 0, 0,
1093 before_trap_entry, NULL,
1094 &g_array_index(hooks, LttvTraceHook, hn++));
1097 ret = lttv_trace_find_hook(ts->parent.parent.t,
1098 LTT_FACILITY_KERNEL, LTT_EVENT_TRAP_EXIT,
1100 before_trap_exit, NULL,
1101 &g_array_index(hooks, LttvTraceHook, hn++));
1104 ret = lttv_trace_find_hook(ts->parent.parent.t,
1105 LTT_FACILITY_KERNEL, LTT_EVENT_IRQ_ENTRY,
1106 LTT_FIELD_IRQ_ID, 0, 0,
1107 before_irq_entry, NULL,
1108 &g_array_index(hooks, LttvTraceHook, hn++));
1111 ret = lttv_trace_find_hook(ts->parent.parent.t,
1112 LTT_FACILITY_KERNEL, LTT_EVENT_IRQ_EXIT,
1114 before_irq_exit, NULL,
1115 &g_array_index(hooks, LttvTraceHook, hn++));
1118 ret = lttv_trace_find_hook(ts->parent.parent.t,
1119 LTT_FACILITY_KERNEL, LTT_EVENT_SOFT_IRQ_ENTRY,
1120 LTT_FIELD_SOFT_IRQ_ID, 0, 0,
1121 before_soft_irq_entry, NULL,
1122 &g_array_index(hooks, LttvTraceHook, hn++));
1125 ret = lttv_trace_find_hook(ts->parent.parent.t,
1126 LTT_FACILITY_KERNEL, LTT_EVENT_SOFT_IRQ_EXIT,
1128 before_soft_irq_exit, NULL,
1129 &g_array_index(hooks, LttvTraceHook, hn++));
1132 ret = lttv_trace_find_hook(ts->parent.parent.t,
1133 LTT_FACILITY_PROCESS, LTT_EVENT_SCHEDCHANGE,
1134 LTT_FIELD_OUT, LTT_FIELD_IN, LTT_FIELD_OUT_STATE,
1135 before_schedchange, NULL,
1136 &g_array_index(hooks, LttvTraceHook, hn++));
1139 ret = lttv_trace_find_hook(ts->parent.parent.t,
1140 LTT_FACILITY_USER_GENERIC, LTT_EVENT_FUNCTION_ENTRY,
1141 LTT_FIELD_THIS_FN, LTT_FIELD_CALL_SITE, 0,
1142 before_function_entry, NULL,
1143 &g_array_index(hooks, LttvTraceHook, hn++));
1146 ret = lttv_trace_find_hook(ts->parent.parent.t,
1147 LTT_FACILITY_USER_GENERIC, LTT_EVENT_FUNCTION_EXIT,
1148 LTT_FIELD_THIS_FN, LTT_FIELD_CALL_SITE, 0,
1149 before_function_exit, NULL,
1150 &g_array_index(hooks, LttvTraceHook, hn++));
1153 /* statedump-related hooks */
1154 ret = lttv_trace_find_hook(ts->parent.parent.t,
1155 LTT_FACILITY_STATEDUMP, LTT_EVENT_ENUM_PROCESS_STATE,
1156 LTT_FIELD_PID, LTT_FIELD_PARENT_PID, LTT_FIELD_NAME,
1157 before_enum_process_state, NULL,
1158 &g_array_index(hooks, LttvTraceHook, hn++));
1161 ret = lttv_trace_find_hook(ts->parent.parent.t,
1162 LTT_FACILITY_XENOLTT, LTT_EVENT_XENOLTT_THREAD_START,
1164 xenoltt_before_change_state, NULL,
1165 &g_array_index(hooks, LttvTraceHook, hn++));
1168 ret = lttv_trace_find_hook(ts->parent.parent.t,
1169 LTT_FACILITY_XENOLTT, LTT_EVENT_XENOLTT_THREAD_RESUME,
1171 xenoltt_before_change_state, NULL,
1172 &g_array_index(hooks, LttvTraceHook, hn++));
1175 ret = lttv_trace_find_hook(ts->parent.parent.t,
1176 LTT_FACILITY_XENOLTT, LTT_EVENT_XENOLTT_THREAD_WAIT_PERIOD,
1178 xenoltt_before_change_state, NULL,
1179 &g_array_index(hooks, LttvTraceHook, hn++));
1182 ret = lttv_trace_find_hook(ts->parent.parent.t,
1183 LTT_FACILITY_XENOLTT, LTT_EVENT_XENOLTT_THREAD_SUSPEND,
1185 xenoltt_before_change_state, NULL,
1186 &g_array_index(hooks, LttvTraceHook, hn++));
1189 ret = lttv_trace_find_hook(ts->parent.parent.t,
1190 LTT_FACILITY_XENOLTT, LTT_EVENT_XENOLTT_THREAD_SWITCH,
1192 xenoltt_before_change_state, NULL,
1193 &g_array_index(hooks, LttvTraceHook, hn++));
1196 ret = lttv_trace_find_hook(ts->parent.parent.t,
1197 LTT_FACILITY_XENOLTT, LTT_EVENT_XENOLTT_SYNCH_UNLOCK,
1198 LTT_FIELD_XENOLTT_SYNCH, 0, 0,
1199 xenoltt_synch_unblock, NULL,
1200 &g_array_index(hooks, LttvTraceHook, hn++));
1203 g_array_set_size(hooks, hn);
1205 before_hooks = hooks;
1207 hooks = g_array_sized_new(FALSE, FALSE, sizeof(LttvTraceHook), 24);
1208 g_array_set_size(hooks, 24);
1211 ret = lttv_trace_find_hook(ts->parent.parent.t,
1212 LTT_FACILITY_KERNEL_ARCH, LTT_EVENT_SYSCALL_ENTRY,
1213 LTT_FIELD_SYSCALL_ID, 0, 0,
1214 after_syscall_entry, NULL,
1215 &g_array_index(hooks, LttvTraceHook, hn++));
1218 ret = lttv_trace_find_hook(ts->parent.parent.t,
1219 LTT_FACILITY_KERNEL_ARCH, LTT_EVENT_SYSCALL_EXIT,
1221 after_syscall_exit, NULL,
1222 &g_array_index(hooks, LttvTraceHook, hn++));
1225 ret = lttv_trace_find_hook(ts->parent.parent.t,
1226 LTT_FACILITY_KERNEL, LTT_EVENT_TRAP_ENTRY,
1227 LTT_FIELD_TRAP_ID, 0, 0,
1228 after_trap_entry, NULL,
1229 &g_array_index(hooks, LttvTraceHook, hn++));
1232 ret = lttv_trace_find_hook(ts->parent.parent.t,
1233 LTT_FACILITY_KERNEL, LTT_EVENT_TRAP_EXIT,
1235 after_trap_exit, NULL,
1236 &g_array_index(hooks, LttvTraceHook, hn++));
1239 ret = lttv_trace_find_hook(ts->parent.parent.t,
1240 LTT_FACILITY_KERNEL, LTT_EVENT_IRQ_ENTRY,
1241 LTT_FIELD_IRQ_ID, 0, 0,
1242 after_irq_entry, NULL,
1243 &g_array_index(hooks, LttvTraceHook, hn++));
1246 ret = lttv_trace_find_hook(ts->parent.parent.t,
1247 LTT_FACILITY_KERNEL, LTT_EVENT_IRQ_EXIT,
1249 after_irq_exit, NULL,
1250 &g_array_index(hooks, LttvTraceHook, hn++));
1253 ret = lttv_trace_find_hook(ts->parent.parent.t,
1254 LTT_FACILITY_KERNEL, LTT_EVENT_SOFT_IRQ_ENTRY,
1255 LTT_FIELD_SOFT_IRQ_ID, 0, 0,
1256 after_irq_entry, NULL,
1257 &g_array_index(hooks, LttvTraceHook, hn++));
1260 ret = lttv_trace_find_hook(ts->parent.parent.t,
1261 LTT_FACILITY_KERNEL, LTT_EVENT_SOFT_IRQ_EXIT,
1263 after_soft_irq_exit, NULL,
1264 &g_array_index(hooks, LttvTraceHook, hn++));
1267 ret = lttv_trace_find_hook(ts->parent.parent.t,
1268 LTT_FACILITY_PROCESS, LTT_EVENT_SCHEDCHANGE,
1269 LTT_FIELD_OUT, LTT_FIELD_IN, LTT_FIELD_OUT_STATE,
1270 after_schedchange, NULL,
1271 &g_array_index(hooks, LttvTraceHook, hn++));
1274 ret = lttv_trace_find_hook(ts->parent.parent.t,
1275 LTT_FACILITY_PROCESS, LTT_EVENT_FORK,
1276 LTT_FIELD_PARENT_PID, LTT_FIELD_CHILD_PID, 0,
1278 &g_array_index(hooks, LttvTraceHook, hn++));
1281 ret = lttv_trace_find_hook(ts->parent.parent.t,
1282 LTT_FACILITY_PROCESS, LTT_EVENT_EXIT,
1283 LTT_FIELD_PID, 0, 0,
1285 &g_array_index(hooks, LttvTraceHook, hn++));
1288 ret = lttv_trace_find_hook(ts->parent.parent.t,
1289 LTT_FACILITY_PROCESS, LTT_EVENT_FREE,
1290 LTT_FIELD_PID, 0, 0,
1292 &g_array_index(hooks, LttvTraceHook, hn++));
1295 ret = lttv_trace_find_hook(ts->parent.parent.t,
1296 LTT_FACILITY_USER_GENERIC, LTT_EVENT_FUNCTION_ENTRY,
1297 LTT_FIELD_THIS_FN, LTT_FIELD_CALL_SITE, 0,
1298 after_function_entry, NULL,
1299 &g_array_index(hooks, LttvTraceHook, hn++));
1302 ret = lttv_trace_find_hook(ts->parent.parent.t,
1303 LTT_FACILITY_USER_GENERIC, LTT_EVENT_FUNCTION_EXIT,
1304 LTT_FIELD_THIS_FN, LTT_FIELD_CALL_SITE, 0,
1305 after_function_exit, NULL,
1306 &g_array_index(hooks, LttvTraceHook, hn++));
1309 /* statedump-related hooks */
1310 ret = lttv_trace_find_hook(ts->parent.parent.t,
1311 LTT_FACILITY_STATEDUMP, LTT_EVENT_ENUM_PROCESS_STATE,
1312 LTT_FIELD_PID, LTT_FIELD_PARENT_PID, LTT_FIELD_NAME,
1313 after_enum_process_state, NULL,
1314 &g_array_index(hooks, LttvTraceHook, hn++));
1318 /* xenoltt-related hooks */
1319 ret = lttv_trace_find_hook(ts->parent.parent.t,
1320 LTT_FACILITY_XENOLTT, LTT_EVENT_XENOLTT_THREAD_INIT,
1321 LTT_FIELD_XENOLTT_NAME, 0, 0,
1322 xenoltt_thread_init, NULL,
1323 &g_array_index(hooks, LttvTraceHook, hn++));
1326 ret = lttv_trace_find_hook(ts->parent.parent.t,
1327 LTT_FACILITY_XENOLTT, LTT_EVENT_XENOLTT_THREAD_SET_PERIOD,
1329 xenoltt_thread_set_period, NULL,
1330 &g_array_index(hooks, LttvTraceHook, hn++));
1333 ret = lttv_trace_find_hook(ts->parent.parent.t,
1334 LTT_FACILITY_XENOLTT, LTT_EVENT_XENOLTT_THREAD_RENICE,
1336 xenoltt_thread_renice, NULL,
1337 &g_array_index(hooks, LttvTraceHook, hn++));
1340 ret = lttv_trace_find_hook(ts->parent.parent.t,
1341 LTT_FACILITY_XENOLTT, LTT_EVENT_XENOLTT_THREAD_MISSED_PERIOD,
1342 LTT_FIELD_XENOLTT_NAME, LTT_FIELD_XENOLTT_ADDRESS, LTT_FIELD_XENOLTT_OVERRUNS,
1343 xenoltt_thread_overruns, NULL,
1344 &g_array_index(hooks, LttvTraceHook, hn++));
1347 ret = lttv_trace_find_hook(ts->parent.parent.t,
1348 LTT_FACILITY_XENOLTT, LTT_EVENT_XENOLTT_SYNCH_SET_OWNER,
1349 LTT_FIELD_XENOLTT_SYNCH, 0, 0,
1350 xenoltt_synch_owner, NULL,
1351 &g_array_index(hooks, LttvTraceHook, hn++));
1354 ret = lttv_trace_find_hook(ts->parent.parent.t,
1355 LTT_FACILITY_XENOLTT, LTT_EVENT_XENOLTT_SYNCH_WAKEUPX,
1356 LTT_FIELD_XENOLTT_SYNCH, LTT_FIELD_XENOLTT_NAME, LTT_FIELD_XENOLTT_ADDRESS,
1357 xenoltt_synch_wakeup, NULL,
1358 &g_array_index(hooks, LttvTraceHook, hn++));
1361 ret = lttv_trace_find_hook(ts->parent.parent.t,
1362 LTT_FACILITY_XENOLTT, LTT_EVENT_XENOLTT_SYNCH_WAKEUP1,
1363 LTT_FIELD_XENOLTT_SYNCH, LTT_FIELD_XENOLTT_NAME, LTT_FIELD_XENOLTT_ADDRESS,
1364 xenoltt_synch_wakeup, NULL,
1365 &g_array_index(hooks, LttvTraceHook, hn++));
1368 ret = lttv_trace_find_hook(ts->parent.parent.t,
1369 LTT_FACILITY_XENOLTT, LTT_EVENT_XENOLTT_SYNCH_SLEEP_ON,
1370 LTT_FIELD_XENOLTT_SYNCH, LTT_FIELD_XENOLTT_NAME, LTT_FIELD_XENOLTT_ADDRESS,
1371 xenoltt_synch_wait, NULL,
1372 &g_array_index(hooks, LttvTraceHook, hn++));
1376 ret = lttv_trace_find_hook(ts->parent.parent.t,
1377 LTT_FACILITY_XENOLTT, LTT_EVENT_XENOLTT_SYNCH_FLUSH,
1378 LTT_FIELD_XENOLTT_SYNCH, 0, 0,
1379 xenoltt_synch_flush, NULL, &g_array_index(hooks, LttvTraceHook, hn++));
1383 ret = lttv_trace_find_hook(ts->parent.parent.t,
1384 LTT_FACILITY_XENOLTT, LTT_EVENT_XENOLTT_SYNCH_FORGET,
1385 LTT_FIELD_XENOLTT_SYNCH, LTT_FIELD_XENOLTT_NAME, LTT_FIELD_XENOLTT_ADDRESS,
1386 xenoltt_synch_wakeup, NULL, &g_array_index(hooks, LttvTraceHook, hn++));
1389 ret = lttv_trace_find_hook(ts->parent.parent.t,
1390 LTT_FACILITY_XENOLTT, LTT_EVENT_XENOLTT_THREAD_START,
1392 xenoltt_after_change_state, NULL,
1393 &g_array_index(hooks, LttvTraceHook, hn++));
1396 ret = lttv_trace_find_hook(ts->parent.parent.t,
1397 LTT_FACILITY_XENOLTT, LTT_EVENT_XENOLTT_THREAD_RESUME,
1399 xenoltt_after_change_state, NULL,
1400 &g_array_index(hooks, LttvTraceHook, hn++));
1403 ret = lttv_trace_find_hook(ts->parent.parent.t,
1404 LTT_FACILITY_XENOLTT, LTT_EVENT_XENOLTT_THREAD_WAIT_PERIOD,
1406 xenoltt_after_change_state, NULL,
1407 &g_array_index(hooks, LttvTraceHook, hn++));
1410 ret = lttv_trace_find_hook(ts->parent.parent.t,
1411 LTT_FACILITY_XENOLTT, LTT_EVENT_XENOLTT_THREAD_SUSPEND,
1413 xenoltt_after_change_state, NULL,
1414 &g_array_index(hooks, LttvTraceHook, hn++));
1417 ret = lttv_trace_find_hook(ts->parent.parent.t,
1418 LTT_FACILITY_XENOLTT, LTT_EVENT_XENOLTT_THREAD_SWITCH,
1420 xenoltt_after_change_state, NULL,
1421 &g_array_index(hooks, LttvTraceHook, hn++));
1424 g_array_set_size(hooks, hn);
1426 after_hooks = hooks;
1428 /* Add these hooks to each event_by_id hooks list */
1430 nb_tracefile = ts->parent.parent.tracefiles->len;
1432 for(j = 0 ; j < nb_tracefile ; j++) {
1433 tfs = LTTV_TRACEFILE_STATS(g_array_index(ts->parent.parent.tracefiles,
1434 LttvTracefileContext*, j));
1435 lttv_hooks_add(tfs->parent.parent.event, every_event, NULL,
1438 for(k = 0 ; k < before_hooks->len ; k++) {
1439 hook = &g_array_index(before_hooks, LttvTraceHook, k);
1440 for(l = 0; l<hook->fac_list->len;l++) {
1441 thf = g_array_index(hook->fac_list, LttvTraceHookByFacility*, l);
1443 lttv_hooks_by_id_find(tfs->parent.parent.event_by_id, thf->id),
1446 LTTV_PRIO_STATS_BEFORE_STATE);
1449 for(k = 0 ; k < after_hooks->len ; k++) {
1450 hook = &g_array_index(after_hooks, LttvTraceHook, k);
1451 for(l = 0; l<hook->fac_list->len;l++) {
1452 thf = g_array_index(hook->fac_list, LttvTraceHookByFacility*, l);
1454 lttv_hooks_by_id_find(tfs->parent.parent.event_by_id, thf->id),
1457 LTTV_PRIO_STATS_AFTER_STATE);
1461 lttv_attribute_find(self->parent.parent.a, LTTV_STATS_BEFORE_HOOKS,
1462 LTTV_POINTER, &val);
1463 *(val.v_pointer) = before_hooks;
1464 lttv_attribute_find(self->parent.parent.a, LTTV_STATS_AFTER_HOOKS,
1465 LTTV_POINTER, &val);
1466 *(val.v_pointer) = after_hooks;
1470 // Hook wrapper. call_data is a traceset context.
1471 gboolean lttv_stats_hook_remove_event_hooks(void *hook_data, void *call_data)
1473 LttvTracesetStats *tss = (LttvTracesetStats*)call_data;
1475 lttv_stats_remove_event_hooks(tss);
1480 void lttv_stats_remove_event_hooks(LttvTracesetStats *self)
1482 LttvTraceset *traceset = self->parent.parent.ts;
1484 guint i, j, k, l, nb_trace, nb_tracefile;
1488 LttvTracefileStats *tfs;
1492 GArray *before_hooks, *after_hooks;
1494 LttvTraceHook *hook;
1496 LttvTraceHookByFacility *thf;
1498 LttvAttributeValue val;
1500 nb_trace = lttv_traceset_number(traceset);
1501 for(i = 0 ; i < nb_trace ; i++) {
1502 ts = (LttvTraceStats*)self->parent.parent.traces[i];
1503 lttv_attribute_find(self->parent.parent.a, LTTV_STATS_BEFORE_HOOKS,
1504 LTTV_POINTER, &val);
1505 before_hooks = *(val.v_pointer);
1506 lttv_attribute_find(self->parent.parent.a, LTTV_STATS_AFTER_HOOKS,
1507 LTTV_POINTER, &val);
1508 after_hooks = *(val.v_pointer);
1510 /* Remove these hooks from each event_by_id hooks list */
1512 nb_tracefile = ts->parent.parent.tracefiles->len;
1514 for(j = 0 ; j < nb_tracefile ; j++) {
1515 tfs = LTTV_TRACEFILE_STATS(g_array_index(ts->parent.parent.tracefiles,
1516 LttvTracefileContext*, j));
1517 lttv_hooks_remove_data(tfs->parent.parent.event, every_event,
1520 for(k = 0 ; k < before_hooks->len ; k++) {
1521 hook = &g_array_index(before_hooks, LttvTraceHook, k);
1522 for(l = 0 ; l < hook->fac_list->len ; l++) {
1523 thf = g_array_index(hook->fac_list, LttvTraceHookByFacility*, l);
1524 lttv_hooks_remove_data(
1525 lttv_hooks_by_id_find(tfs->parent.parent.event_by_id, thf->id),
1530 for(k = 0 ; k < after_hooks->len ; k++) {
1531 hook = &g_array_index(after_hooks, LttvTraceHook, k);
1532 for(l = 0 ; l < hook->fac_list->len ; l++) {
1533 thf = g_array_index(hook->fac_list, LttvTraceHookByFacility*, l);
1534 lttv_hooks_remove_data(
1535 lttv_hooks_by_id_find(tfs->parent.parent.event_by_id, thf->id),
1541 g_debug("lttv_stats_remove_event_hooks()");
1542 g_array_free(before_hooks, TRUE);
1543 g_array_free(after_hooks, TRUE);
1549 /****************************************************************************************************************************/
1551 void lttv_xeno_stats_sum_trace(LttvTraceStats *self, LttvAttribute *ts_stats){
1552 LttvAttribute *sum_container = self->xenoltt_stats;
1553 LttvAttributeType type;
1554 LttvAttributeValue value;
1555 LttvAttributeName name;
1558 int trace_is_summed;
1561 LttvAttribute *main_tree, *threads_tree, *thread_tree;
1563 main_tree = sum_container;
1565 lttv_attribute_find(sum_container,LTTV_STATS_SUMMED, LTTV_UINT, &value);
1566 trace_is_summed = *(value.v_uint);
1567 *(value.v_uint) = 1;
1569 /* First cleanup the state : sum all stalled information (never ending
1571 if(!trace_is_summed) lttv_stats_cleanup_state(self);
1573 // First level of Xenomai Tasks Statistics Tree
1574 threads_tree = lttv_attribute_find_subdir(main_tree, LTTV_XENO_STATS_THREADS);
1575 nb_threads = lttv_attribute_get_number(threads_tree);
1580 void lttv_xeno_stats_sum_traceset(LttvTracesetStats *self){
1581 LttvTraceset *traceset = self->parent.parent.ts;
1582 LttvAttribute *sum_container = self->xenoltt_stats;
1584 LttvTraceStats *tcs;
1588 LttvAttribute *main_tree;
1590 LttvAttributeValue value;
1592 lttv_attribute_find(sum_container, LTTV_STATS_SUMMED,
1594 if(*(value.v_uint) != 0) return;
1595 *(value.v_uint) = 1;
1597 nb_trace = lttv_traceset_number(traceset);
1599 for(i = 0 ; i < nb_trace ; i++) {
1600 tcs = (LttvTraceStats *)(self->parent.parent.traces[i]);
1601 lttv_xeno_stats_sum_trace(tcs, self->xenoltt_stats);
1606 /****************************************************************************
1607 - Task Name ( Address, Priority, Period )
1609 * Running Avg, Max, Min
1610 * Suspend Avg, Max, Min
1611 * Ready Avg, Max, Min
1613 - # ( ticks missed, time )
1615 - Status name (#, total time, avg)
1618 - Possession (#, time, avg)
1619 - Waiting (#, time, avg)
1621 *****************************************************************************/
1623 static void xeno_find_task_tree(LttvTracefileStats *tfcs, GQuark name, gulong address, guint cpu,
1624 LttvAttribute **events_tree, LttvAttribute **event_types_tree){
1625 LttvAttribute *a, *task_tree, *period_tree, *state_tree, *synch_tree;
1627 LttvAttributeValue thread_name, thread_address, prio, period;
1629 LttvTraceStats *tcs = (LttvTraceStats*)tfcs->parent.parent.t_context;
1630 task_tree = lttv_attribute_find_subdir(tcs->xenoltt_stats, LTTV_XENO_STATS_THREADS);
1632 task_tree = lttv_attribute_find_subdir(task_tree, name);
1633 lttv_attribute_find(task_tree, LTTV_XENO_STATS_THREAD_ADDRESS, LTTV_POINTER, &thread_address);
1634 *(thread_address.v_pointer) = address;
1636 lttv_attribute_find(task_tree, LTTV_XENO_STATS_THREAD_PERIOD, LTTV_UINT, &period);
1637 lttv_attribute_find(task_tree, LTTV_XENO_STATS_THREAD_PRIO, LTTV_UINT, &prio);
1638 *events_tree = task_tree;
1640 period_tree = lttv_attribute_find_subdir(task_tree, LTTV_XENO_STATS_PERIOD);
1641 lttv_attribute_find(period_tree, LTTV_XENO_STATS_THREAD_PERIOD, LTTV_UINT, &period);
1642 lttv_attribute_find(period_tree, LTTV_XENO_STATS_NB_PERIOD, LTTV_UINT, &period);
1644 lttv_attribute_find(period_tree, LTTV_XENO_STATE_READY, LTTV_STRING, &prio);
1645 *(prio.v_string) = "";
1646 lttv_attribute_find(period_tree, LTTV_XENO_STATS_TEXT_READY_AVG, LTTV_UINT, &prio);
1647 lttv_attribute_find(period_tree, LTTV_XENO_STATS_TEXT_READY_MAX, LTTV_UINT, &prio);
1648 lttv_attribute_find(period_tree, LTTV_XENO_STATS_TEXT_READY_MIN, LTTV_UINT, &prio);
1649 lttv_attribute_find(period_tree, LTTV_XENO_STATE_RUN, LTTV_STRING, &prio);
1650 *(prio.v_string) = "";
1651 lttv_attribute_find(period_tree, LTTV_XENO_STATS_TEXT_RUNNING_AVG, LTTV_UINT, &prio);
1652 lttv_attribute_find(period_tree, LTTV_XENO_STATS_TEXT_RUNNING_MAX, LTTV_UINT, &prio);
1653 lttv_attribute_find(period_tree, LTTV_XENO_STATS_TEXT_RUNNING_MIN, LTTV_UINT, &prio);
1654 lttv_attribute_find(period_tree, LTTV_XENO_STATE_SUSPEND, LTTV_STRING, &prio);
1655 *(prio.v_string) = "";
1656 lttv_attribute_find(period_tree, LTTV_XENO_STATS_TEXT_SUSPEND_AVG, LTTV_UINT, &prio);
1657 lttv_attribute_find(period_tree, LTTV_XENO_STATS_TEXT_SUSPEND_MAX, LTTV_UINT, &prio);
1658 lttv_attribute_find(period_tree, LTTV_XENO_STATS_TEXT_SUSPEND_MIN, LTTV_UINT, &prio);
1661 lttv_attribute_find_subdir(task_tree, LTTV_XENO_STATS_PERIOD_OVERRUNS);
1664 state_tree = lttv_attribute_find_subdir(task_tree, LTTV_XENO_STATS_STATE);
1666 synch_tree = lttv_attribute_find_subdir(task_tree, LTTV_XENO_STATS_SYNCH);
1668 a = lttv_attribute_find_subdir(task_tree, LTTV_STATS_EVENT_TYPES);
1669 *event_types_tree = a;
1672 gboolean xenoltt_thread_init(void *hook_data, void *call_data){
1673 LttvTracefileStats *tfcs = (LttvTracefileStats *)call_data;
1674 LttvTraceState *ts = (LttvTraceState*)tfcs->parent.parent.t_context;
1675 LttvXenoThreadState *thread;
1676 LttvAttributeValue prio;
1677 guint cpu = tfcs->parent.cpu;
1678 thread = ts->running_thread[cpu];
1680 xeno_find_task_tree(tfcs, thread->name, thread->address,cpu, &(tfcs->current_events_tree), &(tfcs->current_event_types_tree));
1682 lttv_attribute_find(tfcs->current_events_tree, LTTV_XENO_STATS_THREAD_PRIO, LTTV_UINT, &prio);
1683 *(prio.v_uint) = thread->prio;
1685 xenoltt_after_change_state(hook_data,call_data);
1687 printf("init %s\n",g_quark_to_string(thread->name));
1691 gboolean xenoltt_thread_renice(void *hook_data, void *call_data){
1692 LttvTracefileStats *tfcs = (LttvTracefileStats *)call_data;
1693 LttvTraceState *ts = (LttvTraceState*)tfcs->parent.parent.t_context;
1694 LttvXenoThreadState *thread;
1695 LttvAttributeValue prio;
1696 guint cpu = tfcs->parent.cpu;
1697 thread = ts->running_thread[cpu];
1699 xeno_find_task_tree(tfcs, thread->name, thread->address,cpu, &(tfcs->current_events_tree), &(tfcs->current_event_types_tree));
1701 lttv_attribute_find(tfcs->current_events_tree, LTTV_XENO_STATS_THREAD_PRIO, LTTV_UINT, &prio);
1702 *(prio.v_uint) = thread->prio;
1707 gboolean xenoltt_thread_set_period(void *hook_data, void *call_data){
1708 LttvTracefileStats *tfcs = (LttvTracefileStats *)call_data;
1709 LttvTraceState *ts = (LttvTraceState*)tfcs->parent.parent.t_context;
1710 LttvXenoThreadState *thread;
1711 LttvAttributeValue period, *period_tree;
1712 guint cpu = tfcs->parent.cpu;
1713 thread = ts->running_thread[cpu];
1715 // Find corresponding task
1716 xeno_find_task_tree(tfcs, thread->name, thread->address,cpu, &(tfcs->current_events_tree), &(tfcs->current_event_types_tree));
1718 // Write the period of the task
1719 lttv_attribute_find(tfcs->current_events_tree, LTTV_XENO_STATS_THREAD_PERIOD, LTTV_UINT, &period);
1720 *(period.v_uint) = thread->period;
1722 period_tree = lttv_attribute_find_subdir(tfcs->current_events_tree, LTTV_XENO_STATS_PERIOD);
1723 lttv_attribute_find(period_tree, LTTV_XENO_STATS_THREAD_PERIOD, LTTV_UINT, &period);
1724 *(period.v_uint) = thread->period;
1729 gboolean xenoltt_thread_overruns(void *hook_data, void *call_data){
1730 LttvTracefileStats *tfcs = (LttvTracefileStats *)call_data;
1731 LttvTraceState *ts = (LttvTraceState*)tfcs->parent.parent.t_context;
1732 LttEvent *e = ltt_tracefile_get_event(tfcs->parent.parent.tf);
1733 LttvTraceHookByFacility *thf = (LttvTraceHookByFacility *)hook_data;
1734 LttvAttributeValue overrun, *overrun_tree;
1735 guint cpu = tfcs->parent.cpu;
1737 g_assert(thf->f1 != NULL);
1738 GQuark name = g_quark_from_string(ltt_event_get_string(e, thf->f1));
1739 g_assert(thf->f2 != NULL);
1740 gulong address = ltt_event_get_long_unsigned(e, thf->f2);
1741 g_assert(thf->f3 != NULL);
1742 guint overruns = ltt_event_get_long_unsigned(e, thf->f3);
1743 LttvXenoThreadState *thread = lttv_xeno_state_find_thread(ts,cpu,address);
1744 xeno_find_task_tree(tfcs, name, address,cpu, &(tfcs->current_events_tree), &(tfcs->current_event_types_tree));
1746 // overrun_tree = lttv_attribute_find_subdir(tfcs->current_events_tree, LTTV_XENO_STATS_PERIOD);
1747 overrun_tree = lttv_attribute_find_subdir(tfcs->current_events_tree, LTTV_XENO_STATS_PERIOD_OVERRUNS);
1749 gchar overrun_time[MAX_64_HEX_STRING_LEN];
1750 sprintf(overrun_time,"%lu,%lu", tfcs->parent.parent.timestamp.tv_sec,tfcs->parent.parent.timestamp.tv_nsec);
1751 overrun_tree = lttv_attribute_find_subdir(overrun_tree, g_quark_from_string(overrun_time));
1753 lttv_attribute_find(overrun_tree, LTTV_XENO_STATS_TEXT_TICKS, LTTV_UINT, &overrun);
1754 *(overrun.v_uint) = overruns;
1756 LttTime delta = ltt_time_sub(tfcs->parent.parent.timestamp, thread->state->overrun_start);
1757 lttv_attribute_find(overrun_tree, LTTV_XENO_STATS_TEXT_TOTAL, LTTV_TIME, &overrun);
1758 *(overrun.v_time) = delta;
1762 gboolean xenoltt_before_change_state(void *hook_data, void *call_data){
1763 LttvTracefileStats *tfcs = (LttvTracefileStats *)call_data;
1764 LttvTraceState *ts = (LttvTraceState*)tfcs->parent.parent.t_context;
1765 LttvXenoThreadState *thread;
1766 LttvAttributeValue *a, state_count, state_time, state_time_average, time, period_count, time_ready, time_run, time_suspend;
1767 guint cpu = tfcs->parent.cpu;
1768 thread = ts->running_thread[cpu];
1771 xeno_find_task_tree(tfcs, thread->name, thread->address,cpu, &(tfcs->current_events_tree), &(tfcs->current_event_types_tree));
1773 // Create or go to State subtree
1774 a = lttv_attribute_find_subdir(tfcs->current_events_tree, LTTV_XENO_STATS_STATE);
1775 // Create or go to the current state subtree
1776 a = lttv_attribute_find_subdir(a, thread->state->status);
1777 lttv_attribute_find(a, g_quark_from_string("Number of times in this state"), LTTV_UINT, &state_count);
1779 LttTime delta = ltt_time_sub(tfcs->parent.parent.timestamp, thread->state->change);
1780 lttv_attribute_find(a, g_quark_from_string("Cumulative time"), LTTV_TIME, &state_time);
1781 *(state_time.v_time) = ltt_time_add(*(state_time.v_time), delta);
1783 lttv_attribute_find(a, g_quark_from_string("Average elapsed time"), LTTV_TIME, &state_time_average);
1784 if (*(state_count.v_uint) == 0 || ltt_time_compare(*(state_time.v_time),ltt_time_zero) == 0) *(state_time_average.v_time) = *(state_time.v_time);
1785 else *(state_time_average.v_time) = ltt_time_div(*(state_time.v_time), *(state_count.v_uint));
1787 // When wait_period is called, this means that the thread as finished executing the current period
1788 LttvTracefileContext *tfc = (LttvTracefileContext *)call_data;
1789 LttEvent *e = ltt_tracefile_get_event(tfc->tf);
1790 GQuark event_name = ltt_eventtype_name(ltt_event_eventtype(e));
1791 if (event_name == LTT_EVENT_XENOLTT_THREAD_WAIT_PERIOD){
1792 a = lttv_attribute_find_subdir(tfcs->current_events_tree, LTTV_XENO_STATS_PERIOD);
1793 lttv_attribute_find(a, LTTV_XENO_STATS_NB_PERIOD, LTTV_UINT, &period_count);
1794 // Now we need to update all fields
1795 a = lttv_attribute_find_subdir(tfcs->current_events_tree, LTTV_XENO_STATS_PERIOD);
1797 lttv_attribute_find(a, LTTV_XENO_STATE_READY, LTTV_TIME, &time_ready);
1799 lttv_attribute_find(a, LTTV_XENO_STATS_TEXT_READY_AVG, LTTV_TIME, &time);
1800 total = ltt_time_mul(*(time_ready.v_time),*(period_count.v_uint));
1801 total = ltt_time_add(*(time.v_time),total);
1802 if (ltt_time_compare(total,ltt_time_zero) != 0) *(time.v_time) = ltt_time_div(total,(*(period_count.v_uint)+1));
1804 lttv_attribute_find(a, LTTV_XENO_STATS_TEXT_READY_MAX, LTTV_TIME, &time);
1805 if(ltt_time_compare(*(time_ready.v_time),*(time.v_time)) == 1) *(time.v_time) = *(time_ready.v_time);
1807 lttv_attribute_find(a, LTTV_XENO_STATS_TEXT_READY_MIN, LTTV_TIME, &time);
1808 if(ltt_time_compare(*(time_ready.v_time),*(time.v_time)) == -1) *(time.v_time) = *(time_ready.v_time);
1810 *(time_ready.v_time) = ltt_time_zero;
1812 lttv_attribute_find(a, LTTV_XENO_STATE_RUN, LTTV_TIME, &time_run);
1813 lttv_attribute_find(a, LTTV_XENO_STATS_TEXT_RUNNING_AVG, LTTV_TIME, &time);
1814 total = ltt_time_mul(*(time_run.v_time),*(period_count.v_uint));
1815 total = ltt_time_add(*(time.v_time),total);
1816 if (ltt_time_compare(total,ltt_time_zero) != 0) *(time.v_time) = ltt_time_div(total,(*(period_count.v_uint)+1));
1818 lttv_attribute_find(a, LTTV_XENO_STATS_TEXT_RUNNING_MAX, LTTV_TIME, &time);
1819 if(ltt_time_compare(*(time_run.v_time),*(time.v_time)) == 1) *(time.v_time) = *(time_run.v_time);
1821 lttv_attribute_find(a, LTTV_XENO_STATS_TEXT_RUNNING_MIN, LTTV_TIME, &time);
1822 if(ltt_time_compare(*(time_run.v_time),*(time.v_time)) == -1) *(time.v_time) = *(time_run.v_time);
1824 *(time_run.v_time) = ltt_time_zero;
1826 lttv_attribute_find(a, LTTV_XENO_STATE_SUSPEND, LTTV_TIME, &time_suspend);
1827 lttv_attribute_find(a, LTTV_XENO_STATS_TEXT_SUSPEND_AVG, LTTV_TIME, &time);
1828 total = ltt_time_mul(*(time_suspend.v_time),*(period_count.v_uint));
1829 total = ltt_time_add(*(time.v_time),total);
1830 if (ltt_time_compare(total,ltt_time_zero) != 0) *(time.v_time) = ltt_time_div(total,(*(period_count.v_uint)+1));
1832 lttv_attribute_find(a, LTTV_XENO_STATS_TEXT_SUSPEND_MAX, LTTV_TIME, &time);
1833 if(ltt_time_compare(*(time_suspend.v_time),*(time.v_time)) == 1) *(time.v_time) = *(time_suspend.v_time);
1835 lttv_attribute_find(a, LTTV_XENO_STATS_TEXT_SUSPEND_MIN, LTTV_TIME, &time);
1836 if(ltt_time_compare(*(time_suspend.v_time),*(time.v_time)) == -1) *(time.v_time) = *(time_suspend.v_time);
1838 *(time_suspend.v_time) = ltt_time_zero;
1840 *(period_count.v_uint) = *(period_count.v_uint) + 1;
1844 // We want to update the period specific information about the state of the task
1845 if (thread->state->status == LTTV_XENO_STATE_READY){
1846 printf("add ready\n");
1847 a = lttv_attribute_find_subdir(tfcs->current_events_tree, LTTV_XENO_STATS_PERIOD);
1848 lttv_attribute_find(a, LTTV_XENO_STATE_READY, LTTV_TIME, &time);
1849 *(time.v_time) = ltt_time_add(*(time.v_time),delta);
1851 else if (thread->state->status == LTTV_XENO_STATE_RUN){
1852 printf("add run\n");
1853 a = lttv_attribute_find_subdir(tfcs->current_events_tree, LTTV_XENO_STATS_PERIOD);
1854 lttv_attribute_find(a, LTTV_XENO_STATE_RUN, LTTV_TIME, &time);
1855 *(time.v_time) = ltt_time_add(*(time.v_time),delta);
1857 else if (thread->state->status == LTTV_XENO_STATE_SUSPEND){
1858 a = lttv_attribute_find_subdir(tfcs->current_events_tree, LTTV_XENO_STATS_PERIOD);
1859 lttv_attribute_find(a, LTTV_XENO_STATE_SUSPEND, LTTV_TIME, &time);
1860 *(time.v_time) = ltt_time_add(*(time.v_time),delta);
1861 printf("add suspend\n");
1867 gboolean xenoltt_after_change_state(void *hook_data, void *call_data){
1868 LttvTracefileStats *tfcs = (LttvTracefileStats *)call_data;
1869 LttvTraceState *ts = (LttvTraceState*)tfcs->parent.parent.t_context;
1870 LttvXenoThreadState *thread;
1871 LttvAttributeValue *a, state_count, state_time, state_time_average;
1872 guint cpu = tfcs->parent.cpu;
1873 thread = ts->running_thread[cpu];
1875 xeno_find_task_tree(tfcs, thread->name, thread->address,cpu, &(tfcs->current_events_tree), &(tfcs->current_event_types_tree));
1877 // Create or go to State subtree
1878 a = lttv_attribute_find_subdir(tfcs->current_events_tree, LTTV_XENO_STATS_STATE);
1879 // Create or go to the current state subtree
1880 a = lttv_attribute_find_subdir(a, thread->state->status);
1881 lttv_attribute_find(a, g_quark_from_string("Number of times in this state"), LTTV_UINT, &state_count);
1882 *(state_count.v_uint) = *(state_count.v_uint) + 1;
1884 LttTime delta = ltt_time_sub(tfcs->parent.parent.timestamp, thread->state->entry);
1885 lttv_attribute_find(a, g_quark_from_string("Cumulative time"), LTTV_TIME, &state_time);
1886 *(state_time.v_time) = ltt_time_add(*(state_time.v_time), delta);
1888 lttv_attribute_find(a, g_quark_from_string("Average elapsed time"), LTTV_TIME, &state_time_average);
1889 if (*(state_count.v_uint) == 0 || ltt_time_compare(*(state_time.v_time),ltt_time_zero) == 0) *(state_time_average.v_time) = *(state_time.v_time);
1890 else *(state_time_average.v_time) = ltt_time_div(*(state_time.v_time), *(state_count.v_uint));
1896 gboolean xenoltt_synch_owner(void *hook_data, void *call_data){
1897 LttvTracefileStats *tfcs = (LttvTracefileStats *)call_data;
1898 LttvTraceState *ts = (LttvTraceState*)tfcs->parent.parent.t_context;
1899 LttEvent *e = ltt_tracefile_get_event(tfcs->parent.parent.tf);
1900 LttvTraceHookByFacility *thf = (LttvTraceHookByFacility *)hook_data;
1901 LttvAttributeValue synch, total_time, avg_time, max_time, min_time,*synch_tree;
1902 guint cpu = tfcs->parent.cpu;
1903 LttvXenoThreadState *thread = ts->running_thread[cpu];
1905 if (thread->state->started == TRUE){
1906 g_assert(thf->f1 != NULL);
1907 gulong synch_address = ltt_event_get_long_unsigned(e, thf->f1);
1909 xeno_find_task_tree(tfcs, thread->name, thread->address,cpu, &(tfcs->current_events_tree), &(tfcs->current_event_types_tree));
1911 synch_tree = lttv_attribute_find_subdir(tfcs->current_events_tree, LTTV_XENO_STATS_SYNCH);
1913 gchar synch_id[MAX_64_HEX_STRING_LEN];
1914 sprintf(synch_id,"%p", synch_address);
1915 synch_tree = lttv_attribute_find_subdir(synch_tree, g_quark_from_string(synch_id));
1917 lttv_attribute_find(synch_tree, LTTV_XENO_STATS_TEXT_OWNER, LTTV_UINT, &synch);
1918 *(synch.v_uint) = *(synch.v_uint) + 1;
1923 // When sleep-on is called
1924 gboolean xenoltt_synch_wait(void *hook_data, void *call_data){
1925 LttvTracefileStats *tfcs = (LttvTracefileStats *)call_data;
1926 LttvTraceState *ts = (LttvTraceState*)tfcs->parent.parent.t_context;
1927 LttEvent *e = ltt_tracefile_get_event(tfcs->parent.parent.tf);
1928 LttvTraceHookByFacility *thf = (LttvTraceHookByFacility *)hook_data;
1929 LttvAttributeValue synch, total_time, avg_time, max_time, min_time, *synch_tree;
1930 guint cpu = tfcs->parent.cpu;
1931 LttvXenoThreadState *thread;
1932 thread = ts->running_thread[cpu];
1934 g_assert(thf->f1 != NULL);
1935 gulong synch_address = ltt_event_get_long_unsigned(e, thf->f1);
1936 g_assert(thf->f2 != NULL);
1937 GQuark name = g_quark_from_string(ltt_event_get_string(e, thf->f2));
1938 g_assert(thf->f3 != NULL);
1939 gulong address = ltt_event_get_long_unsigned(e, thf->f3);
1941 xeno_find_task_tree(tfcs, name, address,cpu, &(tfcs->current_events_tree), &(tfcs->current_event_types_tree));
1943 synch_tree = lttv_attribute_find_subdir(tfcs->current_events_tree, LTTV_XENO_STATS_SYNCH);
1945 gchar synch_id[MAX_64_HEX_STRING_LEN];
1946 sprintf(synch_id,"%p", synch_address);
1947 synch_tree = lttv_attribute_find_subdir(synch_tree, g_quark_from_string(synch_id));
1949 // We have one more waiting call to register
1950 lttv_attribute_find(synch_tree, LTTV_XENO_STATS_TEXT_WAITING, LTTV_UINT, &synch);
1951 *(synch.v_uint) = *(synch.v_uint) + 1;
1956 gboolean xenoltt_synch_wakeup(void *hook_data, void *call_data){
1957 LttvTracefileStats *tfcs = (LttvTracefileStats *)call_data;
1958 LttvTraceState *ts = (LttvTraceState*)tfcs->parent.parent.t_context;
1959 LttEvent *e = ltt_tracefile_get_event(tfcs->parent.parent.tf);
1960 LttvTraceHookByFacility *thf = (LttvTraceHookByFacility *)hook_data;
1961 LttvAttributeValue synch, total_time, avg_time, max_time, min_time,*synch_tree;
1962 guint cpu = tfcs->parent.cpu;
1963 GQuark event_name = ltt_eventtype_name(ltt_event_eventtype(e));
1965 g_assert(thf->f1 != NULL);
1966 gulong synch_address = ltt_event_get_long_unsigned(e, thf->f1);
1967 g_assert(thf->f2 != NULL);
1968 GQuark name = g_quark_from_string(ltt_event_get_string(e, thf->f2));
1969 g_assert(thf->f3 != NULL);
1970 gulong address = ltt_event_get_long_unsigned(e, thf->f3);
1971 LttvXenoSynchState *synch_state = lttv_xeno_state_find_synch(ts,synch_address);
1972 LttvXenoThreadState *thread = lttv_xeno_state_find_thread(ts,cpu,address);
1973 if (synch_state != NULL && thread != NULL ){
1974 xeno_find_task_tree(tfcs, name, address,cpu, &(tfcs->current_events_tree), &(tfcs->current_event_types_tree));
1976 synch_tree = lttv_attribute_find_subdir(tfcs->current_events_tree, LTTV_XENO_STATS_SYNCH);
1978 gchar synch_id[MAX_64_HEX_STRING_LEN];
1979 sprintf(synch_id,"%p", synch_address);
1980 synch_tree = lttv_attribute_find_subdir(synch_tree, g_quark_from_string(synch_id));
1982 if (event_name != LTT_EVENT_XENOLTT_SYNCH_FORGET){
1983 lttv_attribute_find(synch_tree, LTTV_XENO_STATS_TEXT_OWNER, LTTV_UINT, &synch);
1984 *(synch.v_uint) = *(synch.v_uint) + 1;
1987 lttv_attribute_find(synch_tree, LTTV_XENO_STATS_TEXT_WAITING, LTTV_UINT, &synch);
1990 LttTime delta = ltt_time_sub(tfcs->parent.parent.timestamp, thread->start_wait_synch);
1991 lttv_attribute_find(synch_tree, LTTV_XENO_STATS_TEXT_WAITING_TOTAL, LTTV_TIME, &total_time);
1992 *(total_time.v_time) = ltt_time_add(*(total_time.v_time), delta);
1994 lttv_attribute_find(synch_tree, LTTV_XENO_STATS_TEXT_WAITING_AVG, LTTV_TIME, &avg_time);
1995 if (*(synch.v_uint) == 0 || ltt_time_compare(*(total_time.v_time),ltt_time_zero) == 0) *(avg_time.v_time) = *(total_time.v_time);
1996 else *(avg_time.v_time) = ltt_time_div(*(total_time.v_time), *(synch.v_uint));
1998 lttv_attribute_find(synch_tree, LTTV_XENO_STATS_TEXT_WAITING_MAX, LTTV_TIME, &max_time);
1999 // If this owning time is longer than any other before
2000 if (ltt_time_compare(delta,*(max_time.v_time)) == 1) *(max_time.v_time) = delta;
2002 lttv_attribute_find(synch_tree, LTTV_XENO_STATS_TEXT_WAITING_MIN, LTTV_TIME, &min_time);
2003 // If this owning time is shorter than any other before
2004 if (*(synch.v_uint) == 1) *(min_time.v_time) = delta;
2005 else if (ltt_time_compare(*(min_time.v_time), delta) == 1) *(min_time.v_time) = delta;
2012 gboolean xenoltt_synch_flush(void *hook_data, void *call_data){
2013 LttvTracefileStats *tfcs = (LttvTracefileStats *)call_data;
2014 LttvTraceState *ts = (LttvTraceState*)tfcs->parent.parent.t_context;
2015 LttEvent *e = ltt_tracefile_get_event(tfcs->parent.parent.tf);
2016 LttvTraceHookByFacility *thf = (LttvTraceHookByFacility *)hook_data;
2017 LttvAttributeValue synch, total_time, avg_time, max_time, min_time,*synch_tree;
2018 guint cpu = tfcs->parent.cpu;
2019 GQuark event_name = ltt_eventtype_name(ltt_event_eventtype(e));
2021 g_assert(thf->f1 != NULL);
2022 gulong synch_address = ltt_event_get_long_unsigned(e, thf->f1);
2024 LttvXenoSynchState *synch_state = lttv_xeno_state_find_synch(ts,synch_address);
2025 LttvXenoThreadState *thread;
2026 if (synch_state != NULL && thread != NULL ){
2028 for(i=0;i<synch_state->state->waiting_threads->len;i++){
2029 thread = g_array_index(synch_state->state->waiting_threads, LttvXenoThreadState*, i);
2031 xeno_find_task_tree(tfcs, thread->name, thread->address,cpu, &(tfcs->current_events_tree), &(tfcs->current_event_types_tree));
2033 synch_tree = lttv_attribute_find_subdir(tfcs->current_events_tree, LTTV_XENO_STATS_SYNCH);
2035 gchar synch_id[MAX_64_HEX_STRING_LEN];
2036 sprintf(synch_id,"%p", synch_address);
2037 synch_tree = lttv_attribute_find_subdir(synch_tree, g_quark_from_string(synch_id));
2039 if (event_name != LTT_EVENT_XENOLTT_SYNCH_FORGET){
2040 lttv_attribute_find(synch_tree, LTTV_XENO_STATS_TEXT_OWNER, LTTV_UINT, &synch);
2041 *(synch.v_uint) = *(synch.v_uint) + 1;
2044 lttv_attribute_find(synch_tree, LTTV_XENO_STATS_TEXT_WAITING, LTTV_UINT, &synch);
2046 LttTime delta = ltt_time_sub(tfcs->parent.parent.timestamp, thread->start_wait_synch);
2047 lttv_attribute_find(synch_tree, LTTV_XENO_STATS_TEXT_WAITING_TOTAL, LTTV_TIME, &total_time);
2048 *(total_time.v_time) = ltt_time_add(*(total_time.v_time), delta);
2050 lttv_attribute_find(synch_tree, LTTV_XENO_STATS_TEXT_WAITING_AVG, LTTV_TIME, &avg_time);
2051 if (*(synch.v_uint) == 0 || ltt_time_compare(*(total_time.v_time),ltt_time_zero) == 0) *(avg_time.v_time) = *(total_time.v_time);
2052 else *(avg_time.v_time) = ltt_time_div(*(total_time.v_time), *(synch.v_uint));
2054 lttv_attribute_find(synch_tree, LTTV_XENO_STATS_TEXT_WAITING_MAX, LTTV_TIME, &max_time);
2055 // If this owning time is longer than any other before
2056 if (ltt_time_compare(delta,*(max_time.v_time)) == 1) *(max_time.v_time) = delta;
2058 lttv_attribute_find(synch_tree, LTTV_XENO_STATS_TEXT_WAITING_MIN, LTTV_TIME, &min_time);
2059 // If this owning time is shorter than any other before
2060 if (*(synch.v_uint) == 1) *(min_time.v_time) = delta;
2061 else if (ltt_time_compare(*(min_time.v_time), delta) == 1) *(min_time.v_time) = delta;
2067 gboolean xenoltt_synch_unblock(void *hook_data, void *call_data){
2068 LttvTracefileStats *tfcs = (LttvTracefileStats *)call_data;
2069 LttvTraceState *ts = (LttvTraceState*)tfcs->parent.parent.t_context;
2070 LttEvent *e = ltt_tracefile_get_event(tfcs->parent.parent.tf);
2071 LttvTraceHookByFacility *thf = (LttvTraceHookByFacility *)hook_data;
2072 LttvAttributeValue synch, total_time, avg_time, max_time, min_time, *synch_tree;
2073 guint cpu = tfcs->parent.cpu;
2074 LttvXenoThreadState *thread = ts->running_thread[cpu];
2076 g_assert(thf->f1 != NULL);
2077 gulong synch_address = ltt_event_get_long_unsigned(e, thf->f1);
2078 LttvXenoSynchState *synch_state = lttv_xeno_state_find_synch(ts,synch_address);
2079 if (synch_state != NULL){
2081 xeno_find_task_tree(tfcs, thread->name, thread->address,cpu, &(tfcs->current_events_tree), &(tfcs->current_event_types_tree));
2083 synch_tree = lttv_attribute_find_subdir(tfcs->current_events_tree, LTTV_XENO_STATS_SYNCH);
2085 gchar synch_id[MAX_64_HEX_STRING_LEN];
2086 sprintf(synch_id,"%p", synch_address);
2087 synch_tree = lttv_attribute_find_subdir(synch_tree, g_quark_from_string(synch_id));
2089 lttv_attribute_find(synch_tree, LTTV_XENO_STATS_TEXT_OWNER, LTTV_UINT, &synch);
2091 LttTime delta = ltt_time_sub(tfcs->parent.parent.timestamp, synch_state->state->start_time);
2092 lttv_attribute_find(synch_tree, LTTV_XENO_STATS_TEXT_OWNER_TOTAL, LTTV_TIME, &total_time);
2093 *(total_time.v_time) = ltt_time_add(*(total_time.v_time), delta);
2095 lttv_attribute_find(synch_tree, LTTV_XENO_STATS_TEXT_OWNER_AVG, LTTV_TIME, &avg_time);
2096 if (*(synch.v_uint) == 0 || ltt_time_compare(*(total_time.v_time),ltt_time_zero) == 0) *(avg_time.v_time) = *(total_time.v_time);
2097 else *(avg_time.v_time) = ltt_time_div(*(total_time.v_time), *(synch.v_uint));
2099 lttv_attribute_find(synch_tree, LTTV_XENO_STATS_TEXT_OWNER_MAX, LTTV_TIME, &max_time);
2100 // If this owning time is longer than any other before
2101 if (ltt_time_compare(delta,*(max_time.v_time)) == 1) *(max_time.v_time) = delta;
2103 lttv_attribute_find(synch_tree, LTTV_XENO_STATS_TEXT_OWNER_MIN, LTTV_TIME, &min_time);
2104 // If this owning time is shorter than any other before
2105 if (*(synch.v_uint) == 1) *(min_time.v_time) = delta;
2106 else if (ltt_time_compare(*(min_time.v_time), delta) == 1) *(min_time.v_time) = delta;
2114 /****************************************************************************************************************************/
2119 static void module_init()
2121 LTTV_STATS_PROCESS_UNKNOWN = g_quark_from_string("unknown process");
2122 LTTV_STATS_PROCESSES = g_quark_from_string("processes");
2123 LTTV_STATS_CPU = g_quark_from_string("cpu");
2124 LTTV_STATS_MODE_TYPES = g_quark_from_string("mode_types");
2125 LTTV_STATS_MODES = g_quark_from_string("modes");
2126 LTTV_STATS_SUBMODES = g_quark_from_string("submodes");
2127 LTTV_STATS_FUNCTIONS = g_quark_from_string("functions");
2128 LTTV_STATS_EVENT_TYPES = g_quark_from_string("event_types");
2129 LTTV_STATS_CPU_TIME = g_quark_from_string("cpu time");
2130 LTTV_STATS_CUMULATIVE_CPU_TIME = g_quark_from_string("cumulative cpu time (includes nested routines and modes)");
2131 LTTV_STATS_ELAPSED_TIME = g_quark_from_string("elapsed time (includes per process waiting time)");
2132 LTTV_STATS_EVENTS = g_quark_from_string("events");
2133 LTTV_STATS_EVENTS_COUNT = g_quark_from_string("events count");
2134 LTTV_STATS_BEFORE_HOOKS = g_quark_from_string("saved stats before hooks");
2135 LTTV_STATS_AFTER_HOOKS = g_quark_from_string("saved stats after hooks");
2136 LTTV_STATS_USE_COUNT = g_quark_from_string("stats_use_count");
2137 LTTV_STATS = g_quark_from_string("statistics");
2138 LTTV_STATS_TRACEFILES = g_quark_from_string("tracefiles statistics");
2139 LTTV_STATS_SUMMED = g_quark_from_string("statistics summed");
2140 /****************************************************************************************************************************/
2141 LTTV_XENO_STATS_THREADS = g_quark_from_string("Xenomai Tasks");
2142 LTTV_XENO_STATS_PERIOD = g_quark_from_string("Periods");
2143 LTTV_XENO_STATS_STATE = g_quark_from_string("Status");
2144 LTTV_XENO_STATS_SYNCH = g_quark_from_string("Resources");
2145 LTTV_XENO_STATS_THREAD_ADDRESS = g_quark_from_string("Address");
2146 LTTV_XENO_STATS_THREAD_PRIO = g_quark_from_string("Priority");
2147 LTTV_XENO_STATS_THREAD_PERIOD = g_quark_from_string("Period");
2148 LTTV_XENO_STATS_PERIOD_OVERRUNS = g_quark_from_string("Overruns(s)");
2149 LTTV_XENO_STATS_TEXT_OVERRUNS = g_quark_from_string("Overrun(s)");
2150 LTTV_XENO_STATS_TEXT_TICKS = g_quark_from_string("Number of ticks");
2151 LTTV_XENO_STATS_TEXT_OWNER = g_quark_from_string("Owner");
2152 LTTV_XENO_STATS_TEXT_OWNER_TOTAL = g_quark_from_string("\tTotal time");
2153 LTTV_XENO_STATS_TEXT_OWNER_MAX = g_quark_from_string("\tMax time");
2154 LTTV_XENO_STATS_TEXT_OWNER_MIN = g_quark_from_string("\tMin time");
2155 LTTV_XENO_STATS_TEXT_OWNER_AVG = g_quark_from_string("\tAverage time");
2156 LTTV_XENO_STATS_TEXT_WAITING = g_quark_from_string("Waiting");
2157 LTTV_XENO_STATS_TEXT_WAITING_TOTAL = g_quark_from_string("\tTotal time waiting");
2158 LTTV_XENO_STATS_TEXT_WAITING_MAX = g_quark_from_string("\tMax time waiting");
2159 LTTV_XENO_STATS_TEXT_WAITING_MIN = g_quark_from_string("\tMin time waiting");
2160 LTTV_XENO_STATS_TEXT_WAITING_AVG = g_quark_from_string("\tAverage time waiting");
2161 LTTV_XENO_STATS_TEXT_TOTAL = g_quark_from_string("\tTotal time");
2162 LTTV_XENO_STATS_TEXT_READY_MAX = g_quark_from_string("\tMax time in readyq");
2163 LTTV_XENO_STATS_TEXT_READY_MIN = g_quark_from_string("\tMin time in readyq");
2164 LTTV_XENO_STATS_TEXT_READY_AVG = g_quark_from_string("\tAverage time in readyq");
2165 LTTV_XENO_STATS_TEXT_RUNNING_MAX = g_quark_from_string("\tMax time running");
2166 LTTV_XENO_STATS_TEXT_RUNNING_MIN = g_quark_from_string("\tMin time running");
2167 LTTV_XENO_STATS_TEXT_RUNNING_AVG = g_quark_from_string("\tAverage time running");
2168 LTTV_XENO_STATS_TEXT_SUSPEND_MAX = g_quark_from_string("\tMax time suspended");
2169 LTTV_XENO_STATS_TEXT_SUSPEND_MIN = g_quark_from_string("\tMin time suspended");
2170 LTTV_XENO_STATS_TEXT_SUSPEND_AVG = g_quark_from_string("\tAverage time suspended");
2171 LTTV_XENO_STATS_NB_PERIOD = g_quark_from_string("Number of periods executed");
2172 /****************************************************************************************************************************/
2175 static void module_destroy()
2180 LTTV_MODULE("stats", "Compute processes statistics", \
2181 "Accumulate statistics for event types, processes and CPUs", \
2182 module_init, module_destroy, "state");
2184 /* Change the places where stats are called (create/read/write stats)
2186 Check for options in batchtest.c to reduce writing and see what tests are
2187 best candidates for performance analysis. Once OK, commit, move to main
2188 and run tests. Update the gui for statistics. */