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>
29 LTTV_STATE_MODE_UNKNOWN
,
36 LTTV_STATE_SUBMODE_UNKNOWN
,
37 LTTV_STATE_SUBMODE_NONE
;
48 LTTV_STATE_TRACEFILES
,
52 LTTV_STATE_SAVED_STATES
,
53 LTTV_STATE_SAVED_STATES_TIME
,
58 static void fill_name_tables(LttvTraceState
*tcs
);
60 static void free_name_tables(LttvTraceState
*tcs
);
62 static void lttv_state_free_process_table(GHashTable
*processes
);
65 void lttv_state_save(LttvTraceState
*self
, LttvAttribute
*container
)
67 LTTV_TRACE_STATE_GET_CLASS(self
)->state_save(self
, container
);
71 void lttv_state_restore(LttvTraceState
*self
, LttvAttribute
*container
)
73 LTTV_TRACE_STATE_GET_CLASS(self
)->state_restore(self
, container
);
77 void lttv_state_saved_state_free(LttvTraceState
*self
,
78 LttvAttribute
*container
)
80 LTTV_TRACE_STATE_GET_CLASS(self
)->state_restore(self
, container
);
84 guint
process_hash(gconstpointer key
)
86 return ((LttvProcessState
*)key
)->pid
;
90 gboolean
process_equal(gconstpointer a
, gconstpointer b
)
92 LttvProcessState
*process_a
, *process_b
;
94 process_a
= (LttvProcessState
*)a
;
95 process_b
= (LttvProcessState
*)b
;
97 if(process_a
->pid
!= process_b
->pid
) return FALSE
;
98 if(process_a
->pid
== 0 &&
99 process_a
->last_cpu
!= process_b
->last_cpu
) return FALSE
;
105 restore_init_state(LttvTraceState
*self
)
107 guint i
, nb_tracefile
;
109 LttvTracefileState
*tfcs
;
111 LttTime null_time
= {0,0};
113 if(self
->processes
!= NULL
) lttv_state_free_process_table(self
->processes
);
114 self
->processes
= g_hash_table_new(process_hash
, process_equal
);
117 nb_tracefile
= ltt_trace_control_tracefile_number(self
->parent
.t
) +
118 ltt_trace_per_cpu_tracefile_number(self
->parent
.t
);
120 for(i
= 0 ; i
< nb_tracefile
; i
++) {
121 tfcs
= LTTV_TRACEFILE_STATE(self
->parent
.tracefiles
[i
]);
122 tfcs
->parent
.timestamp
= null_time
;
123 tfcs
->saved_position
= 0;
124 tfcs
->process
= lttv_state_create_process(tfcs
, NULL
,0);
125 tfcs
->process
->state
->s
= LTTV_STATE_RUN
;
126 tfcs
->process
->last_cpu
= tfcs
->cpu_name
;
130 static LttTime time_zero
= {0,0};
133 init(LttvTracesetState
*self
, LttvTraceset
*ts
)
135 guint i
, j
, nb_trace
, nb_tracefile
;
137 LttvTraceContext
*tc
;
141 LttvTracefileState
*tfcs
;
143 LttvAttributeValue v
;
145 LTTV_TRACESET_CONTEXT_CLASS(g_type_class_peek(LTTV_TRACESET_CONTEXT_TYPE
))->
146 init((LttvTracesetContext
*)self
, ts
);
148 nb_trace
= lttv_traceset_number(ts
);
149 for(i
= 0 ; i
< nb_trace
; i
++) {
150 tc
= self
->parent
.traces
[i
];
151 tcs
= (LttvTraceState
*)tc
;
152 tcs
->save_interval
= 50000;
153 lttv_attribute_find(tcs
->parent
.t_a
, LTTV_STATE_SAVED_STATES_TIME
,
155 if(*(v
.v_pointer
) == NULL
) {
156 *(v
.v_pointer
) = g_new(LttTime
,1);
157 *((LttTime
*)*(v
.v_pointer
)) = time_zero
;
159 tcs
->max_time_state_recomputed_in_seek
= (LttTime
*)*(v
.v_pointer
);
161 fill_name_tables(tcs
);
163 nb_tracefile
= ltt_trace_control_tracefile_number(tc
->t
) +
164 ltt_trace_per_cpu_tracefile_number(tc
->t
);
166 for(j
= 0 ; j
< nb_tracefile
; j
++) {
167 tfcs
= LTTV_TRACEFILE_STATE(tc
->tracefiles
[j
]);
168 tfcs
->cpu_name
= g_quark_from_string(ltt_tracefile_name(tfcs
->parent
.tf
));
170 tcs
->processes
= NULL
;
171 restore_init_state(tcs
);
177 fini(LttvTracesetState
*self
)
179 guint i
, j
, nb_trace
;
183 LttvTracefileState
*tfcs
;
185 nb_trace
= lttv_traceset_number(LTTV_TRACESET_CONTEXT(self
)->ts
);
186 for(i
= 0 ; i
< nb_trace
; i
++) {
187 tcs
= (LttvTraceState
*)(LTTV_TRACESET_CONTEXT(self
)->traces
[i
]);
188 lttv_state_free_process_table(tcs
->processes
);
189 tcs
->processes
= NULL
;
190 free_name_tables(tcs
);
192 LTTV_TRACESET_CONTEXT_CLASS(g_type_class_peek(LTTV_TRACESET_CONTEXT_TYPE
))->
193 fini((LttvTracesetContext
*)self
);
197 static LttvTracesetContext
*
198 new_traceset_context(LttvTracesetContext
*self
)
200 return LTTV_TRACESET_CONTEXT(g_object_new(LTTV_TRACESET_STATE_TYPE
, NULL
));
204 static LttvTraceContext
*
205 new_trace_context(LttvTracesetContext
*self
)
207 return LTTV_TRACE_CONTEXT(g_object_new(LTTV_TRACE_STATE_TYPE
, NULL
));
211 static LttvTracefileContext
*
212 new_tracefile_context(LttvTracesetContext
*self
)
214 return LTTV_TRACEFILE_CONTEXT(g_object_new(LTTV_TRACEFILE_STATE_TYPE
, NULL
));
218 /* Write the process state of the trace */
220 static void write_process_state(gpointer key
, gpointer value
,
223 LttvProcessState
*process
;
225 LttvExecutionState
*es
;
227 FILE *fp
= (FILE *)user_data
;
231 process
= (LttvProcessState
*)value
;
233 " <PROCESS PID=%u PPID=%u CTIME_S=%lu CTIME_NS=%lu NAME=\"%s\" CPU=\"%s\">\n",
234 process
->pid
, process
->ppid
, process
->creation_time
.tv_sec
,
235 process
->creation_time
.tv_nsec
, g_quark_to_string(process
->name
),
236 g_quark_to_string(process
->last_cpu
));
238 for(i
= 0 ; i
< process
->execution_stack
->len
; i
++) {
239 es
= &g_array_index(process
->execution_stack
, LttvExecutionState
, i
);
240 fprintf(fp
, " <ES MODE=\"%s\" SUBMODE=\"%s\" ENTRY_S=%lu ENTRY_NS=%lu",
241 g_quark_to_string(es
->t
), g_quark_to_string(es
->n
),
242 es
->entry
.tv_sec
, es
->entry
.tv_nsec
);
243 fprintf(fp
, " CHANGE_S=%lu CHANGE_NS=%lu STATUS=\"%s\"/>\n",
244 es
->change
.tv_sec
, es
->change
.tv_nsec
, g_quark_to_string(es
->s
));
246 fprintf(fp
, " </PROCESS>\n");
250 void lttv_state_write(LttvTraceState
*self
, LttTime t
, FILE *fp
)
252 guint i
, nb_tracefile
, nb_block
, nb_event
;
254 LttvTracefileState
*tfcs
;
258 LttEventPosition
*ep
;
260 ep
= ltt_event_position_new();
262 fprintf(fp
,"<PROCESS_STATE TIME_S=%lu TIME_NS=%lu>\n", t
.tv_sec
, t
.tv_nsec
);
264 g_hash_table_foreach(self
->processes
, write_process_state
, fp
);
266 nb_tracefile
= ltt_trace_control_tracefile_number(self
->parent
.t
) +
267 ltt_trace_per_cpu_tracefile_number(self
->parent
.t
);
269 for(i
= 0 ; i
< nb_tracefile
; i
++) {
270 tfcs
= (LttvTracefileState
*)self
->parent
.tracefiles
[i
];
271 fprintf(fp
, " <TRACEFILE PID=%u TIMESTAMP_S=%lu TIMESTAMP_NS=%lu",
272 tfcs
->process
->pid
, tfcs
->parent
.timestamp
.tv_sec
,
273 tfcs
->parent
.timestamp
.tv_nsec
);
274 if(tfcs
->parent
.e
== NULL
) fprintf(fp
,"/>\n");
276 ltt_event_position(tfcs
->parent
.e
, ep
);
277 ltt_event_position_get(ep
, &nb_block
, &nb_event
, &tf
);
278 fprintf(fp
, " BLOCK=%u EVENT=%u/>\n", nb_block
, nb_event
);
282 fprintf(fp
,"</PROCESS_STATE>");
286 /* Copy each process from an existing hash table to a new one */
288 static void copy_process_state(gpointer key
, gpointer value
,gpointer user_data
)
290 LttvProcessState
*process
, *new_process
;
292 GHashTable
*new_processes
= (GHashTable
*)user_data
;
296 process
= (LttvProcessState
*)value
;
297 new_process
= g_new(LttvProcessState
, 1);
298 *new_process
= *process
;
299 new_process
->execution_stack
= g_array_new(FALSE
, FALSE
,
300 sizeof(LttvExecutionState
));
301 g_array_set_size(new_process
->execution_stack
,process
->execution_stack
->len
);
302 for(i
= 0 ; i
< process
->execution_stack
->len
; i
++) {
303 g_array_index(new_process
->execution_stack
, LttvExecutionState
, i
) =
304 g_array_index(process
->execution_stack
, LttvExecutionState
, i
);
306 new_process
->state
= &g_array_index(new_process
->execution_stack
,
307 LttvExecutionState
, new_process
->execution_stack
->len
- 1);
308 g_hash_table_insert(new_processes
, new_process
, new_process
);
312 static GHashTable
*lttv_state_copy_process_table(GHashTable
*processes
)
314 GHashTable
*new_processes
= g_hash_table_new(process_hash
, process_equal
);
316 g_hash_table_foreach(processes
, copy_process_state
, new_processes
);
317 return new_processes
;
321 /* The saved state for each trace contains a member "processes", which
322 stores a copy of the process table, and a member "tracefiles" with
323 one entry per tracefile. Each tracefile has a "process" member pointing
324 to the current process and a "position" member storing the tracefile
325 position (needed to seek to the current "next" event. */
327 static void state_save(LttvTraceState
*self
, LttvAttribute
*container
)
329 guint i
, nb_tracefile
;
331 LttvTracefileState
*tfcs
;
333 LttvAttribute
*tracefiles_tree
, *tracefile_tree
;
335 LttvAttributeType type
;
337 LttvAttributeValue value
;
339 LttvAttributeName name
;
341 LttEventPosition
*ep
;
343 tracefiles_tree
= lttv_attribute_find_subdir(container
,
344 LTTV_STATE_TRACEFILES
);
346 value
= lttv_attribute_add(container
, LTTV_STATE_PROCESSES
,
348 *(value
.v_pointer
) = lttv_state_copy_process_table(self
->processes
);
350 nb_tracefile
= ltt_trace_control_tracefile_number(self
->parent
.t
) +
351 ltt_trace_per_cpu_tracefile_number(self
->parent
.t
);
353 for(i
= 0 ; i
< nb_tracefile
; i
++) {
354 tfcs
= (LttvTracefileState
*)self
->parent
.tracefiles
[i
];
355 tracefile_tree
= g_object_new(LTTV_ATTRIBUTE_TYPE
, NULL
);
356 value
= lttv_attribute_add(tracefiles_tree
, i
,
358 *(value
.v_gobject
) = (GObject
*)tracefile_tree
;
359 value
= lttv_attribute_add(tracefile_tree
, LTTV_STATE_PROCESS
,
361 *(value
.v_uint
) = tfcs
->process
->pid
;
362 value
= lttv_attribute_add(tracefile_tree
, LTTV_STATE_EVENT
,
364 if(tfcs
->parent
.e
== NULL
) *(value
.v_pointer
) = NULL
;
366 ep
= ltt_event_position_new();
367 ltt_event_position(tfcs
->parent
.e
, ep
);
368 *(value
.v_pointer
) = ep
;
370 guint nb_block
, nb_event
;
372 ltt_event_position_get(ep
, &nb_block
, &nb_event
, &tf
);
373 g_debug("Block %u event %u time %lu.%lu", nb_block
, nb_event
,
374 tfcs
->parent
.timestamp
.tv_sec
, tfcs
->parent
.timestamp
.tv_nsec
);
380 static void state_restore(LttvTraceState
*self
, LttvAttribute
*container
)
382 guint i
, nb_tracefile
, pid
;
384 LttvTracefileState
*tfcs
;
386 LttvAttribute
*tracefiles_tree
, *tracefile_tree
;
388 LttvAttributeType type
;
390 LttvAttributeValue value
;
392 LttvAttributeName name
;
394 LttEventPosition
*ep
;
396 tracefiles_tree
= lttv_attribute_find_subdir(container
,
397 LTTV_STATE_TRACEFILES
);
399 type
= lttv_attribute_get_by_name(container
, LTTV_STATE_PROCESSES
,
401 g_assert(type
== LTTV_POINTER
);
402 lttv_state_free_process_table(self
->processes
);
403 self
->processes
= lttv_state_copy_process_table(*(value
.v_pointer
));
405 nb_tracefile
= ltt_trace_control_tracefile_number(self
->parent
.t
) +
406 ltt_trace_per_cpu_tracefile_number(self
->parent
.t
);
408 for(i
= 0 ; i
< nb_tracefile
; i
++) {
409 tfcs
= (LttvTracefileState
*)self
->parent
.tracefiles
[i
];
410 type
= lttv_attribute_get(tracefiles_tree
, i
, &name
, &value
);
411 g_assert(type
== LTTV_GOBJECT
);
412 tracefile_tree
= *((LttvAttribute
**)(value
.v_gobject
));
414 type
= lttv_attribute_get_by_name(tracefile_tree
, LTTV_STATE_PROCESS
,
416 g_assert(type
== LTTV_UINT
);
417 pid
= *(value
.v_uint
);
418 tfcs
->process
= lttv_state_find_process_or_create(tfcs
, pid
);
420 type
= lttv_attribute_get_by_name(tracefile_tree
, LTTV_STATE_EVENT
,
422 g_assert(type
== LTTV_POINTER
);
423 if(*(value
.v_pointer
) == NULL
) tfcs
->parent
.e
= NULL
;
425 ep
= *(value
.v_pointer
);
426 ltt_tracefile_seek_position(tfcs
->parent
.tf
, ep
);
427 tfcs
->parent
.e
= ltt_tracefile_read(tfcs
->parent
.tf
);
428 tfcs
->parent
.timestamp
= ltt_event_time(tfcs
->parent
.e
);
434 static void state_saved_free(LttvTraceState
*self
, LttvAttribute
*container
)
436 guint i
, nb_tracefile
;
438 LttvTracefileState
*tfcs
;
440 LttvAttribute
*tracefiles_tree
, *tracefile_tree
;
442 LttvAttributeType type
;
444 LttvAttributeValue value
;
446 LttvAttributeName name
;
448 LttEventPosition
*ep
;
450 tracefiles_tree
= lttv_attribute_find_subdir(container
,
451 LTTV_STATE_TRACEFILES
);
452 lttv_attribute_remove_by_name(container
, LTTV_STATE_TRACEFILES
);
454 type
= lttv_attribute_get_by_name(container
, LTTV_STATE_PROCESSES
,
456 g_assert(type
== LTTV_POINTER
);
457 lttv_state_free_process_table(*(value
.v_pointer
));
458 *(value
.v_pointer
) = NULL
;
459 lttv_attribute_remove_by_name(container
, LTTV_STATE_PROCESSES
);
461 nb_tracefile
= ltt_trace_control_tracefile_number(self
->parent
.t
) +
462 ltt_trace_per_cpu_tracefile_number(self
->parent
.t
);
464 for(i
= 0 ; i
< nb_tracefile
; i
++) {
465 tfcs
= (LttvTracefileState
*)self
->parent
.tracefiles
[i
];
466 type
= lttv_attribute_get(tracefiles_tree
, i
, &name
, &value
);
467 g_assert(type
== LTTV_GOBJECT
);
468 tracefile_tree
= *((LttvAttribute
**)(value
.v_gobject
));
470 type
= lttv_attribute_get_by_name(tracefile_tree
, LTTV_STATE_EVENT
,
472 g_assert(type
== LTTV_POINTER
);
473 if(*(value
.v_pointer
) != NULL
) g_free(*(value
.v_pointer
));
475 lttv_attribute_recursive_free(tracefiles_tree
);
480 fill_name_tables(LttvTraceState
*tcs
)
484 char *f_name
, *e_name
;
492 GString
*fe_name
= g_string_new("");
494 nb
= ltt_trace_eventtype_number(tcs
->parent
.t
);
495 tcs
->eventtype_names
= g_new(GQuark
, nb
);
496 for(i
= 0 ; i
< nb
; i
++) {
497 et
= ltt_trace_eventtype_get(tcs
->parent
.t
, i
);
498 e_name
= ltt_eventtype_name(et
);
499 f_name
= ltt_facility_name(ltt_eventtype_facility(et
));
500 g_string_printf(fe_name
, "%s.%s", f_name
, e_name
);
501 tcs
->eventtype_names
[i
] = g_quark_from_string(fe_name
->str
);
504 lttv_trace_find_hook(tcs
->parent
.t
, "core", "syscall_entry",
505 "syscall_id", NULL
, NULL
, NULL
, &h
);
506 t
= ltt_field_type(h
.f1
);
507 nb
= ltt_type_element_number(t
);
509 /* CHECK syscalls should be an emun but currently are not!
510 tcs->syscall_names = g_new(GQuark, nb);
512 for(i = 0 ; i < nb ; i++) {
513 tcs->syscall_names[i] = g_quark_from_string(ltt_enum_string_get(t, i));
517 tcs
->syscall_names
= g_new(GQuark
, 256);
518 for(i
= 0 ; i
< 256 ; i
++) {
519 g_string_printf(fe_name
, "syscall %d", i
);
520 tcs
->syscall_names
[i
] = g_quark_from_string(fe_name
->str
);
523 lttv_trace_find_hook(tcs
->parent
.t
, "core", "trap_entry",
524 "trap_id", NULL
, NULL
, NULL
, &h
);
525 t
= ltt_field_type(h
.f1
);
526 nb
= ltt_type_element_number(t
);
529 tcs->trap_names = g_new(GQuark, nb);
530 for(i = 0 ; i < nb ; i++) {
531 tcs->trap_names[i] = g_quark_from_string(ltt_enum_string_get(t, i));
535 tcs
->trap_names
= g_new(GQuark
, 256);
536 for(i
= 0 ; i
< 256 ; i
++) {
537 g_string_printf(fe_name
, "trap %d", i
);
538 tcs
->trap_names
[i
] = g_quark_from_string(fe_name
->str
);
541 lttv_trace_find_hook(tcs
->parent
.t
, "core", "irq_entry",
542 "irq_id", NULL
, NULL
, NULL
, &h
);
543 t
= ltt_field_type(h
.f1
);
544 nb
= ltt_type_element_number(t
);
547 tcs->irq_names = g_new(GQuark, nb);
548 for(i = 0 ; i < nb ; i++) {
549 tcs->irq_names[i] = g_quark_from_string(ltt_enum_string_get(t, i));
553 tcs
->irq_names
= g_new(GQuark
, 256);
554 for(i
= 0 ; i
< 256 ; i
++) {
555 g_string_printf(fe_name
, "irq %d", i
);
556 tcs
->irq_names
[i
] = g_quark_from_string(fe_name
->str
);
559 g_string_free(fe_name
, TRUE
);
564 free_name_tables(LttvTraceState
*tcs
)
566 g_free(tcs
->eventtype_names
);
567 g_free(tcs
->syscall_names
);
568 g_free(tcs
->trap_names
);
569 g_free(tcs
->irq_names
);
573 static void push_state(LttvTracefileState
*tfs
, LttvExecutionMode t
,
576 LttvExecutionState
*es
;
578 LttvProcessState
*process
= tfs
->process
;
580 guint depth
= process
->execution_stack
->len
;
582 g_array_set_size(process
->execution_stack
, depth
+ 1);
583 es
= &g_array_index(process
->execution_stack
, LttvExecutionState
, depth
);
586 es
->entry
= es
->change
= tfs
->parent
.timestamp
;
587 es
->s
= process
->state
->s
;
592 static void pop_state(LttvTracefileState
*tfs
, LttvExecutionMode t
)
594 LttvProcessState
*process
= tfs
->process
;
596 guint depth
= process
->execution_stack
->len
- 1;
598 if(process
->state
->t
!= t
){
599 g_info("Different execution mode type (%d.%09d): ignore it\n",
600 tfs
->parent
.timestamp
.tv_sec
, tfs
->parent
.timestamp
.tv_nsec
);
601 g_info("process state has %s when pop_int is %s\n",
602 g_quark_to_string(process
->state
->t
),
603 g_quark_to_string(t
));
604 g_info("{ %u, %u, %s, %s }\n",
607 g_quark_to_string(process
->name
),
608 g_quark_to_string(process
->state
->s
));
613 g_info("Trying to pop last state on stack (%d.%09d): ignore it\n",
614 tfs
->parent
.timestamp
.tv_sec
, tfs
->parent
.timestamp
.tv_nsec
);
618 g_array_remove_index(process
->execution_stack
, depth
);
620 process
->state
= &g_array_index(process
->execution_stack
, LttvExecutionState
,
622 process
->state
->change
= tfs
->parent
.timestamp
;
627 lttv_state_create_process(LttvTracefileState
*tfs
, LttvProcessState
*parent
,
630 LttvProcessState
*process
= g_new(LttvProcessState
, 1);
632 LttvExecutionState
*es
;
634 LttvTraceContext
*tc
;
640 tcs
= (LttvTraceState
*)tc
= tfs
->parent
.t_context
;
643 process
->last_cpu
= tfs
->cpu_name
;
644 g_hash_table_insert(tcs
->processes
, process
, process
);
647 process
->ppid
= parent
->pid
;
648 process
->name
= parent
->name
;
649 process
->creation_time
= tfs
->parent
.timestamp
;
652 /* No parent. This process exists but we are missing all information about
653 its creation. The birth time is set to zero but we remember the time of
658 process
->name
= LTTV_STATE_UNNAMED
;
659 process
->creation_time
= ltt_time_zero
;
662 process
->insertion_time
= tfs
->parent
.timestamp
;
663 sprintf(buffer
,"%d-%lu.%lu",pid
, process
->creation_time
.tv_sec
,
664 process
->creation_time
.tv_nsec
);
665 process
->pid_time
= g_quark_from_string(buffer
);
666 process
->last_cpu
= tfs
->cpu_name
;
667 process
->execution_stack
= g_array_new(FALSE
, FALSE
,
668 sizeof(LttvExecutionState
));
669 g_array_set_size(process
->execution_stack
, 1);
670 es
= process
->state
= &g_array_index(process
->execution_stack
,
671 LttvExecutionState
, 0);
672 es
->t
= LTTV_STATE_USER_MODE
;
673 es
->n
= LTTV_STATE_SUBMODE_NONE
;
674 es
->entry
= tfs
->parent
.timestamp
;
675 es
->change
= tfs
->parent
.timestamp
;
676 es
->s
= LTTV_STATE_WAIT_FORK
;
683 lttv_state_find_process_from_trace(LttvTraceState
*ts
, GQuark cpu
, guint pid
)
685 LttvProcessState key
;
686 LttvProcessState
*process
;
690 process
= g_hash_table_lookup(ts
->processes
, &key
);
695 LttvProcessState
*lttv_state_find_process(LttvTracefileState
*tfs
,
698 LttvTraceState
*ts
=(LttvTraceState
*)tfs
->parent
.t_context
;
699 return lttv_state_find_process_from_trace(ts
, tfs
->cpu_name
, pid
);
704 lttv_state_find_process_or_create(LttvTracefileState
*tfs
, guint pid
)
706 LttvProcessState
*process
= lttv_state_find_process(tfs
, pid
);
708 if(process
== NULL
) process
= lttv_state_create_process(tfs
, NULL
, pid
);
713 static void exit_process(LttvTracefileState
*tfs
, LttvProcessState
*process
)
715 LttvTraceState
*ts
= LTTV_TRACE_STATE(tfs
->parent
.t_context
);
716 LttvProcessState key
;
718 key
.pid
= process
->pid
;
719 key
.last_cpu
= process
->last_cpu
;
720 g_hash_table_remove(ts
->processes
, &key
);
721 g_array_free(process
->execution_stack
, TRUE
);
726 static void free_process_state(gpointer key
, gpointer value
,gpointer user_data
)
728 g_array_free(((LttvProcessState
*)value
)->execution_stack
, TRUE
);
733 static void lttv_state_free_process_table(GHashTable
*processes
)
735 g_hash_table_foreach(processes
, free_process_state
, NULL
);
736 g_hash_table_destroy(processes
);
740 static gboolean
syscall_entry(void *hook_data
, void *call_data
)
742 LttField
*f
= ((LttvTraceHook
*)hook_data
)->f1
;
744 LttvTracefileState
*s
= (LttvTracefileState
*)call_data
;
746 LttvExecutionSubmode submode
;
748 submode
= ((LttvTraceState
*)(s
->parent
.t_context
))->syscall_names
[
749 ltt_event_get_unsigned(s
->parent
.e
, f
)];
750 push_state(s
, LTTV_STATE_SYSCALL
, submode
);
755 static gboolean
syscall_exit(void *hook_data
, void *call_data
)
757 LttvTracefileState
*s
= (LttvTracefileState
*)call_data
;
759 pop_state(s
, LTTV_STATE_SYSCALL
);
764 static gboolean
trap_entry(void *hook_data
, void *call_data
)
766 LttField
*f
= ((LttvTraceHook
*)hook_data
)->f1
;
768 LttvTracefileState
*s
= (LttvTracefileState
*)call_data
;
770 LttvExecutionSubmode submode
;
772 submode
= ((LttvTraceState
*)(s
->parent
.t_context
))->trap_names
[
773 ltt_event_get_unsigned(s
->parent
.e
, f
)];
774 push_state(s
, LTTV_STATE_TRAP
, submode
);
779 static gboolean
trap_exit(void *hook_data
, void *call_data
)
781 LttvTracefileState
*s
= (LttvTracefileState
*)call_data
;
783 pop_state(s
, LTTV_STATE_TRAP
);
788 static gboolean
irq_entry(void *hook_data
, void *call_data
)
790 LttField
*f
= ((LttvTraceHook
*)hook_data
)->f1
;
792 LttvTracefileState
*s
= (LttvTracefileState
*)call_data
;
794 LttvExecutionSubmode submode
;
796 submode
= ((LttvTraceState
*)(s
->parent
.t_context
))->irq_names
[
797 ltt_event_get_unsigned(s
->parent
.e
, f
)];
799 /* Do something with the info about being in user or system mode when int? */
800 push_state(s
, LTTV_STATE_IRQ
, submode
);
805 static gboolean
irq_exit(void *hook_data
, void *call_data
)
807 LttvTracefileState
*s
= (LttvTracefileState
*)call_data
;
809 pop_state(s
, LTTV_STATE_IRQ
);
814 static gboolean
schedchange(void *hook_data
, void *call_data
)
816 LttvTraceHook
*h
= (LttvTraceHook
*)hook_data
;
818 LttvTracefileState
*s
= (LttvTracefileState
*)call_data
;
820 guint pid_in
, pid_out
, state_out
;
822 pid_in
= ltt_event_get_unsigned(s
->parent
.e
, h
->f1
);
823 pid_out
= ltt_event_get_unsigned(s
->parent
.e
, h
->f2
);
824 state_out
= ltt_event_get_unsigned(s
->parent
.e
, h
->f3
);
826 if(s
->process
!= NULL
) {
828 if(state_out
== 0) s
->process
->state
->s
= LTTV_STATE_WAIT_CPU
;
829 else if(s
->process
->state
->s
== LTTV_STATE_EXIT
)
830 exit_process(s
, s
->process
);
831 else s
->process
->state
->s
= LTTV_STATE_WAIT
;
833 if(s
->process
->pid
== 0)
834 s
->process
->pid
= pid_out
;
836 s
->process
->state
->change
= s
->parent
.timestamp
;
838 s
->process
= lttv_state_find_process_or_create(s
, pid_in
);
839 s
->process
->state
->s
= LTTV_STATE_RUN
;
840 s
->process
->last_cpu
= s
->cpu_name
;
841 s
->process
->state
->change
= s
->parent
.timestamp
;
846 static gboolean
process_fork(void *hook_data
, void *call_data
)
848 LttField
*f
= ((LttvTraceHook
*)hook_data
)->f1
;
850 LttvTracefileState
*s
= (LttvTracefileState
*)call_data
;
854 child_pid
= ltt_event_get_unsigned(s
->parent
.e
, f
);
855 lttv_state_create_process(s
, s
->process
, child_pid
);
860 static gboolean
process_exit(void *hook_data
, void *call_data
)
862 LttvTracefileState
*s
= (LttvTracefileState
*)call_data
;
864 if(s
->process
!= NULL
) {
865 s
->process
->state
->s
= LTTV_STATE_EXIT
;
871 void lttv_state_add_event_hooks(LttvTracesetState
*self
)
873 LttvTraceset
*traceset
= self
->parent
.ts
;
875 guint i
, j
, k
, nb_trace
, nb_tracefile
;
879 LttvTracefileState
*tfs
;
885 LttvAttributeValue val
;
887 nb_trace
= lttv_traceset_number(traceset
);
888 for(i
= 0 ; i
< nb_trace
; i
++) {
889 ts
= (LttvTraceState
*)self
->parent
.traces
[i
];
891 /* Find the eventtype id for the following events and register the
892 associated by id hooks. */
894 hooks
= g_array_new(FALSE
, FALSE
, sizeof(LttvTraceHook
));
895 g_array_set_size(hooks
, 9);
897 lttv_trace_find_hook(ts
->parent
.t
, "core","syscall_entry","syscall_id",
898 NULL
, NULL
, syscall_entry
, &g_array_index(hooks
, LttvTraceHook
, 0));
900 lttv_trace_find_hook(ts
->parent
.t
, "core", "syscall_exit", NULL
, NULL
,
901 NULL
, syscall_exit
, &g_array_index(hooks
, LttvTraceHook
, 1));
903 lttv_trace_find_hook(ts
->parent
.t
, "core", "trap_entry", "trap_id",
904 NULL
, NULL
, trap_entry
, &g_array_index(hooks
, LttvTraceHook
, 2));
906 lttv_trace_find_hook(ts
->parent
.t
, "core", "trap_exit", NULL
, NULL
, NULL
,
907 trap_exit
, &g_array_index(hooks
, LttvTraceHook
, 3));
909 lttv_trace_find_hook(ts
->parent
.t
, "core", "irq_entry", "irq_id", NULL
,
910 NULL
, irq_entry
, &g_array_index(hooks
, LttvTraceHook
, 4));
912 lttv_trace_find_hook(ts
->parent
.t
, "core", "irq_exit", NULL
, NULL
, NULL
,
913 irq_exit
, &g_array_index(hooks
, LttvTraceHook
, 5));
915 lttv_trace_find_hook(ts
->parent
.t
, "core", "schedchange", "in", "out",
916 "out_state", schedchange
, &g_array_index(hooks
, LttvTraceHook
, 6));
918 lttv_trace_find_hook(ts
->parent
.t
, "core", "process_fork", "child_pid",
919 NULL
, NULL
, process_fork
, &g_array_index(hooks
, LttvTraceHook
, 7));
921 lttv_trace_find_hook(ts
->parent
.t
, "core", "process_exit", NULL
, NULL
,
922 NULL
, process_exit
, &g_array_index(hooks
, LttvTraceHook
, 8));
924 /* Add these hooks to each before_event_by_id hooks list */
926 nb_tracefile
= ltt_trace_control_tracefile_number(ts
->parent
.t
) +
927 ltt_trace_per_cpu_tracefile_number(ts
->parent
.t
);
929 for(j
= 0 ; j
< nb_tracefile
; j
++) {
930 tfs
= LTTV_TRACEFILE_STATE(ts
->parent
.tracefiles
[j
]);
932 for(k
= 0 ; k
< hooks
->len
; k
++) {
933 hook
= g_array_index(hooks
, LttvTraceHook
, k
);
934 lttv_hooks_add(lttv_hooks_by_id_find(tfs
->parent
.after_event_by_id
,
935 hook
.id
), hook
.h
, &g_array_index(hooks
, LttvTraceHook
, k
));
938 lttv_attribute_find(self
->parent
.a
, LTTV_STATE_HOOKS
, LTTV_POINTER
, &val
);
939 *(val
.v_pointer
) = hooks
;
944 void lttv_state_remove_event_hooks(LttvTracesetState
*self
)
946 LttvTraceset
*traceset
= self
->parent
.ts
;
948 guint i
, j
, k
, nb_trace
, nb_tracefile
;
952 LttvTracefileState
*tfs
;
958 LttvAttributeValue val
;
960 nb_trace
= lttv_traceset_number(traceset
);
961 for(i
= 0 ; i
< nb_trace
; i
++) {
962 ts
= LTTV_TRACE_STATE(self
->parent
.traces
[i
]);
963 lttv_attribute_find(self
->parent
.a
, LTTV_STATE_HOOKS
, LTTV_POINTER
, &val
);
964 hooks
= *(val
.v_pointer
);
966 /* Add these hooks to each before_event_by_id hooks list */
968 nb_tracefile
= ltt_trace_control_tracefile_number(ts
->parent
.t
) +
969 ltt_trace_per_cpu_tracefile_number(ts
->parent
.t
);
971 for(j
= 0 ; j
< nb_tracefile
; j
++) {
972 tfs
= LTTV_TRACEFILE_STATE(ts
->parent
.tracefiles
[j
]);
974 for(k
= 0 ; k
< hooks
->len
; k
++) {
975 hook
= g_array_index(hooks
, LttvTraceHook
, k
);
976 lttv_hooks_remove_data(
977 lttv_hooks_by_id_find(tfs
->parent
.after_event_by_id
,
978 hook
.id
), hook
.h
, &g_array_index(hooks
, LttvTraceHook
, k
));
981 g_array_free(hooks
, TRUE
);
986 static gboolean
block_start(void *hook_data
, void *call_data
)
988 LttvTracefileState
*self
= (LttvTracefileState
*)call_data
;
990 LttvTracefileState
*tfcs
;
992 LttvTraceState
*tcs
= (LttvTraceState
*)(self
->parent
.t_context
);
994 LttEventPosition
*ep
;
996 guint i
, nb_block
, nb_event
, nb_tracefile
;
1000 LttvAttribute
*saved_states_tree
, *saved_state_tree
;
1002 LttvAttributeValue value
;
1004 ep
= ltt_event_position_new();
1005 nb_tracefile
= ltt_trace_control_tracefile_number(tcs
->parent
.t
) +
1006 ltt_trace_per_cpu_tracefile_number(tcs
->parent
.t
);
1008 /* Count the number of events added since the last block end in any
1011 for(i
= 0 ; i
< nb_tracefile
; i
++) {
1012 tfcs
= (LttvTracefileState
*)tcs
->parent
.tracefiles
[i
];
1013 ltt_event_position(tfcs
->parent
.e
, ep
);
1014 ltt_event_position_get(ep
, &nb_block
, &nb_event
, &tf
);
1015 tcs
->nb_event
+= nb_event
- tfcs
->saved_position
;
1016 tfcs
->saved_position
= nb_event
;
1020 if(tcs
->nb_event
>= tcs
->save_interval
) {
1021 saved_states_tree
= lttv_attribute_find_subdir(tcs
->parent
.t_a
,
1022 LTTV_STATE_SAVED_STATES
);
1023 saved_state_tree
= g_object_new(LTTV_ATTRIBUTE_TYPE
, NULL
);
1024 value
= lttv_attribute_add(saved_states_tree
,
1025 lttv_attribute_get_number(saved_states_tree
), LTTV_GOBJECT
);
1026 *(value
.v_gobject
) = (GObject
*)saved_state_tree
;
1027 value
= lttv_attribute_add(saved_state_tree
, LTTV_STATE_TIME
, LTTV_TIME
);
1028 *(value
.v_time
) = self
->parent
.timestamp
;
1029 lttv_state_save(tcs
, saved_state_tree
);
1031 g_debug("Saving state at time %lu.%lu", self
->parent
.timestamp
.tv_sec
,
1032 self
->parent
.timestamp
.tv_nsec
);
1034 *(tcs
->max_time_state_recomputed_in_seek
) = self
->parent
.timestamp
;
1039 static gboolean
block_end(void *hook_data
, void *call_data
)
1041 LttvTracefileState
*self
= (LttvTracefileState
*)call_data
;
1043 LttvTraceState
*tcs
= (LttvTraceState
*)(self
->parent
.t_context
);
1047 LttEventPosition
*ep
;
1049 guint nb_block
, nb_event
;
1051 ep
= ltt_event_position_new();
1052 ltt_event_position(self
->parent
.e
, ep
);
1053 ltt_event_position_get(ep
, &nb_block
, &nb_event
, &tf
);
1054 tcs
->nb_event
+= nb_event
- self
->saved_position
+ 1;
1055 self
->saved_position
= 0;
1056 *(tcs
->max_time_state_recomputed_in_seek
) = self
->parent
.timestamp
;
1061 void lttv_state_save_add_event_hooks(LttvTracesetState
*self
)
1063 LttvTraceset
*traceset
= self
->parent
.ts
;
1065 guint i
, j
, k
, nb_trace
, nb_tracefile
;
1069 LttvTracefileState
*tfs
;
1071 LttvTraceHook hook_start
, hook_end
;
1073 nb_trace
= lttv_traceset_number(traceset
);
1074 for(i
= 0 ; i
< nb_trace
; i
++) {
1075 ts
= (LttvTraceState
*)self
->parent
.traces
[i
];
1076 lttv_trace_find_hook(ts
->parent
.t
, "core","block_start",NULL
,
1077 NULL
, NULL
, block_start
, &hook_start
);
1078 lttv_trace_find_hook(ts
->parent
.t
, "core","block_end",NULL
,
1079 NULL
, NULL
, block_end
, &hook_end
);
1081 nb_tracefile
= ltt_trace_control_tracefile_number(ts
->parent
.t
) +
1082 ltt_trace_per_cpu_tracefile_number(ts
->parent
.t
);
1084 for(j
= 0 ; j
< nb_tracefile
; j
++) {
1085 tfs
= LTTV_TRACEFILE_STATE(ts
->parent
.tracefiles
[j
]);
1086 lttv_hooks_add(lttv_hooks_by_id_find(tfs
->parent
.after_event_by_id
,
1087 hook_start
.id
), hook_start
.h
, NULL
);
1088 lttv_hooks_add(lttv_hooks_by_id_find(tfs
->parent
.after_event_by_id
,
1089 hook_end
.id
), hook_end
.h
, NULL
);
1095 void lttv_state_save_remove_event_hooks(LttvTracesetState
*self
)
1097 LttvTraceset
*traceset
= self
->parent
.ts
;
1099 guint i
, j
, k
, nb_trace
, nb_tracefile
;
1103 LttvTracefileState
*tfs
;
1105 LttvTraceHook hook_start
, hook_end
;
1107 nb_trace
= lttv_traceset_number(traceset
);
1108 for(i
= 0 ; i
< nb_trace
; i
++) {
1109 ts
= LTTV_TRACE_STATE(self
->parent
.traces
[i
]);
1110 lttv_trace_find_hook(ts
->parent
.t
, "core","block_start",NULL
,
1111 NULL
, NULL
, block_start
, &hook_start
);
1113 lttv_trace_find_hook(ts
->parent
.t
, "core","block_end",NULL
,
1114 NULL
, NULL
, block_end
, &hook_end
);
1116 nb_tracefile
= ltt_trace_control_tracefile_number(ts
->parent
.t
) +
1117 ltt_trace_per_cpu_tracefile_number(ts
->parent
.t
);
1119 for(j
= 0 ; j
< nb_tracefile
; j
++) {
1120 tfs
= LTTV_TRACEFILE_STATE(ts
->parent
.tracefiles
[j
]);
1121 lttv_hooks_remove_data(lttv_hooks_by_id_find(
1122 tfs
->parent
.after_event_by_id
, hook_start
.id
), hook_start
.h
, NULL
);
1123 lttv_hooks_remove_data(lttv_hooks_by_id_find(
1124 tfs
->parent
.after_event_by_id
, hook_end
.id
), hook_end
.h
, NULL
);
1130 void lttv_state_traceset_seek_time_closest(LttvTracesetState
*self
, LttTime t
)
1132 LttvTraceset
*traceset
= self
->parent
.ts
;
1134 guint i
, j
, nb_trace
, nb_saved_state
;
1136 int min_pos
, mid_pos
, max_pos
;
1138 LttvTraceState
*tcs
;
1140 LttvAttributeValue value
;
1142 LttvAttributeType type
;
1144 LttvAttributeName name
;
1146 LttvAttribute
*saved_states_tree
, *saved_state_tree
, *closest_tree
;
1148 nb_trace
= lttv_traceset_number(traceset
);
1149 for(i
= 0 ; i
< nb_trace
; i
++) {
1150 tcs
= (LttvTraceState
*)self
->parent
.traces
[i
];
1152 if(ltt_time_compare(t
, *(tcs
->max_time_state_recomputed_in_seek
)) < 0) {
1153 saved_states_tree
= lttv_attribute_find_subdir(tcs
->parent
.t_a
,
1154 LTTV_STATE_SAVED_STATES
);
1157 if(saved_states_tree
) {
1158 max_pos
= lttv_attribute_get_number(saved_states_tree
) - 1;
1159 mid_pos
= max_pos
/ 2;
1160 while(min_pos
< max_pos
) {
1161 type
= lttv_attribute_get(saved_states_tree
, mid_pos
, &name
, &value
);
1162 g_assert(type
== LTTV_GOBJECT
);
1163 saved_state_tree
= *((LttvAttribute
**)(value
.v_gobject
));
1164 type
= lttv_attribute_get_by_name(saved_state_tree
, LTTV_STATE_TIME
,
1166 g_assert(type
== LTTV_TIME
);
1167 if(ltt_time_compare(*(value
.v_time
), t
) < 0) {
1169 closest_tree
= saved_state_tree
;
1171 else max_pos
= mid_pos
- 1;
1173 mid_pos
= (min_pos
+ max_pos
+ 1) / 2;
1177 /* restore the closest earlier saved state */
1178 if(min_pos
!= -1) lttv_state_restore(tcs
, closest_tree
);
1180 /* There is no saved state, yet we want to have it. Restart at T0 */
1182 restore_init_state(tcs
);
1183 lttv_process_trace_seek_time(&(tcs
->parent
), ltt_time_zero
);
1186 /* We want to seek quickly without restoring/updating the state */
1188 restore_init_state(tcs
);
1189 lttv_process_trace_seek_time(&(tcs
->parent
), t
);
1196 traceset_state_instance_init (GTypeInstance
*instance
, gpointer g_class
)
1202 traceset_state_finalize (LttvTracesetState
*self
)
1204 G_OBJECT_CLASS(g_type_class_peek(LTTV_TRACESET_CONTEXT_TYPE
))->
1205 finalize(G_OBJECT(self
));
1210 traceset_state_class_init (LttvTracesetContextClass
*klass
)
1212 GObjectClass
*gobject_class
= G_OBJECT_CLASS(klass
);
1214 gobject_class
->finalize
= (void (*)(GObject
*self
)) traceset_state_finalize
;
1215 klass
->init
= (void (*)(LttvTracesetContext
*self
, LttvTraceset
*ts
))init
;
1216 klass
->fini
= (void (*)(LttvTracesetContext
*self
))fini
;
1217 klass
->new_traceset_context
= new_traceset_context
;
1218 klass
->new_trace_context
= new_trace_context
;
1219 klass
->new_tracefile_context
= new_tracefile_context
;
1224 lttv_traceset_state_get_type(void)
1226 static GType type
= 0;
1228 static const GTypeInfo info
= {
1229 sizeof (LttvTracesetStateClass
),
1230 NULL
, /* base_init */
1231 NULL
, /* base_finalize */
1232 (GClassInitFunc
) traceset_state_class_init
, /* class_init */
1233 NULL
, /* class_finalize */
1234 NULL
, /* class_data */
1235 sizeof (LttvTracesetState
),
1236 0, /* n_preallocs */
1237 (GInstanceInitFunc
) traceset_state_instance_init
/* instance_init */
1240 type
= g_type_register_static (LTTV_TRACESET_CONTEXT_TYPE
, "LttvTracesetStateType",
1248 trace_state_instance_init (GTypeInstance
*instance
, gpointer g_class
)
1254 trace_state_finalize (LttvTraceState
*self
)
1256 G_OBJECT_CLASS(g_type_class_peek(LTTV_TRACE_CONTEXT_TYPE
))->
1257 finalize(G_OBJECT(self
));
1262 trace_state_class_init (LttvTraceStateClass
*klass
)
1264 GObjectClass
*gobject_class
= G_OBJECT_CLASS(klass
);
1266 gobject_class
->finalize
= (void (*)(GObject
*self
)) trace_state_finalize
;
1267 klass
->state_save
= state_save
;
1268 klass
->state_restore
= state_restore
;
1269 klass
->state_saved_free
= state_saved_free
;
1274 lttv_trace_state_get_type(void)
1276 static GType type
= 0;
1278 static const GTypeInfo info
= {
1279 sizeof (LttvTraceStateClass
),
1280 NULL
, /* base_init */
1281 NULL
, /* base_finalize */
1282 (GClassInitFunc
) trace_state_class_init
, /* class_init */
1283 NULL
, /* class_finalize */
1284 NULL
, /* class_data */
1285 sizeof (LttvTraceState
),
1286 0, /* n_preallocs */
1287 (GInstanceInitFunc
) trace_state_instance_init
/* instance_init */
1290 type
= g_type_register_static (LTTV_TRACE_CONTEXT_TYPE
,
1291 "LttvTraceStateType", &info
, 0);
1298 tracefile_state_instance_init (GTypeInstance
*instance
, gpointer g_class
)
1304 tracefile_state_finalize (LttvTracefileState
*self
)
1306 G_OBJECT_CLASS(g_type_class_peek(LTTV_TRACEFILE_CONTEXT_TYPE
))->
1307 finalize(G_OBJECT(self
));
1312 tracefile_state_class_init (LttvTracefileStateClass
*klass
)
1314 GObjectClass
*gobject_class
= G_OBJECT_CLASS(klass
);
1316 gobject_class
->finalize
= (void (*)(GObject
*self
)) tracefile_state_finalize
;
1321 lttv_tracefile_state_get_type(void)
1323 static GType type
= 0;
1325 static const GTypeInfo info
= {
1326 sizeof (LttvTracefileStateClass
),
1327 NULL
, /* base_init */
1328 NULL
, /* base_finalize */
1329 (GClassInitFunc
) tracefile_state_class_init
, /* class_init */
1330 NULL
, /* class_finalize */
1331 NULL
, /* class_data */
1332 sizeof (LttvTracefileState
),
1333 0, /* n_preallocs */
1334 (GInstanceInitFunc
) tracefile_state_instance_init
/* instance_init */
1337 type
= g_type_register_static (LTTV_TRACEFILE_CONTEXT_TYPE
,
1338 "LttvTracefileStateType", &info
, 0);
1344 static void module_init()
1346 LTTV_STATE_UNNAMED
= g_quark_from_string("unnamed");
1347 LTTV_STATE_MODE_UNKNOWN
= g_quark_from_string("unknown execution mode");
1348 LTTV_STATE_USER_MODE
= g_quark_from_string("user mode");
1349 LTTV_STATE_WAIT_FORK
= g_quark_from_string("wait fork");
1350 LTTV_STATE_SYSCALL
= g_quark_from_string("system call");
1351 LTTV_STATE_TRAP
= g_quark_from_string("trap");
1352 LTTV_STATE_IRQ
= g_quark_from_string("irq");
1353 LTTV_STATE_SUBMODE_UNKNOWN
= g_quark_from_string("unknown submode");
1354 LTTV_STATE_SUBMODE_NONE
= g_quark_from_string("(no submode)");
1355 LTTV_STATE_WAIT_CPU
= g_quark_from_string("wait for cpu");
1356 LTTV_STATE_EXIT
= g_quark_from_string("exiting");
1357 LTTV_STATE_WAIT
= g_quark_from_string("wait for I/O");
1358 LTTV_STATE_RUN
= g_quark_from_string("running");
1359 LTTV_STATE_TRACEFILES
= g_quark_from_string("tracefiles");
1360 LTTV_STATE_PROCESSES
= g_quark_from_string("processes");
1361 LTTV_STATE_PROCESS
= g_quark_from_string("process");
1362 LTTV_STATE_EVENT
= g_quark_from_string("event");
1363 LTTV_STATE_SAVED_STATES
= g_quark_from_string("saved states");
1364 LTTV_STATE_SAVED_STATES_TIME
= g_quark_from_string("saved states time");
1365 LTTV_STATE_TIME
= g_quark_from_string("time");
1366 LTTV_STATE_HOOKS
= g_quark_from_string("saved state hooks");
1369 static void module_destroy()
1374 LTTV_MODULE("state", "State computation", \
1375 "Update the system state, possibly saving it at intervals", \
1376 module_init
, module_destroy
)