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,
23 #include <lttv/lttv.h>
24 #include <lttv/module.h>
25 #include <lttv/state.h>
26 #include <ltt/facility.h>
27 #include <ltt/trace.h>
28 #include <ltt/event.h>
32 #define PREALLOCATED_EXECUTION_STACK 10
34 /* Facilities Quarks */
44 LTT_EVENT_SYSCALL_ENTRY
,
45 LTT_EVENT_SYSCALL_EXIT
,
50 LTT_EVENT_SCHEDCHANGE
,
71 LTTV_STATE_MODE_UNKNOWN
,
78 LTTV_STATE_SUBMODE_UNKNOWN
,
79 LTTV_STATE_SUBMODE_NONE
;
91 LTTV_STATE_TRACEFILES
,
94 LTTV_STATE_RUNNING_PROCESS
,
96 LTTV_STATE_SAVED_STATES
,
97 LTTV_STATE_SAVED_STATES_TIME
,
100 LTTV_STATE_NAME_TABLES
,
101 LTTV_STATE_TRACE_STATE_USE_COUNT
;
103 static void create_max_time(LttvTraceState
*tcs
);
105 static void get_max_time(LttvTraceState
*tcs
);
107 static void free_max_time(LttvTraceState
*tcs
);
109 static void create_name_tables(LttvTraceState
*tcs
);
111 static void get_name_tables(LttvTraceState
*tcs
);
113 static void free_name_tables(LttvTraceState
*tcs
);
115 static void free_saved_state(LttvTraceState
*tcs
);
117 static void lttv_state_free_process_table(GHashTable
*processes
);
120 void lttv_state_save(LttvTraceState
*self
, LttvAttribute
*container
)
122 LTTV_TRACE_STATE_GET_CLASS(self
)->state_save(self
, container
);
126 void lttv_state_restore(LttvTraceState
*self
, LttvAttribute
*container
)
128 LTTV_TRACE_STATE_GET_CLASS(self
)->state_restore(self
, container
);
132 void lttv_state_state_saved_free(LttvTraceState
*self
,
133 LttvAttribute
*container
)
135 LTTV_TRACE_STATE_GET_CLASS(self
)->state_saved_free(self
, container
);
139 guint
process_hash(gconstpointer key
)
141 guint pid
= ((const LttvProcessState
*)key
)->pid
;
142 return (pid
>>8 ^ pid
>>4 ^ pid
>>2 ^ pid
) ;
146 /* If the hash table hash function is well distributed,
147 * the process_equal should compare different pid */
148 gboolean
process_equal(gconstpointer a
, gconstpointer b
)
150 const LttvProcessState
*process_a
, *process_b
;
153 process_a
= (const LttvProcessState
*)a
;
154 process_b
= (const LttvProcessState
*)b
;
156 if(likely(process_a
->pid
!= process_b
->pid
)) ret
= FALSE
;
157 else if(likely(process_a
->pid
== 0 &&
158 process_a
->cpu
!= process_b
->cpu
)) ret
= FALSE
;
165 restore_init_state(LttvTraceState
*self
)
169 LttvTracefileState
*tfcs
;
171 /* Free the process tables */
172 if(self
->processes
!= NULL
) lttv_state_free_process_table(self
->processes
);
173 self
->processes
= g_hash_table_new(process_hash
, process_equal
);
176 /* Seek time to beginning */
177 // Mathieu : fix : don't seek traceset here : causes inconsistency in seek
178 // closest. It's the tracecontext job to seek the trace to the beginning
179 // anyway : the init state might be used at the middle of the trace as well...
180 //g_tree_destroy(self->parent.ts_context->pqueue);
181 //self->parent.ts_context->pqueue = g_tree_new(compare_tracefile);
184 //lttv_process_trace_seek_time(&self->parent, ltt_time_zero);
186 nb_cpus
= ltt_trace_get_num_cpu(self
->parent
.t
);
188 /* Put the per cpu running_process to beginning state : process 0. */
189 for(i
=0; i
< nb_cpus
; i
++) {
190 self
->running_process
[i
] = lttv_state_create_process(self
, NULL
, i
, 0,
192 self
->running_process
[i
]->state
->s
= LTTV_STATE_RUN
;
193 self
->running_process
[i
]->cpu
= i
;
197 nb_tracefile
= self
->parent
.tracefiles
->len
;
199 for(i
= 0 ; i
< nb_tracefile
; i
++) {
201 LTTV_TRACEFILE_STATE(g_array_index(self
->parent
.tracefiles
,
202 LttvTracefileContext
*, i
));
203 ltt_trace_time_span_get(self
->parent
.t
, &tfcs
->parent
.timestamp
, NULL
);
204 // tfcs->saved_position = 0;
205 tfcs
->process
= lttv_state_create_process(tfcs
, NULL
,0);
206 tfcs
->process
->state
->s
= LTTV_STATE_RUN
;
207 tfcs
->process
->last_cpu
= tfcs
->cpu_name
;
208 tfcs
->process
->last_cpu_index
= ltt_tracefile_num(((LttvTracefileContext
*)tfcs
)->tf
);
213 //static LttTime time_zero = {0,0};
216 init(LttvTracesetState
*self
, LttvTraceset
*ts
)
218 guint i
, j
, nb_trace
, nb_tracefile
;
220 LttvTraceContext
*tc
;
224 LttvTracefileState
*tfcs
;
226 LttvAttributeValue v
;
228 LTTV_TRACESET_CONTEXT_CLASS(g_type_class_peek(LTTV_TRACESET_CONTEXT_TYPE
))->
229 init((LttvTracesetContext
*)self
, ts
);
231 nb_trace
= lttv_traceset_number(ts
);
232 for(i
= 0 ; i
< nb_trace
; i
++) {
233 tc
= self
->parent
.traces
[i
];
234 tcs
= LTTV_TRACE_STATE(tc
);
235 tcs
->save_interval
= LTTV_STATE_SAVE_INTERVAL
;
236 lttv_attribute_find(tcs
->parent
.t_a
, LTTV_STATE_TRACE_STATE_USE_COUNT
,
240 if(*(v
.v_uint
) == 1) {
241 create_name_tables(tcs
);
242 create_max_time(tcs
);
244 get_name_tables(tcs
);
247 nb_tracefile
= tc
->tracefiles
->len
;
249 for(j
= 0 ; j
< nb_tracefile
; j
++) {
251 LTTV_TRACEFILE_STATE(g_array_index(tc
->tracefiles
,
252 LttvTracefileContext
*, j
));
253 tfcs
->tracefile_name
= ltt_tracefile_name(tfcs
->parent
.tf
);
256 tcs
->processes
= NULL
;
257 tcs
->running_process
= g_new(LttvProcessState
*,
258 ltt_trace_get_num_cpu(tc
->t
));
259 restore_init_state(tcs
);
265 fini(LttvTracesetState
*self
)
271 LttvTracefileState
*tfcs
;
273 LttvAttributeValue v
;
275 nb_trace
= lttv_traceset_number(LTTV_TRACESET_CONTEXT(self
)->ts
);
276 for(i
= 0 ; i
< nb_trace
; i
++) {
277 tcs
= (LttvTraceState
*)(LTTV_TRACESET_CONTEXT(self
)->traces
[i
]);
278 lttv_attribute_find(tcs
->parent
.t_a
, LTTV_STATE_TRACE_STATE_USE_COUNT
,
281 g_assert(*(v
.v_uint
) != 0);
284 if(*(v
.v_uint
) == 0) {
285 free_name_tables(tcs
);
287 free_saved_state(tcs
);
289 g_free(tcs
->running_process
);
290 tcs
->running_process
= NULL
;
291 lttv_state_free_process_table(tcs
->processes
);
292 tcs
->processes
= NULL
;
294 LTTV_TRACESET_CONTEXT_CLASS(g_type_class_peek(LTTV_TRACESET_CONTEXT_TYPE
))->
295 fini((LttvTracesetContext
*)self
);
299 static LttvTracesetContext
*
300 new_traceset_context(LttvTracesetContext
*self
)
302 return LTTV_TRACESET_CONTEXT(g_object_new(LTTV_TRACESET_STATE_TYPE
, NULL
));
306 static LttvTraceContext
*
307 new_trace_context(LttvTracesetContext
*self
)
309 return LTTV_TRACE_CONTEXT(g_object_new(LTTV_TRACE_STATE_TYPE
, NULL
));
313 static LttvTracefileContext
*
314 new_tracefile_context(LttvTracesetContext
*self
)
316 return LTTV_TRACEFILE_CONTEXT(g_object_new(LTTV_TRACEFILE_STATE_TYPE
, NULL
));
320 /* Write the process state of the trace */
322 static void write_process_state(gpointer key
, gpointer value
,
325 LttvProcessState
*process
;
327 LttvExecutionState
*es
;
329 FILE *fp
= (FILE *)user_data
;
333 process
= (LttvProcessState
*)value
;
335 " <PROCESS CORE=%p PID=%u PPID=%u CTIME_S=%lu CTIME_NS=%lu NAME=\"%s\" CPU=\"%u\">\n",
336 process
, process
->pid
, process
->ppid
, process
->creation_time
.tv_sec
,
337 process
->creation_time
.tv_nsec
, g_quark_to_string(process
->name
),
340 for(i
= 0 ; i
< process
->execution_stack
->len
; i
++) {
341 es
= &g_array_index(process
->execution_stack
, LttvExecutionState
, i
);
342 fprintf(fp
, " <ES MODE=\"%s\" SUBMODE=\"%s\" ENTRY_S=%lu ENTRY_NS=%lu",
343 g_quark_to_string(es
->t
), g_quark_to_string(es
->n
),
344 es
->entry
.tv_sec
, es
->entry
.tv_nsec
);
345 fprintf(fp
, " CHANGE_S=%lu CHANGE_NS=%lu STATUS=\"%s\"/>\n",
346 es
->change
.tv_sec
, es
->change
.tv_nsec
, g_quark_to_string(es
->s
));
348 fprintf(fp
, " </PROCESS>\n");
352 void lttv_state_write(LttvTraceState
*self
, LttTime t
, FILE *fp
)
354 guint i
, nb_tracefile
, nb_block
, offset
;
357 LttvTracefileState
*tfcs
;
361 LttEventPosition
*ep
;
365 ep
= ltt_event_position_new();
367 fprintf(fp
,"<PROCESS_STATE TIME_S=%lu TIME_NS=%lu>\n", t
.tv_sec
, t
.tv_nsec
);
369 g_hash_table_foreach(self
->processes
, write_process_state
, fp
);
371 nb_cpus
= ltt_trace_get_num_cpu(self
->parent
.t
);
372 for(i
=0;i
<nb_cpus
;i
++) {
373 fprintf(fp
,"<CPU NUM=%u RUNNING_PROCESS=%u>\n",
374 i
, self
->running_process
[i
]->pid
);
377 nb_tracefile
= self
->parent
.tracefiles
->len
;
379 for(i
= 0 ; i
< nb_tracefile
; i
++) {
381 LTTV_TRACEFILE_STATE(g_array_index(self
->parent
.tracefiles
,
382 LttvTracefileContext
*, i
));
383 fprintf(fp
, " <TRACEFILE TIMESTAMP_S=%lu TIMESTAMP_NS=%lu",
384 tfcs
->parent
.timestamp
.tv_sec
,
385 tfcs
->parent
.timestamp
.tv_nsec
);
386 LttEvent
*e
= ltt_tracefile_get_event(tfcs
->parent
.tf
);
387 if(e
== NULL
) fprintf(fp
,"/>\n");
389 ltt_event_position(e
, ep
);
390 ltt_event_position_get(ep
, &tf
, &nb_block
, &offset
, &tsc
);
391 fprintf(fp
, " BLOCK=%u OFFSET=%u TSC=%llu/>\n", nb_block
, offset
,
396 fprintf(fp
,"</PROCESS_STATE>");
400 /* Copy each process from an existing hash table to a new one */
402 static void copy_process_state(gpointer key
, gpointer value
,gpointer user_data
)
404 LttvProcessState
*process
, *new_process
;
406 GHashTable
*new_processes
= (GHashTable
*)user_data
;
410 process
= (LttvProcessState
*)value
;
411 new_process
= g_new(LttvProcessState
, 1);
412 *new_process
= *process
;
413 new_process
->execution_stack
= g_array_sized_new(FALSE
, FALSE
,
414 sizeof(LttvExecutionState
), PREALLOCATED_EXECUTION_STACK
);
415 new_process
->execution_stack
=
416 g_array_set_size(new_process
->execution_stack
,
417 process
->execution_stack
->len
);
418 for(i
= 0 ; i
< process
->execution_stack
->len
; i
++) {
419 g_array_index(new_process
->execution_stack
, LttvExecutionState
, i
) =
420 g_array_index(process
->execution_stack
, LttvExecutionState
, i
);
422 new_process
->state
= &g_array_index(new_process
->execution_stack
,
423 LttvExecutionState
, new_process
->execution_stack
->len
- 1);
424 g_hash_table_insert(new_processes
, new_process
, new_process
);
428 static GHashTable
*lttv_state_copy_process_table(GHashTable
*processes
)
430 GHashTable
*new_processes
= g_hash_table_new(process_hash
, process_equal
);
432 g_hash_table_foreach(processes
, copy_process_state
, new_processes
);
433 return new_processes
;
437 /* The saved state for each trace contains a member "processes", which
438 stores a copy of the process table, and a member "tracefiles" with
439 one entry per tracefile. Each tracefile has a "process" member pointing
440 to the current process and a "position" member storing the tracefile
441 position (needed to seek to the current "next" event. */
443 static void state_save(LttvTraceState
*self
, LttvAttribute
*container
)
445 guint i
, nb_tracefile
, nb_cpus
;
447 LttvTracefileState
*tfcs
;
449 LttvAttribute
*tracefiles_tree
, *tracefile_tree
;
451 guint
*running_process
;
453 LttvAttributeType type
;
455 LttvAttributeValue value
;
457 LttvAttributeName name
;
459 LttEventPosition
*ep
;
461 tracefiles_tree
= lttv_attribute_find_subdir(container
,
462 LTTV_STATE_TRACEFILES
);
464 value
= lttv_attribute_add(container
, LTTV_STATE_PROCESSES
,
466 *(value
.v_pointer
) = lttv_state_copy_process_table(self
->processes
);
468 /* Add the currently running processes array */
469 nb_cpus
= ltt_trace_get_num_cpu(self
->parent
.t
);
470 running_process
= g_new(guint
, nb_cpus
);
471 for(i
=0;i
<nb_cpus
;i
++) {
472 running_process
[i
] = self
->running_process
[i
]->pid
;
474 value
= lttv_attribute_add(container
, LTTV_STATE_RUNNING_PROCESS
,
476 *(value
.v_pointer
) = running_process
;
478 g_info("State save");
480 nb_tracefile
= self
->parent
.tracefiles
->len
;
482 for(i
= 0 ; i
< nb_tracefile
; i
++) {
484 LTTV_TRACEFILE_STATE(g_array_index(self
->parent
.tracefiles
,
485 LttvTracefileContext
*, i
));
486 tracefile_tree
= g_object_new(LTTV_ATTRIBUTE_TYPE
, NULL
);
487 value
= lttv_attribute_add(tracefiles_tree
, i
,
489 *(value
.v_gobject
) = (GObject
*)tracefile_tree
;
491 value
= lttv_attribute_add(tracefile_tree
, LTTV_STATE_PROCESS
,
493 *(value
.v_uint
) = tfcs
->process
->pid
;
495 value
= lttv_attribute_add(tracefile_tree
, LTTV_STATE_EVENT
,
497 /* Only save the position if the tfs has not infinite time. */
498 //if(!g_tree_lookup(self->parent.ts_context->pqueue, &tfcs->parent)
499 // && current_tfcs != tfcs) {
500 if(ltt_time_compare(tfcs
->parent
.timestamp
, ltt_time_infinite
) == 0) {
501 *(value
.v_pointer
) = NULL
;
503 LttEvent
*e
= ltt_tracefile_get_event(tfcs
->parent
.tf
);
504 ep
= ltt_event_position_new();
505 ltt_event_position(e
, ep
);
506 *(value
.v_pointer
) = ep
;
508 guint nb_block
, offset
;
511 ltt_event_position_get(ep
, &tf
, &nb_block
, &offset
, &tsc
);
512 g_info("Block %u offset %u tsc %llu time %lu.%lu", nb_block
, offset
,
514 tfcs
->parent
.timestamp
.tv_sec
, tfcs
->parent
.timestamp
.tv_nsec
);
520 static void state_restore(LttvTraceState
*self
, LttvAttribute
*container
)
522 guint i
, nb_tracefile
, pid
, nb_cpus
;
524 LttvTracefileState
*tfcs
;
526 LttvAttribute
*tracefiles_tree
, *tracefile_tree
;
528 guint
*running_process
;
530 LttvAttributeType type
;
532 LttvAttributeValue value
;
534 LttvAttributeName name
;
536 LttEventPosition
*ep
;
538 LttvTracesetContext
*tsc
= self
->parent
.ts_context
;
540 tracefiles_tree
= lttv_attribute_find_subdir(container
,
541 LTTV_STATE_TRACEFILES
);
543 type
= lttv_attribute_get_by_name(container
, LTTV_STATE_PROCESSES
,
545 g_assert(type
== LTTV_POINTER
);
546 lttv_state_free_process_table(self
->processes
);
547 self
->processes
= lttv_state_copy_process_table(*(value
.v_pointer
));
549 /* Add the currently running processes array */
550 nb_cpus
= ltt_trace_get_num_cpu(self
->parent
.t
);
551 type
= lttv_attribute_get_by_name(container
, LTTV_STATE_RUNNING_PROCESS
,
553 g_assert(type
== LTTV_POINTER
);
554 running_process
= *(value
.v_pointer
);
555 for(i
=0;i
<nb_cpus
;i
++) {
556 pid
= running_process
[i
];
557 self
->running_process
[i
] = lttv_state_find_process(self
, i
, pid
);
558 g_assert(self
->running_process
[i
] != NULL
);
562 nb_tracefile
= self
->parent
.tracefiles
->len
;
564 //g_tree_destroy(tsc->pqueue);
565 //tsc->pqueue = g_tree_new(compare_tracefile);
567 for(i
= 0 ; i
< nb_tracefile
; i
++) {
569 LTTV_TRACEFILE_STATE(g_array_index(self
->parent
.tracefiles
,
570 LttvTracefileContext
*, i
));
571 type
= lttv_attribute_get(tracefiles_tree
, i
, &name
, &value
);
572 g_assert(type
== LTTV_GOBJECT
);
573 tracefile_tree
= *((LttvAttribute
**)(value
.v_gobject
));
575 type
= lttv_attribute_get_by_name(tracefile_tree
, LTTV_STATE_PROCESS
,
577 g_assert(type
== LTTV_UINT
);
578 pid
= *(value
.v_uint
);
579 tfcs
->process
= lttv_state_find_process_or_create(tfcs
, pid
);
581 type
= lttv_attribute_get_by_name(tracefile_tree
, LTTV_STATE_EVENT
,
583 g_assert(type
== LTTV_POINTER
);
584 //g_assert(*(value.v_pointer) != NULL);
585 ep
= *(value
.v_pointer
);
586 g_assert(tfcs
->parent
.t_context
!= NULL
);
588 LttvTracefileContext
*tfc
= LTTV_TRACEFILE_CONTEXT(tfcs
);
589 g_tree_remove(tsc
->pqueue
, tfc
);
592 g_assert(ltt_tracefile_seek_position(tfc
->tf
, ep
) == 0);
593 tfc
->timestamp
= ltt_event_time(ltt_tracefile_get_event(tfc
->tf
));
594 g_assert(ltt_time_compare(tfc
->timestamp
, ltt_time_infinite
) != 0);
595 g_tree_insert(tsc
->pqueue
, tfc
, tfc
);
596 g_info("Restoring state for a tf at time %lu.%lu", tfc
->timestamp
.tv_sec
, tfc
->timestamp
.tv_nsec
);
598 tfc
->timestamp
= ltt_time_infinite
;
604 static void state_saved_free(LttvTraceState
*self
, LttvAttribute
*container
)
606 guint i
, nb_tracefile
, nb_cpus
;
608 LttvTracefileState
*tfcs
;
610 LttvAttribute
*tracefiles_tree
, *tracefile_tree
;
612 guint
*running_process
;
614 LttvAttributeType type
;
616 LttvAttributeValue value
;
618 LttvAttributeName name
;
620 LttEventPosition
*ep
;
622 tracefiles_tree
= lttv_attribute_find_subdir(container
,
623 LTTV_STATE_TRACEFILES
);
624 g_object_ref(G_OBJECT(tracefiles_tree
));
625 lttv_attribute_remove_by_name(container
, LTTV_STATE_TRACEFILES
);
627 type
= lttv_attribute_get_by_name(container
, LTTV_STATE_PROCESSES
,
629 g_assert(type
== LTTV_POINTER
);
630 lttv_state_free_process_table(*(value
.v_pointer
));
631 *(value
.v_pointer
) = NULL
;
632 lttv_attribute_remove_by_name(container
, LTTV_STATE_PROCESSES
);
634 /* Free running processes array */
635 nb_cpus
= ltt_trace_get_num_cpu(self
->parent
.t
);
636 type
= lttv_attribute_get_by_name(container
, LTTV_STATE_RUNNING_PROCESS
,
638 g_assert(type
== LTTV_POINTER
);
639 running_process
= *(value
.v_pointer
);
640 g_free(running_process
);
642 nb_tracefile
= self
->parent
.tracefiles
->len
;
644 for(i
= 0 ; i
< nb_tracefile
; i
++) {
646 LTTV_TRACEFILE_STATE(g_array_index(self
->parent
.tracefiles
,
647 LttvTracefileContext
*, i
));
648 type
= lttv_attribute_get(tracefiles_tree
, i
, &name
, &value
);
649 g_assert(type
== LTTV_GOBJECT
);
650 tracefile_tree
= *((LttvAttribute
**)(value
.v_gobject
));
652 type
= lttv_attribute_get_by_name(tracefile_tree
, LTTV_STATE_EVENT
,
654 g_assert(type
== LTTV_POINTER
);
655 if(*(value
.v_pointer
) != NULL
) g_free(*(value
.v_pointer
));
657 g_object_unref(G_OBJECT(tracefiles_tree
));
661 static void free_saved_state(LttvTraceState
*self
)
665 LttvAttributeType type
;
667 LttvAttributeValue value
;
669 LttvAttributeName name
;
671 LttvAttribute
*saved_states
;
673 saved_states
= lttv_attribute_find_subdir(self
->parent
.t_a
,
674 LTTV_STATE_SAVED_STATES
);
676 nb
= lttv_attribute_get_number(saved_states
);
677 for(i
= 0 ; i
< nb
; i
++) {
678 type
= lttv_attribute_get(saved_states
, i
, &name
, &value
);
679 g_assert(type
== LTTV_GOBJECT
);
680 state_saved_free(self
, *((LttvAttribute
**)value
.v_gobject
));
683 lttv_attribute_remove_by_name(self
->parent
.t_a
, LTTV_STATE_SAVED_STATES
);
688 create_max_time(LttvTraceState
*tcs
)
690 LttvAttributeValue v
;
692 lttv_attribute_find(tcs
->parent
.t_a
, LTTV_STATE_SAVED_STATES_TIME
,
694 g_assert(*(v
.v_pointer
) == NULL
);
695 *(v
.v_pointer
) = g_new(LttTime
,1);
696 *((LttTime
*)*(v
.v_pointer
)) = ltt_time_zero
;
701 get_max_time(LttvTraceState
*tcs
)
703 LttvAttributeValue v
;
705 lttv_attribute_find(tcs
->parent
.t_a
, LTTV_STATE_SAVED_STATES_TIME
,
707 g_assert(*(v
.v_pointer
) != NULL
);
708 tcs
->max_time_state_recomputed_in_seek
= (LttTime
*)*(v
.v_pointer
);
713 free_max_time(LttvTraceState
*tcs
)
715 LttvAttributeValue v
;
717 lttv_attribute_find(tcs
->parent
.t_a
, LTTV_STATE_SAVED_STATES_TIME
,
719 g_free(*(v
.v_pointer
));
720 *(v
.v_pointer
) = NULL
;
724 typedef struct _LttvNameTables
{
725 // FIXME GQuark *eventtype_names;
726 GQuark
*syscall_names
;
733 create_name_tables(LttvTraceState
*tcs
)
737 GQuark f_name
, e_name
;
741 LttvTraceHookByFacility
*thf
;
747 GString
*fe_name
= g_string_new("");
749 LttvNameTables
*name_tables
= g_new(LttvNameTables
, 1);
751 LttvAttributeValue v
;
753 lttv_attribute_find(tcs
->parent
.t_a
, LTTV_STATE_NAME_TABLES
,
755 g_assert(*(v
.v_pointer
) == NULL
);
756 *(v
.v_pointer
) = name_tables
;
757 #if 0 // Use iteration over the facilities_by_name and then list all event
758 // types of each facility
759 nb
= ltt_trace_eventtype_number(tcs
->parent
.t
);
760 name_tables
->eventtype_names
= g_new(GQuark
, nb
);
761 for(i
= 0 ; i
< nb
; i
++) {
762 et
= ltt_trace_eventtype_get(tcs
->parent
.t
, i
);
763 e_name
= ltt_eventtype_name(et
);
764 f_name
= ltt_facility_name(ltt_eventtype_facility(et
));
765 g_string_printf(fe_name
, "%s.%s", f_name
, e_name
);
766 name_tables
->eventtype_names
[i
] = g_quark_from_string(fe_name
->str
);
769 if(lttv_trace_find_hook(tcs
->parent
.t
,
770 LTT_FACILITY_KERNEL
, LTT_EVENT_SYSCALL_ENTRY
,
771 LTT_FIELD_SYSCALL_ID
, 0, 0,
775 thf
= lttv_trace_hook_get_first(&h
);
777 t
= ltt_field_type(thf
->f1
);
778 nb
= ltt_type_element_number(t
);
780 lttv_trace_hook_destroy(&h
);
782 /* CHECK syscalls should be an enum but currently are not!
783 name_tables->syscall_names = g_new(GQuark, nb);
785 for(i = 0 ; i < nb ; i++) {
786 name_tables->syscall_names[i] = g_quark_from_string(
787 ltt_enum_string_get(t, i));
791 name_tables
->syscall_names
= g_new(GQuark
, 256);
792 for(i
= 0 ; i
< 256 ; i
++) {
793 g_string_printf(fe_name
, "syscall %d", i
);
794 name_tables
->syscall_names
[i
] = g_quark_from_string(fe_name
->str
);
797 if(lttv_trace_find_hook(tcs
->parent
.t
, LTT_FACILITY_KERNEL
,
798 LTT_EVENT_TRAP_ENTRY
,
799 LTT_FIELD_TRAP_ID
, 0, 0,
803 thf
= lttv_trace_hook_get_first(&h
);
805 t
= ltt_field_type(thf
->f1
);
806 nb
= ltt_type_element_number(t
);
808 lttv_trace_hook_destroy(&h
);
811 name_tables->trap_names = g_new(GQuark, nb);
812 for(i = 0 ; i < nb ; i++) {
813 name_tables->trap_names[i] = g_quark_from_string(
814 ltt_enum_string_get(t, i));
818 name_tables
->trap_names
= g_new(GQuark
, 256);
819 for(i
= 0 ; i
< 256 ; i
++) {
820 g_string_printf(fe_name
, "trap %d", i
);
821 name_tables
->trap_names
[i
] = g_quark_from_string(fe_name
->str
);
824 if(lttv_trace_find_hook(tcs
->parent
.t
,
825 LTT_FACILITY_KERNEL
, LTT_EVENT_IRQ_ENTRY
,
826 LTT_FIELD_IRQ_ID
, 0, 0,
830 thf
= lttv_trace_hook_get_first(&h
);
832 t
= ltt_field_type(thf
->f1
);
833 nb
= ltt_type_element_number(t
);
835 lttv_trace_hook_destroy(&h
);
838 name_tables->irq_names = g_new(GQuark, nb);
839 for(i = 0 ; i < nb ; i++) {
840 name_tables->irq_names[i] = g_quark_from_string(ltt_enum_string_get(t, i));
844 name_tables
->irq_names
= g_new(GQuark
, 256);
845 for(i
= 0 ; i
< 256 ; i
++) {
846 g_string_printf(fe_name
, "irq %d", i
);
847 name_tables
->irq_names
[i
] = g_quark_from_string(fe_name
->str
);
850 g_string_free(fe_name
, TRUE
);
855 get_name_tables(LttvTraceState
*tcs
)
857 LttvNameTables
*name_tables
;
859 LttvAttributeValue v
;
861 lttv_attribute_find(tcs
->parent
.t_a
, LTTV_STATE_NAME_TABLES
,
863 g_assert(*(v
.v_pointer
) != NULL
);
864 name_tables
= (LttvNameTables
*)*(v
.v_pointer
);
865 //tcs->eventtype_names = name_tables->eventtype_names;
866 tcs
->syscall_names
= name_tables
->syscall_names
;
867 tcs
->trap_names
= name_tables
->trap_names
;
868 tcs
->irq_names
= name_tables
->irq_names
;
873 free_name_tables(LttvTraceState
*tcs
)
875 LttvNameTables
*name_tables
;
877 LttvAttributeValue v
;
879 lttv_attribute_find(tcs
->parent
.t_a
, LTTV_STATE_NAME_TABLES
,
881 name_tables
= (LttvNameTables
*)*(v
.v_pointer
);
882 *(v
.v_pointer
) = NULL
;
884 // g_free(name_tables->eventtype_names);
885 g_free(name_tables
->syscall_names
);
886 g_free(name_tables
->trap_names
);
887 g_free(name_tables
->irq_names
);
891 #ifdef HASH_TABLE_DEBUG
893 static void test_process(gpointer key
, gpointer value
, gpointer user_data
)
895 LttvProcessState
*process
= (LttvProcessState
*)value
;
897 /* Test for process corruption */
898 guint stack_len
= process
->execution_stack
->len
;
901 static void hash_table_check(GHashTable
*table
)
903 g_hash_table_foreach(table
, test_process
, NULL
);
910 static void push_state(LttvTracefileState
*tfs
, LttvExecutionMode t
,
913 LttvExecutionState
*es
;
915 guint cpu
= ltt_tracefile_num(tfs
->parent
.tf
);
916 LttvTraceState
*ts
= (LttvTraceState
*)tfs
->parent
.t_context
;
918 #ifdef HASH_TABLE_DEBUG
919 hash_table_check(ts
->processes
);
921 LttvProcessState
*process
= ts
->running_process
[cpu
];
923 guint depth
= process
->execution_stack
->len
;
925 process
->execution_stack
=
926 g_array_set_size(process
->execution_stack
, depth
+ 1);
929 &g_array_index(process
->execution_stack
, LttvExecutionState
, depth
- 1);
931 es
= &g_array_index(process
->execution_stack
, LttvExecutionState
, depth
);
934 es
->entry
= es
->change
= tfs
->parent
.timestamp
;
935 es
->s
= process
->state
->s
;
940 static void pop_state(LttvTracefileState
*tfs
, LttvExecutionMode t
)
942 guint cpu
= ltt_tracefile_num(tfs
->parent
.tf
);
943 LttvTraceState
*ts
= (LttvTraceState
*)tfs
->parent
.t_context
;
944 LttvProcessState
*process
= ts
->running_process
[cpu
];
946 guint depth
= process
->execution_stack
->len
;
948 if(process
->state
->t
!= t
){
949 g_info("Different execution mode type (%lu.%09lu): ignore it\n",
950 tfs
->parent
.timestamp
.tv_sec
, tfs
->parent
.timestamp
.tv_nsec
);
951 g_info("process state has %s when pop_int is %s\n",
952 g_quark_to_string(process
->state
->t
),
953 g_quark_to_string(t
));
954 g_info("{ %u, %u, %s, %s }\n",
957 g_quark_to_string(process
->name
),
958 g_quark_to_string(process
->state
->s
));
963 g_info("Trying to pop last state on stack (%lu.%09lu): ignore it\n",
964 tfs
->parent
.timestamp
.tv_sec
, tfs
->parent
.timestamp
.tv_nsec
);
968 process
->execution_stack
=
969 g_array_set_size(process
->execution_stack
, depth
- 1);
970 process
->state
= &g_array_index(process
->execution_stack
, LttvExecutionState
,
972 process
->state
->change
= tfs
->parent
.timestamp
;
977 lttv_state_create_process(LttvTraceState
*tcs
, LttvProcessState
*parent
,
978 guint cpu
, guint pid
, const LttTime
*timestamp
)
980 LttvProcessState
*process
= g_new(LttvProcessState
, 1);
982 LttvExecutionState
*es
;
984 LttvTraceContext
*tc
= (LttvTraceContext
*)tcs
;
990 //process->last_cpu = tfs->cpu_name;
991 //process->last_cpu_index = ltt_tracefile_num(((LttvTracefileContext*)tfs)->tf);
992 g_info("Process %u, core %p", process
->pid
, process
);
993 g_hash_table_insert(tcs
->processes
, process
, process
);
996 process
->ppid
= parent
->pid
;
997 process
->name
= parent
->name
;
998 process
->creation_time
= *timestamp
;
1001 /* No parent. This process exists but we are missing all information about
1002 its creation. The birth time is set to zero but we remember the time of
1007 process
->name
= LTTV_STATE_UNNAMED
;
1008 process
->creation_time
= ltt_time_zero
;
1011 process
->insertion_time
= *timestamp
;
1012 sprintf(buffer
,"%d-%lu.%lu",pid
, process
->creation_time
.tv_sec
,
1013 process
->creation_time
.tv_nsec
);
1014 process
->pid_time
= g_quark_from_string(buffer
);
1016 //process->last_cpu = tfs->cpu_name;
1017 //process->last_cpu_index = ltt_tracefile_num(((LttvTracefileContext*)tfs)->tf);
1018 process
->execution_stack
= g_array_sized_new(FALSE
, FALSE
,
1019 sizeof(LttvExecutionState
), PREALLOCATED_EXECUTION_STACK
);
1020 process
->execution_stack
= g_array_set_size(process
->execution_stack
, 2);
1021 es
= process
->state
= &g_array_index(process
->execution_stack
,
1022 LttvExecutionState
, 0);
1023 es
->t
= LTTV_STATE_USER_MODE
;
1024 es
->n
= LTTV_STATE_SUBMODE_NONE
;
1025 es
->entry
= *timestamp
;
1026 //g_assert(timestamp->tv_sec != 0);
1027 es
->change
= *timestamp
;
1028 es
->s
= LTTV_STATE_RUN
;
1030 es
= process
->state
= &g_array_index(process
->execution_stack
,
1031 LttvExecutionState
, 1);
1032 es
->t
= LTTV_STATE_SYSCALL
;
1033 es
->n
= LTTV_STATE_SUBMODE_NONE
;
1034 es
->entry
= *timestamp
;
1035 //g_assert(timestamp->tv_sec != 0);
1036 es
->change
= *timestamp
;
1037 es
->s
= LTTV_STATE_WAIT_FORK
;
1042 LttvProcessState
*lttv_state_find_process(LttvTraceState
*ts
, guint cpu
,
1045 LttvProcessState key
;
1046 LttvProcessState
*process
;
1050 process
= g_hash_table_lookup(ts
->processes
, &key
);
1055 lttv_state_find_process_or_create(LttvTraceState
*ts
, guint cpu
, guint pid
,
1058 LttvProcessState
*process
= lttv_state_find_process(ts
, cpu
, pid
);
1060 /* Put ltt_time_zero creation time for unexisting processes */
1061 if(unlikely(process
== NULL
)) process
= lttv_state_create_process(ts
,
1062 NULL
, cpu
, pid
, timestamp
);
1066 /* FIXME : this function should be called when we receive an event telling that
1067 * release_task has been called in the kernel. In happens generally when
1068 * the parent waits for its child terminaison, but may also happen in special
1069 * cases in the child's exit : when the parent ignores its children SIGCCHLD or
1070 * has the flag SA_NOCLDWAIT. It can also happen when the child is part
1071 * of a killed thread ground, but isn't the leader.
1073 static void exit_process(LttvTracefileState
*tfs
, LttvProcessState
*process
)
1075 LttvTraceState
*ts
= LTTV_TRACE_STATE(tfs
->parent
.t_context
);
1076 LttvProcessState key
;
1078 key
.pid
= process
->pid
;
1079 key
.cpu
= process
->cpu
;
1080 g_hash_table_remove(ts
->processes
, &key
);
1081 g_array_free(process
->execution_stack
, TRUE
);
1086 static void free_process_state(gpointer key
, gpointer value
,gpointer user_data
)
1088 g_array_free(((LttvProcessState
*)value
)->execution_stack
, TRUE
);
1093 static void lttv_state_free_process_table(GHashTable
*processes
)
1095 g_hash_table_foreach(processes
, free_process_state
, NULL
);
1096 g_hash_table_destroy(processes
);
1100 static gboolean
syscall_entry(void *hook_data
, void *call_data
)
1102 LttvTracefileState
*s
= (LttvTracefileState
*)call_data
;
1103 LttEvent
*e
= ltt_tracefile_get_event(s
->parent
.tf
);
1104 LttvTraceHookByFacility
*thf
= (LttvTraceHookByFacility
*)hook_data
;
1105 LttField
*f
= thf
->f1
;
1107 LttvExecutionSubmode submode
;
1109 submode
= ((LttvTraceState
*)(s
->parent
.t_context
))->syscall_names
[
1110 ltt_event_get_unsigned(e
, f
)];
1111 push_state(s
, LTTV_STATE_SYSCALL
, submode
);
1116 static gboolean
syscall_exit(void *hook_data
, void *call_data
)
1118 LttvTracefileState
*s
= (LttvTracefileState
*)call_data
;
1120 pop_state(s
, LTTV_STATE_SYSCALL
);
1125 static gboolean
trap_entry(void *hook_data
, void *call_data
)
1127 LttvTracefileState
*s
= (LttvTracefileState
*)call_data
;
1128 LttEvent
*e
= ltt_tracefile_get_event(s
->parent
.tf
);
1129 LttvTraceHookByFacility
*thf
= (LttvTraceHookByFacility
*)hook_data
;
1130 LttField
*f
= thf
->f1
;
1132 LttvExecutionSubmode submode
;
1134 submode
= ((LttvTraceState
*)(s
->parent
.t_context
))->trap_names
[
1135 ltt_event_get_unsigned(e
, f
)];
1136 push_state(s
, LTTV_STATE_TRAP
, submode
);
1141 static gboolean
trap_exit(void *hook_data
, void *call_data
)
1143 LttvTracefileState
*s
= (LttvTracefileState
*)call_data
;
1145 pop_state(s
, LTTV_STATE_TRAP
);
1150 static gboolean
irq_entry(void *hook_data
, void *call_data
)
1152 LttvTracefileState
*s
= (LttvTracefileState
*)call_data
;
1153 LttEvent
*e
= ltt_tracefile_get_event(s
->parent
.tf
);
1154 guint8 fac_id
= ltt_event_facility_id(e
);
1155 guint8 ev_id
= ltt_event_eventtype_id(e
);
1156 LttvTraceHookByFacility
*thf
= (LttvTraceHookByFacility
*)hook_data
;
1157 // g_assert(lttv_trace_hook_get_first((LttvTraceHook *)hook_data)->f1 != NULL);
1158 g_assert(thf
->f1
!= NULL
);
1159 // g_assert(thf == lttv_trace_hook_get_first((LttvTraceHook *)hook_data));
1160 LttField
*f
= thf
->f1
;
1162 LttvExecutionSubmode submode
;
1164 submode
= ((LttvTraceState
*)(s
->parent
.t_context
))->irq_names
[
1165 ltt_event_get_unsigned(e
, f
)];
1167 /* Do something with the info about being in user or system mode when int? */
1168 push_state(s
, LTTV_STATE_IRQ
, submode
);
1173 static gboolean
irq_exit(void *hook_data
, void *call_data
)
1175 LttvTracefileState
*s
= (LttvTracefileState
*)call_data
;
1177 pop_state(s
, LTTV_STATE_IRQ
);
1182 static gboolean
schedchange(void *hook_data
, void *call_data
)
1184 LttvTracefileState
*s
= (LttvTracefileState
*)call_data
;
1185 guint cpu
= ltt_tracefile_num(s
->parent
.tf
);
1186 LttvTraceState
*ts
= (LttvTraceState
*)s
->parent
.t_context
;
1187 LttvProcessState
*process
= ts
->running_process
[cpu
];
1189 LttEvent
*e
= ltt_tracefile_get_event(s
->parent
.tf
);
1190 LttvTraceHookByFacility
*thf
= (LttvTraceHookByFacility
*)hook_data
;
1191 guint pid_in
, pid_out
;
1194 pid_out
= ltt_event_get_unsigned(e
, thf
->f1
);
1195 pid_in
= ltt_event_get_unsigned(e
, thf
->f2
);
1196 state_out
= ltt_event_get_int(e
, thf
->f3
);
1198 if(likely(process
!= NULL
)) {
1200 /* We could not know but it was not the idle process executing.
1201 This should only happen at the beginning, before the first schedule
1202 event, and when the initial information (current process for each CPU)
1203 is missing. It is not obvious how we could, after the fact, compensate
1204 the wrongly attributed statistics. */
1206 //This test only makes sense once the state is known and if there is no
1208 //if(unlikely(process->pid != pid_out)) {
1209 // g_assert(process->pid == 0);
1212 if(unlikely(process
->state
->s
== LTTV_STATE_EXIT
)) {
1213 process
->state
->s
= LTTV_STATE_ZOMBIE
;
1215 if(unlikely(state_out
== 0)) process
->state
->s
= LTTV_STATE_WAIT_CPU
;
1216 else process
->state
->s
= LTTV_STATE_WAIT
;
1217 } /* FIXME : we do not remove process here, because the kernel
1218 * still has them : they may be zombies. We need to know
1219 * exactly when release_task is executed on the PID to
1220 * know when the zombie is destroyed.
1223 // exit_process(s, process);
1225 process
->state
->change
= s
->parent
.timestamp
;
1227 process
= ts
->running_process
[cpu
] =
1228 lttv_state_find_process_or_create(
1229 (LttvTraceState
*)s
->parent
.t_context
,
1231 &s
->parent
.timestamp
);
1232 process
->state
->s
= LTTV_STATE_RUN
;
1234 // process->last_cpu_index = ltt_tracefile_num(((LttvTracefileContext*)s)->tf);
1235 process
->state
->change
= s
->parent
.timestamp
;
1239 static gboolean
process_fork(void *hook_data
, void *call_data
)
1241 LttvTracefileState
*s
= (LttvTracefileState
*)call_data
;
1242 LttEvent
*e
= ltt_tracefile_get_event(s
->parent
.tf
);
1243 LttvTraceHookByFacility
*thf
= (LttvTraceHookByFacility
*)hook_data
;
1247 LttvProcessState
*zombie_process
;
1248 guint cpu
= ltt_tracefile_num(s
->parent
.tf
);
1249 LttvTraceState
*ts
= (LttvTraceState
*)s
->parent
.t_context
;
1250 LttvProcessState
*process
= ts
->running_process
[cpu
];
1251 LttvProcessState
*child_process
;
1255 parent_pid
= ltt_event_get_unsigned(e
, f
);
1259 child_pid
= ltt_event_get_unsigned(e
, f
);
1261 /* Mathieu : it seems like the process might have been scheduled in before the
1262 * fork, and, in a rare case, might be the current process. This might happen
1263 * in a SMP case where we don't have enough precision on the clocks */
1265 zombie_process
= lttv_state_find_process(ts
, ANY_CPU
, child_pid
);
1267 if(unlikely(zombie_process
!= NULL
)) {
1268 /* Reutilisation of PID. Only now we are sure that the old PID
1269 * has been released. FIXME : should know when release_task happens instead.
1271 guint num_cpus
= ltt_trace_get_num_cpu(ts
->parent
.t
);
1273 for(i
=0; i
< num_cpus
; i
++) {
1274 g_assert(process
!= ts
->running_process
[i
]);
1277 exit_process(s
, zombie_process
);
1280 g_assert(process
->pid
!= child_pid
);
1281 // FIXME : Add this test in the "known state" section
1282 // g_assert(process->pid == parent_pid);
1283 child_process
= lttv_state_find_process(ts
, ANY_CPU
, child_pid
);
1284 if(child_process
== NULL
) {
1285 lttv_state_create_process(ts
, process
, cpu
,
1286 child_pid
, &s
->parent
.timestamp
);
1288 /* The process has already been created : due to time imprecision between
1289 * multiple CPUs : it has been scheduled in before creation.
1291 * Simply put a correct parent.
1293 child_process
->ppid
= process
->pid
;
1300 static gboolean
process_exit(void *hook_data
, void *call_data
)
1302 LttvTracefileState
*s
= (LttvTracefileState
*)call_data
;
1303 LttEvent
*e
= ltt_tracefile_get_event(s
->parent
.tf
);
1304 LttvTraceHookByFacility
*thf
= (LttvTraceHookByFacility
*)hook_data
;
1307 guint cpu
= ltt_tracefile_num(s
->parent
.tf
);
1308 LttvTraceState
*ts
= (LttvTraceState
*)s
->parent
.t_context
;
1309 LttvProcessState
*process
= ts
->running_process
[cpu
];
1311 pid
= ltt_event_get_unsigned(e
, thf
->f1
);
1313 // FIXME : Add this test in the "known state" section
1314 // g_assert(process->pid == pid);
1316 if(likely(process
!= NULL
)) {
1317 process
->state
->s
= LTTV_STATE_EXIT
;
1322 static gboolean
process_free(void *hook_data
, void *call_data
)
1324 LttvTracefileState
*s
= (LttvTracefileState
*)call_data
;
1325 LttvTraceState
*ts
= (LttvTraceState
*)s
->parent
.t_context
;
1326 LttEvent
*e
= ltt_tracefile_get_event(s
->parent
.tf
);
1327 LttvTraceHookByFacility
*thf
= (LttvTraceHookByFacility
*)hook_data
;
1329 LttvProcessState
*process
;
1331 /* PID of the process to release */
1332 release_pid
= ltt_event_get_unsigned(e
, thf
->f1
);
1334 g_assert(release_pid
!= 0);
1336 process
= lttv_state_find_process(ts
, ANY_CPU
, release_pid
);
1338 if(likely(process
!= NULL
)) {
1339 /* release_task is happening at kernel level : we can now safely release
1340 * the data structure of the process */
1341 guint num_cpus
= ltt_trace_get_num_cpu(ts
->parent
.t
);
1343 for(i
=0; i
< num_cpus
; i
++) {
1344 g_assert(process
!= ts
->running_process
[i
]);
1346 exit_process(s
, process
);
1353 static gboolean
process_exec(void *hook_data
, void *call_data
)
1355 LttvTracefileState
*s
= (LttvTracefileState
*)call_data
;
1356 LttvTraceState
*ts
= (LttvTraceState
*)s
->parent
.t_context
;
1357 LttEvent
*e
= ltt_tracefile_get_event(s
->parent
.tf
);
1358 LttvTraceHookByFacility
*thf
= (LttvTraceHookByFacility
*)hook_data
;
1360 guint cpu
= ltt_tracefile_num(s
->parent
.tf
);
1361 LttvProcessState
*process
= ts
->running_process
[cpu
];
1363 /* PID of the process to release */
1364 name
= ltt_event_get_string(e
, thf
->f1
);
1366 process
->name
= g_quark_from_string(name
);
1374 gint
lttv_state_hook_add_event_hooks(void *hook_data
, void *call_data
)
1376 LttvTracesetState
*tss
= (LttvTracesetState
*)(call_data
);
1378 lttv_state_add_event_hooks(tss
);
1383 void lttv_state_add_event_hooks(LttvTracesetState
*self
)
1385 LttvTraceset
*traceset
= self
->parent
.ts
;
1387 guint i
, j
, k
, l
, nb_trace
, nb_tracefile
;
1391 LttvTracefileState
*tfs
;
1395 LttvTraceHookByFacility
*thf
;
1397 LttvTraceHook
*hook
;
1399 LttvAttributeValue val
;
1403 nb_trace
= lttv_traceset_number(traceset
);
1404 for(i
= 0 ; i
< nb_trace
; i
++) {
1405 ts
= (LttvTraceState
*)self
->parent
.traces
[i
];
1407 /* Find the eventtype id for the following events and register the
1408 associated by id hooks. */
1410 hooks
= g_array_sized_new(FALSE
, FALSE
, sizeof(LttvTraceHook
), 11);
1411 hooks
= g_array_set_size(hooks
, 11);
1413 ret
= lttv_trace_find_hook(ts
->parent
.t
,
1414 LTT_FACILITY_KERNEL
, LTT_EVENT_SYSCALL_ENTRY
,
1415 LTT_FIELD_SYSCALL_ID
, 0, 0,
1416 syscall_entry
, NULL
, &g_array_index(hooks
, LttvTraceHook
, 0));
1419 ret
= lttv_trace_find_hook(ts
->parent
.t
,
1420 LTT_FACILITY_KERNEL
, LTT_EVENT_SYSCALL_EXIT
,
1422 syscall_exit
, NULL
, &g_array_index(hooks
, LttvTraceHook
, 1));
1425 ret
= lttv_trace_find_hook(ts
->parent
.t
,
1426 LTT_FACILITY_KERNEL
, LTT_EVENT_TRAP_ENTRY
,
1427 LTT_FIELD_TRAP_ID
, 0, 0,
1428 trap_entry
, NULL
, &g_array_index(hooks
, LttvTraceHook
, 2));
1431 ret
= lttv_trace_find_hook(ts
->parent
.t
,
1432 LTT_FACILITY_KERNEL
, LTT_EVENT_TRAP_EXIT
,
1434 trap_exit
, NULL
, &g_array_index(hooks
, LttvTraceHook
, 3));
1437 ret
= lttv_trace_find_hook(ts
->parent
.t
,
1438 LTT_FACILITY_KERNEL
, LTT_EVENT_IRQ_ENTRY
,
1439 LTT_FIELD_IRQ_ID
, 0, 0,
1440 irq_entry
, NULL
, &g_array_index(hooks
, LttvTraceHook
, 4));
1443 ret
= lttv_trace_find_hook(ts
->parent
.t
,
1444 LTT_FACILITY_KERNEL
, LTT_EVENT_IRQ_EXIT
,
1446 irq_exit
, NULL
, &g_array_index(hooks
, LttvTraceHook
, 5));
1449 ret
= lttv_trace_find_hook(ts
->parent
.t
,
1450 LTT_FACILITY_PROCESS
, LTT_EVENT_SCHEDCHANGE
,
1451 LTT_FIELD_OUT
, LTT_FIELD_IN
, LTT_FIELD_OUT_STATE
,
1452 schedchange
, NULL
, &g_array_index(hooks
, LttvTraceHook
, 6));
1455 ret
= lttv_trace_find_hook(ts
->parent
.t
,
1456 LTT_FACILITY_PROCESS
, LTT_EVENT_FORK
,
1457 LTT_FIELD_PARENT_PID
, LTT_FIELD_CHILD_PID
, 0,
1458 process_fork
, NULL
, &g_array_index(hooks
, LttvTraceHook
, 7));
1461 ret
= lttv_trace_find_hook(ts
->parent
.t
,
1462 LTT_FACILITY_PROCESS
, LTT_EVENT_EXIT
,
1463 LTT_FIELD_PID
, 0, 0,
1464 process_exit
, NULL
, &g_array_index(hooks
, LttvTraceHook
, 8));
1467 ret
= lttv_trace_find_hook(ts
->parent
.t
,
1468 LTT_FACILITY_PROCESS
, LTT_EVENT_FREE
,
1469 LTT_FIELD_PID
, 0, 0,
1470 process_free
, NULL
, &g_array_index(hooks
, LttvTraceHook
, 9));
1473 ret
= lttv_trace_find_hook(ts
->parent
.t
,
1474 LTT_FACILITY_FS
, LTT_EVENT_EXEC
,
1475 LTT_FIELD_FILENAME
, 0, 0,
1476 process_exec
, NULL
, &g_array_index(hooks
, LttvTraceHook
, 10));
1481 /* Add these hooks to each event_by_id hooks list */
1483 nb_tracefile
= ts
->parent
.tracefiles
->len
;
1485 for(j
= 0 ; j
< nb_tracefile
; j
++) {
1487 LTTV_TRACEFILE_STATE(g_array_index(ts
->parent
.tracefiles
,
1488 LttvTracefileContext
*, j
));
1490 for(k
= 0 ; k
< hooks
->len
; k
++) {
1491 hook
= &g_array_index(hooks
, LttvTraceHook
, k
);
1492 for(l
=0;l
<hook
->fac_list
->len
;l
++) {
1493 thf
= g_array_index(hook
->fac_list
, LttvTraceHookByFacility
*, l
);
1495 lttv_hooks_by_id_find(tfs
->parent
.event_by_id
, thf
->id
),
1502 lttv_attribute_find(self
->parent
.a
, LTTV_STATE_HOOKS
, LTTV_POINTER
, &val
);
1503 *(val
.v_pointer
) = hooks
;
1507 gint
lttv_state_hook_remove_event_hooks(void *hook_data
, void *call_data
)
1509 LttvTracesetState
*tss
= (LttvTracesetState
*)(call_data
);
1511 lttv_state_remove_event_hooks(tss
);
1516 void lttv_state_remove_event_hooks(LttvTracesetState
*self
)
1518 LttvTraceset
*traceset
= self
->parent
.ts
;
1520 guint i
, j
, k
, l
, nb_trace
, nb_tracefile
;
1524 LttvTracefileState
*tfs
;
1528 LttvTraceHook
*hook
;
1530 LttvTraceHookByFacility
*thf
;
1532 LttvAttributeValue val
;
1534 nb_trace
= lttv_traceset_number(traceset
);
1535 for(i
= 0 ; i
< nb_trace
; i
++) {
1536 ts
= LTTV_TRACE_STATE(self
->parent
.traces
[i
]);
1537 lttv_attribute_find(self
->parent
.a
, LTTV_STATE_HOOKS
, LTTV_POINTER
, &val
);
1538 hooks
= *(val
.v_pointer
);
1540 /* Remove these hooks from each event_by_id hooks list */
1542 nb_tracefile
= ts
->parent
.tracefiles
->len
;
1544 for(j
= 0 ; j
< nb_tracefile
; j
++) {
1546 LTTV_TRACEFILE_STATE(g_array_index(ts
->parent
.tracefiles
,
1547 LttvTracefileContext
*, j
));
1549 for(k
= 0 ; k
< hooks
->len
; k
++) {
1550 hook
= &g_array_index(hooks
, LttvTraceHook
, k
);
1551 for(l
=0;l
<hook
->fac_list
->len
;l
++) {
1552 thf
= g_array_index(hook
->fac_list
, LttvTraceHookByFacility
*, l
);
1554 lttv_hooks_remove_data(
1555 lttv_hooks_by_id_find(tfs
->parent
.event_by_id
, thf
->id
),
1561 for(k
= 0 ; k
< hooks
->len
; k
++)
1562 lttv_trace_hook_destroy(&g_array_index(hooks
, LttvTraceHook
, k
));
1563 g_array_free(hooks
, TRUE
);
1567 static gboolean
state_save_event_hook(void *hook_data
, void *call_data
)
1569 guint
*event_count
= (guint
*)hook_data
;
1571 /* Only save at LTTV_STATE_SAVE_INTERVAL */
1572 if(likely((*event_count
)++ < LTTV_STATE_SAVE_INTERVAL
))
1577 LttvTracefileState
*self
= (LttvTracefileState
*)call_data
;
1579 LttvTracefileState
*tfcs
;
1581 LttvTraceState
*tcs
= (LttvTraceState
*)(self
->parent
.t_context
);
1583 LttEventPosition
*ep
;
1589 LttvAttribute
*saved_states_tree
, *saved_state_tree
;
1591 LttvAttributeValue value
;
1593 saved_states_tree
= lttv_attribute_find_subdir(tcs
->parent
.t_a
,
1594 LTTV_STATE_SAVED_STATES
);
1595 saved_state_tree
= g_object_new(LTTV_ATTRIBUTE_TYPE
, NULL
);
1596 value
= lttv_attribute_add(saved_states_tree
,
1597 lttv_attribute_get_number(saved_states_tree
), LTTV_GOBJECT
);
1598 *(value
.v_gobject
) = (GObject
*)saved_state_tree
;
1599 value
= lttv_attribute_add(saved_state_tree
, LTTV_STATE_TIME
, LTTV_TIME
);
1600 *(value
.v_time
) = self
->parent
.timestamp
;
1601 lttv_state_save(tcs
, saved_state_tree
);
1602 g_debug("Saving state at time %lu.%lu", self
->parent
.timestamp
.tv_sec
,
1603 self
->parent
.timestamp
.tv_nsec
);
1605 *(tcs
->max_time_state_recomputed_in_seek
) = self
->parent
.timestamp
;
1610 static gboolean
state_save_after_trace_hook(void *hook_data
, void *call_data
)
1612 LttvTraceState
*tcs
= (LttvTraceState
*)(call_data
);
1614 *(tcs
->max_time_state_recomputed_in_seek
) = tcs
->parent
.time_span
.end_time
;
1620 static gboolean
block_start(void *hook_data
, void *call_data
)
1622 LttvTracefileState
*self
= (LttvTracefileState
*)call_data
;
1624 LttvTracefileState
*tfcs
;
1626 LttvTraceState
*tcs
= (LttvTraceState
*)(self
->parent
.t_context
);
1628 LttEventPosition
*ep
;
1630 guint i
, nb_block
, nb_event
, nb_tracefile
;
1634 LttvAttribute
*saved_states_tree
, *saved_state_tree
;
1636 LttvAttributeValue value
;
1638 ep
= ltt_event_position_new();
1640 nb_tracefile
= tcs
->parent
.tracefiles
->len
;
1642 /* Count the number of events added since the last block end in any
1645 for(i
= 0 ; i
< nb_tracefile
; i
++) {
1647 LTTV_TRACEFILE_STATE(&g_array_index(tcs
->parent
.tracefiles
,
1648 LttvTracefileContext
, i
));
1649 ltt_event_position(tfcs
->parent
.e
, ep
);
1650 ltt_event_position_get(ep
, &nb_block
, &nb_event
, &tf
);
1651 tcs
->nb_event
+= nb_event
- tfcs
->saved_position
;
1652 tfcs
->saved_position
= nb_event
;
1656 if(tcs
->nb_event
>= tcs
->save_interval
) {
1657 saved_states_tree
= lttv_attribute_find_subdir(tcs
->parent
.t_a
,
1658 LTTV_STATE_SAVED_STATES
);
1659 saved_state_tree
= g_object_new(LTTV_ATTRIBUTE_TYPE
, NULL
);
1660 value
= lttv_attribute_add(saved_states_tree
,
1661 lttv_attribute_get_number(saved_states_tree
), LTTV_GOBJECT
);
1662 *(value
.v_gobject
) = (GObject
*)saved_state_tree
;
1663 value
= lttv_attribute_add(saved_state_tree
, LTTV_STATE_TIME
, LTTV_TIME
);
1664 *(value
.v_time
) = self
->parent
.timestamp
;
1665 lttv_state_save(tcs
, saved_state_tree
);
1667 g_debug("Saving state at time %lu.%lu", self
->parent
.timestamp
.tv_sec
,
1668 self
->parent
.timestamp
.tv_nsec
);
1670 *(tcs
->max_time_state_recomputed_in_seek
) = self
->parent
.timestamp
;
1676 static gboolean
block_end(void *hook_data
, void *call_data
)
1678 LttvTracefileState
*self
= (LttvTracefileState
*)call_data
;
1680 LttvTraceState
*tcs
= (LttvTraceState
*)(self
->parent
.t_context
);
1684 LttEventPosition
*ep
;
1686 guint nb_block
, nb_event
;
1688 ep
= ltt_event_position_new();
1689 ltt_event_position(self
->parent
.e
, ep
);
1690 ltt_event_position_get(ep
, &nb_block
, &nb_event
, &tf
);
1691 tcs
->nb_event
+= nb_event
- self
->saved_position
+ 1;
1692 self
->saved_position
= 0;
1693 *(tcs
->max_time_state_recomputed_in_seek
) = self
->parent
.timestamp
;
1700 void lttv_state_save_add_event_hooks(LttvTracesetState
*self
)
1702 LttvTraceset
*traceset
= self
->parent
.ts
;
1704 guint i
, j
, nb_trace
, nb_tracefile
;
1708 LttvTracefileState
*tfs
;
1710 LttvTraceHook hook_start
, hook_end
;
1712 nb_trace
= lttv_traceset_number(traceset
);
1713 for(i
= 0 ; i
< nb_trace
; i
++) {
1714 ts
= (LttvTraceState
*)self
->parent
.traces
[i
];
1716 lttv_trace_find_hook(ts
->parent
.t
, "core","block_start",NULL
,
1717 NULL
, NULL
, block_start
, &hook_start
);
1718 lttv_trace_find_hook(ts
->parent
.t
, "core","block_end",NULL
,
1719 NULL
, NULL
, block_end
, &hook_end
);
1721 nb_tracefile
= ts
->parent
.tracefiles
->len
;
1723 for(j
= 0 ; j
< nb_tracefile
; j
++) {
1725 LTTV_TRACEFILE_STATE(&g_array_index(ts
->parent
.tracefiles
,
1726 LttvTracefileContext
, j
));
1727 lttv_hooks_add(lttv_hooks_by_id_find(tfs
->parent
.event_by_id
,
1728 hook_start
.id
), hook_start
.h
, NULL
, LTTV_PRIO_STATE
);
1729 lttv_hooks_add(lttv_hooks_by_id_find(tfs
->parent
.event_by_id
,
1730 hook_end
.id
), hook_end
.h
, NULL
, LTTV_PRIO_STATE
);
1736 void lttv_state_save_add_event_hooks(LttvTracesetState
*self
)
1738 LttvTraceset
*traceset
= self
->parent
.ts
;
1740 guint i
, j
, nb_trace
, nb_tracefile
;
1744 LttvTracefileState
*tfs
;
1747 nb_trace
= lttv_traceset_number(traceset
);
1748 for(i
= 0 ; i
< nb_trace
; i
++) {
1750 ts
= (LttvTraceState
*)self
->parent
.traces
[i
];
1751 nb_tracefile
= ts
->parent
.tracefiles
->len
;
1753 guint
*event_count
= g_new(guint
, 1);
1756 for(j
= 0 ; j
< nb_tracefile
; j
++) {
1758 LTTV_TRACEFILE_STATE(g_array_index(ts
->parent
.tracefiles
,
1759 LttvTracefileContext
*, j
));
1760 lttv_hooks_add(tfs
->parent
.event
,
1761 state_save_event_hook
,
1768 lttv_process_traceset_begin(&self
->parent
,
1769 NULL
, NULL
, NULL
, NULL
, NULL
);
1773 gint
lttv_state_save_hook_add_event_hooks(void *hook_data
, void *call_data
)
1775 LttvTracesetState
*tss
= (LttvTracesetState
*)(call_data
);
1777 lttv_state_save_add_event_hooks(tss
);
1784 void lttv_state_save_remove_event_hooks(LttvTracesetState
*self
)
1786 LttvTraceset
*traceset
= self
->parent
.ts
;
1788 guint i
, j
, nb_trace
, nb_tracefile
;
1792 LttvTracefileState
*tfs
;
1794 LttvTraceHook hook_start
, hook_end
;
1796 nb_trace
= lttv_traceset_number(traceset
);
1797 for(i
= 0 ; i
< nb_trace
; i
++) {
1798 ts
= LTTV_TRACE_STATE(self
->parent
.traces
[i
]);
1800 lttv_trace_find_hook(ts
->parent
.t
, "core","block_start",NULL
,
1801 NULL
, NULL
, block_start
, &hook_start
);
1803 lttv_trace_find_hook(ts
->parent
.t
, "core","block_end",NULL
,
1804 NULL
, NULL
, block_end
, &hook_end
);
1806 nb_tracefile
= ts
->parent
.tracefiles
->len
;
1808 for(j
= 0 ; j
< nb_tracefile
; j
++) {
1810 LTTV_TRACEFILE_STATE(&g_array_index(ts
->parent
.tracefiles
,
1811 LttvTracefileContext
, j
));
1812 lttv_hooks_remove_data(lttv_hooks_by_id_find(
1813 tfs
->parent
.event_by_id
, hook_start
.id
), hook_start
.h
, NULL
);
1814 lttv_hooks_remove_data(lttv_hooks_by_id_find(
1815 tfs
->parent
.event_by_id
, hook_end
.id
), hook_end
.h
, NULL
);
1821 void lttv_state_save_remove_event_hooks(LttvTracesetState
*self
)
1823 LttvTraceset
*traceset
= self
->parent
.ts
;
1825 guint i
, j
, nb_trace
, nb_tracefile
;
1829 LttvTracefileState
*tfs
;
1831 LttvHooks
*after_trace
= lttv_hooks_new();
1833 lttv_hooks_add(after_trace
,
1834 state_save_after_trace_hook
,
1839 lttv_process_traceset_end(&self
->parent
,
1840 NULL
, after_trace
, NULL
, NULL
, NULL
);
1842 lttv_hooks_destroy(after_trace
);
1844 nb_trace
= lttv_traceset_number(traceset
);
1845 for(i
= 0 ; i
< nb_trace
; i
++) {
1847 ts
= (LttvTraceState
*)self
->parent
.traces
[i
];
1848 nb_tracefile
= ts
->parent
.tracefiles
->len
;
1852 for(j
= 0 ; j
< nb_tracefile
; j
++) {
1854 LTTV_TRACEFILE_STATE(g_array_index(ts
->parent
.tracefiles
,
1855 LttvTracefileContext
*, j
));
1856 event_count
= lttv_hooks_remove(tfs
->parent
.event
,
1857 state_save_event_hook
);
1859 g_free(event_count
);
1863 gint
lttv_state_save_hook_remove_event_hooks(void *hook_data
, void *call_data
)
1865 LttvTracesetState
*tss
= (LttvTracesetState
*)(call_data
);
1867 lttv_state_save_remove_event_hooks(tss
);
1872 void lttv_state_traceset_seek_time_closest(LttvTracesetState
*self
, LttTime t
)
1874 LttvTraceset
*traceset
= self
->parent
.ts
;
1878 int min_pos
, mid_pos
, max_pos
;
1880 guint call_rest
= 0;
1882 LttvTraceState
*tcs
;
1884 LttvAttributeValue value
;
1886 LttvAttributeType type
;
1888 LttvAttributeName name
;
1890 LttvAttribute
*saved_states_tree
, *saved_state_tree
, *closest_tree
;
1892 //g_tree_destroy(self->parent.pqueue);
1893 //self->parent.pqueue = g_tree_new(compare_tracefile);
1895 g_info("Entering seek_time_closest for time %lu.%lu", t
.tv_sec
, t
.tv_nsec
);
1897 nb_trace
= lttv_traceset_number(traceset
);
1898 for(i
= 0 ; i
< nb_trace
; i
++) {
1899 tcs
= (LttvTraceState
*)self
->parent
.traces
[i
];
1901 if(ltt_time_compare(t
, *(tcs
->max_time_state_recomputed_in_seek
)) < 0) {
1902 saved_states_tree
= lttv_attribute_find_subdir(tcs
->parent
.t_a
,
1903 LTTV_STATE_SAVED_STATES
);
1906 if(saved_states_tree
) {
1907 max_pos
= lttv_attribute_get_number(saved_states_tree
) - 1;
1908 mid_pos
= max_pos
/ 2;
1909 while(min_pos
< max_pos
) {
1910 type
= lttv_attribute_get(saved_states_tree
, mid_pos
, &name
, &value
);
1911 g_assert(type
== LTTV_GOBJECT
);
1912 saved_state_tree
= *((LttvAttribute
**)(value
.v_gobject
));
1913 type
= lttv_attribute_get_by_name(saved_state_tree
, LTTV_STATE_TIME
,
1915 g_assert(type
== LTTV_TIME
);
1916 if(ltt_time_compare(*(value
.v_time
), t
) < 0) {
1918 closest_tree
= saved_state_tree
;
1920 else max_pos
= mid_pos
- 1;
1922 mid_pos
= (min_pos
+ max_pos
+ 1) / 2;
1926 /* restore the closest earlier saved state */
1928 lttv_state_restore(tcs
, closest_tree
);
1932 /* There is no saved state, yet we want to have it. Restart at T0 */
1934 restore_init_state(tcs
);
1935 lttv_process_trace_seek_time(&(tcs
->parent
), ltt_time_zero
);
1938 /* We want to seek quickly without restoring/updating the state */
1940 restore_init_state(tcs
);
1941 lttv_process_trace_seek_time(&(tcs
->parent
), t
);
1944 if(!call_rest
) g_info("NOT Calling restore");
1949 traceset_state_instance_init (GTypeInstance
*instance
, gpointer g_class
)
1955 traceset_state_finalize (LttvTracesetState
*self
)
1957 G_OBJECT_CLASS(g_type_class_peek(LTTV_TRACESET_CONTEXT_TYPE
))->
1958 finalize(G_OBJECT(self
));
1963 traceset_state_class_init (LttvTracesetContextClass
*klass
)
1965 GObjectClass
*gobject_class
= G_OBJECT_CLASS(klass
);
1967 gobject_class
->finalize
= (void (*)(GObject
*self
)) traceset_state_finalize
;
1968 klass
->init
= (void (*)(LttvTracesetContext
*self
, LttvTraceset
*ts
))init
;
1969 klass
->fini
= (void (*)(LttvTracesetContext
*self
))fini
;
1970 klass
->new_traceset_context
= new_traceset_context
;
1971 klass
->new_trace_context
= new_trace_context
;
1972 klass
->new_tracefile_context
= new_tracefile_context
;
1977 lttv_traceset_state_get_type(void)
1979 static GType type
= 0;
1981 static const GTypeInfo info
= {
1982 sizeof (LttvTracesetStateClass
),
1983 NULL
, /* base_init */
1984 NULL
, /* base_finalize */
1985 (GClassInitFunc
) traceset_state_class_init
, /* class_init */
1986 NULL
, /* class_finalize */
1987 NULL
, /* class_data */
1988 sizeof (LttvTracesetState
),
1989 0, /* n_preallocs */
1990 (GInstanceInitFunc
) traceset_state_instance_init
, /* instance_init */
1991 NULL
/* value handling */
1994 type
= g_type_register_static (LTTV_TRACESET_CONTEXT_TYPE
, "LttvTracesetStateType",
2002 trace_state_instance_init (GTypeInstance
*instance
, gpointer g_class
)
2008 trace_state_finalize (LttvTraceState
*self
)
2010 G_OBJECT_CLASS(g_type_class_peek(LTTV_TRACE_CONTEXT_TYPE
))->
2011 finalize(G_OBJECT(self
));
2016 trace_state_class_init (LttvTraceStateClass
*klass
)
2018 GObjectClass
*gobject_class
= G_OBJECT_CLASS(klass
);
2020 gobject_class
->finalize
= (void (*)(GObject
*self
)) trace_state_finalize
;
2021 klass
->state_save
= state_save
;
2022 klass
->state_restore
= state_restore
;
2023 klass
->state_saved_free
= state_saved_free
;
2028 lttv_trace_state_get_type(void)
2030 static GType type
= 0;
2032 static const GTypeInfo info
= {
2033 sizeof (LttvTraceStateClass
),
2034 NULL
, /* base_init */
2035 NULL
, /* base_finalize */
2036 (GClassInitFunc
) trace_state_class_init
, /* class_init */
2037 NULL
, /* class_finalize */
2038 NULL
, /* class_data */
2039 sizeof (LttvTraceState
),
2040 0, /* n_preallocs */
2041 (GInstanceInitFunc
) trace_state_instance_init
, /* instance_init */
2042 NULL
/* value handling */
2045 type
= g_type_register_static (LTTV_TRACE_CONTEXT_TYPE
,
2046 "LttvTraceStateType", &info
, 0);
2053 tracefile_state_instance_init (GTypeInstance
*instance
, gpointer g_class
)
2059 tracefile_state_finalize (LttvTracefileState
*self
)
2061 G_OBJECT_CLASS(g_type_class_peek(LTTV_TRACEFILE_CONTEXT_TYPE
))->
2062 finalize(G_OBJECT(self
));
2067 tracefile_state_class_init (LttvTracefileStateClass
*klass
)
2069 GObjectClass
*gobject_class
= G_OBJECT_CLASS(klass
);
2071 gobject_class
->finalize
= (void (*)(GObject
*self
)) tracefile_state_finalize
;
2076 lttv_tracefile_state_get_type(void)
2078 static GType type
= 0;
2080 static const GTypeInfo info
= {
2081 sizeof (LttvTracefileStateClass
),
2082 NULL
, /* base_init */
2083 NULL
, /* base_finalize */
2084 (GClassInitFunc
) tracefile_state_class_init
, /* class_init */
2085 NULL
, /* class_finalize */
2086 NULL
, /* class_data */
2087 sizeof (LttvTracefileState
),
2088 0, /* n_preallocs */
2089 (GInstanceInitFunc
) tracefile_state_instance_init
, /* instance_init */
2090 NULL
/* value handling */
2093 type
= g_type_register_static (LTTV_TRACEFILE_CONTEXT_TYPE
,
2094 "LttvTracefileStateType", &info
, 0);
2100 static void module_init()
2102 LTTV_STATE_UNNAMED
= g_quark_from_string("unnamed");
2103 LTTV_STATE_MODE_UNKNOWN
= g_quark_from_string("unknown execution mode");
2104 LTTV_STATE_USER_MODE
= g_quark_from_string("user mode");
2105 LTTV_STATE_WAIT_FORK
= g_quark_from_string("wait fork");
2106 LTTV_STATE_SYSCALL
= g_quark_from_string("system call");
2107 LTTV_STATE_TRAP
= g_quark_from_string("trap");
2108 LTTV_STATE_IRQ
= g_quark_from_string("irq");
2109 LTTV_STATE_SUBMODE_UNKNOWN
= g_quark_from_string("unknown submode");
2110 LTTV_STATE_SUBMODE_NONE
= g_quark_from_string("(no submode)");
2111 LTTV_STATE_WAIT_CPU
= g_quark_from_string("wait for cpu");
2112 LTTV_STATE_EXIT
= g_quark_from_string("exiting");
2113 LTTV_STATE_ZOMBIE
= g_quark_from_string("zombie");
2114 LTTV_STATE_WAIT
= g_quark_from_string("wait for I/O");
2115 LTTV_STATE_RUN
= g_quark_from_string("running");
2116 LTTV_STATE_TRACEFILES
= g_quark_from_string("tracefiles");
2117 LTTV_STATE_PROCESSES
= g_quark_from_string("processes");
2118 LTTV_STATE_PROCESS
= g_quark_from_string("process");
2119 LTTV_STATE_RUNNING_PROCESS
= g_quark_from_string("running_process");
2120 LTTV_STATE_EVENT
= g_quark_from_string("event");
2121 LTTV_STATE_SAVED_STATES
= g_quark_from_string("saved states");
2122 LTTV_STATE_SAVED_STATES_TIME
= g_quark_from_string("saved states time");
2123 LTTV_STATE_TIME
= g_quark_from_string("time");
2124 LTTV_STATE_HOOKS
= g_quark_from_string("saved state hooks");
2125 LTTV_STATE_NAME_TABLES
= g_quark_from_string("name tables");
2126 LTTV_STATE_TRACE_STATE_USE_COUNT
=
2127 g_quark_from_string("trace_state_use_count");
2130 LTT_FACILITY_KERNEL
= g_quark_from_string("kernel");
2131 LTT_FACILITY_PROCESS
= g_quark_from_string("process");
2132 LTT_FACILITY_FS
= g_quark_from_string("fs");
2135 LTT_EVENT_SYSCALL_ENTRY
= g_quark_from_string("syscall_entry");
2136 LTT_EVENT_SYSCALL_EXIT
= g_quark_from_string("syscall_exit");
2137 LTT_EVENT_TRAP_ENTRY
= g_quark_from_string("trap_entry");
2138 LTT_EVENT_TRAP_EXIT
= g_quark_from_string("trap_exit");
2139 LTT_EVENT_IRQ_ENTRY
= g_quark_from_string("irq_entry");
2140 LTT_EVENT_IRQ_EXIT
= g_quark_from_string("irq_exit");
2141 LTT_EVENT_SCHEDCHANGE
= g_quark_from_string("schedchange");
2142 LTT_EVENT_FORK
= g_quark_from_string("fork");
2143 LTT_EVENT_EXIT
= g_quark_from_string("exit");
2144 LTT_EVENT_FREE
= g_quark_from_string("free");
2145 LTT_EVENT_EXEC
= g_quark_from_string("exec");
2148 LTT_FIELD_SYSCALL_ID
= g_quark_from_string("syscall_id");
2149 LTT_FIELD_TRAP_ID
= g_quark_from_string("trap_id");
2150 LTT_FIELD_IRQ_ID
= g_quark_from_string("irq_id");
2151 LTT_FIELD_OUT
= g_quark_from_string("out");
2152 LTT_FIELD_IN
= g_quark_from_string("in");
2153 LTT_FIELD_OUT_STATE
= g_quark_from_string("out_state");
2154 LTT_FIELD_PARENT_PID
= g_quark_from_string("parent_pid");
2155 LTT_FIELD_CHILD_PID
= g_quark_from_string("child_pid");
2156 LTT_FIELD_PID
= g_quark_from_string("pid");
2157 LTT_FIELD_FILENAME
= g_quark_from_string("filename");
2161 static void module_destroy()
2166 LTTV_MODULE("state", "State computation", \
2167 "Update the system state, possibly saving it at intervals", \
2168 module_init
, module_destroy
)