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 #ifdef HASH_TABLE_DEBUG
892 static void test_process(gpointer key
, gpointer value
, gpointer user_data
)
894 LttvProcessState
*process
= (LttvProcessState
*)value
;
896 /* Test for process corruption */
897 guint stack_len
= process
->execution_stack
->len
;
900 static void hash_table_check(GHashTable
*table
)
902 g_hash_table_foreach(table
, test_process
, NULL
);
909 static void push_state(LttvTracefileState
*tfs
, LttvExecutionMode t
,
912 LttvExecutionState
*es
;
914 guint cpu
= ltt_tracefile_num(tfs
->parent
.tf
);
915 LttvTraceState
*ts
= (LttvTraceState
*)tfs
->parent
.t_context
;
917 #ifdef HASH_TABLE_DEBUG
918 hash_table_check(ts
->processes
);
920 LttvProcessState
*process
= ts
->running_process
[cpu
];
922 guint depth
= process
->execution_stack
->len
;
924 process
->execution_stack
=
925 g_array_set_size(process
->execution_stack
, depth
+ 1);
928 &g_array_index(process
->execution_stack
, LttvExecutionState
, depth
- 1);
930 es
= &g_array_index(process
->execution_stack
, LttvExecutionState
, depth
);
933 es
->entry
= es
->change
= tfs
->parent
.timestamp
;
934 es
->s
= process
->state
->s
;
939 static void pop_state(LttvTracefileState
*tfs
, LttvExecutionMode t
)
941 guint cpu
= ltt_tracefile_num(tfs
->parent
.tf
);
942 LttvTraceState
*ts
= (LttvTraceState
*)tfs
->parent
.t_context
;
943 LttvProcessState
*process
= ts
->running_process
[cpu
];
945 guint depth
= process
->execution_stack
->len
;
947 if(process
->state
->t
!= t
){
948 g_info("Different execution mode type (%lu.%09lu): ignore it\n",
949 tfs
->parent
.timestamp
.tv_sec
, tfs
->parent
.timestamp
.tv_nsec
);
950 g_info("process state has %s when pop_int is %s\n",
951 g_quark_to_string(process
->state
->t
),
952 g_quark_to_string(t
));
953 g_info("{ %u, %u, %s, %s }\n",
956 g_quark_to_string(process
->name
),
957 g_quark_to_string(process
->state
->s
));
962 g_info("Trying to pop last state on stack (%lu.%09lu): ignore it\n",
963 tfs
->parent
.timestamp
.tv_sec
, tfs
->parent
.timestamp
.tv_nsec
);
967 process
->execution_stack
=
968 g_array_set_size(process
->execution_stack
, depth
- 1);
969 process
->state
= &g_array_index(process
->execution_stack
, LttvExecutionState
,
971 process
->state
->change
= tfs
->parent
.timestamp
;
976 lttv_state_create_process(LttvTraceState
*tcs
, LttvProcessState
*parent
,
977 guint cpu
, guint pid
, const LttTime
*timestamp
)
979 LttvProcessState
*process
= g_new(LttvProcessState
, 1);
981 LttvExecutionState
*es
;
983 LttvTraceContext
*tc
= (LttvTraceContext
*)tcs
;
989 //process->last_cpu = tfs->cpu_name;
990 //process->last_cpu_index = ltt_tracefile_num(((LttvTracefileContext*)tfs)->tf);
991 g_info("Process %u, core %p", process
->pid
, process
);
992 g_hash_table_insert(tcs
->processes
, process
, process
);
995 process
->ppid
= parent
->pid
;
996 process
->name
= parent
->name
;
997 process
->creation_time
= *timestamp
;
1000 /* No parent. This process exists but we are missing all information about
1001 its creation. The birth time is set to zero but we remember the time of
1006 process
->name
= LTTV_STATE_UNNAMED
;
1007 process
->creation_time
= ltt_time_zero
;
1010 process
->insertion_time
= *timestamp
;
1011 sprintf(buffer
,"%d-%lu.%lu",pid
, process
->creation_time
.tv_sec
,
1012 process
->creation_time
.tv_nsec
);
1013 process
->pid_time
= g_quark_from_string(buffer
);
1015 //process->last_cpu = tfs->cpu_name;
1016 //process->last_cpu_index = ltt_tracefile_num(((LttvTracefileContext*)tfs)->tf);
1017 process
->execution_stack
= g_array_sized_new(FALSE
, FALSE
,
1018 sizeof(LttvExecutionState
), PREALLOCATED_EXECUTION_STACK
);
1019 process
->execution_stack
= g_array_set_size(process
->execution_stack
, 1);
1020 es
= process
->state
= &g_array_index(process
->execution_stack
,
1021 LttvExecutionState
, 0);
1022 es
->t
= LTTV_STATE_USER_MODE
;
1023 es
->n
= LTTV_STATE_SUBMODE_NONE
;
1024 es
->entry
= *timestamp
;
1025 //g_assert(timestamp->tv_sec != 0);
1026 es
->change
= *timestamp
;
1027 es
->s
= LTTV_STATE_WAIT_FORK
;
1032 LttvProcessState
*lttv_state_find_process(LttvTraceState
*ts
, guint cpu
,
1035 LttvProcessState key
;
1036 LttvProcessState
*process
;
1040 process
= g_hash_table_lookup(ts
->processes
, &key
);
1045 lttv_state_find_process_or_create(LttvTraceState
*ts
, guint cpu
, guint pid
,
1048 LttvProcessState
*process
= lttv_state_find_process(ts
, cpu
, pid
);
1050 /* Put ltt_time_zero creation time for unexisting processes */
1051 if(unlikely(process
== NULL
)) process
= lttv_state_create_process(ts
,
1052 NULL
, cpu
, pid
, timestamp
);
1056 /* FIXME : this function should be called when we receive an event telling that
1057 * release_task has been called in the kernel. In happens generally when
1058 * the parent waits for its child terminaison, but may also happen in special
1059 * cases in the child's exit : when the parent ignores its children SIGCCHLD or
1060 * has the flag SA_NOCLDWAIT. It can also happen when the child is part
1061 * of a killed thread ground, but isn't the leader.
1063 static void exit_process(LttvTracefileState
*tfs
, LttvProcessState
*process
)
1065 LttvTraceState
*ts
= LTTV_TRACE_STATE(tfs
->parent
.t_context
);
1066 LttvProcessState key
;
1068 key
.pid
= process
->pid
;
1069 key
.cpu
= process
->cpu
;
1070 g_hash_table_remove(ts
->processes
, &key
);
1071 g_array_free(process
->execution_stack
, TRUE
);
1076 static void free_process_state(gpointer key
, gpointer value
,gpointer user_data
)
1078 g_array_free(((LttvProcessState
*)value
)->execution_stack
, TRUE
);
1083 static void lttv_state_free_process_table(GHashTable
*processes
)
1085 g_hash_table_foreach(processes
, free_process_state
, NULL
);
1086 g_hash_table_destroy(processes
);
1090 static gboolean
syscall_entry(void *hook_data
, void *call_data
)
1092 LttvTracefileState
*s
= (LttvTracefileState
*)call_data
;
1093 LttEvent
*e
= ltt_tracefile_get_event(s
->parent
.tf
);
1094 LttvTraceHookByFacility
*thf
= (LttvTraceHookByFacility
*)hook_data
;
1095 LttField
*f
= thf
->f1
;
1097 LttvExecutionSubmode submode
;
1099 submode
= ((LttvTraceState
*)(s
->parent
.t_context
))->syscall_names
[
1100 ltt_event_get_unsigned(e
, f
)];
1101 push_state(s
, LTTV_STATE_SYSCALL
, submode
);
1106 static gboolean
syscall_exit(void *hook_data
, void *call_data
)
1108 LttvTracefileState
*s
= (LttvTracefileState
*)call_data
;
1110 pop_state(s
, LTTV_STATE_SYSCALL
);
1115 static gboolean
trap_entry(void *hook_data
, void *call_data
)
1117 LttvTracefileState
*s
= (LttvTracefileState
*)call_data
;
1118 LttEvent
*e
= ltt_tracefile_get_event(s
->parent
.tf
);
1119 LttvTraceHookByFacility
*thf
= (LttvTraceHookByFacility
*)hook_data
;
1120 LttField
*f
= thf
->f1
;
1122 LttvExecutionSubmode submode
;
1124 submode
= ((LttvTraceState
*)(s
->parent
.t_context
))->trap_names
[
1125 ltt_event_get_unsigned(e
, f
)];
1126 push_state(s
, LTTV_STATE_TRAP
, submode
);
1131 static gboolean
trap_exit(void *hook_data
, void *call_data
)
1133 LttvTracefileState
*s
= (LttvTracefileState
*)call_data
;
1135 pop_state(s
, LTTV_STATE_TRAP
);
1140 static gboolean
irq_entry(void *hook_data
, void *call_data
)
1142 LttvTracefileState
*s
= (LttvTracefileState
*)call_data
;
1143 LttEvent
*e
= ltt_tracefile_get_event(s
->parent
.tf
);
1144 guint8 fac_id
= ltt_event_facility_id(e
);
1145 guint8 ev_id
= ltt_event_eventtype_id(e
);
1146 LttvTraceHookByFacility
*thf
= (LttvTraceHookByFacility
*)hook_data
;
1147 // g_assert(lttv_trace_hook_get_first((LttvTraceHook *)hook_data)->f1 != NULL);
1148 g_assert(thf
->f1
!= NULL
);
1149 // g_assert(thf == lttv_trace_hook_get_first((LttvTraceHook *)hook_data));
1150 LttField
*f
= thf
->f1
;
1152 LttvExecutionSubmode submode
;
1154 submode
= ((LttvTraceState
*)(s
->parent
.t_context
))->irq_names
[
1155 ltt_event_get_unsigned(e
, f
)];
1157 /* Do something with the info about being in user or system mode when int? */
1158 push_state(s
, LTTV_STATE_IRQ
, submode
);
1163 static gboolean
irq_exit(void *hook_data
, void *call_data
)
1165 LttvTracefileState
*s
= (LttvTracefileState
*)call_data
;
1167 pop_state(s
, LTTV_STATE_IRQ
);
1172 static gboolean
schedchange(void *hook_data
, void *call_data
)
1174 LttvTracefileState
*s
= (LttvTracefileState
*)call_data
;
1175 guint cpu
= ltt_tracefile_num(s
->parent
.tf
);
1176 LttvTraceState
*ts
= (LttvTraceState
*)s
->parent
.t_context
;
1177 LttvProcessState
*process
= ts
->running_process
[cpu
];
1179 LttEvent
*e
= ltt_tracefile_get_event(s
->parent
.tf
);
1180 LttvTraceHookByFacility
*thf
= (LttvTraceHookByFacility
*)hook_data
;
1181 guint pid_in
, pid_out
;
1184 pid_out
= ltt_event_get_unsigned(e
, thf
->f1
);
1185 pid_in
= ltt_event_get_unsigned(e
, thf
->f2
);
1186 state_out
= ltt_event_get_int(e
, thf
->f3
);
1188 if(likely(process
!= NULL
)) {
1190 /* We could not know but it was not the idle process executing.
1191 This should only happen at the beginning, before the first schedule
1192 event, and when the initial information (current process for each CPU)
1193 is missing. It is not obvious how we could, after the fact, compensate
1194 the wrongly attributed statistics. */
1196 //This test only makes sense once the state is known and if there is no
1198 //if(unlikely(process->pid != pid_out)) {
1199 // g_assert(process->pid == 0);
1202 if(unlikely(process
->state
->s
== LTTV_STATE_EXIT
)) {
1203 process
->state
->s
= LTTV_STATE_ZOMBIE
;
1205 if(unlikely(state_out
== 0)) process
->state
->s
= LTTV_STATE_WAIT_CPU
;
1206 else process
->state
->s
= LTTV_STATE_WAIT
;
1207 } /* FIXME : we do not remove process here, because the kernel
1208 * still has them : they may be zombies. We need to know
1209 * exactly when release_task is executed on the PID to
1210 * know when the zombie is destroyed.
1213 // exit_process(s, process);
1215 process
->state
->change
= s
->parent
.timestamp
;
1217 process
= ts
->running_process
[cpu
] =
1218 lttv_state_find_process_or_create(
1219 (LttvTraceState
*)s
->parent
.t_context
,
1221 &s
->parent
.timestamp
);
1222 process
->state
->s
= LTTV_STATE_RUN
;
1224 // process->last_cpu_index = ltt_tracefile_num(((LttvTracefileContext*)s)->tf);
1225 process
->state
->change
= s
->parent
.timestamp
;
1229 static gboolean
process_fork(void *hook_data
, void *call_data
)
1231 LttvTracefileState
*s
= (LttvTracefileState
*)call_data
;
1232 LttEvent
*e
= ltt_tracefile_get_event(s
->parent
.tf
);
1233 LttvTraceHookByFacility
*thf
= (LttvTraceHookByFacility
*)hook_data
;
1237 LttvProcessState
*zombie_process
;
1238 guint cpu
= ltt_tracefile_num(s
->parent
.tf
);
1239 LttvTraceState
*ts
= (LttvTraceState
*)s
->parent
.t_context
;
1240 LttvProcessState
*process
= ts
->running_process
[cpu
];
1244 parent_pid
= ltt_event_get_unsigned(e
, f
);
1248 child_pid
= ltt_event_get_unsigned(e
, f
);
1250 /* Mathieu : it seems like the process might have been scheduled in before the
1251 * fork, and, in a rare case, might be the current process. This might happen
1252 * in a SMP case where we don't have enough precision on the clocks */
1254 zombie_process
= lttv_state_find_process(ts
, ANY_CPU
, child_pid
);
1256 if(unlikely(zombie_process
!= NULL
)) {
1257 /* Reutilisation of PID. Only now we are sure that the old PID
1258 * has been released. FIXME : should know when release_task happens instead.
1260 guint num_cpus
= ltt_trace_get_num_cpu(ts
->parent
.t
);
1262 for(i
=0; i
< num_cpus
; i
++) {
1263 g_assert(process
!= ts
->running_process
[i
]);
1266 exit_process(s
, zombie_process
);
1269 g_assert(process
->pid
!= child_pid
);
1270 // FIXME : Add this test in the "known state" section
1271 // g_assert(process->pid == parent_pid);
1272 lttv_state_create_process(ts
, process
, cpu
, child_pid
, &s
->parent
.timestamp
);
1278 static gboolean
process_exit(void *hook_data
, void *call_data
)
1280 LttvTracefileState
*s
= (LttvTracefileState
*)call_data
;
1281 LttEvent
*e
= ltt_tracefile_get_event(s
->parent
.tf
);
1282 LttvTraceHookByFacility
*thf
= (LttvTraceHookByFacility
*)hook_data
;
1285 guint cpu
= ltt_tracefile_num(s
->parent
.tf
);
1286 LttvTraceState
*ts
= (LttvTraceState
*)s
->parent
.t_context
;
1287 LttvProcessState
*process
= ts
->running_process
[cpu
];
1289 pid
= ltt_event_get_unsigned(e
, thf
->f1
);
1291 // FIXME : Add this test in the "known state" section
1292 // g_assert(process->pid == pid);
1294 if(likely(process
!= NULL
)) {
1295 process
->state
->s
= LTTV_STATE_EXIT
;
1300 static gboolean
process_free(void *hook_data
, void *call_data
)
1302 LttvTracefileState
*s
= (LttvTracefileState
*)call_data
;
1303 LttvTraceState
*ts
= (LttvTraceState
*)s
->parent
.t_context
;
1304 LttEvent
*e
= ltt_tracefile_get_event(s
->parent
.tf
);
1305 LttvTraceHookByFacility
*thf
= (LttvTraceHookByFacility
*)hook_data
;
1307 LttvProcessState
*process
;
1309 /* PID of the process to release */
1310 release_pid
= ltt_event_get_unsigned(e
, thf
->f1
);
1312 g_assert(release_pid
!= 0);
1314 process
= lttv_state_find_process(ts
, ANY_CPU
, release_pid
);
1316 if(likely(process
!= NULL
)) {
1317 /* release_task is happening at kernel level : we can now safely release
1318 * the data structure of the process */
1319 guint num_cpus
= ltt_trace_get_num_cpu(ts
->parent
.t
);
1321 for(i
=0; i
< num_cpus
; i
++) {
1322 g_assert(process
!= ts
->running_process
[i
]);
1324 exit_process(s
, process
);
1331 static gboolean
process_exec(void *hook_data
, void *call_data
)
1333 LttvTracefileState
*s
= (LttvTracefileState
*)call_data
;
1334 LttvTraceState
*ts
= (LttvTraceState
*)s
->parent
.t_context
;
1335 LttEvent
*e
= ltt_tracefile_get_event(s
->parent
.tf
);
1336 LttvTraceHookByFacility
*thf
= (LttvTraceHookByFacility
*)hook_data
;
1338 guint cpu
= ltt_tracefile_num(s
->parent
.tf
);
1339 LttvProcessState
*process
= ts
->running_process
[cpu
];
1341 /* PID of the process to release */
1342 name
= ltt_event_get_string(e
, thf
->f1
);
1344 process
->name
= g_quark_from_string(name
);
1352 gint
lttv_state_hook_add_event_hooks(void *hook_data
, void *call_data
)
1354 LttvTracesetState
*tss
= (LttvTracesetState
*)(call_data
);
1356 lttv_state_add_event_hooks(tss
);
1361 void lttv_state_add_event_hooks(LttvTracesetState
*self
)
1363 LttvTraceset
*traceset
= self
->parent
.ts
;
1365 guint i
, j
, k
, l
, nb_trace
, nb_tracefile
;
1369 LttvTracefileState
*tfs
;
1373 LttvTraceHookByFacility
*thf
;
1375 LttvTraceHook
*hook
;
1377 LttvAttributeValue val
;
1381 nb_trace
= lttv_traceset_number(traceset
);
1382 for(i
= 0 ; i
< nb_trace
; i
++) {
1383 ts
= (LttvTraceState
*)self
->parent
.traces
[i
];
1385 /* Find the eventtype id for the following events and register the
1386 associated by id hooks. */
1388 hooks
= g_array_sized_new(FALSE
, FALSE
, sizeof(LttvTraceHook
), 11);
1389 hooks
= g_array_set_size(hooks
, 11);
1391 ret
= lttv_trace_find_hook(ts
->parent
.t
,
1392 LTT_FACILITY_KERNEL
, LTT_EVENT_SYSCALL_ENTRY
,
1393 LTT_FIELD_SYSCALL_ID
, 0, 0,
1394 syscall_entry
, NULL
, &g_array_index(hooks
, LttvTraceHook
, 0));
1397 ret
= lttv_trace_find_hook(ts
->parent
.t
,
1398 LTT_FACILITY_KERNEL
, LTT_EVENT_SYSCALL_EXIT
,
1400 syscall_exit
, NULL
, &g_array_index(hooks
, LttvTraceHook
, 1));
1403 ret
= lttv_trace_find_hook(ts
->parent
.t
,
1404 LTT_FACILITY_KERNEL
, LTT_EVENT_TRAP_ENTRY
,
1405 LTT_FIELD_TRAP_ID
, 0, 0,
1406 trap_entry
, NULL
, &g_array_index(hooks
, LttvTraceHook
, 2));
1409 ret
= lttv_trace_find_hook(ts
->parent
.t
,
1410 LTT_FACILITY_KERNEL
, LTT_EVENT_TRAP_EXIT
,
1412 trap_exit
, NULL
, &g_array_index(hooks
, LttvTraceHook
, 3));
1415 ret
= lttv_trace_find_hook(ts
->parent
.t
,
1416 LTT_FACILITY_KERNEL
, LTT_EVENT_IRQ_ENTRY
,
1417 LTT_FIELD_IRQ_ID
, 0, 0,
1418 irq_entry
, NULL
, &g_array_index(hooks
, LttvTraceHook
, 4));
1421 ret
= lttv_trace_find_hook(ts
->parent
.t
,
1422 LTT_FACILITY_KERNEL
, LTT_EVENT_IRQ_EXIT
,
1424 irq_exit
, NULL
, &g_array_index(hooks
, LttvTraceHook
, 5));
1427 ret
= lttv_trace_find_hook(ts
->parent
.t
,
1428 LTT_FACILITY_PROCESS
, LTT_EVENT_SCHEDCHANGE
,
1429 LTT_FIELD_OUT
, LTT_FIELD_IN
, LTT_FIELD_OUT_STATE
,
1430 schedchange
, NULL
, &g_array_index(hooks
, LttvTraceHook
, 6));
1433 ret
= lttv_trace_find_hook(ts
->parent
.t
,
1434 LTT_FACILITY_PROCESS
, LTT_EVENT_FORK
,
1435 LTT_FIELD_PARENT_PID
, LTT_FIELD_CHILD_PID
, 0,
1436 process_fork
, NULL
, &g_array_index(hooks
, LttvTraceHook
, 7));
1439 ret
= lttv_trace_find_hook(ts
->parent
.t
,
1440 LTT_FACILITY_PROCESS
, LTT_EVENT_EXIT
,
1441 LTT_FIELD_PID
, 0, 0,
1442 process_exit
, NULL
, &g_array_index(hooks
, LttvTraceHook
, 8));
1445 ret
= lttv_trace_find_hook(ts
->parent
.t
,
1446 LTT_FACILITY_PROCESS
, LTT_EVENT_FREE
,
1447 LTT_FIELD_PID
, 0, 0,
1448 process_free
, NULL
, &g_array_index(hooks
, LttvTraceHook
, 9));
1451 ret
= lttv_trace_find_hook(ts
->parent
.t
,
1452 LTT_FACILITY_FS
, LTT_EVENT_EXEC
,
1453 LTT_FIELD_FILENAME
, 0, 0,
1454 process_exec
, NULL
, &g_array_index(hooks
, LttvTraceHook
, 10));
1459 /* Add these hooks to each event_by_id hooks list */
1461 nb_tracefile
= ts
->parent
.tracefiles
->len
;
1463 for(j
= 0 ; j
< nb_tracefile
; j
++) {
1465 LTTV_TRACEFILE_STATE(g_array_index(ts
->parent
.tracefiles
,
1466 LttvTracefileContext
*, j
));
1468 for(k
= 0 ; k
< hooks
->len
; k
++) {
1469 hook
= &g_array_index(hooks
, LttvTraceHook
, k
);
1470 for(l
=0;l
<hook
->fac_list
->len
;l
++) {
1471 thf
= g_array_index(hook
->fac_list
, LttvTraceHookByFacility
*, l
);
1473 lttv_hooks_by_id_find(tfs
->parent
.event_by_id
, thf
->id
),
1480 lttv_attribute_find(self
->parent
.a
, LTTV_STATE_HOOKS
, LTTV_POINTER
, &val
);
1481 *(val
.v_pointer
) = hooks
;
1485 gint
lttv_state_hook_remove_event_hooks(void *hook_data
, void *call_data
)
1487 LttvTracesetState
*tss
= (LttvTracesetState
*)(call_data
);
1489 lttv_state_remove_event_hooks(tss
);
1494 void lttv_state_remove_event_hooks(LttvTracesetState
*self
)
1496 LttvTraceset
*traceset
= self
->parent
.ts
;
1498 guint i
, j
, k
, l
, nb_trace
, nb_tracefile
;
1502 LttvTracefileState
*tfs
;
1506 LttvTraceHook
*hook
;
1508 LttvTraceHookByFacility
*thf
;
1510 LttvAttributeValue val
;
1512 nb_trace
= lttv_traceset_number(traceset
);
1513 for(i
= 0 ; i
< nb_trace
; i
++) {
1514 ts
= LTTV_TRACE_STATE(self
->parent
.traces
[i
]);
1515 lttv_attribute_find(self
->parent
.a
, LTTV_STATE_HOOKS
, LTTV_POINTER
, &val
);
1516 hooks
= *(val
.v_pointer
);
1518 /* Remove these hooks from each event_by_id hooks list */
1520 nb_tracefile
= ts
->parent
.tracefiles
->len
;
1522 for(j
= 0 ; j
< nb_tracefile
; j
++) {
1524 LTTV_TRACEFILE_STATE(g_array_index(ts
->parent
.tracefiles
,
1525 LttvTracefileContext
*, j
));
1527 for(k
= 0 ; k
< hooks
->len
; k
++) {
1528 hook
= &g_array_index(hooks
, LttvTraceHook
, k
);
1529 for(l
=0;l
<hook
->fac_list
->len
;l
++) {
1530 thf
= g_array_index(hook
->fac_list
, LttvTraceHookByFacility
*, l
);
1532 lttv_hooks_remove_data(
1533 lttv_hooks_by_id_find(tfs
->parent
.event_by_id
, thf
->id
),
1539 for(k
= 0 ; k
< hooks
->len
; k
++)
1540 lttv_trace_hook_destroy(&g_array_index(hooks
, LttvTraceHook
, k
));
1541 g_array_free(hooks
, TRUE
);
1545 static gboolean
state_save_event_hook(void *hook_data
, void *call_data
)
1547 guint
*event_count
= (guint
*)hook_data
;
1549 /* Only save at LTTV_STATE_SAVE_INTERVAL */
1550 if(likely((*event_count
)++ < LTTV_STATE_SAVE_INTERVAL
))
1555 LttvTracefileState
*self
= (LttvTracefileState
*)call_data
;
1557 LttvTracefileState
*tfcs
;
1559 LttvTraceState
*tcs
= (LttvTraceState
*)(self
->parent
.t_context
);
1561 LttEventPosition
*ep
;
1567 LttvAttribute
*saved_states_tree
, *saved_state_tree
;
1569 LttvAttributeValue value
;
1571 saved_states_tree
= lttv_attribute_find_subdir(tcs
->parent
.t_a
,
1572 LTTV_STATE_SAVED_STATES
);
1573 saved_state_tree
= g_object_new(LTTV_ATTRIBUTE_TYPE
, NULL
);
1574 value
= lttv_attribute_add(saved_states_tree
,
1575 lttv_attribute_get_number(saved_states_tree
), LTTV_GOBJECT
);
1576 *(value
.v_gobject
) = (GObject
*)saved_state_tree
;
1577 value
= lttv_attribute_add(saved_state_tree
, LTTV_STATE_TIME
, LTTV_TIME
);
1578 *(value
.v_time
) = self
->parent
.timestamp
;
1579 lttv_state_save(tcs
, saved_state_tree
);
1580 g_debug("Saving state at time %lu.%lu", self
->parent
.timestamp
.tv_sec
,
1581 self
->parent
.timestamp
.tv_nsec
);
1583 *(tcs
->max_time_state_recomputed_in_seek
) = self
->parent
.timestamp
;
1589 static gboolean
block_start(void *hook_data
, void *call_data
)
1591 LttvTracefileState
*self
= (LttvTracefileState
*)call_data
;
1593 LttvTracefileState
*tfcs
;
1595 LttvTraceState
*tcs
= (LttvTraceState
*)(self
->parent
.t_context
);
1597 LttEventPosition
*ep
;
1599 guint i
, nb_block
, nb_event
, nb_tracefile
;
1603 LttvAttribute
*saved_states_tree
, *saved_state_tree
;
1605 LttvAttributeValue value
;
1607 ep
= ltt_event_position_new();
1609 nb_tracefile
= tcs
->parent
.tracefiles
->len
;
1611 /* Count the number of events added since the last block end in any
1614 for(i
= 0 ; i
< nb_tracefile
; i
++) {
1616 LTTV_TRACEFILE_STATE(&g_array_index(tcs
->parent
.tracefiles
,
1617 LttvTracefileContext
, i
));
1618 ltt_event_position(tfcs
->parent
.e
, ep
);
1619 ltt_event_position_get(ep
, &nb_block
, &nb_event
, &tf
);
1620 tcs
->nb_event
+= nb_event
- tfcs
->saved_position
;
1621 tfcs
->saved_position
= nb_event
;
1625 if(tcs
->nb_event
>= tcs
->save_interval
) {
1626 saved_states_tree
= lttv_attribute_find_subdir(tcs
->parent
.t_a
,
1627 LTTV_STATE_SAVED_STATES
);
1628 saved_state_tree
= g_object_new(LTTV_ATTRIBUTE_TYPE
, NULL
);
1629 value
= lttv_attribute_add(saved_states_tree
,
1630 lttv_attribute_get_number(saved_states_tree
), LTTV_GOBJECT
);
1631 *(value
.v_gobject
) = (GObject
*)saved_state_tree
;
1632 value
= lttv_attribute_add(saved_state_tree
, LTTV_STATE_TIME
, LTTV_TIME
);
1633 *(value
.v_time
) = self
->parent
.timestamp
;
1634 lttv_state_save(tcs
, saved_state_tree
);
1636 g_debug("Saving state at time %lu.%lu", self
->parent
.timestamp
.tv_sec
,
1637 self
->parent
.timestamp
.tv_nsec
);
1639 *(tcs
->max_time_state_recomputed_in_seek
) = self
->parent
.timestamp
;
1645 static gboolean
block_end(void *hook_data
, void *call_data
)
1647 LttvTracefileState
*self
= (LttvTracefileState
*)call_data
;
1649 LttvTraceState
*tcs
= (LttvTraceState
*)(self
->parent
.t_context
);
1653 LttEventPosition
*ep
;
1655 guint nb_block
, nb_event
;
1657 ep
= ltt_event_position_new();
1658 ltt_event_position(self
->parent
.e
, ep
);
1659 ltt_event_position_get(ep
, &nb_block
, &nb_event
, &tf
);
1660 tcs
->nb_event
+= nb_event
- self
->saved_position
+ 1;
1661 self
->saved_position
= 0;
1662 *(tcs
->max_time_state_recomputed_in_seek
) = self
->parent
.timestamp
;
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
;
1679 LttvTraceHook hook_start
, hook_end
;
1681 nb_trace
= lttv_traceset_number(traceset
);
1682 for(i
= 0 ; i
< nb_trace
; i
++) {
1683 ts
= (LttvTraceState
*)self
->parent
.traces
[i
];
1685 lttv_trace_find_hook(ts
->parent
.t
, "core","block_start",NULL
,
1686 NULL
, NULL
, block_start
, &hook_start
);
1687 lttv_trace_find_hook(ts
->parent
.t
, "core","block_end",NULL
,
1688 NULL
, NULL
, block_end
, &hook_end
);
1690 nb_tracefile
= ts
->parent
.tracefiles
->len
;
1692 for(j
= 0 ; j
< nb_tracefile
; j
++) {
1694 LTTV_TRACEFILE_STATE(&g_array_index(ts
->parent
.tracefiles
,
1695 LttvTracefileContext
, j
));
1696 lttv_hooks_add(lttv_hooks_by_id_find(tfs
->parent
.event_by_id
,
1697 hook_start
.id
), hook_start
.h
, NULL
, LTTV_PRIO_STATE
);
1698 lttv_hooks_add(lttv_hooks_by_id_find(tfs
->parent
.event_by_id
,
1699 hook_end
.id
), hook_end
.h
, NULL
, LTTV_PRIO_STATE
);
1705 void lttv_state_save_add_event_hooks(LttvTracesetState
*self
)
1707 LttvTraceset
*traceset
= self
->parent
.ts
;
1709 guint i
, j
, nb_trace
, nb_tracefile
;
1713 LttvTracefileState
*tfs
;
1716 nb_trace
= lttv_traceset_number(traceset
);
1717 for(i
= 0 ; i
< nb_trace
; i
++) {
1719 ts
= (LttvTraceState
*)self
->parent
.traces
[i
];
1720 nb_tracefile
= ts
->parent
.tracefiles
->len
;
1722 guint
*event_count
= g_new(guint
, 1);
1725 for(j
= 0 ; j
< nb_tracefile
; j
++) {
1727 LTTV_TRACEFILE_STATE(g_array_index(ts
->parent
.tracefiles
,
1728 LttvTracefileContext
*, j
));
1729 lttv_hooks_add(tfs
->parent
.event
,
1730 state_save_event_hook
,
1738 gint
lttv_state_save_hook_add_event_hooks(void *hook_data
, void *call_data
)
1740 LttvTracesetState
*tss
= (LttvTracesetState
*)(call_data
);
1742 lttv_state_save_add_event_hooks(tss
);
1749 void lttv_state_save_remove_event_hooks(LttvTracesetState
*self
)
1751 LttvTraceset
*traceset
= self
->parent
.ts
;
1753 guint i
, j
, nb_trace
, nb_tracefile
;
1757 LttvTracefileState
*tfs
;
1759 LttvTraceHook hook_start
, hook_end
;
1761 nb_trace
= lttv_traceset_number(traceset
);
1762 for(i
= 0 ; i
< nb_trace
; i
++) {
1763 ts
= LTTV_TRACE_STATE(self
->parent
.traces
[i
]);
1765 lttv_trace_find_hook(ts
->parent
.t
, "core","block_start",NULL
,
1766 NULL
, NULL
, block_start
, &hook_start
);
1768 lttv_trace_find_hook(ts
->parent
.t
, "core","block_end",NULL
,
1769 NULL
, NULL
, block_end
, &hook_end
);
1771 nb_tracefile
= ts
->parent
.tracefiles
->len
;
1773 for(j
= 0 ; j
< nb_tracefile
; j
++) {
1775 LTTV_TRACEFILE_STATE(&g_array_index(ts
->parent
.tracefiles
,
1776 LttvTracefileContext
, j
));
1777 lttv_hooks_remove_data(lttv_hooks_by_id_find(
1778 tfs
->parent
.event_by_id
, hook_start
.id
), hook_start
.h
, NULL
);
1779 lttv_hooks_remove_data(lttv_hooks_by_id_find(
1780 tfs
->parent
.event_by_id
, hook_end
.id
), hook_end
.h
, NULL
);
1786 void lttv_state_save_remove_event_hooks(LttvTracesetState
*self
)
1788 LttvTraceset
*traceset
= self
->parent
.ts
;
1790 guint i
, j
, nb_trace
, nb_tracefile
;
1794 LttvTracefileState
*tfs
;
1797 nb_trace
= lttv_traceset_number(traceset
);
1798 for(i
= 0 ; i
< nb_trace
; i
++) {
1800 ts
= (LttvTraceState
*)self
->parent
.traces
[i
];
1801 nb_tracefile
= ts
->parent
.tracefiles
->len
;
1805 for(j
= 0 ; j
< nb_tracefile
; j
++) {
1807 LTTV_TRACEFILE_STATE(g_array_index(ts
->parent
.tracefiles
,
1808 LttvTracefileContext
*, j
));
1809 event_count
= lttv_hooks_remove(tfs
->parent
.event
,
1810 state_save_event_hook
);
1813 g_free(event_count
);
1817 gint
lttv_state_save_hook_remove_event_hooks(void *hook_data
, void *call_data
)
1819 LttvTracesetState
*tss
= (LttvTracesetState
*)(call_data
);
1821 lttv_state_save_remove_event_hooks(tss
);
1826 void lttv_state_traceset_seek_time_closest(LttvTracesetState
*self
, LttTime t
)
1828 LttvTraceset
*traceset
= self
->parent
.ts
;
1832 int min_pos
, mid_pos
, max_pos
;
1834 guint call_rest
= 0;
1836 LttvTraceState
*tcs
;
1838 LttvAttributeValue value
;
1840 LttvAttributeType type
;
1842 LttvAttributeName name
;
1844 LttvAttribute
*saved_states_tree
, *saved_state_tree
, *closest_tree
;
1846 g_tree_destroy(self
->parent
.pqueue
);
1847 self
->parent
.pqueue
= g_tree_new(compare_tracefile
);
1849 g_info("Entering seek_time_closest for time %lu.%lu", t
.tv_sec
, t
.tv_nsec
);
1851 nb_trace
= lttv_traceset_number(traceset
);
1852 for(i
= 0 ; i
< nb_trace
; i
++) {
1853 tcs
= (LttvTraceState
*)self
->parent
.traces
[i
];
1855 if(ltt_time_compare(t
, *(tcs
->max_time_state_recomputed_in_seek
)) < 0) {
1856 saved_states_tree
= lttv_attribute_find_subdir(tcs
->parent
.t_a
,
1857 LTTV_STATE_SAVED_STATES
);
1860 if(saved_states_tree
) {
1861 max_pos
= lttv_attribute_get_number(saved_states_tree
) - 1;
1862 mid_pos
= max_pos
/ 2;
1863 while(min_pos
< max_pos
) {
1864 type
= lttv_attribute_get(saved_states_tree
, mid_pos
, &name
, &value
);
1865 g_assert(type
== LTTV_GOBJECT
);
1866 saved_state_tree
= *((LttvAttribute
**)(value
.v_gobject
));
1867 type
= lttv_attribute_get_by_name(saved_state_tree
, LTTV_STATE_TIME
,
1869 g_assert(type
== LTTV_TIME
);
1870 if(ltt_time_compare(*(value
.v_time
), t
) < 0) {
1872 closest_tree
= saved_state_tree
;
1874 else max_pos
= mid_pos
- 1;
1876 mid_pos
= (min_pos
+ max_pos
+ 1) / 2;
1880 /* restore the closest earlier saved state */
1882 lttv_state_restore(tcs
, closest_tree
);
1886 /* There is no saved state, yet we want to have it. Restart at T0 */
1888 restore_init_state(tcs
);
1889 lttv_process_trace_seek_time(&(tcs
->parent
), ltt_time_zero
);
1892 /* We want to seek quickly without restoring/updating the state */
1894 restore_init_state(tcs
);
1895 lttv_process_trace_seek_time(&(tcs
->parent
), t
);
1898 if(!call_rest
) g_info("NOT Calling restore");
1903 traceset_state_instance_init (GTypeInstance
*instance
, gpointer g_class
)
1909 traceset_state_finalize (LttvTracesetState
*self
)
1911 G_OBJECT_CLASS(g_type_class_peek(LTTV_TRACESET_CONTEXT_TYPE
))->
1912 finalize(G_OBJECT(self
));
1917 traceset_state_class_init (LttvTracesetContextClass
*klass
)
1919 GObjectClass
*gobject_class
= G_OBJECT_CLASS(klass
);
1921 gobject_class
->finalize
= (void (*)(GObject
*self
)) traceset_state_finalize
;
1922 klass
->init
= (void (*)(LttvTracesetContext
*self
, LttvTraceset
*ts
))init
;
1923 klass
->fini
= (void (*)(LttvTracesetContext
*self
))fini
;
1924 klass
->new_traceset_context
= new_traceset_context
;
1925 klass
->new_trace_context
= new_trace_context
;
1926 klass
->new_tracefile_context
= new_tracefile_context
;
1931 lttv_traceset_state_get_type(void)
1933 static GType type
= 0;
1935 static const GTypeInfo info
= {
1936 sizeof (LttvTracesetStateClass
),
1937 NULL
, /* base_init */
1938 NULL
, /* base_finalize */
1939 (GClassInitFunc
) traceset_state_class_init
, /* class_init */
1940 NULL
, /* class_finalize */
1941 NULL
, /* class_data */
1942 sizeof (LttvTracesetState
),
1943 0, /* n_preallocs */
1944 (GInstanceInitFunc
) traceset_state_instance_init
, /* instance_init */
1945 NULL
/* value handling */
1948 type
= g_type_register_static (LTTV_TRACESET_CONTEXT_TYPE
, "LttvTracesetStateType",
1956 trace_state_instance_init (GTypeInstance
*instance
, gpointer g_class
)
1962 trace_state_finalize (LttvTraceState
*self
)
1964 G_OBJECT_CLASS(g_type_class_peek(LTTV_TRACE_CONTEXT_TYPE
))->
1965 finalize(G_OBJECT(self
));
1970 trace_state_class_init (LttvTraceStateClass
*klass
)
1972 GObjectClass
*gobject_class
= G_OBJECT_CLASS(klass
);
1974 gobject_class
->finalize
= (void (*)(GObject
*self
)) trace_state_finalize
;
1975 klass
->state_save
= state_save
;
1976 klass
->state_restore
= state_restore
;
1977 klass
->state_saved_free
= state_saved_free
;
1982 lttv_trace_state_get_type(void)
1984 static GType type
= 0;
1986 static const GTypeInfo info
= {
1987 sizeof (LttvTraceStateClass
),
1988 NULL
, /* base_init */
1989 NULL
, /* base_finalize */
1990 (GClassInitFunc
) trace_state_class_init
, /* class_init */
1991 NULL
, /* class_finalize */
1992 NULL
, /* class_data */
1993 sizeof (LttvTraceState
),
1994 0, /* n_preallocs */
1995 (GInstanceInitFunc
) trace_state_instance_init
, /* instance_init */
1996 NULL
/* value handling */
1999 type
= g_type_register_static (LTTV_TRACE_CONTEXT_TYPE
,
2000 "LttvTraceStateType", &info
, 0);
2007 tracefile_state_instance_init (GTypeInstance
*instance
, gpointer g_class
)
2013 tracefile_state_finalize (LttvTracefileState
*self
)
2015 G_OBJECT_CLASS(g_type_class_peek(LTTV_TRACEFILE_CONTEXT_TYPE
))->
2016 finalize(G_OBJECT(self
));
2021 tracefile_state_class_init (LttvTracefileStateClass
*klass
)
2023 GObjectClass
*gobject_class
= G_OBJECT_CLASS(klass
);
2025 gobject_class
->finalize
= (void (*)(GObject
*self
)) tracefile_state_finalize
;
2030 lttv_tracefile_state_get_type(void)
2032 static GType type
= 0;
2034 static const GTypeInfo info
= {
2035 sizeof (LttvTracefileStateClass
),
2036 NULL
, /* base_init */
2037 NULL
, /* base_finalize */
2038 (GClassInitFunc
) tracefile_state_class_init
, /* class_init */
2039 NULL
, /* class_finalize */
2040 NULL
, /* class_data */
2041 sizeof (LttvTracefileState
),
2042 0, /* n_preallocs */
2043 (GInstanceInitFunc
) tracefile_state_instance_init
, /* instance_init */
2044 NULL
/* value handling */
2047 type
= g_type_register_static (LTTV_TRACEFILE_CONTEXT_TYPE
,
2048 "LttvTracefileStateType", &info
, 0);
2054 static void module_init()
2056 LTTV_STATE_UNNAMED
= g_quark_from_string("unnamed");
2057 LTTV_STATE_MODE_UNKNOWN
= g_quark_from_string("unknown execution mode");
2058 LTTV_STATE_USER_MODE
= g_quark_from_string("user mode");
2059 LTTV_STATE_WAIT_FORK
= g_quark_from_string("wait fork");
2060 LTTV_STATE_SYSCALL
= g_quark_from_string("system call");
2061 LTTV_STATE_TRAP
= g_quark_from_string("trap");
2062 LTTV_STATE_IRQ
= g_quark_from_string("irq");
2063 LTTV_STATE_SUBMODE_UNKNOWN
= g_quark_from_string("unknown submode");
2064 LTTV_STATE_SUBMODE_NONE
= g_quark_from_string("(no submode)");
2065 LTTV_STATE_WAIT_CPU
= g_quark_from_string("wait for cpu");
2066 LTTV_STATE_EXIT
= g_quark_from_string("exiting");
2067 LTTV_STATE_ZOMBIE
= g_quark_from_string("zombie");
2068 LTTV_STATE_WAIT
= g_quark_from_string("wait for I/O");
2069 LTTV_STATE_RUN
= g_quark_from_string("running");
2070 LTTV_STATE_TRACEFILES
= g_quark_from_string("tracefiles");
2071 LTTV_STATE_PROCESSES
= g_quark_from_string("processes");
2072 LTTV_STATE_PROCESS
= g_quark_from_string("process");
2073 LTTV_STATE_RUNNING_PROCESS
= g_quark_from_string("running_process");
2074 LTTV_STATE_EVENT
= g_quark_from_string("event");
2075 LTTV_STATE_SAVED_STATES
= g_quark_from_string("saved states");
2076 LTTV_STATE_SAVED_STATES_TIME
= g_quark_from_string("saved states time");
2077 LTTV_STATE_TIME
= g_quark_from_string("time");
2078 LTTV_STATE_HOOKS
= g_quark_from_string("saved state hooks");
2079 LTTV_STATE_NAME_TABLES
= g_quark_from_string("name tables");
2080 LTTV_STATE_TRACE_STATE_USE_COUNT
=
2081 g_quark_from_string("trace_state_use_count");
2084 LTT_FACILITY_KERNEL
= g_quark_from_string("kernel");
2085 LTT_FACILITY_PROCESS
= g_quark_from_string("process");
2086 LTT_FACILITY_FS
= g_quark_from_string("fs");
2089 LTT_EVENT_SYSCALL_ENTRY
= g_quark_from_string("syscall_entry");
2090 LTT_EVENT_SYSCALL_EXIT
= g_quark_from_string("syscall_exit");
2091 LTT_EVENT_TRAP_ENTRY
= g_quark_from_string("trap_entry");
2092 LTT_EVENT_TRAP_EXIT
= g_quark_from_string("trap_exit");
2093 LTT_EVENT_IRQ_ENTRY
= g_quark_from_string("irq_entry");
2094 LTT_EVENT_IRQ_EXIT
= g_quark_from_string("irq_exit");
2095 LTT_EVENT_SCHEDCHANGE
= g_quark_from_string("schedchange");
2096 LTT_EVENT_FORK
= g_quark_from_string("fork");
2097 LTT_EVENT_EXIT
= g_quark_from_string("exit");
2098 LTT_EVENT_FREE
= g_quark_from_string("free");
2099 LTT_EVENT_EXEC
= g_quark_from_string("exec");
2102 LTT_FIELD_SYSCALL_ID
= g_quark_from_string("syscall_id");
2103 LTT_FIELD_TRAP_ID
= g_quark_from_string("trap_id");
2104 LTT_FIELD_IRQ_ID
= g_quark_from_string("irq_id");
2105 LTT_FIELD_OUT
= g_quark_from_string("out");
2106 LTT_FIELD_IN
= g_quark_from_string("in");
2107 LTT_FIELD_OUT_STATE
= g_quark_from_string("out_state");
2108 LTT_FIELD_PARENT_PID
= g_quark_from_string("parent_pid");
2109 LTT_FIELD_CHILD_PID
= g_quark_from_string("child_pid");
2110 LTT_FIELD_PID
= g_quark_from_string("pid");
2111 LTT_FIELD_FILENAME
= g_quark_from_string("filename");
2115 static void module_destroy()
2120 LTTV_MODULE("state", "State computation", \
2121 "Update the system state, possibly saving it at intervals", \
2122 module_init
, module_destroy
)