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 * Test reenabled after precision fixes on time. (Mathieu) */
1267 zombie_process
= lttv_state_find_process(ts
, ANY_CPU
, child_pid
);
1269 if(unlikely(zombie_process
!= NULL
)) {
1270 /* Reutilisation of PID. Only now we are sure that the old PID
1271 * has been released. FIXME : should know when release_task happens instead.
1273 guint num_cpus
= ltt_trace_get_num_cpu(ts
->parent
.t
);
1275 for(i
=0; i
< num_cpus
; i
++) {
1276 g_assert(zombie_process
!= ts
->running_process
[i
]);
1279 exit_process(s
, zombie_process
);
1282 g_assert(process
->pid
!= child_pid
);
1283 // FIXME : Add this test in the "known state" section
1284 // g_assert(process->pid == parent_pid);
1285 child_process
= lttv_state_find_process(ts
, ANY_CPU
, child_pid
);
1286 if(child_process
== NULL
) {
1287 lttv_state_create_process(ts
, process
, cpu
,
1288 child_pid
, &s
->parent
.timestamp
);
1290 /* The process has already been created : due to time imprecision between
1291 * multiple CPUs : it has been scheduled in before creation.
1293 * Simply put a correct parent.
1295 child_process
->ppid
= process
->pid
;
1302 static gboolean
process_exit(void *hook_data
, void *call_data
)
1304 LttvTracefileState
*s
= (LttvTracefileState
*)call_data
;
1305 LttEvent
*e
= ltt_tracefile_get_event(s
->parent
.tf
);
1306 LttvTraceHookByFacility
*thf
= (LttvTraceHookByFacility
*)hook_data
;
1309 guint cpu
= ltt_tracefile_num(s
->parent
.tf
);
1310 LttvTraceState
*ts
= (LttvTraceState
*)s
->parent
.t_context
;
1311 LttvProcessState
*process
= ts
->running_process
[cpu
];
1313 pid
= ltt_event_get_unsigned(e
, thf
->f1
);
1315 // FIXME : Add this test in the "known state" section
1316 // g_assert(process->pid == pid);
1318 if(likely(process
!= NULL
)) {
1319 process
->state
->s
= LTTV_STATE_EXIT
;
1324 static gboolean
process_free(void *hook_data
, void *call_data
)
1326 LttvTracefileState
*s
= (LttvTracefileState
*)call_data
;
1327 LttvTraceState
*ts
= (LttvTraceState
*)s
->parent
.t_context
;
1328 LttEvent
*e
= ltt_tracefile_get_event(s
->parent
.tf
);
1329 LttvTraceHookByFacility
*thf
= (LttvTraceHookByFacility
*)hook_data
;
1331 LttvProcessState
*process
;
1333 /* PID of the process to release */
1334 release_pid
= ltt_event_get_unsigned(e
, thf
->f1
);
1336 g_assert(release_pid
!= 0);
1338 process
= lttv_state_find_process(ts
, ANY_CPU
, release_pid
);
1340 if(likely(process
!= NULL
)) {
1341 /* release_task is happening at kernel level : we can now safely release
1342 * the data structure of the process */
1343 //This test is fun, though, as it may happen that
1344 //at time t : CPU 0 : process_free
1345 //at time t+150ns : CPU 1 : schedule out
1346 //Clearly due to time imprecision, we disable it. (Mathieu)
1347 //If this weird case happen, we have no choice but to put the
1348 //Currently running process on the cpu to 0.
1349 guint num_cpus
= ltt_trace_get_num_cpu(ts
->parent
.t
);
1351 for(i
=0; i
< num_cpus
; i
++) {
1352 //g_assert(process != ts->running_process[i]);
1353 if(process
== ts
->running_process
[i
]) {
1354 ts
->running_process
[i
] = lttv_state_find_process(ts
, i
, 0);
1357 exit_process(s
, process
);
1364 static gboolean
process_exec(void *hook_data
, void *call_data
)
1366 LttvTracefileState
*s
= (LttvTracefileState
*)call_data
;
1367 LttvTraceState
*ts
= (LttvTraceState
*)s
->parent
.t_context
;
1368 LttEvent
*e
= ltt_tracefile_get_event(s
->parent
.tf
);
1369 LttvTraceHookByFacility
*thf
= (LttvTraceHookByFacility
*)hook_data
;
1371 guint cpu
= ltt_tracefile_num(s
->parent
.tf
);
1372 LttvProcessState
*process
= ts
->running_process
[cpu
];
1374 /* PID of the process to release */
1375 name
= ltt_event_get_string(e
, thf
->f1
);
1377 process
->name
= g_quark_from_string(name
);
1385 gint
lttv_state_hook_add_event_hooks(void *hook_data
, void *call_data
)
1387 LttvTracesetState
*tss
= (LttvTracesetState
*)(call_data
);
1389 lttv_state_add_event_hooks(tss
);
1394 void lttv_state_add_event_hooks(LttvTracesetState
*self
)
1396 LttvTraceset
*traceset
= self
->parent
.ts
;
1398 guint i
, j
, k
, l
, nb_trace
, nb_tracefile
;
1402 LttvTracefileState
*tfs
;
1406 LttvTraceHookByFacility
*thf
;
1408 LttvTraceHook
*hook
;
1410 LttvAttributeValue val
;
1414 nb_trace
= lttv_traceset_number(traceset
);
1415 for(i
= 0 ; i
< nb_trace
; i
++) {
1416 ts
= (LttvTraceState
*)self
->parent
.traces
[i
];
1418 /* Find the eventtype id for the following events and register the
1419 associated by id hooks. */
1421 hooks
= g_array_sized_new(FALSE
, FALSE
, sizeof(LttvTraceHook
), 11);
1422 hooks
= g_array_set_size(hooks
, 11);
1424 ret
= lttv_trace_find_hook(ts
->parent
.t
,
1425 LTT_FACILITY_KERNEL
, LTT_EVENT_SYSCALL_ENTRY
,
1426 LTT_FIELD_SYSCALL_ID
, 0, 0,
1427 syscall_entry
, NULL
, &g_array_index(hooks
, LttvTraceHook
, 0));
1430 ret
= lttv_trace_find_hook(ts
->parent
.t
,
1431 LTT_FACILITY_KERNEL
, LTT_EVENT_SYSCALL_EXIT
,
1433 syscall_exit
, NULL
, &g_array_index(hooks
, LttvTraceHook
, 1));
1436 ret
= lttv_trace_find_hook(ts
->parent
.t
,
1437 LTT_FACILITY_KERNEL
, LTT_EVENT_TRAP_ENTRY
,
1438 LTT_FIELD_TRAP_ID
, 0, 0,
1439 trap_entry
, NULL
, &g_array_index(hooks
, LttvTraceHook
, 2));
1442 ret
= lttv_trace_find_hook(ts
->parent
.t
,
1443 LTT_FACILITY_KERNEL
, LTT_EVENT_TRAP_EXIT
,
1445 trap_exit
, NULL
, &g_array_index(hooks
, LttvTraceHook
, 3));
1448 ret
= lttv_trace_find_hook(ts
->parent
.t
,
1449 LTT_FACILITY_KERNEL
, LTT_EVENT_IRQ_ENTRY
,
1450 LTT_FIELD_IRQ_ID
, 0, 0,
1451 irq_entry
, NULL
, &g_array_index(hooks
, LttvTraceHook
, 4));
1454 ret
= lttv_trace_find_hook(ts
->parent
.t
,
1455 LTT_FACILITY_KERNEL
, LTT_EVENT_IRQ_EXIT
,
1457 irq_exit
, NULL
, &g_array_index(hooks
, LttvTraceHook
, 5));
1460 ret
= lttv_trace_find_hook(ts
->parent
.t
,
1461 LTT_FACILITY_PROCESS
, LTT_EVENT_SCHEDCHANGE
,
1462 LTT_FIELD_OUT
, LTT_FIELD_IN
, LTT_FIELD_OUT_STATE
,
1463 schedchange
, NULL
, &g_array_index(hooks
, LttvTraceHook
, 6));
1466 ret
= lttv_trace_find_hook(ts
->parent
.t
,
1467 LTT_FACILITY_PROCESS
, LTT_EVENT_FORK
,
1468 LTT_FIELD_PARENT_PID
, LTT_FIELD_CHILD_PID
, 0,
1469 process_fork
, NULL
, &g_array_index(hooks
, LttvTraceHook
, 7));
1472 ret
= lttv_trace_find_hook(ts
->parent
.t
,
1473 LTT_FACILITY_PROCESS
, LTT_EVENT_EXIT
,
1474 LTT_FIELD_PID
, 0, 0,
1475 process_exit
, NULL
, &g_array_index(hooks
, LttvTraceHook
, 8));
1478 ret
= lttv_trace_find_hook(ts
->parent
.t
,
1479 LTT_FACILITY_PROCESS
, LTT_EVENT_FREE
,
1480 LTT_FIELD_PID
, 0, 0,
1481 process_free
, NULL
, &g_array_index(hooks
, LttvTraceHook
, 9));
1484 ret
= lttv_trace_find_hook(ts
->parent
.t
,
1485 LTT_FACILITY_FS
, LTT_EVENT_EXEC
,
1486 LTT_FIELD_FILENAME
, 0, 0,
1487 process_exec
, NULL
, &g_array_index(hooks
, LttvTraceHook
, 10));
1492 /* Add these hooks to each event_by_id hooks list */
1494 nb_tracefile
= ts
->parent
.tracefiles
->len
;
1496 for(j
= 0 ; j
< nb_tracefile
; j
++) {
1498 LTTV_TRACEFILE_STATE(g_array_index(ts
->parent
.tracefiles
,
1499 LttvTracefileContext
*, j
));
1501 for(k
= 0 ; k
< hooks
->len
; k
++) {
1502 hook
= &g_array_index(hooks
, LttvTraceHook
, k
);
1503 for(l
=0;l
<hook
->fac_list
->len
;l
++) {
1504 thf
= g_array_index(hook
->fac_list
, LttvTraceHookByFacility
*, l
);
1506 lttv_hooks_by_id_find(tfs
->parent
.event_by_id
, thf
->id
),
1513 lttv_attribute_find(self
->parent
.a
, LTTV_STATE_HOOKS
, LTTV_POINTER
, &val
);
1514 *(val
.v_pointer
) = hooks
;
1518 gint
lttv_state_hook_remove_event_hooks(void *hook_data
, void *call_data
)
1520 LttvTracesetState
*tss
= (LttvTracesetState
*)(call_data
);
1522 lttv_state_remove_event_hooks(tss
);
1527 void lttv_state_remove_event_hooks(LttvTracesetState
*self
)
1529 LttvTraceset
*traceset
= self
->parent
.ts
;
1531 guint i
, j
, k
, l
, nb_trace
, nb_tracefile
;
1535 LttvTracefileState
*tfs
;
1539 LttvTraceHook
*hook
;
1541 LttvTraceHookByFacility
*thf
;
1543 LttvAttributeValue val
;
1545 nb_trace
= lttv_traceset_number(traceset
);
1546 for(i
= 0 ; i
< nb_trace
; i
++) {
1547 ts
= LTTV_TRACE_STATE(self
->parent
.traces
[i
]);
1548 lttv_attribute_find(self
->parent
.a
, LTTV_STATE_HOOKS
, LTTV_POINTER
, &val
);
1549 hooks
= *(val
.v_pointer
);
1551 /* Remove these hooks from each event_by_id hooks list */
1553 nb_tracefile
= ts
->parent
.tracefiles
->len
;
1555 for(j
= 0 ; j
< nb_tracefile
; j
++) {
1557 LTTV_TRACEFILE_STATE(g_array_index(ts
->parent
.tracefiles
,
1558 LttvTracefileContext
*, j
));
1560 for(k
= 0 ; k
< hooks
->len
; k
++) {
1561 hook
= &g_array_index(hooks
, LttvTraceHook
, k
);
1562 for(l
=0;l
<hook
->fac_list
->len
;l
++) {
1563 thf
= g_array_index(hook
->fac_list
, LttvTraceHookByFacility
*, l
);
1565 lttv_hooks_remove_data(
1566 lttv_hooks_by_id_find(tfs
->parent
.event_by_id
, thf
->id
),
1572 for(k
= 0 ; k
< hooks
->len
; k
++)
1573 lttv_trace_hook_destroy(&g_array_index(hooks
, LttvTraceHook
, k
));
1574 g_array_free(hooks
, TRUE
);
1578 static gboolean
state_save_event_hook(void *hook_data
, void *call_data
)
1580 guint
*event_count
= (guint
*)hook_data
;
1582 /* Only save at LTTV_STATE_SAVE_INTERVAL */
1583 if(likely((*event_count
)++ < LTTV_STATE_SAVE_INTERVAL
))
1588 LttvTracefileState
*self
= (LttvTracefileState
*)call_data
;
1590 LttvTracefileState
*tfcs
;
1592 LttvTraceState
*tcs
= (LttvTraceState
*)(self
->parent
.t_context
);
1594 LttEventPosition
*ep
;
1600 LttvAttribute
*saved_states_tree
, *saved_state_tree
;
1602 LttvAttributeValue value
;
1604 saved_states_tree
= lttv_attribute_find_subdir(tcs
->parent
.t_a
,
1605 LTTV_STATE_SAVED_STATES
);
1606 saved_state_tree
= g_object_new(LTTV_ATTRIBUTE_TYPE
, NULL
);
1607 value
= lttv_attribute_add(saved_states_tree
,
1608 lttv_attribute_get_number(saved_states_tree
), LTTV_GOBJECT
);
1609 *(value
.v_gobject
) = (GObject
*)saved_state_tree
;
1610 value
= lttv_attribute_add(saved_state_tree
, LTTV_STATE_TIME
, LTTV_TIME
);
1611 *(value
.v_time
) = self
->parent
.timestamp
;
1612 lttv_state_save(tcs
, saved_state_tree
);
1613 g_debug("Saving state at time %lu.%lu", self
->parent
.timestamp
.tv_sec
,
1614 self
->parent
.timestamp
.tv_nsec
);
1616 *(tcs
->max_time_state_recomputed_in_seek
) = self
->parent
.timestamp
;
1621 static gboolean
state_save_after_trace_hook(void *hook_data
, void *call_data
)
1623 LttvTraceState
*tcs
= (LttvTraceState
*)(call_data
);
1625 *(tcs
->max_time_state_recomputed_in_seek
) = tcs
->parent
.time_span
.end_time
;
1631 static gboolean
block_start(void *hook_data
, void *call_data
)
1633 LttvTracefileState
*self
= (LttvTracefileState
*)call_data
;
1635 LttvTracefileState
*tfcs
;
1637 LttvTraceState
*tcs
= (LttvTraceState
*)(self
->parent
.t_context
);
1639 LttEventPosition
*ep
;
1641 guint i
, nb_block
, nb_event
, nb_tracefile
;
1645 LttvAttribute
*saved_states_tree
, *saved_state_tree
;
1647 LttvAttributeValue value
;
1649 ep
= ltt_event_position_new();
1651 nb_tracefile
= tcs
->parent
.tracefiles
->len
;
1653 /* Count the number of events added since the last block end in any
1656 for(i
= 0 ; i
< nb_tracefile
; i
++) {
1658 LTTV_TRACEFILE_STATE(&g_array_index(tcs
->parent
.tracefiles
,
1659 LttvTracefileContext
, i
));
1660 ltt_event_position(tfcs
->parent
.e
, ep
);
1661 ltt_event_position_get(ep
, &nb_block
, &nb_event
, &tf
);
1662 tcs
->nb_event
+= nb_event
- tfcs
->saved_position
;
1663 tfcs
->saved_position
= nb_event
;
1667 if(tcs
->nb_event
>= tcs
->save_interval
) {
1668 saved_states_tree
= lttv_attribute_find_subdir(tcs
->parent
.t_a
,
1669 LTTV_STATE_SAVED_STATES
);
1670 saved_state_tree
= g_object_new(LTTV_ATTRIBUTE_TYPE
, NULL
);
1671 value
= lttv_attribute_add(saved_states_tree
,
1672 lttv_attribute_get_number(saved_states_tree
), LTTV_GOBJECT
);
1673 *(value
.v_gobject
) = (GObject
*)saved_state_tree
;
1674 value
= lttv_attribute_add(saved_state_tree
, LTTV_STATE_TIME
, LTTV_TIME
);
1675 *(value
.v_time
) = self
->parent
.timestamp
;
1676 lttv_state_save(tcs
, saved_state_tree
);
1678 g_debug("Saving state at time %lu.%lu", self
->parent
.timestamp
.tv_sec
,
1679 self
->parent
.timestamp
.tv_nsec
);
1681 *(tcs
->max_time_state_recomputed_in_seek
) = self
->parent
.timestamp
;
1687 static gboolean
block_end(void *hook_data
, void *call_data
)
1689 LttvTracefileState
*self
= (LttvTracefileState
*)call_data
;
1691 LttvTraceState
*tcs
= (LttvTraceState
*)(self
->parent
.t_context
);
1695 LttEventPosition
*ep
;
1697 guint nb_block
, nb_event
;
1699 ep
= ltt_event_position_new();
1700 ltt_event_position(self
->parent
.e
, ep
);
1701 ltt_event_position_get(ep
, &nb_block
, &nb_event
, &tf
);
1702 tcs
->nb_event
+= nb_event
- self
->saved_position
+ 1;
1703 self
->saved_position
= 0;
1704 *(tcs
->max_time_state_recomputed_in_seek
) = self
->parent
.timestamp
;
1711 void lttv_state_save_add_event_hooks(LttvTracesetState
*self
)
1713 LttvTraceset
*traceset
= self
->parent
.ts
;
1715 guint i
, j
, nb_trace
, nb_tracefile
;
1719 LttvTracefileState
*tfs
;
1721 LttvTraceHook hook_start
, hook_end
;
1723 nb_trace
= lttv_traceset_number(traceset
);
1724 for(i
= 0 ; i
< nb_trace
; i
++) {
1725 ts
= (LttvTraceState
*)self
->parent
.traces
[i
];
1727 lttv_trace_find_hook(ts
->parent
.t
, "core","block_start",NULL
,
1728 NULL
, NULL
, block_start
, &hook_start
);
1729 lttv_trace_find_hook(ts
->parent
.t
, "core","block_end",NULL
,
1730 NULL
, NULL
, block_end
, &hook_end
);
1732 nb_tracefile
= ts
->parent
.tracefiles
->len
;
1734 for(j
= 0 ; j
< nb_tracefile
; j
++) {
1736 LTTV_TRACEFILE_STATE(&g_array_index(ts
->parent
.tracefiles
,
1737 LttvTracefileContext
, j
));
1738 lttv_hooks_add(lttv_hooks_by_id_find(tfs
->parent
.event_by_id
,
1739 hook_start
.id
), hook_start
.h
, NULL
, LTTV_PRIO_STATE
);
1740 lttv_hooks_add(lttv_hooks_by_id_find(tfs
->parent
.event_by_id
,
1741 hook_end
.id
), hook_end
.h
, NULL
, LTTV_PRIO_STATE
);
1747 void lttv_state_save_add_event_hooks(LttvTracesetState
*self
)
1749 LttvTraceset
*traceset
= self
->parent
.ts
;
1751 guint i
, j
, nb_trace
, nb_tracefile
;
1755 LttvTracefileState
*tfs
;
1758 nb_trace
= lttv_traceset_number(traceset
);
1759 for(i
= 0 ; i
< nb_trace
; i
++) {
1761 ts
= (LttvTraceState
*)self
->parent
.traces
[i
];
1762 nb_tracefile
= ts
->parent
.tracefiles
->len
;
1764 guint
*event_count
= g_new(guint
, 1);
1767 for(j
= 0 ; j
< nb_tracefile
; j
++) {
1769 LTTV_TRACEFILE_STATE(g_array_index(ts
->parent
.tracefiles
,
1770 LttvTracefileContext
*, j
));
1771 lttv_hooks_add(tfs
->parent
.event
,
1772 state_save_event_hook
,
1779 lttv_process_traceset_begin(&self
->parent
,
1780 NULL
, NULL
, NULL
, NULL
, NULL
);
1784 gint
lttv_state_save_hook_add_event_hooks(void *hook_data
, void *call_data
)
1786 LttvTracesetState
*tss
= (LttvTracesetState
*)(call_data
);
1788 lttv_state_save_add_event_hooks(tss
);
1795 void lttv_state_save_remove_event_hooks(LttvTracesetState
*self
)
1797 LttvTraceset
*traceset
= self
->parent
.ts
;
1799 guint i
, j
, nb_trace
, nb_tracefile
;
1803 LttvTracefileState
*tfs
;
1805 LttvTraceHook hook_start
, hook_end
;
1807 nb_trace
= lttv_traceset_number(traceset
);
1808 for(i
= 0 ; i
< nb_trace
; i
++) {
1809 ts
= LTTV_TRACE_STATE(self
->parent
.traces
[i
]);
1811 lttv_trace_find_hook(ts
->parent
.t
, "core","block_start",NULL
,
1812 NULL
, NULL
, block_start
, &hook_start
);
1814 lttv_trace_find_hook(ts
->parent
.t
, "core","block_end",NULL
,
1815 NULL
, NULL
, block_end
, &hook_end
);
1817 nb_tracefile
= ts
->parent
.tracefiles
->len
;
1819 for(j
= 0 ; j
< nb_tracefile
; j
++) {
1821 LTTV_TRACEFILE_STATE(&g_array_index(ts
->parent
.tracefiles
,
1822 LttvTracefileContext
, j
));
1823 lttv_hooks_remove_data(lttv_hooks_by_id_find(
1824 tfs
->parent
.event_by_id
, hook_start
.id
), hook_start
.h
, NULL
);
1825 lttv_hooks_remove_data(lttv_hooks_by_id_find(
1826 tfs
->parent
.event_by_id
, hook_end
.id
), hook_end
.h
, NULL
);
1832 void lttv_state_save_remove_event_hooks(LttvTracesetState
*self
)
1834 LttvTraceset
*traceset
= self
->parent
.ts
;
1836 guint i
, j
, nb_trace
, nb_tracefile
;
1840 LttvTracefileState
*tfs
;
1842 LttvHooks
*after_trace
= lttv_hooks_new();
1844 lttv_hooks_add(after_trace
,
1845 state_save_after_trace_hook
,
1850 lttv_process_traceset_end(&self
->parent
,
1851 NULL
, after_trace
, NULL
, NULL
, NULL
);
1853 lttv_hooks_destroy(after_trace
);
1855 nb_trace
= lttv_traceset_number(traceset
);
1856 for(i
= 0 ; i
< nb_trace
; i
++) {
1858 ts
= (LttvTraceState
*)self
->parent
.traces
[i
];
1859 nb_tracefile
= ts
->parent
.tracefiles
->len
;
1863 for(j
= 0 ; j
< nb_tracefile
; j
++) {
1865 LTTV_TRACEFILE_STATE(g_array_index(ts
->parent
.tracefiles
,
1866 LttvTracefileContext
*, j
));
1867 event_count
= lttv_hooks_remove(tfs
->parent
.event
,
1868 state_save_event_hook
);
1870 g_free(event_count
);
1874 gint
lttv_state_save_hook_remove_event_hooks(void *hook_data
, void *call_data
)
1876 LttvTracesetState
*tss
= (LttvTracesetState
*)(call_data
);
1878 lttv_state_save_remove_event_hooks(tss
);
1883 void lttv_state_traceset_seek_time_closest(LttvTracesetState
*self
, LttTime t
)
1885 LttvTraceset
*traceset
= self
->parent
.ts
;
1889 int min_pos
, mid_pos
, max_pos
;
1891 guint call_rest
= 0;
1893 LttvTraceState
*tcs
;
1895 LttvAttributeValue value
;
1897 LttvAttributeType type
;
1899 LttvAttributeName name
;
1901 LttvAttribute
*saved_states_tree
, *saved_state_tree
, *closest_tree
;
1903 //g_tree_destroy(self->parent.pqueue);
1904 //self->parent.pqueue = g_tree_new(compare_tracefile);
1906 g_info("Entering seek_time_closest for time %lu.%lu", t
.tv_sec
, t
.tv_nsec
);
1908 nb_trace
= lttv_traceset_number(traceset
);
1909 for(i
= 0 ; i
< nb_trace
; i
++) {
1910 tcs
= (LttvTraceState
*)self
->parent
.traces
[i
];
1912 if(ltt_time_compare(t
, *(tcs
->max_time_state_recomputed_in_seek
)) < 0) {
1913 saved_states_tree
= lttv_attribute_find_subdir(tcs
->parent
.t_a
,
1914 LTTV_STATE_SAVED_STATES
);
1917 if(saved_states_tree
) {
1918 max_pos
= lttv_attribute_get_number(saved_states_tree
) - 1;
1919 mid_pos
= max_pos
/ 2;
1920 while(min_pos
< max_pos
) {
1921 type
= lttv_attribute_get(saved_states_tree
, mid_pos
, &name
, &value
);
1922 g_assert(type
== LTTV_GOBJECT
);
1923 saved_state_tree
= *((LttvAttribute
**)(value
.v_gobject
));
1924 type
= lttv_attribute_get_by_name(saved_state_tree
, LTTV_STATE_TIME
,
1926 g_assert(type
== LTTV_TIME
);
1927 if(ltt_time_compare(*(value
.v_time
), t
) < 0) {
1929 closest_tree
= saved_state_tree
;
1931 else max_pos
= mid_pos
- 1;
1933 mid_pos
= (min_pos
+ max_pos
+ 1) / 2;
1937 /* restore the closest earlier saved state */
1939 lttv_state_restore(tcs
, closest_tree
);
1943 /* There is no saved state, yet we want to have it. Restart at T0 */
1945 restore_init_state(tcs
);
1946 lttv_process_trace_seek_time(&(tcs
->parent
), ltt_time_zero
);
1949 /* We want to seek quickly without restoring/updating the state */
1951 restore_init_state(tcs
);
1952 lttv_process_trace_seek_time(&(tcs
->parent
), t
);
1955 if(!call_rest
) g_info("NOT Calling restore");
1960 traceset_state_instance_init (GTypeInstance
*instance
, gpointer g_class
)
1966 traceset_state_finalize (LttvTracesetState
*self
)
1968 G_OBJECT_CLASS(g_type_class_peek(LTTV_TRACESET_CONTEXT_TYPE
))->
1969 finalize(G_OBJECT(self
));
1974 traceset_state_class_init (LttvTracesetContextClass
*klass
)
1976 GObjectClass
*gobject_class
= G_OBJECT_CLASS(klass
);
1978 gobject_class
->finalize
= (void (*)(GObject
*self
)) traceset_state_finalize
;
1979 klass
->init
= (void (*)(LttvTracesetContext
*self
, LttvTraceset
*ts
))init
;
1980 klass
->fini
= (void (*)(LttvTracesetContext
*self
))fini
;
1981 klass
->new_traceset_context
= new_traceset_context
;
1982 klass
->new_trace_context
= new_trace_context
;
1983 klass
->new_tracefile_context
= new_tracefile_context
;
1988 lttv_traceset_state_get_type(void)
1990 static GType type
= 0;
1992 static const GTypeInfo info
= {
1993 sizeof (LttvTracesetStateClass
),
1994 NULL
, /* base_init */
1995 NULL
, /* base_finalize */
1996 (GClassInitFunc
) traceset_state_class_init
, /* class_init */
1997 NULL
, /* class_finalize */
1998 NULL
, /* class_data */
1999 sizeof (LttvTracesetState
),
2000 0, /* n_preallocs */
2001 (GInstanceInitFunc
) traceset_state_instance_init
, /* instance_init */
2002 NULL
/* value handling */
2005 type
= g_type_register_static (LTTV_TRACESET_CONTEXT_TYPE
, "LttvTracesetStateType",
2013 trace_state_instance_init (GTypeInstance
*instance
, gpointer g_class
)
2019 trace_state_finalize (LttvTraceState
*self
)
2021 G_OBJECT_CLASS(g_type_class_peek(LTTV_TRACE_CONTEXT_TYPE
))->
2022 finalize(G_OBJECT(self
));
2027 trace_state_class_init (LttvTraceStateClass
*klass
)
2029 GObjectClass
*gobject_class
= G_OBJECT_CLASS(klass
);
2031 gobject_class
->finalize
= (void (*)(GObject
*self
)) trace_state_finalize
;
2032 klass
->state_save
= state_save
;
2033 klass
->state_restore
= state_restore
;
2034 klass
->state_saved_free
= state_saved_free
;
2039 lttv_trace_state_get_type(void)
2041 static GType type
= 0;
2043 static const GTypeInfo info
= {
2044 sizeof (LttvTraceStateClass
),
2045 NULL
, /* base_init */
2046 NULL
, /* base_finalize */
2047 (GClassInitFunc
) trace_state_class_init
, /* class_init */
2048 NULL
, /* class_finalize */
2049 NULL
, /* class_data */
2050 sizeof (LttvTraceState
),
2051 0, /* n_preallocs */
2052 (GInstanceInitFunc
) trace_state_instance_init
, /* instance_init */
2053 NULL
/* value handling */
2056 type
= g_type_register_static (LTTV_TRACE_CONTEXT_TYPE
,
2057 "LttvTraceStateType", &info
, 0);
2064 tracefile_state_instance_init (GTypeInstance
*instance
, gpointer g_class
)
2070 tracefile_state_finalize (LttvTracefileState
*self
)
2072 G_OBJECT_CLASS(g_type_class_peek(LTTV_TRACEFILE_CONTEXT_TYPE
))->
2073 finalize(G_OBJECT(self
));
2078 tracefile_state_class_init (LttvTracefileStateClass
*klass
)
2080 GObjectClass
*gobject_class
= G_OBJECT_CLASS(klass
);
2082 gobject_class
->finalize
= (void (*)(GObject
*self
)) tracefile_state_finalize
;
2087 lttv_tracefile_state_get_type(void)
2089 static GType type
= 0;
2091 static const GTypeInfo info
= {
2092 sizeof (LttvTracefileStateClass
),
2093 NULL
, /* base_init */
2094 NULL
, /* base_finalize */
2095 (GClassInitFunc
) tracefile_state_class_init
, /* class_init */
2096 NULL
, /* class_finalize */
2097 NULL
, /* class_data */
2098 sizeof (LttvTracefileState
),
2099 0, /* n_preallocs */
2100 (GInstanceInitFunc
) tracefile_state_instance_init
, /* instance_init */
2101 NULL
/* value handling */
2104 type
= g_type_register_static (LTTV_TRACEFILE_CONTEXT_TYPE
,
2105 "LttvTracefileStateType", &info
, 0);
2111 static void module_init()
2113 LTTV_STATE_UNNAMED
= g_quark_from_string("unnamed");
2114 LTTV_STATE_MODE_UNKNOWN
= g_quark_from_string("unknown execution mode");
2115 LTTV_STATE_USER_MODE
= g_quark_from_string("user mode");
2116 LTTV_STATE_WAIT_FORK
= g_quark_from_string("wait fork");
2117 LTTV_STATE_SYSCALL
= g_quark_from_string("system call");
2118 LTTV_STATE_TRAP
= g_quark_from_string("trap");
2119 LTTV_STATE_IRQ
= g_quark_from_string("irq");
2120 LTTV_STATE_SUBMODE_UNKNOWN
= g_quark_from_string("unknown submode");
2121 LTTV_STATE_SUBMODE_NONE
= g_quark_from_string("(no submode)");
2122 LTTV_STATE_WAIT_CPU
= g_quark_from_string("wait for cpu");
2123 LTTV_STATE_EXIT
= g_quark_from_string("exiting");
2124 LTTV_STATE_ZOMBIE
= g_quark_from_string("zombie");
2125 LTTV_STATE_WAIT
= g_quark_from_string("wait for I/O");
2126 LTTV_STATE_RUN
= g_quark_from_string("running");
2127 LTTV_STATE_TRACEFILES
= g_quark_from_string("tracefiles");
2128 LTTV_STATE_PROCESSES
= g_quark_from_string("processes");
2129 LTTV_STATE_PROCESS
= g_quark_from_string("process");
2130 LTTV_STATE_RUNNING_PROCESS
= g_quark_from_string("running_process");
2131 LTTV_STATE_EVENT
= g_quark_from_string("event");
2132 LTTV_STATE_SAVED_STATES
= g_quark_from_string("saved states");
2133 LTTV_STATE_SAVED_STATES_TIME
= g_quark_from_string("saved states time");
2134 LTTV_STATE_TIME
= g_quark_from_string("time");
2135 LTTV_STATE_HOOKS
= g_quark_from_string("saved state hooks");
2136 LTTV_STATE_NAME_TABLES
= g_quark_from_string("name tables");
2137 LTTV_STATE_TRACE_STATE_USE_COUNT
=
2138 g_quark_from_string("trace_state_use_count");
2141 LTT_FACILITY_KERNEL
= g_quark_from_string("kernel");
2142 LTT_FACILITY_PROCESS
= g_quark_from_string("process");
2143 LTT_FACILITY_FS
= g_quark_from_string("fs");
2146 LTT_EVENT_SYSCALL_ENTRY
= g_quark_from_string("syscall_entry");
2147 LTT_EVENT_SYSCALL_EXIT
= g_quark_from_string("syscall_exit");
2148 LTT_EVENT_TRAP_ENTRY
= g_quark_from_string("trap_entry");
2149 LTT_EVENT_TRAP_EXIT
= g_quark_from_string("trap_exit");
2150 LTT_EVENT_IRQ_ENTRY
= g_quark_from_string("irq_entry");
2151 LTT_EVENT_IRQ_EXIT
= g_quark_from_string("irq_exit");
2152 LTT_EVENT_SCHEDCHANGE
= g_quark_from_string("schedchange");
2153 LTT_EVENT_FORK
= g_quark_from_string("fork");
2154 LTT_EVENT_EXIT
= g_quark_from_string("exit");
2155 LTT_EVENT_FREE
= g_quark_from_string("free");
2156 LTT_EVENT_EXEC
= g_quark_from_string("exec");
2159 LTT_FIELD_SYSCALL_ID
= g_quark_from_string("syscall_id");
2160 LTT_FIELD_TRAP_ID
= g_quark_from_string("trap_id");
2161 LTT_FIELD_IRQ_ID
= g_quark_from_string("irq_id");
2162 LTT_FIELD_OUT
= g_quark_from_string("out");
2163 LTT_FIELD_IN
= g_quark_from_string("in");
2164 LTT_FIELD_OUT_STATE
= g_quark_from_string("out_state");
2165 LTT_FIELD_PARENT_PID
= g_quark_from_string("parent_pid");
2166 LTT_FIELD_CHILD_PID
= g_quark_from_string("child_pid");
2167 LTT_FIELD_PID
= g_quark_from_string("pid");
2168 LTT_FIELD_FILENAME
= g_quark_from_string("filename");
2172 static void module_destroy()
2177 LTTV_MODULE("state", "State computation", \
2178 "Update the system state, possibly saving it at intervals", \
2179 module_init
, module_destroy
)