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,
20 #include <lttv/lttv.h>
21 #include <lttv/module.h>
22 #include <lttv/state.h>
23 #include <ltt/facility.h>
24 #include <ltt/trace.h>
25 #include <ltt/event.h>
30 LTTV_STATE_MODE_UNKNOWN
,
37 LTTV_STATE_SUBMODE_UNKNOWN
,
38 LTTV_STATE_SUBMODE_NONE
;
49 LTTV_STATE_TRACEFILES
,
53 LTTV_STATE_SAVED_STATES
,
54 LTTV_STATE_SAVED_STATES_TIME
,
57 LTTV_STATE_NAME_TABLES
,
58 LTTV_STATE_TRACE_STATE_USE_COUNT
;
61 static void create_max_time(LttvTraceState
*tcs
);
63 static void get_max_time(LttvTraceState
*tcs
);
65 static void free_max_time(LttvTraceState
*tcs
);
67 static void create_name_tables(LttvTraceState
*tcs
);
69 static void get_name_tables(LttvTraceState
*tcs
);
71 static void free_name_tables(LttvTraceState
*tcs
);
73 static void free_saved_state(LttvTraceState
*tcs
);
75 static void lttv_state_free_process_table(GHashTable
*processes
);
78 void lttv_state_save(LttvTraceState
*self
, LttvAttribute
*container
)
80 LTTV_TRACE_STATE_GET_CLASS(self
)->state_save(self
, container
);
84 void lttv_state_restore(LttvTraceState
*self
, LttvAttribute
*container
)
86 LTTV_TRACE_STATE_GET_CLASS(self
)->state_restore(self
, container
);
90 void lttv_state_state_saved_free(LttvTraceState
*self
,
91 LttvAttribute
*container
)
93 LTTV_TRACE_STATE_GET_CLASS(self
)->state_saved_free(self
, container
);
97 guint
process_hash(gconstpointer key
)
99 return ((LttvProcessState
*)key
)->pid
;
103 gboolean
process_equal(gconstpointer a
, gconstpointer b
)
105 LttvProcessState
*process_a
, *process_b
;
107 process_a
= (LttvProcessState
*)a
;
108 process_b
= (LttvProcessState
*)b
;
110 if(process_a
->pid
!= process_b
->pid
) return FALSE
;
111 if(process_a
->pid
== 0 &&
112 process_a
->last_cpu
!= process_b
->last_cpu
) return FALSE
;
118 restore_init_state(LttvTraceState
*self
)
120 guint i
, nb_tracefile
;
122 LttvTracefileState
*tfcs
;
124 LttTime null_time
= {0,0};
126 if(self
->processes
!= NULL
) lttv_state_free_process_table(self
->processes
);
127 self
->processes
= g_hash_table_new(process_hash
, process_equal
);
130 nb_tracefile
= ltt_trace_control_tracefile_number(self
->parent
.t
) +
131 ltt_trace_per_cpu_tracefile_number(self
->parent
.t
);
133 for(i
= 0 ; i
< nb_tracefile
; i
++) {
134 tfcs
= LTTV_TRACEFILE_STATE(self
->parent
.tracefiles
[i
]);
135 tfcs
->parent
.timestamp
= null_time
;
136 tfcs
->saved_position
= 0;
137 tfcs
->process
= lttv_state_create_process(tfcs
, NULL
,0);
138 tfcs
->process
->state
->s
= LTTV_STATE_RUN
;
139 tfcs
->process
->last_cpu
= tfcs
->cpu_name
;
143 static LttTime time_zero
= {0,0};
146 init(LttvTracesetState
*self
, LttvTraceset
*ts
)
148 guint i
, j
, nb_trace
, nb_tracefile
;
150 LttvTraceContext
*tc
;
154 LttvTracefileState
*tfcs
;
156 LttvAttributeValue v
;
158 LTTV_TRACESET_CONTEXT_CLASS(g_type_class_peek(LTTV_TRACESET_CONTEXT_TYPE
))->
159 init((LttvTracesetContext
*)self
, ts
);
161 nb_trace
= lttv_traceset_number(ts
);
162 for(i
= 0 ; i
< nb_trace
; i
++) {
163 tc
= self
->parent
.traces
[i
];
164 tcs
= (LttvTraceState
*)tc
;
165 tcs
->save_interval
= 50000;
166 lttv_attribute_find(tcs
->parent
.t_a
, LTTV_STATE_TRACE_STATE_USE_COUNT
,
170 if(*(v
.v_uint
) == 1) {
171 create_name_tables(tcs
);
172 create_max_time(tcs
);
174 get_name_tables(tcs
);
177 nb_tracefile
= ltt_trace_control_tracefile_number(tc
->t
) +
178 ltt_trace_per_cpu_tracefile_number(tc
->t
);
180 for(j
= 0 ; j
< nb_tracefile
; j
++) {
181 tfcs
= LTTV_TRACEFILE_STATE(tc
->tracefiles
[j
]);
182 tfcs
->cpu_name
= g_quark_from_string(ltt_tracefile_name(tfcs
->parent
.tf
));
184 tcs
->processes
= NULL
;
185 restore_init_state(tcs
);
191 fini(LttvTracesetState
*self
)
193 guint i
, j
, nb_trace
;
197 LttvTracefileState
*tfcs
;
199 LttvAttributeValue v
;
201 nb_trace
= lttv_traceset_number(LTTV_TRACESET_CONTEXT(self
)->ts
);
202 for(i
= 0 ; i
< nb_trace
; i
++) {
203 tcs
= (LttvTraceState
*)(LTTV_TRACESET_CONTEXT(self
)->traces
[i
]);
204 lttv_attribute_find(tcs
->parent
.t_a
, LTTV_STATE_TRACE_STATE_USE_COUNT
,
208 g_assert(*(v
.v_uint
) >= 0);
209 if(*(v
.v_uint
) == 0) {
210 free_name_tables(tcs
);
212 free_saved_state(tcs
);
214 lttv_state_free_process_table(tcs
->processes
);
215 tcs
->processes
= NULL
;
217 LTTV_TRACESET_CONTEXT_CLASS(g_type_class_peek(LTTV_TRACESET_CONTEXT_TYPE
))->
218 fini((LttvTracesetContext
*)self
);
222 static LttvTracesetContext
*
223 new_traceset_context(LttvTracesetContext
*self
)
225 return LTTV_TRACESET_CONTEXT(g_object_new(LTTV_TRACESET_STATE_TYPE
, NULL
));
229 static LttvTraceContext
*
230 new_trace_context(LttvTracesetContext
*self
)
232 return LTTV_TRACE_CONTEXT(g_object_new(LTTV_TRACE_STATE_TYPE
, NULL
));
236 static LttvTracefileContext
*
237 new_tracefile_context(LttvTracesetContext
*self
)
239 return LTTV_TRACEFILE_CONTEXT(g_object_new(LTTV_TRACEFILE_STATE_TYPE
, NULL
));
243 /* Write the process state of the trace */
245 static void write_process_state(gpointer key
, gpointer value
,
248 LttvProcessState
*process
;
250 LttvExecutionState
*es
;
252 FILE *fp
= (FILE *)user_data
;
256 process
= (LttvProcessState
*)value
;
258 " <PROCESS CORE=%p PID=%u PPID=%u CTIME_S=%lu CTIME_NS=%lu NAME=\"%s\" CPU=\"%s\">\n",
259 process
, process
->pid
, process
->ppid
, process
->creation_time
.tv_sec
,
260 process
->creation_time
.tv_nsec
, g_quark_to_string(process
->name
),
261 g_quark_to_string(process
->last_cpu
));
263 for(i
= 0 ; i
< process
->execution_stack
->len
; i
++) {
264 es
= &g_array_index(process
->execution_stack
, LttvExecutionState
, i
);
265 fprintf(fp
, " <ES MODE=\"%s\" SUBMODE=\"%s\" ENTRY_S=%lu ENTRY_NS=%lu",
266 g_quark_to_string(es
->t
), g_quark_to_string(es
->n
),
267 es
->entry
.tv_sec
, es
->entry
.tv_nsec
);
268 fprintf(fp
, " CHANGE_S=%lu CHANGE_NS=%lu STATUS=\"%s\"/>\n",
269 es
->change
.tv_sec
, es
->change
.tv_nsec
, g_quark_to_string(es
->s
));
271 fprintf(fp
, " </PROCESS>\n");
275 void lttv_state_write(LttvTraceState
*self
, LttTime t
, FILE *fp
)
277 guint i
, nb_tracefile
, nb_block
, nb_event
;
279 LttvTracefileState
*tfcs
;
283 LttEventPosition
*ep
;
285 ep
= ltt_event_position_new();
287 fprintf(fp
,"<PROCESS_STATE TIME_S=%lu TIME_NS=%lu>\n", t
.tv_sec
, t
.tv_nsec
);
289 g_hash_table_foreach(self
->processes
, write_process_state
, fp
);
291 nb_tracefile
= ltt_trace_control_tracefile_number(self
->parent
.t
) +
292 ltt_trace_per_cpu_tracefile_number(self
->parent
.t
);
294 for(i
= 0 ; i
< nb_tracefile
; i
++) {
295 tfcs
= (LttvTracefileState
*)self
->parent
.tracefiles
[i
];
296 fprintf(fp
, " <TRACEFILE PID=%u TIMESTAMP_S=%lu TIMESTAMP_NS=%lu",
297 tfcs
->process
->pid
, tfcs
->parent
.timestamp
.tv_sec
,
298 tfcs
->parent
.timestamp
.tv_nsec
);
299 if(tfcs
->parent
.e
== NULL
) fprintf(fp
,"/>\n");
301 ltt_event_position(tfcs
->parent
.e
, ep
);
302 ltt_event_position_get(ep
, &nb_block
, &nb_event
, &tf
);
303 fprintf(fp
, " BLOCK=%u EVENT=%u/>\n", nb_block
, nb_event
);
307 fprintf(fp
,"</PROCESS_STATE>");
311 /* Copy each process from an existing hash table to a new one */
313 static void copy_process_state(gpointer key
, gpointer value
,gpointer user_data
)
315 LttvProcessState
*process
, *new_process
;
317 GHashTable
*new_processes
= (GHashTable
*)user_data
;
321 process
= (LttvProcessState
*)value
;
322 new_process
= g_new(LttvProcessState
, 1);
323 *new_process
= *process
;
324 new_process
->execution_stack
= g_array_new(FALSE
, FALSE
,
325 sizeof(LttvExecutionState
));
326 g_array_set_size(new_process
->execution_stack
,process
->execution_stack
->len
);
327 for(i
= 0 ; i
< process
->execution_stack
->len
; i
++) {
328 g_array_index(new_process
->execution_stack
, LttvExecutionState
, i
) =
329 g_array_index(process
->execution_stack
, LttvExecutionState
, i
);
331 new_process
->state
= &g_array_index(new_process
->execution_stack
,
332 LttvExecutionState
, new_process
->execution_stack
->len
- 1);
333 g_hash_table_insert(new_processes
, new_process
, new_process
);
337 static GHashTable
*lttv_state_copy_process_table(GHashTable
*processes
)
339 GHashTable
*new_processes
= g_hash_table_new(process_hash
, process_equal
);
341 g_hash_table_foreach(processes
, copy_process_state
, new_processes
);
342 return new_processes
;
346 /* The saved state for each trace contains a member "processes", which
347 stores a copy of the process table, and a member "tracefiles" with
348 one entry per tracefile. Each tracefile has a "process" member pointing
349 to the current process and a "position" member storing the tracefile
350 position (needed to seek to the current "next" event. */
352 static void state_save(LttvTraceState
*self
, LttvAttribute
*container
)
354 guint i
, nb_tracefile
;
356 LttvTracefileState
*tfcs
;
358 LttvAttribute
*tracefiles_tree
, *tracefile_tree
;
360 LttvAttributeType type
;
362 LttvAttributeValue value
;
364 LttvAttributeName name
;
366 LttEventPosition
*ep
;
368 tracefiles_tree
= lttv_attribute_find_subdir(container
,
369 LTTV_STATE_TRACEFILES
);
371 value
= lttv_attribute_add(container
, LTTV_STATE_PROCESSES
,
373 *(value
.v_pointer
) = lttv_state_copy_process_table(self
->processes
);
375 nb_tracefile
= ltt_trace_control_tracefile_number(self
->parent
.t
) +
376 ltt_trace_per_cpu_tracefile_number(self
->parent
.t
);
378 for(i
= 0 ; i
< nb_tracefile
; i
++) {
379 tfcs
= (LttvTracefileState
*)self
->parent
.tracefiles
[i
];
380 tracefile_tree
= g_object_new(LTTV_ATTRIBUTE_TYPE
, NULL
);
381 value
= lttv_attribute_add(tracefiles_tree
, i
,
383 *(value
.v_gobject
) = (GObject
*)tracefile_tree
;
384 value
= lttv_attribute_add(tracefile_tree
, LTTV_STATE_PROCESS
,
386 *(value
.v_uint
) = tfcs
->process
->pid
;
387 value
= lttv_attribute_add(tracefile_tree
, LTTV_STATE_EVENT
,
389 if(tfcs
->parent
.e
== NULL
) *(value
.v_pointer
) = NULL
;
391 ep
= ltt_event_position_new();
392 ltt_event_position(tfcs
->parent
.e
, ep
);
393 *(value
.v_pointer
) = ep
;
395 guint nb_block
, nb_event
;
397 ltt_event_position_get(ep
, &nb_block
, &nb_event
, &tf
);
398 g_debug("Block %u event %u time %lu.%lu", nb_block
, nb_event
,
399 tfcs
->parent
.timestamp
.tv_sec
, tfcs
->parent
.timestamp
.tv_nsec
);
405 static void state_restore(LttvTraceState
*self
, LttvAttribute
*container
)
407 guint i
, nb_tracefile
, pid
;
409 LttvTracefileState
*tfcs
;
411 LttvAttribute
*tracefiles_tree
, *tracefile_tree
;
413 LttvAttributeType type
;
415 LttvAttributeValue value
;
417 LttvAttributeName name
;
419 LttEventPosition
*ep
;
421 tracefiles_tree
= lttv_attribute_find_subdir(container
,
422 LTTV_STATE_TRACEFILES
);
424 type
= lttv_attribute_get_by_name(container
, LTTV_STATE_PROCESSES
,
426 g_assert(type
== LTTV_POINTER
);
427 lttv_state_free_process_table(self
->processes
);
428 self
->processes
= lttv_state_copy_process_table(*(value
.v_pointer
));
430 nb_tracefile
= ltt_trace_control_tracefile_number(self
->parent
.t
) +
431 ltt_trace_per_cpu_tracefile_number(self
->parent
.t
);
433 for(i
= 0 ; i
< nb_tracefile
; i
++) {
434 tfcs
= (LttvTracefileState
*)self
->parent
.tracefiles
[i
];
435 type
= lttv_attribute_get(tracefiles_tree
, i
, &name
, &value
);
436 g_assert(type
== LTTV_GOBJECT
);
437 tracefile_tree
= *((LttvAttribute
**)(value
.v_gobject
));
439 type
= lttv_attribute_get_by_name(tracefile_tree
, LTTV_STATE_PROCESS
,
441 g_assert(type
== LTTV_UINT
);
442 pid
= *(value
.v_uint
);
443 tfcs
->process
= lttv_state_find_process_or_create(tfcs
, pid
);
445 type
= lttv_attribute_get_by_name(tracefile_tree
, LTTV_STATE_EVENT
,
447 g_assert(type
== LTTV_POINTER
);
448 if(*(value
.v_pointer
) == NULL
) tfcs
->parent
.e
= NULL
;
450 ep
= *(value
.v_pointer
);
451 lttv_process_tracefile_seek_position(tfcs
->parent
, ep
);
457 static void state_saved_free(LttvTraceState
*self
, LttvAttribute
*container
)
459 guint i
, nb_tracefile
;
461 LttvTracefileState
*tfcs
;
463 LttvAttribute
*tracefiles_tree
, *tracefile_tree
;
465 LttvAttributeType type
;
467 LttvAttributeValue value
;
469 LttvAttributeName name
;
471 LttEventPosition
*ep
;
473 tracefiles_tree
= lttv_attribute_find_subdir(container
,
474 LTTV_STATE_TRACEFILES
);
475 lttv_attribute_remove_by_name(container
, LTTV_STATE_TRACEFILES
);
477 type
= lttv_attribute_get_by_name(container
, LTTV_STATE_PROCESSES
,
479 g_assert(type
== LTTV_POINTER
);
480 lttv_state_free_process_table(*(value
.v_pointer
));
481 *(value
.v_pointer
) = NULL
;
482 lttv_attribute_remove_by_name(container
, LTTV_STATE_PROCESSES
);
484 nb_tracefile
= ltt_trace_control_tracefile_number(self
->parent
.t
) +
485 ltt_trace_per_cpu_tracefile_number(self
->parent
.t
);
487 for(i
= 0 ; i
< nb_tracefile
; i
++) {
488 tfcs
= (LttvTracefileState
*)self
->parent
.tracefiles
[i
];
489 type
= lttv_attribute_get(tracefiles_tree
, i
, &name
, &value
);
490 g_assert(type
== LTTV_GOBJECT
);
491 tracefile_tree
= *((LttvAttribute
**)(value
.v_gobject
));
493 type
= lttv_attribute_get_by_name(tracefile_tree
, LTTV_STATE_EVENT
,
495 g_assert(type
== LTTV_POINTER
);
496 if(*(value
.v_pointer
) != NULL
) g_free(*(value
.v_pointer
));
498 lttv_attribute_recursive_free(tracefiles_tree
);
502 static void free_saved_state(LttvTraceState
*self
)
506 LttvAttributeType type
;
508 LttvAttributeValue value
;
510 LttvAttributeName name
;
512 LttvAttribute
*saved_states
;
514 saved_states
= lttv_attribute_find_subdir(self
->parent
.t_a
,
515 LTTV_STATE_SAVED_STATES
);
517 nb
= lttv_attribute_get_number(saved_states
);
518 for(i
= 0 ; i
< nb
; i
++) {
519 type
= lttv_attribute_get(saved_states
, i
, &name
, &value
);
520 g_assert(type
== LTTV_GOBJECT
);
521 state_saved_free(self
, *((LttvAttribute
**)value
.v_gobject
));
524 lttv_attribute_remove_by_name(self
->parent
.t_a
, LTTV_STATE_SAVED_STATES
);
525 lttv_attribute_recursive_free(saved_states
);
530 create_max_time(LttvTraceState
*tcs
)
532 LttvAttributeValue v
;
534 lttv_attribute_find(tcs
->parent
.t_a
, LTTV_STATE_SAVED_STATES_TIME
,
536 g_assert(*(v
.v_pointer
) == NULL
);
537 *(v
.v_pointer
) = g_new(LttTime
,1);
538 *((LttTime
*)*(v
.v_pointer
)) = time_zero
;
543 get_max_time(LttvTraceState
*tcs
)
545 LttvAttributeValue v
;
547 lttv_attribute_find(tcs
->parent
.t_a
, LTTV_STATE_SAVED_STATES_TIME
,
549 g_assert(*(v
.v_pointer
) != NULL
);
550 tcs
->max_time_state_recomputed_in_seek
= (LttTime
*)*(v
.v_pointer
);
555 free_max_time(LttvTraceState
*tcs
)
557 LttvAttributeValue v
;
559 lttv_attribute_find(tcs
->parent
.t_a
, LTTV_STATE_SAVED_STATES_TIME
,
561 g_free(*(v
.v_pointer
));
562 *(v
.v_pointer
) = NULL
;
566 typedef struct _LttvNameTables
{
567 GQuark
*eventtype_names
;
568 GQuark
*syscall_names
;
575 create_name_tables(LttvTraceState
*tcs
)
579 char *f_name
, *e_name
;
587 GString
*fe_name
= g_string_new("");
589 LttvNameTables
*name_tables
= g_new(LttvNameTables
, 1);
591 LttvAttributeValue v
;
593 lttv_attribute_find(tcs
->parent
.t_a
, LTTV_STATE_NAME_TABLES
,
595 g_assert(*(v
.v_pointer
) == NULL
);
596 *(v
.v_pointer
) = name_tables
;
598 nb
= ltt_trace_eventtype_number(tcs
->parent
.t
);
599 name_tables
->eventtype_names
= g_new(GQuark
, nb
);
600 for(i
= 0 ; i
< nb
; i
++) {
601 et
= ltt_trace_eventtype_get(tcs
->parent
.t
, i
);
602 e_name
= ltt_eventtype_name(et
);
603 f_name
= ltt_facility_name(ltt_eventtype_facility(et
));
604 g_string_printf(fe_name
, "%s.%s", f_name
, e_name
);
605 name_tables
->eventtype_names
[i
] = g_quark_from_string(fe_name
->str
);
608 lttv_trace_find_hook(tcs
->parent
.t
, "core", "syscall_entry",
609 "syscall_id", NULL
, NULL
, NULL
, &h
);
610 t
= ltt_field_type(h
.f1
);
611 nb
= ltt_type_element_number(t
);
613 /* CHECK syscalls should be an emun but currently are not!
614 name_tables->syscall_names = g_new(GQuark, nb);
616 for(i = 0 ; i < nb ; i++) {
617 name_tables->syscall_names[i] = g_quark_from_string(
618 ltt_enum_string_get(t, i));
622 name_tables
->syscall_names
= g_new(GQuark
, 256);
623 for(i
= 0 ; i
< 256 ; i
++) {
624 g_string_printf(fe_name
, "syscall %d", i
);
625 name_tables
->syscall_names
[i
] = g_quark_from_string(fe_name
->str
);
628 lttv_trace_find_hook(tcs
->parent
.t
, "core", "trap_entry",
629 "trap_id", NULL
, NULL
, NULL
, &h
);
630 t
= ltt_field_type(h
.f1
);
631 nb
= ltt_type_element_number(t
);
634 name_tables->trap_names = g_new(GQuark, nb);
635 for(i = 0 ; i < nb ; i++) {
636 name_tables->trap_names[i] = g_quark_from_string(
637 ltt_enum_string_get(t, i));
641 name_tables
->trap_names
= g_new(GQuark
, 256);
642 for(i
= 0 ; i
< 256 ; i
++) {
643 g_string_printf(fe_name
, "trap %d", i
);
644 name_tables
->trap_names
[i
] = g_quark_from_string(fe_name
->str
);
647 lttv_trace_find_hook(tcs
->parent
.t
, "core", "irq_entry",
648 "irq_id", NULL
, NULL
, NULL
, &h
);
649 t
= ltt_field_type(h
.f1
);
650 nb
= ltt_type_element_number(t
);
653 name_tables->irq_names = g_new(GQuark, nb);
654 for(i = 0 ; i < nb ; i++) {
655 name_tables->irq_names[i] = g_quark_from_string(ltt_enum_string_get(t, i));
659 name_tables
->irq_names
= g_new(GQuark
, 256);
660 for(i
= 0 ; i
< 256 ; i
++) {
661 g_string_printf(fe_name
, "irq %d", i
);
662 name_tables
->irq_names
[i
] = g_quark_from_string(fe_name
->str
);
665 g_string_free(fe_name
, TRUE
);
670 get_name_tables(LttvTraceState
*tcs
)
672 LttvNameTables
*name_tables
;
674 LttvAttributeValue v
;
676 lttv_attribute_find(tcs
->parent
.t_a
, LTTV_STATE_NAME_TABLES
,
678 g_assert(*(v
.v_pointer
) != NULL
);
679 name_tables
= (LttvNameTables
*)*(v
.v_pointer
);
680 tcs
->eventtype_names
= name_tables
->eventtype_names
;
681 tcs
->syscall_names
= name_tables
->syscall_names
;
682 tcs
->trap_names
= name_tables
->trap_names
;
683 tcs
->irq_names
= name_tables
->irq_names
;
688 free_name_tables(LttvTraceState
*tcs
)
690 LttvNameTables
*name_tables
;
692 LttvAttributeValue v
;
694 lttv_attribute_find(tcs
->parent
.t_a
, LTTV_STATE_NAME_TABLES
,
696 name_tables
= (LttvNameTables
*)*(v
.v_pointer
);
697 *(v
.v_pointer
) = NULL
;
699 g_free(name_tables
->eventtype_names
);
700 g_free(name_tables
->syscall_names
);
701 g_free(name_tables
->trap_names
);
702 g_free(name_tables
->irq_names
);
707 static void push_state(LttvTracefileState
*tfs
, LttvExecutionMode t
,
710 LttvExecutionState
*es
;
712 LttvProcessState
*process
= tfs
->process
;
714 guint depth
= process
->execution_stack
->len
;
716 g_array_set_size(process
->execution_stack
, depth
+ 1);
717 es
= &g_array_index(process
->execution_stack
, LttvExecutionState
, depth
);
720 es
->entry
= es
->change
= tfs
->parent
.timestamp
;
721 es
->s
= process
->state
->s
;
726 static void pop_state(LttvTracefileState
*tfs
, LttvExecutionMode t
)
728 LttvProcessState
*process
= tfs
->process
;
730 guint depth
= process
->execution_stack
->len
;
732 if(process
->state
->t
!= t
){
733 g_info("Different execution mode type (%d.%09d): ignore it\n",
734 tfs
->parent
.timestamp
.tv_sec
, tfs
->parent
.timestamp
.tv_nsec
);
735 g_info("process state has %s when pop_int is %s\n",
736 g_quark_to_string(process
->state
->t
),
737 g_quark_to_string(t
));
738 g_info("{ %u, %u, %s, %s }\n",
741 g_quark_to_string(process
->name
),
742 g_quark_to_string(process
->state
->s
));
747 g_info("Trying to pop last state on stack (%d.%09d): ignore it\n",
748 tfs
->parent
.timestamp
.tv_sec
, tfs
->parent
.timestamp
.tv_nsec
);
752 g_array_set_size(process
->execution_stack
, depth
- 1);
753 process
->state
= &g_array_index(process
->execution_stack
, LttvExecutionState
,
755 process
->state
->change
= tfs
->parent
.timestamp
;
760 lttv_state_create_process(LttvTracefileState
*tfs
, LttvProcessState
*parent
,
763 LttvProcessState
*process
= g_new(LttvProcessState
, 1);
765 LttvExecutionState
*es
;
767 LttvTraceContext
*tc
;
773 tc
= tfs
->parent
.t_context
;
774 tcs
= (LttvTraceState
*)tc
;
777 process
->last_cpu
= tfs
->cpu_name
;
778 g_warning("Process %u, core %p", process
->pid
, process
);
779 g_hash_table_insert(tcs
->processes
, process
, process
);
782 process
->ppid
= parent
->pid
;
783 process
->name
= parent
->name
;
784 process
->creation_time
= tfs
->parent
.timestamp
;
787 /* No parent. This process exists but we are missing all information about
788 its creation. The birth time is set to zero but we remember the time of
793 process
->name
= LTTV_STATE_UNNAMED
;
794 process
->creation_time
= ltt_time_zero
;
797 process
->insertion_time
= tfs
->parent
.timestamp
;
798 sprintf(buffer
,"%d-%lu.%lu",pid
, process
->creation_time
.tv_sec
,
799 process
->creation_time
.tv_nsec
);
800 process
->pid_time
= g_quark_from_string(buffer
);
801 process
->last_cpu
= tfs
->cpu_name
;
802 process
->execution_stack
= g_array_new(FALSE
, FALSE
,
803 sizeof(LttvExecutionState
));
804 g_array_set_size(process
->execution_stack
, 1);
805 es
= process
->state
= &g_array_index(process
->execution_stack
,
806 LttvExecutionState
, 0);
807 es
->t
= LTTV_STATE_USER_MODE
;
808 es
->n
= LTTV_STATE_SUBMODE_NONE
;
809 es
->entry
= tfs
->parent
.timestamp
;
810 es
->change
= tfs
->parent
.timestamp
;
811 es
->s
= LTTV_STATE_WAIT_FORK
;
818 lttv_state_find_process_from_trace(LttvTraceState
*ts
, GQuark cpu
, guint pid
)
820 LttvProcessState key
;
821 LttvProcessState
*process
;
825 process
= g_hash_table_lookup(ts
->processes
, &key
);
830 LttvProcessState
*lttv_state_find_process(LttvTracefileState
*tfs
,
833 LttvTraceState
*ts
=(LttvTraceState
*)tfs
->parent
.t_context
;
834 return lttv_state_find_process_from_trace(ts
, tfs
->cpu_name
, pid
);
839 lttv_state_find_process_or_create(LttvTracefileState
*tfs
, guint pid
)
841 LttvProcessState
*process
= lttv_state_find_process(tfs
, pid
);
843 if(process
== NULL
) process
= lttv_state_create_process(tfs
, NULL
, pid
);
848 static void exit_process(LttvTracefileState
*tfs
, LttvProcessState
*process
)
850 LttvTraceState
*ts
= LTTV_TRACE_STATE(tfs
->parent
.t_context
);
851 LttvProcessState key
;
853 key
.pid
= process
->pid
;
854 key
.last_cpu
= process
->last_cpu
;
855 g_hash_table_remove(ts
->processes
, &key
);
856 g_array_free(process
->execution_stack
, TRUE
);
861 static void free_process_state(gpointer key
, gpointer value
,gpointer user_data
)
863 g_array_free(((LttvProcessState
*)value
)->execution_stack
, TRUE
);
868 static void lttv_state_free_process_table(GHashTable
*processes
)
870 g_hash_table_foreach(processes
, free_process_state
, NULL
);
871 g_hash_table_destroy(processes
);
875 static gboolean
syscall_entry(void *hook_data
, void *call_data
)
877 LttField
*f
= ((LttvTraceHook
*)hook_data
)->f1
;
879 LttvTracefileState
*s
= (LttvTracefileState
*)call_data
;
881 LttvExecutionSubmode submode
;
883 submode
= ((LttvTraceState
*)(s
->parent
.t_context
))->syscall_names
[
884 ltt_event_get_unsigned(s
->parent
.e
, f
)];
885 push_state(s
, LTTV_STATE_SYSCALL
, submode
);
890 static gboolean
syscall_exit(void *hook_data
, void *call_data
)
892 LttvTracefileState
*s
= (LttvTracefileState
*)call_data
;
894 pop_state(s
, LTTV_STATE_SYSCALL
);
899 static gboolean
trap_entry(void *hook_data
, void *call_data
)
901 LttField
*f
= ((LttvTraceHook
*)hook_data
)->f1
;
903 LttvTracefileState
*s
= (LttvTracefileState
*)call_data
;
905 LttvExecutionSubmode submode
;
907 submode
= ((LttvTraceState
*)(s
->parent
.t_context
))->trap_names
[
908 ltt_event_get_unsigned(s
->parent
.e
, f
)];
909 push_state(s
, LTTV_STATE_TRAP
, submode
);
914 static gboolean
trap_exit(void *hook_data
, void *call_data
)
916 LttvTracefileState
*s
= (LttvTracefileState
*)call_data
;
918 pop_state(s
, LTTV_STATE_TRAP
);
923 static gboolean
irq_entry(void *hook_data
, void *call_data
)
925 LttField
*f
= ((LttvTraceHook
*)hook_data
)->f1
;
927 LttvTracefileState
*s
= (LttvTracefileState
*)call_data
;
929 LttvExecutionSubmode submode
;
931 submode
= ((LttvTraceState
*)(s
->parent
.t_context
))->irq_names
[
932 ltt_event_get_unsigned(s
->parent
.e
, f
)];
934 /* Do something with the info about being in user or system mode when int? */
935 push_state(s
, LTTV_STATE_IRQ
, submode
);
940 static gboolean
irq_exit(void *hook_data
, void *call_data
)
942 LttvTracefileState
*s
= (LttvTracefileState
*)call_data
;
944 pop_state(s
, LTTV_STATE_IRQ
);
949 static gboolean
schedchange(void *hook_data
, void *call_data
)
951 LttvTraceHook
*h
= (LttvTraceHook
*)hook_data
;
953 LttvTracefileState
*s
= (LttvTracefileState
*)call_data
;
955 guint pid_in
, pid_out
, state_out
;
957 pid_in
= ltt_event_get_unsigned(s
->parent
.e
, h
->f1
);
958 pid_out
= ltt_event_get_unsigned(s
->parent
.e
, h
->f2
);
959 state_out
= ltt_event_get_unsigned(s
->parent
.e
, h
->f3
);
961 if(s
->process
!= NULL
) {
963 /* We could not know but it was not the idle process executing.
964 This should only happen at the beginning, before the first schedule
965 event, and when the initial information (current process for each CPU)
966 is missing. It is not obvious how we could, after the fact, compensate
967 the wrongly attributed statistics. */
969 if(s
->process
->pid
!= pid_out
) {
970 g_assert(s
->process
->pid
== 0);
973 if(state_out
== 0) s
->process
->state
->s
= LTTV_STATE_WAIT_CPU
;
974 else if(s
->process
->state
->s
== LTTV_STATE_EXIT
)
975 exit_process(s
, s
->process
);
976 else s
->process
->state
->s
= LTTV_STATE_WAIT
;
978 s
->process
->state
->change
= s
->parent
.timestamp
;
980 s
->process
= lttv_state_find_process_or_create(s
, pid_in
);
981 s
->process
->state
->s
= LTTV_STATE_RUN
;
982 s
->process
->last_cpu
= s
->cpu_name
;
983 s
->process
->state
->change
= s
->parent
.timestamp
;
988 static gboolean
process_fork(void *hook_data
, void *call_data
)
990 LttField
*f
= ((LttvTraceHook
*)hook_data
)->f1
;
992 LttvTracefileState
*s
= (LttvTracefileState
*)call_data
;
996 child_pid
= ltt_event_get_unsigned(s
->parent
.e
, f
);
997 lttv_state_create_process(s
, s
->process
, child_pid
);
1002 static gboolean
process_exit(void *hook_data
, void *call_data
)
1004 LttvTracefileState
*s
= (LttvTracefileState
*)call_data
;
1006 if(s
->process
!= NULL
) {
1007 s
->process
->state
->s
= LTTV_STATE_EXIT
;
1013 void lttv_state_add_event_hooks(LttvTracesetState
*self
)
1015 LttvTraceset
*traceset
= self
->parent
.ts
;
1017 guint i
, j
, k
, nb_trace
, nb_tracefile
;
1021 LttvTracefileState
*tfs
;
1027 LttvAttributeValue val
;
1029 nb_trace
= lttv_traceset_number(traceset
);
1030 for(i
= 0 ; i
< nb_trace
; i
++) {
1031 ts
= (LttvTraceState
*)self
->parent
.traces
[i
];
1033 /* Find the eventtype id for the following events and register the
1034 associated by id hooks. */
1036 hooks
= g_array_new(FALSE
, FALSE
, sizeof(LttvTraceHook
));
1037 g_array_set_size(hooks
, 9);
1039 lttv_trace_find_hook(ts
->parent
.t
, "core","syscall_entry","syscall_id",
1040 NULL
, NULL
, syscall_entry
, &g_array_index(hooks
, LttvTraceHook
, 0));
1042 lttv_trace_find_hook(ts
->parent
.t
, "core", "syscall_exit", NULL
, NULL
,
1043 NULL
, syscall_exit
, &g_array_index(hooks
, LttvTraceHook
, 1));
1045 lttv_trace_find_hook(ts
->parent
.t
, "core", "trap_entry", "trap_id",
1046 NULL
, NULL
, trap_entry
, &g_array_index(hooks
, LttvTraceHook
, 2));
1048 lttv_trace_find_hook(ts
->parent
.t
, "core", "trap_exit", NULL
, NULL
, NULL
,
1049 trap_exit
, &g_array_index(hooks
, LttvTraceHook
, 3));
1051 lttv_trace_find_hook(ts
->parent
.t
, "core", "irq_entry", "irq_id", NULL
,
1052 NULL
, irq_entry
, &g_array_index(hooks
, LttvTraceHook
, 4));
1054 lttv_trace_find_hook(ts
->parent
.t
, "core", "irq_exit", NULL
, NULL
, NULL
,
1055 irq_exit
, &g_array_index(hooks
, LttvTraceHook
, 5));
1057 lttv_trace_find_hook(ts
->parent
.t
, "core", "schedchange", "in", "out",
1058 "out_state", schedchange
, &g_array_index(hooks
, LttvTraceHook
, 6));
1060 lttv_trace_find_hook(ts
->parent
.t
, "core", "process_fork", "child_pid",
1061 NULL
, NULL
, process_fork
, &g_array_index(hooks
, LttvTraceHook
, 7));
1063 lttv_trace_find_hook(ts
->parent
.t
, "core", "process_exit", NULL
, NULL
,
1064 NULL
, process_exit
, &g_array_index(hooks
, LttvTraceHook
, 8));
1066 /* Add these hooks to each event_by_id hooks list */
1068 nb_tracefile
= ltt_trace_control_tracefile_number(ts
->parent
.t
) +
1069 ltt_trace_per_cpu_tracefile_number(ts
->parent
.t
);
1071 for(j
= 0 ; j
< nb_tracefile
; j
++) {
1072 tfs
= LTTV_TRACEFILE_STATE(ts
->parent
.tracefiles
[j
]);
1074 for(k
= 0 ; k
< hooks
->len
; k
++) {
1075 hook
= g_array_index(hooks
, LttvTraceHook
, k
);
1076 lttv_hooks_add(lttv_hooks_by_id_find(tfs
->parent
.event_by_id
,
1077 hook
.id
), hook
.h
, &g_array_index(hooks
, LttvTraceHook
, k
), LTTV_PRIO_STATE
);
1080 lttv_attribute_find(self
->parent
.a
, LTTV_STATE_HOOKS
, LTTV_POINTER
, &val
);
1081 *(val
.v_pointer
) = hooks
;
1086 void lttv_state_remove_event_hooks(LttvTracesetState
*self
)
1088 LttvTraceset
*traceset
= self
->parent
.ts
;
1090 guint i
, j
, k
, nb_trace
, nb_tracefile
;
1094 LttvTracefileState
*tfs
;
1100 LttvAttributeValue val
;
1102 nb_trace
= lttv_traceset_number(traceset
);
1103 for(i
= 0 ; i
< nb_trace
; i
++) {
1104 ts
= LTTV_TRACE_STATE(self
->parent
.traces
[i
]);
1105 lttv_attribute_find(self
->parent
.a
, LTTV_STATE_HOOKS
, LTTV_POINTER
, &val
);
1106 hooks
= *(val
.v_pointer
);
1108 /* Remove these hooks from each event_by_id hooks list */
1110 nb_tracefile
= ltt_trace_control_tracefile_number(ts
->parent
.t
) +
1111 ltt_trace_per_cpu_tracefile_number(ts
->parent
.t
);
1113 for(j
= 0 ; j
< nb_tracefile
; j
++) {
1114 tfs
= LTTV_TRACEFILE_STATE(ts
->parent
.tracefiles
[j
]);
1116 for(k
= 0 ; k
< hooks
->len
; k
++) {
1117 hook
= g_array_index(hooks
, LttvTraceHook
, k
);
1118 lttv_hooks_remove_data(
1119 lttv_hooks_by_id_find(tfs
->parent
.event_by_id
,
1120 hook
.id
), hook
.h
, &g_array_index(hooks
, LttvTraceHook
, k
));
1123 g_array_free(hooks
, TRUE
);
1128 static gboolean
block_start(void *hook_data
, void *call_data
)
1130 LttvTracefileState
*self
= (LttvTracefileState
*)call_data
;
1132 LttvTracefileState
*tfcs
;
1134 LttvTraceState
*tcs
= (LttvTraceState
*)(self
->parent
.t_context
);
1136 LttEventPosition
*ep
;
1138 guint i
, nb_block
, nb_event
, nb_tracefile
;
1142 LttvAttribute
*saved_states_tree
, *saved_state_tree
;
1144 LttvAttributeValue value
;
1146 ep
= ltt_event_position_new();
1147 nb_tracefile
= ltt_trace_control_tracefile_number(tcs
->parent
.t
) +
1148 ltt_trace_per_cpu_tracefile_number(tcs
->parent
.t
);
1150 /* Count the number of events added since the last block end in any
1153 for(i
= 0 ; i
< nb_tracefile
; i
++) {
1154 tfcs
= (LttvTracefileState
*)tcs
->parent
.tracefiles
[i
];
1155 ltt_event_position(tfcs
->parent
.e
, ep
);
1156 ltt_event_position_get(ep
, &nb_block
, &nb_event
, &tf
);
1157 tcs
->nb_event
+= nb_event
- tfcs
->saved_position
;
1158 tfcs
->saved_position
= nb_event
;
1162 if(tcs
->nb_event
>= tcs
->save_interval
) {
1163 saved_states_tree
= lttv_attribute_find_subdir(tcs
->parent
.t_a
,
1164 LTTV_STATE_SAVED_STATES
);
1165 saved_state_tree
= g_object_new(LTTV_ATTRIBUTE_TYPE
, NULL
);
1166 value
= lttv_attribute_add(saved_states_tree
,
1167 lttv_attribute_get_number(saved_states_tree
), LTTV_GOBJECT
);
1168 *(value
.v_gobject
) = (GObject
*)saved_state_tree
;
1169 value
= lttv_attribute_add(saved_state_tree
, LTTV_STATE_TIME
, LTTV_TIME
);
1170 *(value
.v_time
) = self
->parent
.timestamp
;
1171 lttv_state_save(tcs
, saved_state_tree
);
1173 g_debug("Saving state at time %lu.%lu", self
->parent
.timestamp
.tv_sec
,
1174 self
->parent
.timestamp
.tv_nsec
);
1176 *(tcs
->max_time_state_recomputed_in_seek
) = self
->parent
.timestamp
;
1181 static gboolean
block_end(void *hook_data
, void *call_data
)
1183 LttvTracefileState
*self
= (LttvTracefileState
*)call_data
;
1185 LttvTraceState
*tcs
= (LttvTraceState
*)(self
->parent
.t_context
);
1189 LttEventPosition
*ep
;
1191 guint nb_block
, nb_event
;
1193 ep
= ltt_event_position_new();
1194 ltt_event_position(self
->parent
.e
, ep
);
1195 ltt_event_position_get(ep
, &nb_block
, &nb_event
, &tf
);
1196 tcs
->nb_event
+= nb_event
- self
->saved_position
+ 1;
1197 self
->saved_position
= 0;
1198 *(tcs
->max_time_state_recomputed_in_seek
) = self
->parent
.timestamp
;
1203 void lttv_state_save_add_event_hooks(LttvTracesetState
*self
)
1205 LttvTraceset
*traceset
= self
->parent
.ts
;
1207 guint i
, j
, k
, nb_trace
, nb_tracefile
;
1211 LttvTracefileState
*tfs
;
1213 LttvTraceHook hook_start
, hook_end
;
1215 nb_trace
= lttv_traceset_number(traceset
);
1216 for(i
= 0 ; i
< nb_trace
; i
++) {
1217 ts
= (LttvTraceState
*)self
->parent
.traces
[i
];
1218 lttv_trace_find_hook(ts
->parent
.t
, "core","block_start",NULL
,
1219 NULL
, NULL
, block_start
, &hook_start
);
1220 lttv_trace_find_hook(ts
->parent
.t
, "core","block_end",NULL
,
1221 NULL
, NULL
, block_end
, &hook_end
);
1223 nb_tracefile
= ltt_trace_control_tracefile_number(ts
->parent
.t
) +
1224 ltt_trace_per_cpu_tracefile_number(ts
->parent
.t
);
1226 for(j
= 0 ; j
< nb_tracefile
; j
++) {
1227 tfs
= LTTV_TRACEFILE_STATE(ts
->parent
.tracefiles
[j
]);
1228 lttv_hooks_add(lttv_hooks_by_id_find(tfs
->parent
.event_by_id
,
1229 hook_start
.id
), hook_start
.h
, NULL
, LTTV_PRIO_STATE
);
1230 lttv_hooks_add(lttv_hooks_by_id_find(tfs
->parent
.event_by_id
,
1231 hook_end
.id
), hook_end
.h
, NULL
, LTTV_PRIO_STATE
);
1237 void lttv_state_save_remove_event_hooks(LttvTracesetState
*self
)
1239 LttvTraceset
*traceset
= self
->parent
.ts
;
1241 guint i
, j
, k
, nb_trace
, nb_tracefile
;
1245 LttvTracefileState
*tfs
;
1247 LttvTraceHook hook_start
, hook_end
;
1249 nb_trace
= lttv_traceset_number(traceset
);
1250 for(i
= 0 ; i
< nb_trace
; i
++) {
1251 ts
= LTTV_TRACE_STATE(self
->parent
.traces
[i
]);
1252 lttv_trace_find_hook(ts
->parent
.t
, "core","block_start",NULL
,
1253 NULL
, NULL
, block_start
, &hook_start
);
1255 lttv_trace_find_hook(ts
->parent
.t
, "core","block_end",NULL
,
1256 NULL
, NULL
, block_end
, &hook_end
);
1258 nb_tracefile
= ltt_trace_control_tracefile_number(ts
->parent
.t
) +
1259 ltt_trace_per_cpu_tracefile_number(ts
->parent
.t
);
1261 for(j
= 0 ; j
< nb_tracefile
; j
++) {
1262 tfs
= LTTV_TRACEFILE_STATE(ts
->parent
.tracefiles
[j
]);
1263 lttv_hooks_remove_data(lttv_hooks_by_id_find(
1264 tfs
->parent
.event_by_id
, hook_start
.id
), hook_start
.h
, NULL
);
1265 lttv_hooks_remove_data(lttv_hooks_by_id_find(
1266 tfs
->parent
.event_by_id
, hook_end
.id
), hook_end
.h
, NULL
);
1272 void lttv_state_traceset_seek_time_closest(LttvTracesetState
*self
, LttTime t
)
1274 LttvTraceset
*traceset
= self
->parent
.ts
;
1276 guint i
, j
, nb_trace
, nb_saved_state
;
1278 int min_pos
, mid_pos
, max_pos
;
1280 LttvTraceState
*tcs
;
1282 LttvAttributeValue value
;
1284 LttvAttributeType type
;
1286 LttvAttributeName name
;
1288 LttvAttribute
*saved_states_tree
, *saved_state_tree
, *closest_tree
;
1290 nb_trace
= lttv_traceset_number(traceset
);
1291 for(i
= 0 ; i
< nb_trace
; i
++) {
1292 tcs
= (LttvTraceState
*)self
->parent
.traces
[i
];
1294 if(ltt_time_compare(t
, *(tcs
->max_time_state_recomputed_in_seek
)) < 0) {
1295 saved_states_tree
= lttv_attribute_find_subdir(tcs
->parent
.t_a
,
1296 LTTV_STATE_SAVED_STATES
);
1299 if(saved_states_tree
) {
1300 max_pos
= lttv_attribute_get_number(saved_states_tree
) - 1;
1301 mid_pos
= max_pos
/ 2;
1302 while(min_pos
< max_pos
) {
1303 type
= lttv_attribute_get(saved_states_tree
, mid_pos
, &name
, &value
);
1304 g_assert(type
== LTTV_GOBJECT
);
1305 saved_state_tree
= *((LttvAttribute
**)(value
.v_gobject
));
1306 type
= lttv_attribute_get_by_name(saved_state_tree
, LTTV_STATE_TIME
,
1308 g_assert(type
== LTTV_TIME
);
1309 if(ltt_time_compare(*(value
.v_time
), t
) < 0) {
1311 closest_tree
= saved_state_tree
;
1313 else max_pos
= mid_pos
- 1;
1315 mid_pos
= (min_pos
+ max_pos
+ 1) / 2;
1319 /* restore the closest earlier saved state */
1321 lttv_state_restore(tcs
, closest_tree
);
1324 /* There is no saved state, yet we want to have it. Restart at T0 */
1326 restore_init_state(tcs
);
1327 lttv_process_trace_seek_time(&(tcs
->parent
), ltt_time_zero
);
1330 /* We want to seek quickly without restoring/updating the state */
1332 restore_init_state(tcs
);
1333 lttv_process_trace_seek_time(&(tcs
->parent
), t
);
1340 traceset_state_instance_init (GTypeInstance
*instance
, gpointer g_class
)
1346 traceset_state_finalize (LttvTracesetState
*self
)
1348 G_OBJECT_CLASS(g_type_class_peek(LTTV_TRACESET_CONTEXT_TYPE
))->
1349 finalize(G_OBJECT(self
));
1354 traceset_state_class_init (LttvTracesetContextClass
*klass
)
1356 GObjectClass
*gobject_class
= G_OBJECT_CLASS(klass
);
1358 gobject_class
->finalize
= (void (*)(GObject
*self
)) traceset_state_finalize
;
1359 klass
->init
= (void (*)(LttvTracesetContext
*self
, LttvTraceset
*ts
))init
;
1360 klass
->fini
= (void (*)(LttvTracesetContext
*self
))fini
;
1361 klass
->new_traceset_context
= new_traceset_context
;
1362 klass
->new_trace_context
= new_trace_context
;
1363 klass
->new_tracefile_context
= new_tracefile_context
;
1368 lttv_traceset_state_get_type(void)
1370 static GType type
= 0;
1372 static const GTypeInfo info
= {
1373 sizeof (LttvTracesetStateClass
),
1374 NULL
, /* base_init */
1375 NULL
, /* base_finalize */
1376 (GClassInitFunc
) traceset_state_class_init
, /* class_init */
1377 NULL
, /* class_finalize */
1378 NULL
, /* class_data */
1379 sizeof (LttvTracesetState
),
1380 0, /* n_preallocs */
1381 (GInstanceInitFunc
) traceset_state_instance_init
/* instance_init */
1384 type
= g_type_register_static (LTTV_TRACESET_CONTEXT_TYPE
, "LttvTracesetStateType",
1392 trace_state_instance_init (GTypeInstance
*instance
, gpointer g_class
)
1398 trace_state_finalize (LttvTraceState
*self
)
1400 G_OBJECT_CLASS(g_type_class_peek(LTTV_TRACE_CONTEXT_TYPE
))->
1401 finalize(G_OBJECT(self
));
1406 trace_state_class_init (LttvTraceStateClass
*klass
)
1408 GObjectClass
*gobject_class
= G_OBJECT_CLASS(klass
);
1410 gobject_class
->finalize
= (void (*)(GObject
*self
)) trace_state_finalize
;
1411 klass
->state_save
= state_save
;
1412 klass
->state_restore
= state_restore
;
1413 klass
->state_saved_free
= state_saved_free
;
1418 lttv_trace_state_get_type(void)
1420 static GType type
= 0;
1422 static const GTypeInfo info
= {
1423 sizeof (LttvTraceStateClass
),
1424 NULL
, /* base_init */
1425 NULL
, /* base_finalize */
1426 (GClassInitFunc
) trace_state_class_init
, /* class_init */
1427 NULL
, /* class_finalize */
1428 NULL
, /* class_data */
1429 sizeof (LttvTraceState
),
1430 0, /* n_preallocs */
1431 (GInstanceInitFunc
) trace_state_instance_init
/* instance_init */
1434 type
= g_type_register_static (LTTV_TRACE_CONTEXT_TYPE
,
1435 "LttvTraceStateType", &info
, 0);
1442 tracefile_state_instance_init (GTypeInstance
*instance
, gpointer g_class
)
1448 tracefile_state_finalize (LttvTracefileState
*self
)
1450 G_OBJECT_CLASS(g_type_class_peek(LTTV_TRACEFILE_CONTEXT_TYPE
))->
1451 finalize(G_OBJECT(self
));
1456 tracefile_state_class_init (LttvTracefileStateClass
*klass
)
1458 GObjectClass
*gobject_class
= G_OBJECT_CLASS(klass
);
1460 gobject_class
->finalize
= (void (*)(GObject
*self
)) tracefile_state_finalize
;
1465 lttv_tracefile_state_get_type(void)
1467 static GType type
= 0;
1469 static const GTypeInfo info
= {
1470 sizeof (LttvTracefileStateClass
),
1471 NULL
, /* base_init */
1472 NULL
, /* base_finalize */
1473 (GClassInitFunc
) tracefile_state_class_init
, /* class_init */
1474 NULL
, /* class_finalize */
1475 NULL
, /* class_data */
1476 sizeof (LttvTracefileState
),
1477 0, /* n_preallocs */
1478 (GInstanceInitFunc
) tracefile_state_instance_init
/* instance_init */
1481 type
= g_type_register_static (LTTV_TRACEFILE_CONTEXT_TYPE
,
1482 "LttvTracefileStateType", &info
, 0);
1488 static void module_init()
1490 LTTV_STATE_UNNAMED
= g_quark_from_string("unnamed");
1491 LTTV_STATE_MODE_UNKNOWN
= g_quark_from_string("unknown execution mode");
1492 LTTV_STATE_USER_MODE
= g_quark_from_string("user mode");
1493 LTTV_STATE_WAIT_FORK
= g_quark_from_string("wait fork");
1494 LTTV_STATE_SYSCALL
= g_quark_from_string("system call");
1495 LTTV_STATE_TRAP
= g_quark_from_string("trap");
1496 LTTV_STATE_IRQ
= g_quark_from_string("irq");
1497 LTTV_STATE_SUBMODE_UNKNOWN
= g_quark_from_string("unknown submode");
1498 LTTV_STATE_SUBMODE_NONE
= g_quark_from_string("(no submode)");
1499 LTTV_STATE_WAIT_CPU
= g_quark_from_string("wait for cpu");
1500 LTTV_STATE_EXIT
= g_quark_from_string("exiting");
1501 LTTV_STATE_WAIT
= g_quark_from_string("wait for I/O");
1502 LTTV_STATE_RUN
= g_quark_from_string("running");
1503 LTTV_STATE_TRACEFILES
= g_quark_from_string("tracefiles");
1504 LTTV_STATE_PROCESSES
= g_quark_from_string("processes");
1505 LTTV_STATE_PROCESS
= g_quark_from_string("process");
1506 LTTV_STATE_EVENT
= g_quark_from_string("event");
1507 LTTV_STATE_SAVED_STATES
= g_quark_from_string("saved states");
1508 LTTV_STATE_SAVED_STATES_TIME
= g_quark_from_string("saved states time");
1509 LTTV_STATE_TIME
= g_quark_from_string("time");
1510 LTTV_STATE_HOOKS
= g_quark_from_string("saved state hooks");
1511 LTTV_STATE_NAME_TABLES
= g_quark_from_string("name tables");
1512 LTTV_STATE_TRACE_STATE_USE_COUNT
=
1513 g_quark_from_string("trace_state_use_count");
1516 static void module_destroy()
1521 LTTV_MODULE("state", "State computation", \
1522 "Update the system state, possibly saving it at intervals", \
1523 module_init
, module_destroy
)