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
);
591 g_assert(ltt_tracefile_seek_position(tfc
->tf
, ep
) == 0);
592 tfc
->timestamp
= ltt_event_time(ltt_tracefile_get_event(tfc
->tf
));
593 g_assert(ltt_time_compare(tfc
->timestamp
, ltt_time_infinite
) != 0);
594 g_tree_insert(tsc
->pqueue
, tfc
, tfc
);
595 g_info("Restoring state for a tf at time %lu.%lu", tfc
->timestamp
.tv_sec
, tfc
->timestamp
.tv_nsec
);
597 tfc
->timestamp
= ltt_time_infinite
;
603 static void state_saved_free(LttvTraceState
*self
, LttvAttribute
*container
)
605 guint i
, nb_tracefile
, nb_cpus
;
607 LttvTracefileState
*tfcs
;
609 LttvAttribute
*tracefiles_tree
, *tracefile_tree
;
611 guint
*running_process
;
613 LttvAttributeType type
;
615 LttvAttributeValue value
;
617 LttvAttributeName name
;
619 LttEventPosition
*ep
;
621 tracefiles_tree
= lttv_attribute_find_subdir(container
,
622 LTTV_STATE_TRACEFILES
);
623 g_object_ref(G_OBJECT(tracefiles_tree
));
624 lttv_attribute_remove_by_name(container
, LTTV_STATE_TRACEFILES
);
626 type
= lttv_attribute_get_by_name(container
, LTTV_STATE_PROCESSES
,
628 g_assert(type
== LTTV_POINTER
);
629 lttv_state_free_process_table(*(value
.v_pointer
));
630 *(value
.v_pointer
) = NULL
;
631 lttv_attribute_remove_by_name(container
, LTTV_STATE_PROCESSES
);
633 /* Free running processes array */
634 nb_cpus
= ltt_trace_get_num_cpu(self
->parent
.t
);
635 type
= lttv_attribute_get_by_name(container
, LTTV_STATE_RUNNING_PROCESS
,
637 g_assert(type
== LTTV_POINTER
);
638 running_process
= *(value
.v_pointer
);
639 g_free(running_process
);
641 nb_tracefile
= self
->parent
.tracefiles
->len
;
643 for(i
= 0 ; i
< nb_tracefile
; i
++) {
645 LTTV_TRACEFILE_STATE(g_array_index(self
->parent
.tracefiles
,
646 LttvTracefileContext
*, i
));
647 type
= lttv_attribute_get(tracefiles_tree
, i
, &name
, &value
);
648 g_assert(type
== LTTV_GOBJECT
);
649 tracefile_tree
= *((LttvAttribute
**)(value
.v_gobject
));
651 type
= lttv_attribute_get_by_name(tracefile_tree
, LTTV_STATE_EVENT
,
653 g_assert(type
== LTTV_POINTER
);
654 if(*(value
.v_pointer
) != NULL
) g_free(*(value
.v_pointer
));
656 g_object_unref(G_OBJECT(tracefiles_tree
));
660 static void free_saved_state(LttvTraceState
*self
)
664 LttvAttributeType type
;
666 LttvAttributeValue value
;
668 LttvAttributeName name
;
670 LttvAttribute
*saved_states
;
672 saved_states
= lttv_attribute_find_subdir(self
->parent
.t_a
,
673 LTTV_STATE_SAVED_STATES
);
675 nb
= lttv_attribute_get_number(saved_states
);
676 for(i
= 0 ; i
< nb
; i
++) {
677 type
= lttv_attribute_get(saved_states
, i
, &name
, &value
);
678 g_assert(type
== LTTV_GOBJECT
);
679 state_saved_free(self
, *((LttvAttribute
**)value
.v_gobject
));
682 lttv_attribute_remove_by_name(self
->parent
.t_a
, LTTV_STATE_SAVED_STATES
);
687 create_max_time(LttvTraceState
*tcs
)
689 LttvAttributeValue v
;
691 lttv_attribute_find(tcs
->parent
.t_a
, LTTV_STATE_SAVED_STATES_TIME
,
693 g_assert(*(v
.v_pointer
) == NULL
);
694 *(v
.v_pointer
) = g_new(LttTime
,1);
695 *((LttTime
*)*(v
.v_pointer
)) = ltt_time_zero
;
700 get_max_time(LttvTraceState
*tcs
)
702 LttvAttributeValue v
;
704 lttv_attribute_find(tcs
->parent
.t_a
, LTTV_STATE_SAVED_STATES_TIME
,
706 g_assert(*(v
.v_pointer
) != NULL
);
707 tcs
->max_time_state_recomputed_in_seek
= (LttTime
*)*(v
.v_pointer
);
712 free_max_time(LttvTraceState
*tcs
)
714 LttvAttributeValue v
;
716 lttv_attribute_find(tcs
->parent
.t_a
, LTTV_STATE_SAVED_STATES_TIME
,
718 g_free(*(v
.v_pointer
));
719 *(v
.v_pointer
) = NULL
;
723 typedef struct _LttvNameTables
{
724 // FIXME GQuark *eventtype_names;
725 GQuark
*syscall_names
;
732 create_name_tables(LttvTraceState
*tcs
)
736 GQuark f_name
, e_name
;
740 LttvTraceHookByFacility
*thf
;
746 GString
*fe_name
= g_string_new("");
748 LttvNameTables
*name_tables
= g_new(LttvNameTables
, 1);
750 LttvAttributeValue v
;
752 lttv_attribute_find(tcs
->parent
.t_a
, LTTV_STATE_NAME_TABLES
,
754 g_assert(*(v
.v_pointer
) == NULL
);
755 *(v
.v_pointer
) = name_tables
;
756 #if 0 // Use iteration over the facilities_by_name and then list all event
757 // types of each facility
758 nb
= ltt_trace_eventtype_number(tcs
->parent
.t
);
759 name_tables
->eventtype_names
= g_new(GQuark
, nb
);
760 for(i
= 0 ; i
< nb
; i
++) {
761 et
= ltt_trace_eventtype_get(tcs
->parent
.t
, i
);
762 e_name
= ltt_eventtype_name(et
);
763 f_name
= ltt_facility_name(ltt_eventtype_facility(et
));
764 g_string_printf(fe_name
, "%s.%s", f_name
, e_name
);
765 name_tables
->eventtype_names
[i
] = g_quark_from_string(fe_name
->str
);
768 if(lttv_trace_find_hook(tcs
->parent
.t
,
769 LTT_FACILITY_KERNEL
, LTT_EVENT_SYSCALL_ENTRY
,
770 LTT_FIELD_SYSCALL_ID
, 0, 0,
774 thf
= lttv_trace_hook_get_first(&h
);
776 t
= ltt_field_type(thf
->f1
);
777 nb
= ltt_type_element_number(t
);
779 lttv_trace_hook_destroy(&h
);
781 /* CHECK syscalls should be an enum but currently are not!
782 name_tables->syscall_names = g_new(GQuark, nb);
784 for(i = 0 ; i < nb ; i++) {
785 name_tables->syscall_names[i] = g_quark_from_string(
786 ltt_enum_string_get(t, i));
790 name_tables
->syscall_names
= g_new(GQuark
, 256);
791 for(i
= 0 ; i
< 256 ; i
++) {
792 g_string_printf(fe_name
, "syscall %d", i
);
793 name_tables
->syscall_names
[i
] = g_quark_from_string(fe_name
->str
);
796 if(lttv_trace_find_hook(tcs
->parent
.t
, LTT_FACILITY_KERNEL
,
797 LTT_EVENT_TRAP_ENTRY
,
798 LTT_FIELD_TRAP_ID
, 0, 0,
802 thf
= lttv_trace_hook_get_first(&h
);
804 t
= ltt_field_type(thf
->f1
);
805 nb
= ltt_type_element_number(t
);
807 lttv_trace_hook_destroy(&h
);
810 name_tables->trap_names = g_new(GQuark, nb);
811 for(i = 0 ; i < nb ; i++) {
812 name_tables->trap_names[i] = g_quark_from_string(
813 ltt_enum_string_get(t, i));
817 name_tables
->trap_names
= g_new(GQuark
, 256);
818 for(i
= 0 ; i
< 256 ; i
++) {
819 g_string_printf(fe_name
, "trap %d", i
);
820 name_tables
->trap_names
[i
] = g_quark_from_string(fe_name
->str
);
823 if(lttv_trace_find_hook(tcs
->parent
.t
,
824 LTT_FACILITY_KERNEL
, LTT_EVENT_IRQ_ENTRY
,
825 LTT_FIELD_IRQ_ID
, 0, 0,
829 thf
= lttv_trace_hook_get_first(&h
);
831 t
= ltt_field_type(thf
->f1
);
832 nb
= ltt_type_element_number(t
);
834 lttv_trace_hook_destroy(&h
);
837 name_tables->irq_names = g_new(GQuark, nb);
838 for(i = 0 ; i < nb ; i++) {
839 name_tables->irq_names[i] = g_quark_from_string(ltt_enum_string_get(t, i));
843 name_tables
->irq_names
= g_new(GQuark
, 256);
844 for(i
= 0 ; i
< 256 ; i
++) {
845 g_string_printf(fe_name
, "irq %d", i
);
846 name_tables
->irq_names
[i
] = g_quark_from_string(fe_name
->str
);
849 g_string_free(fe_name
, TRUE
);
854 get_name_tables(LttvTraceState
*tcs
)
856 LttvNameTables
*name_tables
;
858 LttvAttributeValue v
;
860 lttv_attribute_find(tcs
->parent
.t_a
, LTTV_STATE_NAME_TABLES
,
862 g_assert(*(v
.v_pointer
) != NULL
);
863 name_tables
= (LttvNameTables
*)*(v
.v_pointer
);
864 //tcs->eventtype_names = name_tables->eventtype_names;
865 tcs
->syscall_names
= name_tables
->syscall_names
;
866 tcs
->trap_names
= name_tables
->trap_names
;
867 tcs
->irq_names
= name_tables
->irq_names
;
872 free_name_tables(LttvTraceState
*tcs
)
874 LttvNameTables
*name_tables
;
876 LttvAttributeValue v
;
878 lttv_attribute_find(tcs
->parent
.t_a
, LTTV_STATE_NAME_TABLES
,
880 name_tables
= (LttvNameTables
*)*(v
.v_pointer
);
881 *(v
.v_pointer
) = NULL
;
883 // g_free(name_tables->eventtype_names);
884 g_free(name_tables
->syscall_names
);
885 g_free(name_tables
->trap_names
);
886 g_free(name_tables
->irq_names
);
890 static void push_state(LttvTracefileState
*tfs
, LttvExecutionMode t
,
893 LttvExecutionState
*es
;
895 guint cpu
= ltt_tracefile_num(tfs
->parent
.tf
);
896 LttvTraceState
*ts
= (LttvTraceState
*)tfs
->parent
.t_context
;
897 LttvProcessState
*process
= ts
->running_process
[cpu
];
899 guint depth
= process
->execution_stack
->len
;
901 process
->execution_stack
=
902 g_array_set_size(process
->execution_stack
, depth
+ 1);
905 &g_array_index(process
->execution_stack
, LttvExecutionState
, depth
- 1);
907 es
= &g_array_index(process
->execution_stack
, LttvExecutionState
, depth
);
910 es
->entry
= es
->change
= tfs
->parent
.timestamp
;
911 es
->s
= process
->state
->s
;
916 static void pop_state(LttvTracefileState
*tfs
, LttvExecutionMode t
)
918 guint cpu
= ltt_tracefile_num(tfs
->parent
.tf
);
919 LttvTraceState
*ts
= (LttvTraceState
*)tfs
->parent
.t_context
;
920 LttvProcessState
*process
= ts
->running_process
[cpu
];
922 guint depth
= process
->execution_stack
->len
;
924 if(process
->state
->t
!= t
){
925 g_info("Different execution mode type (%lu.%09lu): ignore it\n",
926 tfs
->parent
.timestamp
.tv_sec
, tfs
->parent
.timestamp
.tv_nsec
);
927 g_info("process state has %s when pop_int is %s\n",
928 g_quark_to_string(process
->state
->t
),
929 g_quark_to_string(t
));
930 g_info("{ %u, %u, %s, %s }\n",
933 g_quark_to_string(process
->name
),
934 g_quark_to_string(process
->state
->s
));
939 g_info("Trying to pop last state on stack (%lu.%09lu): ignore it\n",
940 tfs
->parent
.timestamp
.tv_sec
, tfs
->parent
.timestamp
.tv_nsec
);
944 process
->execution_stack
=
945 g_array_set_size(process
->execution_stack
, depth
- 1);
946 process
->state
= &g_array_index(process
->execution_stack
, LttvExecutionState
,
948 process
->state
->change
= tfs
->parent
.timestamp
;
953 lttv_state_create_process(LttvTraceState
*tcs
, LttvProcessState
*parent
,
954 guint cpu
, guint pid
, const LttTime
*timestamp
)
956 LttvProcessState
*process
= g_new(LttvProcessState
, 1);
958 LttvExecutionState
*es
;
960 LttvTraceContext
*tc
= (LttvTraceContext
*)tcs
;
966 //process->last_cpu = tfs->cpu_name;
967 //process->last_cpu_index = ltt_tracefile_num(((LttvTracefileContext*)tfs)->tf);
968 g_info("Process %u, core %p", process
->pid
, process
);
969 g_hash_table_insert(tcs
->processes
, process
, process
);
972 process
->ppid
= parent
->pid
;
973 process
->name
= parent
->name
;
974 process
->creation_time
= *timestamp
;
977 /* No parent. This process exists but we are missing all information about
978 its creation. The birth time is set to zero but we remember the time of
983 process
->name
= LTTV_STATE_UNNAMED
;
984 process
->creation_time
= ltt_time_zero
;
987 process
->insertion_time
= *timestamp
;
988 sprintf(buffer
,"%d-%lu.%lu",pid
, process
->creation_time
.tv_sec
,
989 process
->creation_time
.tv_nsec
);
990 process
->pid_time
= g_quark_from_string(buffer
);
992 //process->last_cpu = tfs->cpu_name;
993 //process->last_cpu_index = ltt_tracefile_num(((LttvTracefileContext*)tfs)->tf);
994 process
->execution_stack
= g_array_sized_new(FALSE
, FALSE
,
995 sizeof(LttvExecutionState
), PREALLOCATED_EXECUTION_STACK
);
996 process
->execution_stack
= g_array_set_size(process
->execution_stack
, 1);
997 es
= process
->state
= &g_array_index(process
->execution_stack
,
998 LttvExecutionState
, 0);
999 es
->t
= LTTV_STATE_USER_MODE
;
1000 es
->n
= LTTV_STATE_SUBMODE_NONE
;
1001 es
->entry
= *timestamp
;
1002 //g_assert(timestamp->tv_sec != 0);
1003 es
->change
= *timestamp
;
1004 es
->s
= LTTV_STATE_WAIT_FORK
;
1009 LttvProcessState
*lttv_state_find_process(LttvTraceState
*ts
, guint cpu
,
1012 LttvProcessState key
;
1013 LttvProcessState
*process
;
1017 process
= g_hash_table_lookup(ts
->processes
, &key
);
1022 lttv_state_find_process_or_create(LttvTraceState
*ts
, guint cpu
, guint pid
,
1025 LttvProcessState
*process
= lttv_state_find_process(ts
, cpu
, pid
);
1027 /* Put ltt_time_zero creation time for unexisting processes */
1028 if(unlikely(process
== NULL
)) process
= lttv_state_create_process(ts
,
1029 NULL
, cpu
, pid
, timestamp
);
1033 /* FIXME : this function should be called when we receive an event telling that
1034 * release_task has been called in the kernel. In happens generally when
1035 * the parent waits for its child terminaison, but may also happen in special
1036 * cases in the child's exit : when the parent ignores its children SIGCCHLD or
1037 * has the flag SA_NOCLDWAIT. It can also happen when the child is part
1038 * of a killed thread ground, but isn't the leader.
1040 static void exit_process(LttvTracefileState
*tfs
, LttvProcessState
*process
)
1042 LttvTraceState
*ts
= LTTV_TRACE_STATE(tfs
->parent
.t_context
);
1043 LttvProcessState key
;
1045 key
.pid
= process
->pid
;
1046 key
.cpu
= process
->cpu
;
1047 g_hash_table_remove(ts
->processes
, &key
);
1048 g_array_free(process
->execution_stack
, TRUE
);
1053 static void free_process_state(gpointer key
, gpointer value
,gpointer user_data
)
1055 g_array_free(((LttvProcessState
*)value
)->execution_stack
, TRUE
);
1060 static void lttv_state_free_process_table(GHashTable
*processes
)
1062 g_hash_table_foreach(processes
, free_process_state
, NULL
);
1063 g_hash_table_destroy(processes
);
1067 static gboolean
syscall_entry(void *hook_data
, void *call_data
)
1069 LttvTracefileState
*s
= (LttvTracefileState
*)call_data
;
1070 LttEvent
*e
= ltt_tracefile_get_event(s
->parent
.tf
);
1071 LttvTraceHookByFacility
*thf
= (LttvTraceHookByFacility
*)hook_data
;
1072 LttField
*f
= thf
->f1
;
1074 LttvExecutionSubmode submode
;
1076 submode
= ((LttvTraceState
*)(s
->parent
.t_context
))->syscall_names
[
1077 ltt_event_get_unsigned(e
, f
)];
1078 push_state(s
, LTTV_STATE_SYSCALL
, submode
);
1083 static gboolean
syscall_exit(void *hook_data
, void *call_data
)
1085 LttvTracefileState
*s
= (LttvTracefileState
*)call_data
;
1087 pop_state(s
, LTTV_STATE_SYSCALL
);
1092 static gboolean
trap_entry(void *hook_data
, void *call_data
)
1094 LttvTracefileState
*s
= (LttvTracefileState
*)call_data
;
1095 LttEvent
*e
= ltt_tracefile_get_event(s
->parent
.tf
);
1096 LttvTraceHookByFacility
*thf
= (LttvTraceHookByFacility
*)hook_data
;
1097 LttField
*f
= thf
->f1
;
1099 LttvExecutionSubmode submode
;
1101 submode
= ((LttvTraceState
*)(s
->parent
.t_context
))->trap_names
[
1102 ltt_event_get_unsigned(e
, f
)];
1103 push_state(s
, LTTV_STATE_TRAP
, submode
);
1108 static gboolean
trap_exit(void *hook_data
, void *call_data
)
1110 LttvTracefileState
*s
= (LttvTracefileState
*)call_data
;
1112 pop_state(s
, LTTV_STATE_TRAP
);
1117 static gboolean
irq_entry(void *hook_data
, void *call_data
)
1119 LttvTracefileState
*s
= (LttvTracefileState
*)call_data
;
1120 LttEvent
*e
= ltt_tracefile_get_event(s
->parent
.tf
);
1121 guint8 fac_id
= ltt_event_facility_id(e
);
1122 guint8 ev_id
= ltt_event_eventtype_id(e
);
1123 LttvTraceHookByFacility
*thf
= (LttvTraceHookByFacility
*)hook_data
;
1124 // g_assert(lttv_trace_hook_get_first((LttvTraceHook *)hook_data)->f1 != NULL);
1125 g_assert(thf
->f1
!= NULL
);
1126 // g_assert(thf == lttv_trace_hook_get_first((LttvTraceHook *)hook_data));
1127 LttField
*f
= thf
->f1
;
1129 LttvExecutionSubmode submode
;
1131 submode
= ((LttvTraceState
*)(s
->parent
.t_context
))->irq_names
[
1132 ltt_event_get_unsigned(e
, f
)];
1134 /* Do something with the info about being in user or system mode when int? */
1135 push_state(s
, LTTV_STATE_IRQ
, submode
);
1140 static gboolean
irq_exit(void *hook_data
, void *call_data
)
1142 LttvTracefileState
*s
= (LttvTracefileState
*)call_data
;
1144 pop_state(s
, LTTV_STATE_IRQ
);
1149 static gboolean
schedchange(void *hook_data
, void *call_data
)
1151 LttvTracefileState
*s
= (LttvTracefileState
*)call_data
;
1152 guint cpu
= ltt_tracefile_num(s
->parent
.tf
);
1153 LttvTraceState
*ts
= (LttvTraceState
*)s
->parent
.t_context
;
1154 LttvProcessState
*process
= ts
->running_process
[cpu
];
1156 LttEvent
*e
= ltt_tracefile_get_event(s
->parent
.tf
);
1157 LttvTraceHookByFacility
*thf
= (LttvTraceHookByFacility
*)hook_data
;
1158 guint pid_in
, pid_out
;
1161 pid_out
= ltt_event_get_unsigned(e
, thf
->f1
);
1162 pid_in
= ltt_event_get_unsigned(e
, thf
->f2
);
1163 state_out
= ltt_event_get_int(e
, thf
->f3
);
1165 if(likely(process
!= NULL
)) {
1167 /* We could not know but it was not the idle process executing.
1168 This should only happen at the beginning, before the first schedule
1169 event, and when the initial information (current process for each CPU)
1170 is missing. It is not obvious how we could, after the fact, compensate
1171 the wrongly attributed statistics. */
1173 //This test only makes sense once the state is known and if there is no
1175 //if(unlikely(process->pid != pid_out)) {
1176 // g_assert(process->pid == 0);
1179 if(unlikely(process
->state
->s
== LTTV_STATE_EXIT
)) {
1180 process
->state
->s
= LTTV_STATE_ZOMBIE
;
1182 if(unlikely(state_out
== 0)) process
->state
->s
= LTTV_STATE_WAIT_CPU
;
1183 else process
->state
->s
= LTTV_STATE_WAIT
;
1184 } /* FIXME : we do not remove process here, because the kernel
1185 * still has them : they may be zombies. We need to know
1186 * exactly when release_task is executed on the PID to
1187 * know when the zombie is destroyed.
1190 // exit_process(s, process);
1192 process
->state
->change
= s
->parent
.timestamp
;
1194 process
= ts
->running_process
[cpu
] =
1195 lttv_state_find_process_or_create(
1196 (LttvTraceState
*)s
->parent
.t_context
,
1198 &s
->parent
.timestamp
);
1199 process
->state
->s
= LTTV_STATE_RUN
;
1201 // process->last_cpu_index = ltt_tracefile_num(((LttvTracefileContext*)s)->tf);
1202 process
->state
->change
= s
->parent
.timestamp
;
1206 static gboolean
process_fork(void *hook_data
, void *call_data
)
1208 LttvTracefileState
*s
= (LttvTracefileState
*)call_data
;
1209 LttEvent
*e
= ltt_tracefile_get_event(s
->parent
.tf
);
1210 LttvTraceHookByFacility
*thf
= (LttvTraceHookByFacility
*)hook_data
;
1214 LttvProcessState
*zombie_process
;
1215 guint cpu
= ltt_tracefile_num(s
->parent
.tf
);
1216 LttvTraceState
*ts
= (LttvTraceState
*)s
->parent
.t_context
;
1217 LttvProcessState
*process
= ts
->running_process
[cpu
];
1221 parent_pid
= ltt_event_get_unsigned(e
, f
);
1225 child_pid
= ltt_event_get_unsigned(e
, f
);
1227 zombie_process
= lttv_state_find_process(ts
, ANY_CPU
, child_pid
);
1229 if(unlikely(zombie_process
!= NULL
)) {
1230 /* Reutilisation of PID. Only now we are sure that the old PID
1231 * has been released. FIXME : should know when release_task happens instead.
1233 exit_process(s
, zombie_process
);
1235 g_assert(process
->pid
!= child_pid
);
1236 // FIXME : Add this test in the "known state" section
1237 // g_assert(process->pid == parent_pid);
1238 lttv_state_create_process(ts
, process
, cpu
, child_pid
, &s
->parent
.timestamp
);
1244 static gboolean
process_exit(void *hook_data
, void *call_data
)
1246 LttvTracefileState
*s
= (LttvTracefileState
*)call_data
;
1247 LttEvent
*e
= ltt_tracefile_get_event(s
->parent
.tf
);
1248 LttvTraceHookByFacility
*thf
= (LttvTraceHookByFacility
*)hook_data
;
1251 guint cpu
= ltt_tracefile_num(s
->parent
.tf
);
1252 LttvTraceState
*ts
= (LttvTraceState
*)s
->parent
.t_context
;
1253 LttvProcessState
*process
= ts
->running_process
[cpu
];
1255 pid
= ltt_event_get_unsigned(e
, thf
->f1
);
1257 // FIXME : Add this test in the "known state" section
1258 // g_assert(process->pid == pid);
1260 if(likely(process
!= NULL
)) {
1261 process
->state
->s
= LTTV_STATE_EXIT
;
1266 static gboolean
process_free(void *hook_data
, void *call_data
)
1268 LttvTracefileState
*s
= (LttvTracefileState
*)call_data
;
1269 LttvTraceState
*ts
= (LttvTraceState
*)s
->parent
.t_context
;
1270 LttEvent
*e
= ltt_tracefile_get_event(s
->parent
.tf
);
1271 LttvTraceHookByFacility
*thf
= (LttvTraceHookByFacility
*)hook_data
;
1273 LttvProcessState
*process
;
1275 /* PID of the process to release */
1276 release_pid
= ltt_event_get_unsigned(e
, thf
->f1
);
1278 process
= lttv_state_find_process(ts
, ANY_CPU
, release_pid
);
1280 if(likely(process
!= NULL
)) {
1281 /* release_task is happening at kernel level : we can now safely release
1282 * the data structure of the process */
1283 guint num_cpus
= ltt_trace_get_num_cpu(ts
->parent
.t
);
1285 for(i
=0; i
< num_cpus
; i
++) {
1286 g_assert(process
!= ts
->running_process
[i
]);
1288 exit_process(s
, process
);
1295 static gboolean
process_exec(void *hook_data
, void *call_data
)
1297 LttvTracefileState
*s
= (LttvTracefileState
*)call_data
;
1298 LttvTraceState
*ts
= (LttvTraceState
*)s
->parent
.t_context
;
1299 LttEvent
*e
= ltt_tracefile_get_event(s
->parent
.tf
);
1300 LttvTraceHookByFacility
*thf
= (LttvTraceHookByFacility
*)hook_data
;
1302 guint cpu
= ltt_tracefile_num(s
->parent
.tf
);
1303 LttvProcessState
*process
= ts
->running_process
[cpu
];
1305 /* PID of the process to release */
1306 name
= ltt_event_get_string(e
, thf
->f1
);
1308 process
->name
= g_quark_from_string(name
);
1316 gint
lttv_state_hook_add_event_hooks(void *hook_data
, void *call_data
)
1318 LttvTracesetState
*tss
= (LttvTracesetState
*)(call_data
);
1320 lttv_state_add_event_hooks(tss
);
1325 void lttv_state_add_event_hooks(LttvTracesetState
*self
)
1327 LttvTraceset
*traceset
= self
->parent
.ts
;
1329 guint i
, j
, k
, l
, nb_trace
, nb_tracefile
;
1333 LttvTracefileState
*tfs
;
1337 LttvTraceHookByFacility
*thf
;
1339 LttvTraceHook
*hook
;
1341 LttvAttributeValue val
;
1345 nb_trace
= lttv_traceset_number(traceset
);
1346 for(i
= 0 ; i
< nb_trace
; i
++) {
1347 ts
= (LttvTraceState
*)self
->parent
.traces
[i
];
1349 /* Find the eventtype id for the following events and register the
1350 associated by id hooks. */
1352 hooks
= g_array_sized_new(FALSE
, FALSE
, sizeof(LttvTraceHook
), 11);
1353 hooks
= g_array_set_size(hooks
, 11);
1355 ret
= lttv_trace_find_hook(ts
->parent
.t
,
1356 LTT_FACILITY_KERNEL
, LTT_EVENT_SYSCALL_ENTRY
,
1357 LTT_FIELD_SYSCALL_ID
, 0, 0,
1358 syscall_entry
, NULL
, &g_array_index(hooks
, LttvTraceHook
, 0));
1361 ret
= lttv_trace_find_hook(ts
->parent
.t
,
1362 LTT_FACILITY_KERNEL
, LTT_EVENT_SYSCALL_EXIT
,
1364 syscall_exit
, NULL
, &g_array_index(hooks
, LttvTraceHook
, 1));
1367 ret
= lttv_trace_find_hook(ts
->parent
.t
,
1368 LTT_FACILITY_KERNEL
, LTT_EVENT_TRAP_ENTRY
,
1369 LTT_FIELD_TRAP_ID
, 0, 0,
1370 trap_entry
, NULL
, &g_array_index(hooks
, LttvTraceHook
, 2));
1373 ret
= lttv_trace_find_hook(ts
->parent
.t
,
1374 LTT_FACILITY_KERNEL
, LTT_EVENT_TRAP_EXIT
,
1376 trap_exit
, NULL
, &g_array_index(hooks
, LttvTraceHook
, 3));
1379 ret
= lttv_trace_find_hook(ts
->parent
.t
,
1380 LTT_FACILITY_KERNEL
, LTT_EVENT_IRQ_ENTRY
,
1381 LTT_FIELD_IRQ_ID
, 0, 0,
1382 irq_entry
, NULL
, &g_array_index(hooks
, LttvTraceHook
, 4));
1385 ret
= lttv_trace_find_hook(ts
->parent
.t
,
1386 LTT_FACILITY_KERNEL
, LTT_EVENT_IRQ_EXIT
,
1388 irq_exit
, NULL
, &g_array_index(hooks
, LttvTraceHook
, 5));
1391 ret
= lttv_trace_find_hook(ts
->parent
.t
,
1392 LTT_FACILITY_PROCESS
, LTT_EVENT_SCHEDCHANGE
,
1393 LTT_FIELD_OUT
, LTT_FIELD_IN
, LTT_FIELD_OUT_STATE
,
1394 schedchange
, NULL
, &g_array_index(hooks
, LttvTraceHook
, 6));
1397 ret
= lttv_trace_find_hook(ts
->parent
.t
,
1398 LTT_FACILITY_PROCESS
, LTT_EVENT_FORK
,
1399 LTT_FIELD_PARENT_PID
, LTT_FIELD_CHILD_PID
, 0,
1400 process_fork
, NULL
, &g_array_index(hooks
, LttvTraceHook
, 7));
1403 ret
= lttv_trace_find_hook(ts
->parent
.t
,
1404 LTT_FACILITY_PROCESS
, LTT_EVENT_EXIT
,
1405 LTT_FIELD_PID
, 0, 0,
1406 process_exit
, NULL
, &g_array_index(hooks
, LttvTraceHook
, 8));
1409 ret
= lttv_trace_find_hook(ts
->parent
.t
,
1410 LTT_FACILITY_PROCESS
, LTT_EVENT_FREE
,
1411 LTT_FIELD_PID
, 0, 0,
1412 process_free
, NULL
, &g_array_index(hooks
, LttvTraceHook
, 9));
1415 ret
= lttv_trace_find_hook(ts
->parent
.t
,
1416 LTT_FACILITY_FS
, LTT_EVENT_EXEC
,
1417 LTT_FIELD_FILENAME
, 0, 0,
1418 process_exec
, NULL
, &g_array_index(hooks
, LttvTraceHook
, 10));
1423 /* Add these hooks to each event_by_id hooks list */
1425 nb_tracefile
= ts
->parent
.tracefiles
->len
;
1427 for(j
= 0 ; j
< nb_tracefile
; j
++) {
1429 LTTV_TRACEFILE_STATE(g_array_index(ts
->parent
.tracefiles
,
1430 LttvTracefileContext
*, j
));
1432 for(k
= 0 ; k
< hooks
->len
; k
++) {
1433 hook
= &g_array_index(hooks
, LttvTraceHook
, k
);
1434 for(l
=0;l
<hook
->fac_list
->len
;l
++) {
1435 thf
= g_array_index(hook
->fac_list
, LttvTraceHookByFacility
*, l
);
1437 lttv_hooks_by_id_find(tfs
->parent
.event_by_id
, thf
->id
),
1444 lttv_attribute_find(self
->parent
.a
, LTTV_STATE_HOOKS
, LTTV_POINTER
, &val
);
1445 *(val
.v_pointer
) = hooks
;
1449 gint
lttv_state_hook_remove_event_hooks(void *hook_data
, void *call_data
)
1451 LttvTracesetState
*tss
= (LttvTracesetState
*)(call_data
);
1453 lttv_state_remove_event_hooks(tss
);
1458 void lttv_state_remove_event_hooks(LttvTracesetState
*self
)
1460 LttvTraceset
*traceset
= self
->parent
.ts
;
1462 guint i
, j
, k
, l
, nb_trace
, nb_tracefile
;
1466 LttvTracefileState
*tfs
;
1470 LttvTraceHook
*hook
;
1472 LttvTraceHookByFacility
*thf
;
1474 LttvAttributeValue val
;
1476 nb_trace
= lttv_traceset_number(traceset
);
1477 for(i
= 0 ; i
< nb_trace
; i
++) {
1478 ts
= LTTV_TRACE_STATE(self
->parent
.traces
[i
]);
1479 lttv_attribute_find(self
->parent
.a
, LTTV_STATE_HOOKS
, LTTV_POINTER
, &val
);
1480 hooks
= *(val
.v_pointer
);
1482 /* Remove these hooks from each event_by_id hooks list */
1484 nb_tracefile
= ts
->parent
.tracefiles
->len
;
1486 for(j
= 0 ; j
< nb_tracefile
; j
++) {
1488 LTTV_TRACEFILE_STATE(g_array_index(ts
->parent
.tracefiles
,
1489 LttvTracefileContext
*, j
));
1491 for(k
= 0 ; k
< hooks
->len
; k
++) {
1492 hook
= &g_array_index(hooks
, LttvTraceHook
, k
);
1493 for(l
=0;l
<hook
->fac_list
->len
;l
++) {
1494 thf
= g_array_index(hook
->fac_list
, LttvTraceHookByFacility
*, l
);
1496 lttv_hooks_remove_data(
1497 lttv_hooks_by_id_find(tfs
->parent
.event_by_id
, thf
->id
),
1503 for(k
= 0 ; k
< hooks
->len
; k
++)
1504 lttv_trace_hook_destroy(&g_array_index(hooks
, LttvTraceHook
, k
));
1505 g_array_free(hooks
, TRUE
);
1509 static gboolean
state_save_event_hook(void *hook_data
, void *call_data
)
1511 guint
*event_count
= (guint
*)hook_data
;
1513 /* Only save at LTTV_STATE_SAVE_INTERVAL */
1514 if(likely((*event_count
)++ < LTTV_STATE_SAVE_INTERVAL
))
1519 LttvTracefileState
*self
= (LttvTracefileState
*)call_data
;
1521 LttvTracefileState
*tfcs
;
1523 LttvTraceState
*tcs
= (LttvTraceState
*)(self
->parent
.t_context
);
1525 LttEventPosition
*ep
;
1531 LttvAttribute
*saved_states_tree
, *saved_state_tree
;
1533 LttvAttributeValue value
;
1535 saved_states_tree
= lttv_attribute_find_subdir(tcs
->parent
.t_a
,
1536 LTTV_STATE_SAVED_STATES
);
1537 saved_state_tree
= g_object_new(LTTV_ATTRIBUTE_TYPE
, NULL
);
1538 value
= lttv_attribute_add(saved_states_tree
,
1539 lttv_attribute_get_number(saved_states_tree
), LTTV_GOBJECT
);
1540 *(value
.v_gobject
) = (GObject
*)saved_state_tree
;
1541 value
= lttv_attribute_add(saved_state_tree
, LTTV_STATE_TIME
, LTTV_TIME
);
1542 *(value
.v_time
) = self
->parent
.timestamp
;
1543 lttv_state_save(tcs
, saved_state_tree
);
1544 g_debug("Saving state at time %lu.%lu", self
->parent
.timestamp
.tv_sec
,
1545 self
->parent
.timestamp
.tv_nsec
);
1547 *(tcs
->max_time_state_recomputed_in_seek
) = self
->parent
.timestamp
;
1553 static gboolean
block_start(void *hook_data
, void *call_data
)
1555 LttvTracefileState
*self
= (LttvTracefileState
*)call_data
;
1557 LttvTracefileState
*tfcs
;
1559 LttvTraceState
*tcs
= (LttvTraceState
*)(self
->parent
.t_context
);
1561 LttEventPosition
*ep
;
1563 guint i
, nb_block
, nb_event
, nb_tracefile
;
1567 LttvAttribute
*saved_states_tree
, *saved_state_tree
;
1569 LttvAttributeValue value
;
1571 ep
= ltt_event_position_new();
1573 nb_tracefile
= tcs
->parent
.tracefiles
->len
;
1575 /* Count the number of events added since the last block end in any
1578 for(i
= 0 ; i
< nb_tracefile
; i
++) {
1580 LTTV_TRACEFILE_STATE(&g_array_index(tcs
->parent
.tracefiles
,
1581 LttvTracefileContext
, i
));
1582 ltt_event_position(tfcs
->parent
.e
, ep
);
1583 ltt_event_position_get(ep
, &nb_block
, &nb_event
, &tf
);
1584 tcs
->nb_event
+= nb_event
- tfcs
->saved_position
;
1585 tfcs
->saved_position
= nb_event
;
1589 if(tcs
->nb_event
>= tcs
->save_interval
) {
1590 saved_states_tree
= lttv_attribute_find_subdir(tcs
->parent
.t_a
,
1591 LTTV_STATE_SAVED_STATES
);
1592 saved_state_tree
= g_object_new(LTTV_ATTRIBUTE_TYPE
, NULL
);
1593 value
= lttv_attribute_add(saved_states_tree
,
1594 lttv_attribute_get_number(saved_states_tree
), LTTV_GOBJECT
);
1595 *(value
.v_gobject
) = (GObject
*)saved_state_tree
;
1596 value
= lttv_attribute_add(saved_state_tree
, LTTV_STATE_TIME
, LTTV_TIME
);
1597 *(value
.v_time
) = self
->parent
.timestamp
;
1598 lttv_state_save(tcs
, saved_state_tree
);
1600 g_debug("Saving state at time %lu.%lu", self
->parent
.timestamp
.tv_sec
,
1601 self
->parent
.timestamp
.tv_nsec
);
1603 *(tcs
->max_time_state_recomputed_in_seek
) = self
->parent
.timestamp
;
1609 static gboolean
block_end(void *hook_data
, void *call_data
)
1611 LttvTracefileState
*self
= (LttvTracefileState
*)call_data
;
1613 LttvTraceState
*tcs
= (LttvTraceState
*)(self
->parent
.t_context
);
1617 LttEventPosition
*ep
;
1619 guint nb_block
, nb_event
;
1621 ep
= ltt_event_position_new();
1622 ltt_event_position(self
->parent
.e
, ep
);
1623 ltt_event_position_get(ep
, &nb_block
, &nb_event
, &tf
);
1624 tcs
->nb_event
+= nb_event
- self
->saved_position
+ 1;
1625 self
->saved_position
= 0;
1626 *(tcs
->max_time_state_recomputed_in_seek
) = self
->parent
.timestamp
;
1633 void lttv_state_save_add_event_hooks(LttvTracesetState
*self
)
1635 LttvTraceset
*traceset
= self
->parent
.ts
;
1637 guint i
, j
, nb_trace
, nb_tracefile
;
1641 LttvTracefileState
*tfs
;
1643 LttvTraceHook hook_start
, hook_end
;
1645 nb_trace
= lttv_traceset_number(traceset
);
1646 for(i
= 0 ; i
< nb_trace
; i
++) {
1647 ts
= (LttvTraceState
*)self
->parent
.traces
[i
];
1649 lttv_trace_find_hook(ts
->parent
.t
, "core","block_start",NULL
,
1650 NULL
, NULL
, block_start
, &hook_start
);
1651 lttv_trace_find_hook(ts
->parent
.t
, "core","block_end",NULL
,
1652 NULL
, NULL
, block_end
, &hook_end
);
1654 nb_tracefile
= ts
->parent
.tracefiles
->len
;
1656 for(j
= 0 ; j
< nb_tracefile
; j
++) {
1658 LTTV_TRACEFILE_STATE(&g_array_index(ts
->parent
.tracefiles
,
1659 LttvTracefileContext
, j
));
1660 lttv_hooks_add(lttv_hooks_by_id_find(tfs
->parent
.event_by_id
,
1661 hook_start
.id
), hook_start
.h
, NULL
, LTTV_PRIO_STATE
);
1662 lttv_hooks_add(lttv_hooks_by_id_find(tfs
->parent
.event_by_id
,
1663 hook_end
.id
), hook_end
.h
, NULL
, LTTV_PRIO_STATE
);
1669 void lttv_state_save_add_event_hooks(LttvTracesetState
*self
)
1671 LttvTraceset
*traceset
= self
->parent
.ts
;
1673 guint i
, j
, nb_trace
, nb_tracefile
;
1677 LttvTracefileState
*tfs
;
1680 nb_trace
= lttv_traceset_number(traceset
);
1681 for(i
= 0 ; i
< nb_trace
; i
++) {
1683 ts
= (LttvTraceState
*)self
->parent
.traces
[i
];
1684 nb_tracefile
= ts
->parent
.tracefiles
->len
;
1686 guint
*event_count
= g_new(guint
, 1);
1689 for(j
= 0 ; j
< nb_tracefile
; j
++) {
1691 LTTV_TRACEFILE_STATE(g_array_index(ts
->parent
.tracefiles
,
1692 LttvTracefileContext
*, j
));
1693 lttv_hooks_add(tfs
->parent
.event
,
1694 state_save_event_hook
,
1702 gint
lttv_state_save_hook_add_event_hooks(void *hook_data
, void *call_data
)
1704 LttvTracesetState
*tss
= (LttvTracesetState
*)(call_data
);
1706 lttv_state_save_add_event_hooks(tss
);
1713 void lttv_state_save_remove_event_hooks(LttvTracesetState
*self
)
1715 LttvTraceset
*traceset
= self
->parent
.ts
;
1717 guint i
, j
, nb_trace
, nb_tracefile
;
1721 LttvTracefileState
*tfs
;
1723 LttvTraceHook hook_start
, hook_end
;
1725 nb_trace
= lttv_traceset_number(traceset
);
1726 for(i
= 0 ; i
< nb_trace
; i
++) {
1727 ts
= LTTV_TRACE_STATE(self
->parent
.traces
[i
]);
1729 lttv_trace_find_hook(ts
->parent
.t
, "core","block_start",NULL
,
1730 NULL
, NULL
, block_start
, &hook_start
);
1732 lttv_trace_find_hook(ts
->parent
.t
, "core","block_end",NULL
,
1733 NULL
, NULL
, block_end
, &hook_end
);
1735 nb_tracefile
= ts
->parent
.tracefiles
->len
;
1737 for(j
= 0 ; j
< nb_tracefile
; j
++) {
1739 LTTV_TRACEFILE_STATE(&g_array_index(ts
->parent
.tracefiles
,
1740 LttvTracefileContext
, j
));
1741 lttv_hooks_remove_data(lttv_hooks_by_id_find(
1742 tfs
->parent
.event_by_id
, hook_start
.id
), hook_start
.h
, NULL
);
1743 lttv_hooks_remove_data(lttv_hooks_by_id_find(
1744 tfs
->parent
.event_by_id
, hook_end
.id
), hook_end
.h
, NULL
);
1750 void lttv_state_save_remove_event_hooks(LttvTracesetState
*self
)
1752 LttvTraceset
*traceset
= self
->parent
.ts
;
1754 guint i
, j
, nb_trace
, nb_tracefile
;
1758 LttvTracefileState
*tfs
;
1761 nb_trace
= lttv_traceset_number(traceset
);
1762 for(i
= 0 ; i
< nb_trace
; i
++) {
1764 ts
= (LttvTraceState
*)self
->parent
.traces
[i
];
1765 nb_tracefile
= ts
->parent
.tracefiles
->len
;
1769 for(j
= 0 ; j
< nb_tracefile
; j
++) {
1771 LTTV_TRACEFILE_STATE(g_array_index(ts
->parent
.tracefiles
,
1772 LttvTracefileContext
*, j
));
1773 event_count
= lttv_hooks_remove(tfs
->parent
.event
,
1774 state_save_event_hook
);
1777 g_free(event_count
);
1781 gint
lttv_state_save_hook_remove_event_hooks(void *hook_data
, void *call_data
)
1783 LttvTracesetState
*tss
= (LttvTracesetState
*)(call_data
);
1785 lttv_state_save_remove_event_hooks(tss
);
1790 void lttv_state_traceset_seek_time_closest(LttvTracesetState
*self
, LttTime t
)
1792 LttvTraceset
*traceset
= self
->parent
.ts
;
1796 int min_pos
, mid_pos
, max_pos
;
1798 guint call_rest
= 0;
1800 LttvTraceState
*tcs
;
1802 LttvAttributeValue value
;
1804 LttvAttributeType type
;
1806 LttvAttributeName name
;
1808 LttvAttribute
*saved_states_tree
, *saved_state_tree
, *closest_tree
;
1810 g_tree_destroy(self
->parent
.pqueue
);
1811 self
->parent
.pqueue
= g_tree_new(compare_tracefile
);
1813 g_info("Entering seek_time_closest for time %lu.%lu", t
.tv_sec
, t
.tv_nsec
);
1815 nb_trace
= lttv_traceset_number(traceset
);
1816 for(i
= 0 ; i
< nb_trace
; i
++) {
1817 tcs
= (LttvTraceState
*)self
->parent
.traces
[i
];
1819 if(ltt_time_compare(t
, *(tcs
->max_time_state_recomputed_in_seek
)) < 0) {
1820 saved_states_tree
= lttv_attribute_find_subdir(tcs
->parent
.t_a
,
1821 LTTV_STATE_SAVED_STATES
);
1824 if(saved_states_tree
) {
1825 max_pos
= lttv_attribute_get_number(saved_states_tree
) - 1;
1826 mid_pos
= max_pos
/ 2;
1827 while(min_pos
< max_pos
) {
1828 type
= lttv_attribute_get(saved_states_tree
, mid_pos
, &name
, &value
);
1829 g_assert(type
== LTTV_GOBJECT
);
1830 saved_state_tree
= *((LttvAttribute
**)(value
.v_gobject
));
1831 type
= lttv_attribute_get_by_name(saved_state_tree
, LTTV_STATE_TIME
,
1833 g_assert(type
== LTTV_TIME
);
1834 if(ltt_time_compare(*(value
.v_time
), t
) < 0) {
1836 closest_tree
= saved_state_tree
;
1838 else max_pos
= mid_pos
- 1;
1840 mid_pos
= (min_pos
+ max_pos
+ 1) / 2;
1844 /* restore the closest earlier saved state */
1846 lttv_state_restore(tcs
, closest_tree
);
1850 /* There is no saved state, yet we want to have it. Restart at T0 */
1852 restore_init_state(tcs
);
1853 lttv_process_trace_seek_time(&(tcs
->parent
), ltt_time_zero
);
1856 /* We want to seek quickly without restoring/updating the state */
1858 restore_init_state(tcs
);
1859 lttv_process_trace_seek_time(&(tcs
->parent
), t
);
1862 if(!call_rest
) g_info("NOT Calling restore");
1867 traceset_state_instance_init (GTypeInstance
*instance
, gpointer g_class
)
1873 traceset_state_finalize (LttvTracesetState
*self
)
1875 G_OBJECT_CLASS(g_type_class_peek(LTTV_TRACESET_CONTEXT_TYPE
))->
1876 finalize(G_OBJECT(self
));
1881 traceset_state_class_init (LttvTracesetContextClass
*klass
)
1883 GObjectClass
*gobject_class
= G_OBJECT_CLASS(klass
);
1885 gobject_class
->finalize
= (void (*)(GObject
*self
)) traceset_state_finalize
;
1886 klass
->init
= (void (*)(LttvTracesetContext
*self
, LttvTraceset
*ts
))init
;
1887 klass
->fini
= (void (*)(LttvTracesetContext
*self
))fini
;
1888 klass
->new_traceset_context
= new_traceset_context
;
1889 klass
->new_trace_context
= new_trace_context
;
1890 klass
->new_tracefile_context
= new_tracefile_context
;
1895 lttv_traceset_state_get_type(void)
1897 static GType type
= 0;
1899 static const GTypeInfo info
= {
1900 sizeof (LttvTracesetStateClass
),
1901 NULL
, /* base_init */
1902 NULL
, /* base_finalize */
1903 (GClassInitFunc
) traceset_state_class_init
, /* class_init */
1904 NULL
, /* class_finalize */
1905 NULL
, /* class_data */
1906 sizeof (LttvTracesetState
),
1907 0, /* n_preallocs */
1908 (GInstanceInitFunc
) traceset_state_instance_init
, /* instance_init */
1909 NULL
/* value handling */
1912 type
= g_type_register_static (LTTV_TRACESET_CONTEXT_TYPE
, "LttvTracesetStateType",
1920 trace_state_instance_init (GTypeInstance
*instance
, gpointer g_class
)
1926 trace_state_finalize (LttvTraceState
*self
)
1928 G_OBJECT_CLASS(g_type_class_peek(LTTV_TRACE_CONTEXT_TYPE
))->
1929 finalize(G_OBJECT(self
));
1934 trace_state_class_init (LttvTraceStateClass
*klass
)
1936 GObjectClass
*gobject_class
= G_OBJECT_CLASS(klass
);
1938 gobject_class
->finalize
= (void (*)(GObject
*self
)) trace_state_finalize
;
1939 klass
->state_save
= state_save
;
1940 klass
->state_restore
= state_restore
;
1941 klass
->state_saved_free
= state_saved_free
;
1946 lttv_trace_state_get_type(void)
1948 static GType type
= 0;
1950 static const GTypeInfo info
= {
1951 sizeof (LttvTraceStateClass
),
1952 NULL
, /* base_init */
1953 NULL
, /* base_finalize */
1954 (GClassInitFunc
) trace_state_class_init
, /* class_init */
1955 NULL
, /* class_finalize */
1956 NULL
, /* class_data */
1957 sizeof (LttvTraceState
),
1958 0, /* n_preallocs */
1959 (GInstanceInitFunc
) trace_state_instance_init
, /* instance_init */
1960 NULL
/* value handling */
1963 type
= g_type_register_static (LTTV_TRACE_CONTEXT_TYPE
,
1964 "LttvTraceStateType", &info
, 0);
1971 tracefile_state_instance_init (GTypeInstance
*instance
, gpointer g_class
)
1977 tracefile_state_finalize (LttvTracefileState
*self
)
1979 G_OBJECT_CLASS(g_type_class_peek(LTTV_TRACEFILE_CONTEXT_TYPE
))->
1980 finalize(G_OBJECT(self
));
1985 tracefile_state_class_init (LttvTracefileStateClass
*klass
)
1987 GObjectClass
*gobject_class
= G_OBJECT_CLASS(klass
);
1989 gobject_class
->finalize
= (void (*)(GObject
*self
)) tracefile_state_finalize
;
1994 lttv_tracefile_state_get_type(void)
1996 static GType type
= 0;
1998 static const GTypeInfo info
= {
1999 sizeof (LttvTracefileStateClass
),
2000 NULL
, /* base_init */
2001 NULL
, /* base_finalize */
2002 (GClassInitFunc
) tracefile_state_class_init
, /* class_init */
2003 NULL
, /* class_finalize */
2004 NULL
, /* class_data */
2005 sizeof (LttvTracefileState
),
2006 0, /* n_preallocs */
2007 (GInstanceInitFunc
) tracefile_state_instance_init
, /* instance_init */
2008 NULL
/* value handling */
2011 type
= g_type_register_static (LTTV_TRACEFILE_CONTEXT_TYPE
,
2012 "LttvTracefileStateType", &info
, 0);
2018 static void module_init()
2020 LTTV_STATE_UNNAMED
= g_quark_from_string("unnamed");
2021 LTTV_STATE_MODE_UNKNOWN
= g_quark_from_string("unknown execution mode");
2022 LTTV_STATE_USER_MODE
= g_quark_from_string("user mode");
2023 LTTV_STATE_WAIT_FORK
= g_quark_from_string("wait fork");
2024 LTTV_STATE_SYSCALL
= g_quark_from_string("system call");
2025 LTTV_STATE_TRAP
= g_quark_from_string("trap");
2026 LTTV_STATE_IRQ
= g_quark_from_string("irq");
2027 LTTV_STATE_SUBMODE_UNKNOWN
= g_quark_from_string("unknown submode");
2028 LTTV_STATE_SUBMODE_NONE
= g_quark_from_string("(no submode)");
2029 LTTV_STATE_WAIT_CPU
= g_quark_from_string("wait for cpu");
2030 LTTV_STATE_EXIT
= g_quark_from_string("exiting");
2031 LTTV_STATE_ZOMBIE
= g_quark_from_string("zombie");
2032 LTTV_STATE_WAIT
= g_quark_from_string("wait for I/O");
2033 LTTV_STATE_RUN
= g_quark_from_string("running");
2034 LTTV_STATE_TRACEFILES
= g_quark_from_string("tracefiles");
2035 LTTV_STATE_PROCESSES
= g_quark_from_string("processes");
2036 LTTV_STATE_PROCESS
= g_quark_from_string("process");
2037 LTTV_STATE_RUNNING_PROCESS
= g_quark_from_string("running_process");
2038 LTTV_STATE_EVENT
= g_quark_from_string("event");
2039 LTTV_STATE_SAVED_STATES
= g_quark_from_string("saved states");
2040 LTTV_STATE_SAVED_STATES_TIME
= g_quark_from_string("saved states time");
2041 LTTV_STATE_TIME
= g_quark_from_string("time");
2042 LTTV_STATE_HOOKS
= g_quark_from_string("saved state hooks");
2043 LTTV_STATE_NAME_TABLES
= g_quark_from_string("name tables");
2044 LTTV_STATE_TRACE_STATE_USE_COUNT
=
2045 g_quark_from_string("trace_state_use_count");
2048 LTT_FACILITY_KERNEL
= g_quark_from_string("kernel");
2049 LTT_FACILITY_PROCESS
= g_quark_from_string("process");
2050 LTT_FACILITY_FS
= g_quark_from_string("fs");
2053 LTT_EVENT_SYSCALL_ENTRY
= g_quark_from_string("syscall_entry");
2054 LTT_EVENT_SYSCALL_EXIT
= g_quark_from_string("syscall_exit");
2055 LTT_EVENT_TRAP_ENTRY
= g_quark_from_string("trap_entry");
2056 LTT_EVENT_TRAP_EXIT
= g_quark_from_string("trap_exit");
2057 LTT_EVENT_IRQ_ENTRY
= g_quark_from_string("irq_entry");
2058 LTT_EVENT_IRQ_EXIT
= g_quark_from_string("irq_exit");
2059 LTT_EVENT_SCHEDCHANGE
= g_quark_from_string("schedchange");
2060 LTT_EVENT_FORK
= g_quark_from_string("fork");
2061 LTT_EVENT_EXIT
= g_quark_from_string("exit");
2062 LTT_EVENT_FREE
= g_quark_from_string("free");
2063 LTT_EVENT_EXEC
= g_quark_from_string("exec");
2066 LTT_FIELD_SYSCALL_ID
= g_quark_from_string("syscall_id");
2067 LTT_FIELD_TRAP_ID
= g_quark_from_string("trap_id");
2068 LTT_FIELD_IRQ_ID
= g_quark_from_string("irq_id");
2069 LTT_FIELD_OUT
= g_quark_from_string("out");
2070 LTT_FIELD_IN
= g_quark_from_string("in");
2071 LTT_FIELD_OUT_STATE
= g_quark_from_string("out_state");
2072 LTT_FIELD_PARENT_PID
= g_quark_from_string("parent_pid");
2073 LTT_FIELD_CHILD_PID
= g_quark_from_string("child_pid");
2074 LTT_FIELD_PID
= g_quark_from_string("pid");
2075 LTT_FIELD_FILENAME
= g_quark_from_string("filename");
2079 static void module_destroy()
2084 LTTV_MODULE("state", "State computation", \
2085 "Update the system state, possibly saving it at intervals", \
2086 module_init
, module_destroy
)