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 //This test is fun, though, as it may happen that
1342 //at time t : CPU 0 : process_free
1343 //at time t+150ns : CPU 1 : schedule out
1344 //Clearly due to time imprecision, we disable it. (Mathieu)
1345 //If this weird case happen, we have no choice but to put the
1346 //Currently running process on the cpu to 0.
1347 guint num_cpus
= ltt_trace_get_num_cpu(ts
->parent
.t
);
1349 for(i
=0; i
< num_cpus
; i
++) {
1350 //g_assert(process != ts->running_process[i]);
1351 if(process
== ts
->running_process
[i
]) {
1352 ts
->running_process
[i
] = lttv_state_find_process(ts
, i
, 0);
1355 exit_process(s
, process
);
1362 static gboolean
process_exec(void *hook_data
, void *call_data
)
1364 LttvTracefileState
*s
= (LttvTracefileState
*)call_data
;
1365 LttvTraceState
*ts
= (LttvTraceState
*)s
->parent
.t_context
;
1366 LttEvent
*e
= ltt_tracefile_get_event(s
->parent
.tf
);
1367 LttvTraceHookByFacility
*thf
= (LttvTraceHookByFacility
*)hook_data
;
1369 guint cpu
= ltt_tracefile_num(s
->parent
.tf
);
1370 LttvProcessState
*process
= ts
->running_process
[cpu
];
1372 /* PID of the process to release */
1373 name
= ltt_event_get_string(e
, thf
->f1
);
1375 process
->name
= g_quark_from_string(name
);
1383 gint
lttv_state_hook_add_event_hooks(void *hook_data
, void *call_data
)
1385 LttvTracesetState
*tss
= (LttvTracesetState
*)(call_data
);
1387 lttv_state_add_event_hooks(tss
);
1392 void lttv_state_add_event_hooks(LttvTracesetState
*self
)
1394 LttvTraceset
*traceset
= self
->parent
.ts
;
1396 guint i
, j
, k
, l
, nb_trace
, nb_tracefile
;
1400 LttvTracefileState
*tfs
;
1404 LttvTraceHookByFacility
*thf
;
1406 LttvTraceHook
*hook
;
1408 LttvAttributeValue val
;
1412 nb_trace
= lttv_traceset_number(traceset
);
1413 for(i
= 0 ; i
< nb_trace
; i
++) {
1414 ts
= (LttvTraceState
*)self
->parent
.traces
[i
];
1416 /* Find the eventtype id for the following events and register the
1417 associated by id hooks. */
1419 hooks
= g_array_sized_new(FALSE
, FALSE
, sizeof(LttvTraceHook
), 11);
1420 hooks
= g_array_set_size(hooks
, 11);
1422 ret
= lttv_trace_find_hook(ts
->parent
.t
,
1423 LTT_FACILITY_KERNEL
, LTT_EVENT_SYSCALL_ENTRY
,
1424 LTT_FIELD_SYSCALL_ID
, 0, 0,
1425 syscall_entry
, NULL
, &g_array_index(hooks
, LttvTraceHook
, 0));
1428 ret
= lttv_trace_find_hook(ts
->parent
.t
,
1429 LTT_FACILITY_KERNEL
, LTT_EVENT_SYSCALL_EXIT
,
1431 syscall_exit
, NULL
, &g_array_index(hooks
, LttvTraceHook
, 1));
1434 ret
= lttv_trace_find_hook(ts
->parent
.t
,
1435 LTT_FACILITY_KERNEL
, LTT_EVENT_TRAP_ENTRY
,
1436 LTT_FIELD_TRAP_ID
, 0, 0,
1437 trap_entry
, NULL
, &g_array_index(hooks
, LttvTraceHook
, 2));
1440 ret
= lttv_trace_find_hook(ts
->parent
.t
,
1441 LTT_FACILITY_KERNEL
, LTT_EVENT_TRAP_EXIT
,
1443 trap_exit
, NULL
, &g_array_index(hooks
, LttvTraceHook
, 3));
1446 ret
= lttv_trace_find_hook(ts
->parent
.t
,
1447 LTT_FACILITY_KERNEL
, LTT_EVENT_IRQ_ENTRY
,
1448 LTT_FIELD_IRQ_ID
, 0, 0,
1449 irq_entry
, NULL
, &g_array_index(hooks
, LttvTraceHook
, 4));
1452 ret
= lttv_trace_find_hook(ts
->parent
.t
,
1453 LTT_FACILITY_KERNEL
, LTT_EVENT_IRQ_EXIT
,
1455 irq_exit
, NULL
, &g_array_index(hooks
, LttvTraceHook
, 5));
1458 ret
= lttv_trace_find_hook(ts
->parent
.t
,
1459 LTT_FACILITY_PROCESS
, LTT_EVENT_SCHEDCHANGE
,
1460 LTT_FIELD_OUT
, LTT_FIELD_IN
, LTT_FIELD_OUT_STATE
,
1461 schedchange
, NULL
, &g_array_index(hooks
, LttvTraceHook
, 6));
1464 ret
= lttv_trace_find_hook(ts
->parent
.t
,
1465 LTT_FACILITY_PROCESS
, LTT_EVENT_FORK
,
1466 LTT_FIELD_PARENT_PID
, LTT_FIELD_CHILD_PID
, 0,
1467 process_fork
, NULL
, &g_array_index(hooks
, LttvTraceHook
, 7));
1470 ret
= lttv_trace_find_hook(ts
->parent
.t
,
1471 LTT_FACILITY_PROCESS
, LTT_EVENT_EXIT
,
1472 LTT_FIELD_PID
, 0, 0,
1473 process_exit
, NULL
, &g_array_index(hooks
, LttvTraceHook
, 8));
1476 ret
= lttv_trace_find_hook(ts
->parent
.t
,
1477 LTT_FACILITY_PROCESS
, LTT_EVENT_FREE
,
1478 LTT_FIELD_PID
, 0, 0,
1479 process_free
, NULL
, &g_array_index(hooks
, LttvTraceHook
, 9));
1482 ret
= lttv_trace_find_hook(ts
->parent
.t
,
1483 LTT_FACILITY_FS
, LTT_EVENT_EXEC
,
1484 LTT_FIELD_FILENAME
, 0, 0,
1485 process_exec
, NULL
, &g_array_index(hooks
, LttvTraceHook
, 10));
1490 /* Add these hooks to each event_by_id hooks list */
1492 nb_tracefile
= ts
->parent
.tracefiles
->len
;
1494 for(j
= 0 ; j
< nb_tracefile
; j
++) {
1496 LTTV_TRACEFILE_STATE(g_array_index(ts
->parent
.tracefiles
,
1497 LttvTracefileContext
*, j
));
1499 for(k
= 0 ; k
< hooks
->len
; k
++) {
1500 hook
= &g_array_index(hooks
, LttvTraceHook
, k
);
1501 for(l
=0;l
<hook
->fac_list
->len
;l
++) {
1502 thf
= g_array_index(hook
->fac_list
, LttvTraceHookByFacility
*, l
);
1504 lttv_hooks_by_id_find(tfs
->parent
.event_by_id
, thf
->id
),
1511 lttv_attribute_find(self
->parent
.a
, LTTV_STATE_HOOKS
, LTTV_POINTER
, &val
);
1512 *(val
.v_pointer
) = hooks
;
1516 gint
lttv_state_hook_remove_event_hooks(void *hook_data
, void *call_data
)
1518 LttvTracesetState
*tss
= (LttvTracesetState
*)(call_data
);
1520 lttv_state_remove_event_hooks(tss
);
1525 void lttv_state_remove_event_hooks(LttvTracesetState
*self
)
1527 LttvTraceset
*traceset
= self
->parent
.ts
;
1529 guint i
, j
, k
, l
, nb_trace
, nb_tracefile
;
1533 LttvTracefileState
*tfs
;
1537 LttvTraceHook
*hook
;
1539 LttvTraceHookByFacility
*thf
;
1541 LttvAttributeValue val
;
1543 nb_trace
= lttv_traceset_number(traceset
);
1544 for(i
= 0 ; i
< nb_trace
; i
++) {
1545 ts
= LTTV_TRACE_STATE(self
->parent
.traces
[i
]);
1546 lttv_attribute_find(self
->parent
.a
, LTTV_STATE_HOOKS
, LTTV_POINTER
, &val
);
1547 hooks
= *(val
.v_pointer
);
1549 /* Remove these hooks from each event_by_id hooks list */
1551 nb_tracefile
= ts
->parent
.tracefiles
->len
;
1553 for(j
= 0 ; j
< nb_tracefile
; j
++) {
1555 LTTV_TRACEFILE_STATE(g_array_index(ts
->parent
.tracefiles
,
1556 LttvTracefileContext
*, j
));
1558 for(k
= 0 ; k
< hooks
->len
; k
++) {
1559 hook
= &g_array_index(hooks
, LttvTraceHook
, k
);
1560 for(l
=0;l
<hook
->fac_list
->len
;l
++) {
1561 thf
= g_array_index(hook
->fac_list
, LttvTraceHookByFacility
*, l
);
1563 lttv_hooks_remove_data(
1564 lttv_hooks_by_id_find(tfs
->parent
.event_by_id
, thf
->id
),
1570 for(k
= 0 ; k
< hooks
->len
; k
++)
1571 lttv_trace_hook_destroy(&g_array_index(hooks
, LttvTraceHook
, k
));
1572 g_array_free(hooks
, TRUE
);
1576 static gboolean
state_save_event_hook(void *hook_data
, void *call_data
)
1578 guint
*event_count
= (guint
*)hook_data
;
1580 /* Only save at LTTV_STATE_SAVE_INTERVAL */
1581 if(likely((*event_count
)++ < LTTV_STATE_SAVE_INTERVAL
))
1586 LttvTracefileState
*self
= (LttvTracefileState
*)call_data
;
1588 LttvTracefileState
*tfcs
;
1590 LttvTraceState
*tcs
= (LttvTraceState
*)(self
->parent
.t_context
);
1592 LttEventPosition
*ep
;
1598 LttvAttribute
*saved_states_tree
, *saved_state_tree
;
1600 LttvAttributeValue value
;
1602 saved_states_tree
= lttv_attribute_find_subdir(tcs
->parent
.t_a
,
1603 LTTV_STATE_SAVED_STATES
);
1604 saved_state_tree
= g_object_new(LTTV_ATTRIBUTE_TYPE
, NULL
);
1605 value
= lttv_attribute_add(saved_states_tree
,
1606 lttv_attribute_get_number(saved_states_tree
), LTTV_GOBJECT
);
1607 *(value
.v_gobject
) = (GObject
*)saved_state_tree
;
1608 value
= lttv_attribute_add(saved_state_tree
, LTTV_STATE_TIME
, LTTV_TIME
);
1609 *(value
.v_time
) = self
->parent
.timestamp
;
1610 lttv_state_save(tcs
, saved_state_tree
);
1611 g_debug("Saving state at time %lu.%lu", self
->parent
.timestamp
.tv_sec
,
1612 self
->parent
.timestamp
.tv_nsec
);
1614 *(tcs
->max_time_state_recomputed_in_seek
) = self
->parent
.timestamp
;
1619 static gboolean
state_save_after_trace_hook(void *hook_data
, void *call_data
)
1621 LttvTraceState
*tcs
= (LttvTraceState
*)(call_data
);
1623 *(tcs
->max_time_state_recomputed_in_seek
) = tcs
->parent
.time_span
.end_time
;
1629 static gboolean
block_start(void *hook_data
, void *call_data
)
1631 LttvTracefileState
*self
= (LttvTracefileState
*)call_data
;
1633 LttvTracefileState
*tfcs
;
1635 LttvTraceState
*tcs
= (LttvTraceState
*)(self
->parent
.t_context
);
1637 LttEventPosition
*ep
;
1639 guint i
, nb_block
, nb_event
, nb_tracefile
;
1643 LttvAttribute
*saved_states_tree
, *saved_state_tree
;
1645 LttvAttributeValue value
;
1647 ep
= ltt_event_position_new();
1649 nb_tracefile
= tcs
->parent
.tracefiles
->len
;
1651 /* Count the number of events added since the last block end in any
1654 for(i
= 0 ; i
< nb_tracefile
; i
++) {
1656 LTTV_TRACEFILE_STATE(&g_array_index(tcs
->parent
.tracefiles
,
1657 LttvTracefileContext
, i
));
1658 ltt_event_position(tfcs
->parent
.e
, ep
);
1659 ltt_event_position_get(ep
, &nb_block
, &nb_event
, &tf
);
1660 tcs
->nb_event
+= nb_event
- tfcs
->saved_position
;
1661 tfcs
->saved_position
= nb_event
;
1665 if(tcs
->nb_event
>= tcs
->save_interval
) {
1666 saved_states_tree
= lttv_attribute_find_subdir(tcs
->parent
.t_a
,
1667 LTTV_STATE_SAVED_STATES
);
1668 saved_state_tree
= g_object_new(LTTV_ATTRIBUTE_TYPE
, NULL
);
1669 value
= lttv_attribute_add(saved_states_tree
,
1670 lttv_attribute_get_number(saved_states_tree
), LTTV_GOBJECT
);
1671 *(value
.v_gobject
) = (GObject
*)saved_state_tree
;
1672 value
= lttv_attribute_add(saved_state_tree
, LTTV_STATE_TIME
, LTTV_TIME
);
1673 *(value
.v_time
) = self
->parent
.timestamp
;
1674 lttv_state_save(tcs
, saved_state_tree
);
1676 g_debug("Saving state at time %lu.%lu", self
->parent
.timestamp
.tv_sec
,
1677 self
->parent
.timestamp
.tv_nsec
);
1679 *(tcs
->max_time_state_recomputed_in_seek
) = self
->parent
.timestamp
;
1685 static gboolean
block_end(void *hook_data
, void *call_data
)
1687 LttvTracefileState
*self
= (LttvTracefileState
*)call_data
;
1689 LttvTraceState
*tcs
= (LttvTraceState
*)(self
->parent
.t_context
);
1693 LttEventPosition
*ep
;
1695 guint nb_block
, nb_event
;
1697 ep
= ltt_event_position_new();
1698 ltt_event_position(self
->parent
.e
, ep
);
1699 ltt_event_position_get(ep
, &nb_block
, &nb_event
, &tf
);
1700 tcs
->nb_event
+= nb_event
- self
->saved_position
+ 1;
1701 self
->saved_position
= 0;
1702 *(tcs
->max_time_state_recomputed_in_seek
) = self
->parent
.timestamp
;
1709 void lttv_state_save_add_event_hooks(LttvTracesetState
*self
)
1711 LttvTraceset
*traceset
= self
->parent
.ts
;
1713 guint i
, j
, nb_trace
, nb_tracefile
;
1717 LttvTracefileState
*tfs
;
1719 LttvTraceHook hook_start
, hook_end
;
1721 nb_trace
= lttv_traceset_number(traceset
);
1722 for(i
= 0 ; i
< nb_trace
; i
++) {
1723 ts
= (LttvTraceState
*)self
->parent
.traces
[i
];
1725 lttv_trace_find_hook(ts
->parent
.t
, "core","block_start",NULL
,
1726 NULL
, NULL
, block_start
, &hook_start
);
1727 lttv_trace_find_hook(ts
->parent
.t
, "core","block_end",NULL
,
1728 NULL
, NULL
, block_end
, &hook_end
);
1730 nb_tracefile
= ts
->parent
.tracefiles
->len
;
1732 for(j
= 0 ; j
< nb_tracefile
; j
++) {
1734 LTTV_TRACEFILE_STATE(&g_array_index(ts
->parent
.tracefiles
,
1735 LttvTracefileContext
, j
));
1736 lttv_hooks_add(lttv_hooks_by_id_find(tfs
->parent
.event_by_id
,
1737 hook_start
.id
), hook_start
.h
, NULL
, LTTV_PRIO_STATE
);
1738 lttv_hooks_add(lttv_hooks_by_id_find(tfs
->parent
.event_by_id
,
1739 hook_end
.id
), hook_end
.h
, NULL
, LTTV_PRIO_STATE
);
1745 void lttv_state_save_add_event_hooks(LttvTracesetState
*self
)
1747 LttvTraceset
*traceset
= self
->parent
.ts
;
1749 guint i
, j
, nb_trace
, nb_tracefile
;
1753 LttvTracefileState
*tfs
;
1756 nb_trace
= lttv_traceset_number(traceset
);
1757 for(i
= 0 ; i
< nb_trace
; i
++) {
1759 ts
= (LttvTraceState
*)self
->parent
.traces
[i
];
1760 nb_tracefile
= ts
->parent
.tracefiles
->len
;
1762 guint
*event_count
= g_new(guint
, 1);
1765 for(j
= 0 ; j
< nb_tracefile
; j
++) {
1767 LTTV_TRACEFILE_STATE(g_array_index(ts
->parent
.tracefiles
,
1768 LttvTracefileContext
*, j
));
1769 lttv_hooks_add(tfs
->parent
.event
,
1770 state_save_event_hook
,
1777 lttv_process_traceset_begin(&self
->parent
,
1778 NULL
, NULL
, NULL
, NULL
, NULL
);
1782 gint
lttv_state_save_hook_add_event_hooks(void *hook_data
, void *call_data
)
1784 LttvTracesetState
*tss
= (LttvTracesetState
*)(call_data
);
1786 lttv_state_save_add_event_hooks(tss
);
1793 void lttv_state_save_remove_event_hooks(LttvTracesetState
*self
)
1795 LttvTraceset
*traceset
= self
->parent
.ts
;
1797 guint i
, j
, nb_trace
, nb_tracefile
;
1801 LttvTracefileState
*tfs
;
1803 LttvTraceHook hook_start
, hook_end
;
1805 nb_trace
= lttv_traceset_number(traceset
);
1806 for(i
= 0 ; i
< nb_trace
; i
++) {
1807 ts
= LTTV_TRACE_STATE(self
->parent
.traces
[i
]);
1809 lttv_trace_find_hook(ts
->parent
.t
, "core","block_start",NULL
,
1810 NULL
, NULL
, block_start
, &hook_start
);
1812 lttv_trace_find_hook(ts
->parent
.t
, "core","block_end",NULL
,
1813 NULL
, NULL
, block_end
, &hook_end
);
1815 nb_tracefile
= ts
->parent
.tracefiles
->len
;
1817 for(j
= 0 ; j
< nb_tracefile
; j
++) {
1819 LTTV_TRACEFILE_STATE(&g_array_index(ts
->parent
.tracefiles
,
1820 LttvTracefileContext
, j
));
1821 lttv_hooks_remove_data(lttv_hooks_by_id_find(
1822 tfs
->parent
.event_by_id
, hook_start
.id
), hook_start
.h
, NULL
);
1823 lttv_hooks_remove_data(lttv_hooks_by_id_find(
1824 tfs
->parent
.event_by_id
, hook_end
.id
), hook_end
.h
, NULL
);
1830 void lttv_state_save_remove_event_hooks(LttvTracesetState
*self
)
1832 LttvTraceset
*traceset
= self
->parent
.ts
;
1834 guint i
, j
, nb_trace
, nb_tracefile
;
1838 LttvTracefileState
*tfs
;
1840 LttvHooks
*after_trace
= lttv_hooks_new();
1842 lttv_hooks_add(after_trace
,
1843 state_save_after_trace_hook
,
1848 lttv_process_traceset_end(&self
->parent
,
1849 NULL
, after_trace
, NULL
, NULL
, NULL
);
1851 lttv_hooks_destroy(after_trace
);
1853 nb_trace
= lttv_traceset_number(traceset
);
1854 for(i
= 0 ; i
< nb_trace
; i
++) {
1856 ts
= (LttvTraceState
*)self
->parent
.traces
[i
];
1857 nb_tracefile
= ts
->parent
.tracefiles
->len
;
1861 for(j
= 0 ; j
< nb_tracefile
; j
++) {
1863 LTTV_TRACEFILE_STATE(g_array_index(ts
->parent
.tracefiles
,
1864 LttvTracefileContext
*, j
));
1865 event_count
= lttv_hooks_remove(tfs
->parent
.event
,
1866 state_save_event_hook
);
1868 g_free(event_count
);
1872 gint
lttv_state_save_hook_remove_event_hooks(void *hook_data
, void *call_data
)
1874 LttvTracesetState
*tss
= (LttvTracesetState
*)(call_data
);
1876 lttv_state_save_remove_event_hooks(tss
);
1881 void lttv_state_traceset_seek_time_closest(LttvTracesetState
*self
, LttTime t
)
1883 LttvTraceset
*traceset
= self
->parent
.ts
;
1887 int min_pos
, mid_pos
, max_pos
;
1889 guint call_rest
= 0;
1891 LttvTraceState
*tcs
;
1893 LttvAttributeValue value
;
1895 LttvAttributeType type
;
1897 LttvAttributeName name
;
1899 LttvAttribute
*saved_states_tree
, *saved_state_tree
, *closest_tree
;
1901 //g_tree_destroy(self->parent.pqueue);
1902 //self->parent.pqueue = g_tree_new(compare_tracefile);
1904 g_info("Entering seek_time_closest for time %lu.%lu", t
.tv_sec
, t
.tv_nsec
);
1906 nb_trace
= lttv_traceset_number(traceset
);
1907 for(i
= 0 ; i
< nb_trace
; i
++) {
1908 tcs
= (LttvTraceState
*)self
->parent
.traces
[i
];
1910 if(ltt_time_compare(t
, *(tcs
->max_time_state_recomputed_in_seek
)) < 0) {
1911 saved_states_tree
= lttv_attribute_find_subdir(tcs
->parent
.t_a
,
1912 LTTV_STATE_SAVED_STATES
);
1915 if(saved_states_tree
) {
1916 max_pos
= lttv_attribute_get_number(saved_states_tree
) - 1;
1917 mid_pos
= max_pos
/ 2;
1918 while(min_pos
< max_pos
) {
1919 type
= lttv_attribute_get(saved_states_tree
, mid_pos
, &name
, &value
);
1920 g_assert(type
== LTTV_GOBJECT
);
1921 saved_state_tree
= *((LttvAttribute
**)(value
.v_gobject
));
1922 type
= lttv_attribute_get_by_name(saved_state_tree
, LTTV_STATE_TIME
,
1924 g_assert(type
== LTTV_TIME
);
1925 if(ltt_time_compare(*(value
.v_time
), t
) < 0) {
1927 closest_tree
= saved_state_tree
;
1929 else max_pos
= mid_pos
- 1;
1931 mid_pos
= (min_pos
+ max_pos
+ 1) / 2;
1935 /* restore the closest earlier saved state */
1937 lttv_state_restore(tcs
, closest_tree
);
1941 /* There is no saved state, yet we want to have it. Restart at T0 */
1943 restore_init_state(tcs
);
1944 lttv_process_trace_seek_time(&(tcs
->parent
), ltt_time_zero
);
1947 /* We want to seek quickly without restoring/updating the state */
1949 restore_init_state(tcs
);
1950 lttv_process_trace_seek_time(&(tcs
->parent
), t
);
1953 if(!call_rest
) g_info("NOT Calling restore");
1958 traceset_state_instance_init (GTypeInstance
*instance
, gpointer g_class
)
1964 traceset_state_finalize (LttvTracesetState
*self
)
1966 G_OBJECT_CLASS(g_type_class_peek(LTTV_TRACESET_CONTEXT_TYPE
))->
1967 finalize(G_OBJECT(self
));
1972 traceset_state_class_init (LttvTracesetContextClass
*klass
)
1974 GObjectClass
*gobject_class
= G_OBJECT_CLASS(klass
);
1976 gobject_class
->finalize
= (void (*)(GObject
*self
)) traceset_state_finalize
;
1977 klass
->init
= (void (*)(LttvTracesetContext
*self
, LttvTraceset
*ts
))init
;
1978 klass
->fini
= (void (*)(LttvTracesetContext
*self
))fini
;
1979 klass
->new_traceset_context
= new_traceset_context
;
1980 klass
->new_trace_context
= new_trace_context
;
1981 klass
->new_tracefile_context
= new_tracefile_context
;
1986 lttv_traceset_state_get_type(void)
1988 static GType type
= 0;
1990 static const GTypeInfo info
= {
1991 sizeof (LttvTracesetStateClass
),
1992 NULL
, /* base_init */
1993 NULL
, /* base_finalize */
1994 (GClassInitFunc
) traceset_state_class_init
, /* class_init */
1995 NULL
, /* class_finalize */
1996 NULL
, /* class_data */
1997 sizeof (LttvTracesetState
),
1998 0, /* n_preallocs */
1999 (GInstanceInitFunc
) traceset_state_instance_init
, /* instance_init */
2000 NULL
/* value handling */
2003 type
= g_type_register_static (LTTV_TRACESET_CONTEXT_TYPE
, "LttvTracesetStateType",
2011 trace_state_instance_init (GTypeInstance
*instance
, gpointer g_class
)
2017 trace_state_finalize (LttvTraceState
*self
)
2019 G_OBJECT_CLASS(g_type_class_peek(LTTV_TRACE_CONTEXT_TYPE
))->
2020 finalize(G_OBJECT(self
));
2025 trace_state_class_init (LttvTraceStateClass
*klass
)
2027 GObjectClass
*gobject_class
= G_OBJECT_CLASS(klass
);
2029 gobject_class
->finalize
= (void (*)(GObject
*self
)) trace_state_finalize
;
2030 klass
->state_save
= state_save
;
2031 klass
->state_restore
= state_restore
;
2032 klass
->state_saved_free
= state_saved_free
;
2037 lttv_trace_state_get_type(void)
2039 static GType type
= 0;
2041 static const GTypeInfo info
= {
2042 sizeof (LttvTraceStateClass
),
2043 NULL
, /* base_init */
2044 NULL
, /* base_finalize */
2045 (GClassInitFunc
) trace_state_class_init
, /* class_init */
2046 NULL
, /* class_finalize */
2047 NULL
, /* class_data */
2048 sizeof (LttvTraceState
),
2049 0, /* n_preallocs */
2050 (GInstanceInitFunc
) trace_state_instance_init
, /* instance_init */
2051 NULL
/* value handling */
2054 type
= g_type_register_static (LTTV_TRACE_CONTEXT_TYPE
,
2055 "LttvTraceStateType", &info
, 0);
2062 tracefile_state_instance_init (GTypeInstance
*instance
, gpointer g_class
)
2068 tracefile_state_finalize (LttvTracefileState
*self
)
2070 G_OBJECT_CLASS(g_type_class_peek(LTTV_TRACEFILE_CONTEXT_TYPE
))->
2071 finalize(G_OBJECT(self
));
2076 tracefile_state_class_init (LttvTracefileStateClass
*klass
)
2078 GObjectClass
*gobject_class
= G_OBJECT_CLASS(klass
);
2080 gobject_class
->finalize
= (void (*)(GObject
*self
)) tracefile_state_finalize
;
2085 lttv_tracefile_state_get_type(void)
2087 static GType type
= 0;
2089 static const GTypeInfo info
= {
2090 sizeof (LttvTracefileStateClass
),
2091 NULL
, /* base_init */
2092 NULL
, /* base_finalize */
2093 (GClassInitFunc
) tracefile_state_class_init
, /* class_init */
2094 NULL
, /* class_finalize */
2095 NULL
, /* class_data */
2096 sizeof (LttvTracefileState
),
2097 0, /* n_preallocs */
2098 (GInstanceInitFunc
) tracefile_state_instance_init
, /* instance_init */
2099 NULL
/* value handling */
2102 type
= g_type_register_static (LTTV_TRACEFILE_CONTEXT_TYPE
,
2103 "LttvTracefileStateType", &info
, 0);
2109 static void module_init()
2111 LTTV_STATE_UNNAMED
= g_quark_from_string("unnamed");
2112 LTTV_STATE_MODE_UNKNOWN
= g_quark_from_string("unknown execution mode");
2113 LTTV_STATE_USER_MODE
= g_quark_from_string("user mode");
2114 LTTV_STATE_WAIT_FORK
= g_quark_from_string("wait fork");
2115 LTTV_STATE_SYSCALL
= g_quark_from_string("system call");
2116 LTTV_STATE_TRAP
= g_quark_from_string("trap");
2117 LTTV_STATE_IRQ
= g_quark_from_string("irq");
2118 LTTV_STATE_SUBMODE_UNKNOWN
= g_quark_from_string("unknown submode");
2119 LTTV_STATE_SUBMODE_NONE
= g_quark_from_string("(no submode)");
2120 LTTV_STATE_WAIT_CPU
= g_quark_from_string("wait for cpu");
2121 LTTV_STATE_EXIT
= g_quark_from_string("exiting");
2122 LTTV_STATE_ZOMBIE
= g_quark_from_string("zombie");
2123 LTTV_STATE_WAIT
= g_quark_from_string("wait for I/O");
2124 LTTV_STATE_RUN
= g_quark_from_string("running");
2125 LTTV_STATE_TRACEFILES
= g_quark_from_string("tracefiles");
2126 LTTV_STATE_PROCESSES
= g_quark_from_string("processes");
2127 LTTV_STATE_PROCESS
= g_quark_from_string("process");
2128 LTTV_STATE_RUNNING_PROCESS
= g_quark_from_string("running_process");
2129 LTTV_STATE_EVENT
= g_quark_from_string("event");
2130 LTTV_STATE_SAVED_STATES
= g_quark_from_string("saved states");
2131 LTTV_STATE_SAVED_STATES_TIME
= g_quark_from_string("saved states time");
2132 LTTV_STATE_TIME
= g_quark_from_string("time");
2133 LTTV_STATE_HOOKS
= g_quark_from_string("saved state hooks");
2134 LTTV_STATE_NAME_TABLES
= g_quark_from_string("name tables");
2135 LTTV_STATE_TRACE_STATE_USE_COUNT
=
2136 g_quark_from_string("trace_state_use_count");
2139 LTT_FACILITY_KERNEL
= g_quark_from_string("kernel");
2140 LTT_FACILITY_PROCESS
= g_quark_from_string("process");
2141 LTT_FACILITY_FS
= g_quark_from_string("fs");
2144 LTT_EVENT_SYSCALL_ENTRY
= g_quark_from_string("syscall_entry");
2145 LTT_EVENT_SYSCALL_EXIT
= g_quark_from_string("syscall_exit");
2146 LTT_EVENT_TRAP_ENTRY
= g_quark_from_string("trap_entry");
2147 LTT_EVENT_TRAP_EXIT
= g_quark_from_string("trap_exit");
2148 LTT_EVENT_IRQ_ENTRY
= g_quark_from_string("irq_entry");
2149 LTT_EVENT_IRQ_EXIT
= g_quark_from_string("irq_exit");
2150 LTT_EVENT_SCHEDCHANGE
= g_quark_from_string("schedchange");
2151 LTT_EVENT_FORK
= g_quark_from_string("fork");
2152 LTT_EVENT_EXIT
= g_quark_from_string("exit");
2153 LTT_EVENT_FREE
= g_quark_from_string("free");
2154 LTT_EVENT_EXEC
= g_quark_from_string("exec");
2157 LTT_FIELD_SYSCALL_ID
= g_quark_from_string("syscall_id");
2158 LTT_FIELD_TRAP_ID
= g_quark_from_string("trap_id");
2159 LTT_FIELD_IRQ_ID
= g_quark_from_string("irq_id");
2160 LTT_FIELD_OUT
= g_quark_from_string("out");
2161 LTT_FIELD_IN
= g_quark_from_string("in");
2162 LTT_FIELD_OUT_STATE
= g_quark_from_string("out_state");
2163 LTT_FIELD_PARENT_PID
= g_quark_from_string("parent_pid");
2164 LTT_FIELD_CHILD_PID
= g_quark_from_string("child_pid");
2165 LTT_FIELD_PID
= g_quark_from_string("pid");
2166 LTT_FIELD_FILENAME
= g_quark_from_string("filename");
2170 static void module_destroy()
2175 LTTV_MODULE("state", "State computation", \
2176 "Update the system state, possibly saving it at intervals", \
2177 module_init
, module_destroy
)