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
;
92 LTTV_STATE_TRACEFILES
,
95 LTTV_STATE_RUNNING_PROCESS
,
97 LTTV_STATE_SAVED_STATES
,
98 LTTV_STATE_SAVED_STATES_TIME
,
101 LTTV_STATE_NAME_TABLES
,
102 LTTV_STATE_TRACE_STATE_USE_COUNT
;
104 static void create_max_time(LttvTraceState
*tcs
);
106 static void get_max_time(LttvTraceState
*tcs
);
108 static void free_max_time(LttvTraceState
*tcs
);
110 static void create_name_tables(LttvTraceState
*tcs
);
112 static void get_name_tables(LttvTraceState
*tcs
);
114 static void free_name_tables(LttvTraceState
*tcs
);
116 static void free_saved_state(LttvTraceState
*tcs
);
118 static void lttv_state_free_process_table(GHashTable
*processes
);
121 void lttv_state_save(LttvTraceState
*self
, LttvAttribute
*container
)
123 LTTV_TRACE_STATE_GET_CLASS(self
)->state_save(self
, container
);
127 void lttv_state_restore(LttvTraceState
*self
, LttvAttribute
*container
)
129 LTTV_TRACE_STATE_GET_CLASS(self
)->state_restore(self
, container
);
133 void lttv_state_state_saved_free(LttvTraceState
*self
,
134 LttvAttribute
*container
)
136 LTTV_TRACE_STATE_GET_CLASS(self
)->state_saved_free(self
, container
);
140 guint
process_hash(gconstpointer key
)
142 guint pid
= ((const LttvProcessState
*)key
)->pid
;
143 return (pid
>>8 ^ pid
>>4 ^ pid
>>2 ^ pid
) ;
147 /* If the hash table hash function is well distributed,
148 * the process_equal should compare different pid */
149 gboolean
process_equal(gconstpointer a
, gconstpointer b
)
151 const LttvProcessState
*process_a
, *process_b
;
154 process_a
= (const LttvProcessState
*)a
;
155 process_b
= (const LttvProcessState
*)b
;
157 if(likely(process_a
->pid
!= process_b
->pid
)) ret
= FALSE
;
158 else if(likely(process_a
->pid
== 0 &&
159 process_a
->cpu
!= process_b
->cpu
)) ret
= FALSE
;
166 restore_init_state(LttvTraceState
*self
)
170 LttvTracefileState
*tfcs
;
172 /* Free the process tables */
173 if(self
->processes
!= NULL
) lttv_state_free_process_table(self
->processes
);
174 self
->processes
= g_hash_table_new(process_hash
, process_equal
);
177 /* Seek time to beginning */
178 // Mathieu : fix : don't seek traceset here : causes inconsistency in seek
179 // closest. It's the tracecontext job to seek the trace to the beginning
180 // anyway : the init state might be used at the middle of the trace as well...
181 //g_tree_destroy(self->parent.ts_context->pqueue);
182 //self->parent.ts_context->pqueue = g_tree_new(compare_tracefile);
185 //lttv_process_trace_seek_time(&self->parent, ltt_time_zero);
187 nb_cpus
= ltt_trace_get_num_cpu(self
->parent
.t
);
189 /* Put the per cpu running_process to beginning state : process 0. */
190 for(i
=0; i
< nb_cpus
; i
++) {
191 self
->running_process
[i
] = lttv_state_create_process(self
, NULL
, i
, 0,
193 self
->running_process
[i
]->state
->s
= LTTV_STATE_RUN
;
194 self
->running_process
[i
]->cpu
= i
;
198 nb_tracefile
= self
->parent
.tracefiles
->len
;
200 for(i
= 0 ; i
< nb_tracefile
; i
++) {
202 LTTV_TRACEFILE_STATE(g_array_index(self
->parent
.tracefiles
,
203 LttvTracefileContext
*, i
));
204 ltt_trace_time_span_get(self
->parent
.t
, &tfcs
->parent
.timestamp
, NULL
);
205 // tfcs->saved_position = 0;
206 tfcs
->process
= lttv_state_create_process(tfcs
, NULL
,0);
207 tfcs
->process
->state
->s
= LTTV_STATE_RUN
;
208 tfcs
->process
->last_cpu
= tfcs
->cpu_name
;
209 tfcs
->process
->last_cpu_index
= ltt_tracefile_num(((LttvTracefileContext
*)tfcs
)->tf
);
214 //static LttTime time_zero = {0,0};
217 init(LttvTracesetState
*self
, LttvTraceset
*ts
)
219 guint i
, j
, nb_trace
, nb_tracefile
;
221 LttvTraceContext
*tc
;
225 LttvTracefileState
*tfcs
;
227 LttvAttributeValue v
;
229 LTTV_TRACESET_CONTEXT_CLASS(g_type_class_peek(LTTV_TRACESET_CONTEXT_TYPE
))->
230 init((LttvTracesetContext
*)self
, ts
);
232 nb_trace
= lttv_traceset_number(ts
);
233 for(i
= 0 ; i
< nb_trace
; i
++) {
234 tc
= self
->parent
.traces
[i
];
235 tcs
= LTTV_TRACE_STATE(tc
);
236 tcs
->save_interval
= LTTV_STATE_SAVE_INTERVAL
;
237 lttv_attribute_find(tcs
->parent
.t_a
, LTTV_STATE_TRACE_STATE_USE_COUNT
,
241 if(*(v
.v_uint
) == 1) {
242 create_name_tables(tcs
);
243 create_max_time(tcs
);
245 get_name_tables(tcs
);
248 nb_tracefile
= tc
->tracefiles
->len
;
250 for(j
= 0 ; j
< nb_tracefile
; j
++) {
252 LTTV_TRACEFILE_STATE(g_array_index(tc
->tracefiles
,
253 LttvTracefileContext
*, j
));
254 tfcs
->tracefile_name
= ltt_tracefile_name(tfcs
->parent
.tf
);
257 tcs
->processes
= NULL
;
258 tcs
->running_process
= g_new(LttvProcessState
*,
259 ltt_trace_get_num_cpu(tc
->t
));
260 restore_init_state(tcs
);
266 fini(LttvTracesetState
*self
)
272 LttvTracefileState
*tfcs
;
274 LttvAttributeValue v
;
276 nb_trace
= lttv_traceset_number(LTTV_TRACESET_CONTEXT(self
)->ts
);
277 for(i
= 0 ; i
< nb_trace
; i
++) {
278 tcs
= (LttvTraceState
*)(LTTV_TRACESET_CONTEXT(self
)->traces
[i
]);
279 lttv_attribute_find(tcs
->parent
.t_a
, LTTV_STATE_TRACE_STATE_USE_COUNT
,
282 g_assert(*(v
.v_uint
) != 0);
285 if(*(v
.v_uint
) == 0) {
286 free_name_tables(tcs
);
288 free_saved_state(tcs
);
290 g_free(tcs
->running_process
);
291 tcs
->running_process
= NULL
;
292 lttv_state_free_process_table(tcs
->processes
);
293 tcs
->processes
= NULL
;
295 LTTV_TRACESET_CONTEXT_CLASS(g_type_class_peek(LTTV_TRACESET_CONTEXT_TYPE
))->
296 fini((LttvTracesetContext
*)self
);
300 static LttvTracesetContext
*
301 new_traceset_context(LttvTracesetContext
*self
)
303 return LTTV_TRACESET_CONTEXT(g_object_new(LTTV_TRACESET_STATE_TYPE
, NULL
));
307 static LttvTraceContext
*
308 new_trace_context(LttvTracesetContext
*self
)
310 return LTTV_TRACE_CONTEXT(g_object_new(LTTV_TRACE_STATE_TYPE
, NULL
));
314 static LttvTracefileContext
*
315 new_tracefile_context(LttvTracesetContext
*self
)
317 return LTTV_TRACEFILE_CONTEXT(g_object_new(LTTV_TRACEFILE_STATE_TYPE
, NULL
));
321 /* Write the process state of the trace */
323 static void write_process_state(gpointer key
, gpointer value
,
326 LttvProcessState
*process
;
328 LttvExecutionState
*es
;
330 FILE *fp
= (FILE *)user_data
;
334 process
= (LttvProcessState
*)value
;
336 " <PROCESS CORE=%p PID=%u PPID=%u CTIME_S=%lu CTIME_NS=%lu NAME=\"%s\" CPU=\"%u\">\n",
337 process
, process
->pid
, process
->ppid
, process
->creation_time
.tv_sec
,
338 process
->creation_time
.tv_nsec
, g_quark_to_string(process
->name
),
341 for(i
= 0 ; i
< process
->execution_stack
->len
; i
++) {
342 es
= &g_array_index(process
->execution_stack
, LttvExecutionState
, i
);
343 fprintf(fp
, " <ES MODE=\"%s\" SUBMODE=\"%s\" ENTRY_S=%lu ENTRY_NS=%lu",
344 g_quark_to_string(es
->t
), g_quark_to_string(es
->n
),
345 es
->entry
.tv_sec
, es
->entry
.tv_nsec
);
346 fprintf(fp
, " CHANGE_S=%lu CHANGE_NS=%lu STATUS=\"%s\"/>\n",
347 es
->change
.tv_sec
, es
->change
.tv_nsec
, g_quark_to_string(es
->s
));
349 fprintf(fp
, " </PROCESS>\n");
353 void lttv_state_write(LttvTraceState
*self
, LttTime t
, FILE *fp
)
355 guint i
, nb_tracefile
, nb_block
, offset
;
358 LttvTracefileState
*tfcs
;
362 LttEventPosition
*ep
;
366 ep
= ltt_event_position_new();
368 fprintf(fp
,"<PROCESS_STATE TIME_S=%lu TIME_NS=%lu>\n", t
.tv_sec
, t
.tv_nsec
);
370 g_hash_table_foreach(self
->processes
, write_process_state
, fp
);
372 nb_cpus
= ltt_trace_get_num_cpu(self
->parent
.t
);
373 for(i
=0;i
<nb_cpus
;i
++) {
374 fprintf(fp
,"<CPU NUM=%u RUNNING_PROCESS=%u>\n",
375 i
, self
->running_process
[i
]->pid
);
378 nb_tracefile
= self
->parent
.tracefiles
->len
;
380 for(i
= 0 ; i
< nb_tracefile
; i
++) {
382 LTTV_TRACEFILE_STATE(g_array_index(self
->parent
.tracefiles
,
383 LttvTracefileContext
*, i
));
384 fprintf(fp
, " <TRACEFILE TIMESTAMP_S=%lu TIMESTAMP_NS=%lu",
385 tfcs
->parent
.timestamp
.tv_sec
,
386 tfcs
->parent
.timestamp
.tv_nsec
);
387 LttEvent
*e
= ltt_tracefile_get_event(tfcs
->parent
.tf
);
388 if(e
== NULL
) fprintf(fp
,"/>\n");
390 ltt_event_position(e
, ep
);
391 ltt_event_position_get(ep
, &tf
, &nb_block
, &offset
, &tsc
);
392 fprintf(fp
, " BLOCK=%u OFFSET=%u TSC=%llu/>\n", nb_block
, offset
,
397 fprintf(fp
,"</PROCESS_STATE>");
401 /* Copy each process from an existing hash table to a new one */
403 static void copy_process_state(gpointer key
, gpointer value
,gpointer user_data
)
405 LttvProcessState
*process
, *new_process
;
407 GHashTable
*new_processes
= (GHashTable
*)user_data
;
411 process
= (LttvProcessState
*)value
;
412 new_process
= g_new(LttvProcessState
, 1);
413 *new_process
= *process
;
414 new_process
->execution_stack
= g_array_sized_new(FALSE
, FALSE
,
415 sizeof(LttvExecutionState
), PREALLOCATED_EXECUTION_STACK
);
416 new_process
->execution_stack
=
417 g_array_set_size(new_process
->execution_stack
,
418 process
->execution_stack
->len
);
419 for(i
= 0 ; i
< process
->execution_stack
->len
; i
++) {
420 g_array_index(new_process
->execution_stack
, LttvExecutionState
, i
) =
421 g_array_index(process
->execution_stack
, LttvExecutionState
, i
);
423 new_process
->state
= &g_array_index(new_process
->execution_stack
,
424 LttvExecutionState
, new_process
->execution_stack
->len
- 1);
425 g_hash_table_insert(new_processes
, new_process
, new_process
);
429 static GHashTable
*lttv_state_copy_process_table(GHashTable
*processes
)
431 GHashTable
*new_processes
= g_hash_table_new(process_hash
, process_equal
);
433 g_hash_table_foreach(processes
, copy_process_state
, new_processes
);
434 return new_processes
;
438 /* The saved state for each trace contains a member "processes", which
439 stores a copy of the process table, and a member "tracefiles" with
440 one entry per tracefile. Each tracefile has a "process" member pointing
441 to the current process and a "position" member storing the tracefile
442 position (needed to seek to the current "next" event. */
444 static void state_save(LttvTraceState
*self
, LttvAttribute
*container
)
446 guint i
, nb_tracefile
, nb_cpus
;
448 LttvTracefileState
*tfcs
;
450 LttvAttribute
*tracefiles_tree
, *tracefile_tree
;
452 guint
*running_process
;
454 LttvAttributeType type
;
456 LttvAttributeValue value
;
458 LttvAttributeName name
;
460 LttEventPosition
*ep
;
462 tracefiles_tree
= lttv_attribute_find_subdir(container
,
463 LTTV_STATE_TRACEFILES
);
465 value
= lttv_attribute_add(container
, LTTV_STATE_PROCESSES
,
467 *(value
.v_pointer
) = lttv_state_copy_process_table(self
->processes
);
469 /* Add the currently running processes array */
470 nb_cpus
= ltt_trace_get_num_cpu(self
->parent
.t
);
471 running_process
= g_new(guint
, nb_cpus
);
472 for(i
=0;i
<nb_cpus
;i
++) {
473 running_process
[i
] = self
->running_process
[i
]->pid
;
475 value
= lttv_attribute_add(container
, LTTV_STATE_RUNNING_PROCESS
,
477 *(value
.v_pointer
) = running_process
;
479 g_info("State save");
481 nb_tracefile
= self
->parent
.tracefiles
->len
;
483 for(i
= 0 ; i
< nb_tracefile
; i
++) {
485 LTTV_TRACEFILE_STATE(g_array_index(self
->parent
.tracefiles
,
486 LttvTracefileContext
*, i
));
487 tracefile_tree
= g_object_new(LTTV_ATTRIBUTE_TYPE
, NULL
);
488 value
= lttv_attribute_add(tracefiles_tree
, i
,
490 *(value
.v_gobject
) = (GObject
*)tracefile_tree
;
492 value
= lttv_attribute_add(tracefile_tree
, LTTV_STATE_PROCESS
,
494 *(value
.v_uint
) = tfcs
->process
->pid
;
496 value
= lttv_attribute_add(tracefile_tree
, LTTV_STATE_EVENT
,
498 /* Only save the position if the tfs has not infinite time. */
499 //if(!g_tree_lookup(self->parent.ts_context->pqueue, &tfcs->parent)
500 // && current_tfcs != tfcs) {
501 if(ltt_time_compare(tfcs
->parent
.timestamp
, ltt_time_infinite
) == 0) {
502 *(value
.v_pointer
) = NULL
;
504 LttEvent
*e
= ltt_tracefile_get_event(tfcs
->parent
.tf
);
505 ep
= ltt_event_position_new();
506 ltt_event_position(e
, ep
);
507 *(value
.v_pointer
) = ep
;
509 guint nb_block
, offset
;
512 ltt_event_position_get(ep
, &tf
, &nb_block
, &offset
, &tsc
);
513 g_info("Block %u offset %u tsc %llu time %lu.%lu", nb_block
, offset
,
515 tfcs
->parent
.timestamp
.tv_sec
, tfcs
->parent
.timestamp
.tv_nsec
);
521 static void state_restore(LttvTraceState
*self
, LttvAttribute
*container
)
523 guint i
, nb_tracefile
, pid
, nb_cpus
;
525 LttvTracefileState
*tfcs
;
527 LttvAttribute
*tracefiles_tree
, *tracefile_tree
;
529 guint
*running_process
;
531 LttvAttributeType type
;
533 LttvAttributeValue value
;
535 LttvAttributeName name
;
537 LttEventPosition
*ep
;
539 LttvTracesetContext
*tsc
= self
->parent
.ts_context
;
541 tracefiles_tree
= lttv_attribute_find_subdir(container
,
542 LTTV_STATE_TRACEFILES
);
544 type
= lttv_attribute_get_by_name(container
, LTTV_STATE_PROCESSES
,
546 g_assert(type
== LTTV_POINTER
);
547 lttv_state_free_process_table(self
->processes
);
548 self
->processes
= lttv_state_copy_process_table(*(value
.v_pointer
));
550 /* Add the currently running processes array */
551 nb_cpus
= ltt_trace_get_num_cpu(self
->parent
.t
);
552 type
= lttv_attribute_get_by_name(container
, LTTV_STATE_RUNNING_PROCESS
,
554 g_assert(type
== LTTV_POINTER
);
555 running_process
= *(value
.v_pointer
);
556 for(i
=0;i
<nb_cpus
;i
++) {
557 pid
= running_process
[i
];
558 self
->running_process
[i
] = lttv_state_find_process(self
, i
, pid
);
559 g_assert(self
->running_process
[i
] != NULL
);
563 nb_tracefile
= self
->parent
.tracefiles
->len
;
565 //g_tree_destroy(tsc->pqueue);
566 //tsc->pqueue = g_tree_new(compare_tracefile);
568 for(i
= 0 ; i
< nb_tracefile
; i
++) {
570 LTTV_TRACEFILE_STATE(g_array_index(self
->parent
.tracefiles
,
571 LttvTracefileContext
*, i
));
572 type
= lttv_attribute_get(tracefiles_tree
, i
, &name
, &value
);
573 g_assert(type
== LTTV_GOBJECT
);
574 tracefile_tree
= *((LttvAttribute
**)(value
.v_gobject
));
576 type
= lttv_attribute_get_by_name(tracefile_tree
, LTTV_STATE_PROCESS
,
578 g_assert(type
== LTTV_UINT
);
579 pid
= *(value
.v_uint
);
580 tfcs
->process
= lttv_state_find_process_or_create(tfcs
, pid
);
582 type
= lttv_attribute_get_by_name(tracefile_tree
, LTTV_STATE_EVENT
,
584 g_assert(type
== LTTV_POINTER
);
585 //g_assert(*(value.v_pointer) != NULL);
586 ep
= *(value
.v_pointer
);
587 g_assert(tfcs
->parent
.t_context
!= NULL
);
589 LttvTracefileContext
*tfc
= LTTV_TRACEFILE_CONTEXT(tfcs
);
590 g_tree_remove(tsc
->pqueue
, tfc
);
593 g_assert(ltt_tracefile_seek_position(tfc
->tf
, ep
) == 0);
594 tfc
->timestamp
= ltt_event_time(ltt_tracefile_get_event(tfc
->tf
));
595 g_assert(ltt_time_compare(tfc
->timestamp
, ltt_time_infinite
) != 0);
596 g_tree_insert(tsc
->pqueue
, tfc
, tfc
);
597 g_info("Restoring state for a tf at time %lu.%lu", tfc
->timestamp
.tv_sec
, tfc
->timestamp
.tv_nsec
);
599 tfc
->timestamp
= ltt_time_infinite
;
605 static void state_saved_free(LttvTraceState
*self
, LttvAttribute
*container
)
607 guint i
, nb_tracefile
, nb_cpus
;
609 LttvTracefileState
*tfcs
;
611 LttvAttribute
*tracefiles_tree
, *tracefile_tree
;
613 guint
*running_process
;
615 LttvAttributeType type
;
617 LttvAttributeValue value
;
619 LttvAttributeName name
;
621 LttEventPosition
*ep
;
623 tracefiles_tree
= lttv_attribute_find_subdir(container
,
624 LTTV_STATE_TRACEFILES
);
625 g_object_ref(G_OBJECT(tracefiles_tree
));
626 lttv_attribute_remove_by_name(container
, LTTV_STATE_TRACEFILES
);
628 type
= lttv_attribute_get_by_name(container
, LTTV_STATE_PROCESSES
,
630 g_assert(type
== LTTV_POINTER
);
631 lttv_state_free_process_table(*(value
.v_pointer
));
632 *(value
.v_pointer
) = NULL
;
633 lttv_attribute_remove_by_name(container
, LTTV_STATE_PROCESSES
);
635 /* Free running processes array */
636 nb_cpus
= ltt_trace_get_num_cpu(self
->parent
.t
);
637 type
= lttv_attribute_get_by_name(container
, LTTV_STATE_RUNNING_PROCESS
,
639 g_assert(type
== LTTV_POINTER
);
640 running_process
= *(value
.v_pointer
);
641 g_free(running_process
);
643 nb_tracefile
= self
->parent
.tracefiles
->len
;
645 for(i
= 0 ; i
< nb_tracefile
; i
++) {
647 LTTV_TRACEFILE_STATE(g_array_index(self
->parent
.tracefiles
,
648 LttvTracefileContext
*, i
));
649 type
= lttv_attribute_get(tracefiles_tree
, i
, &name
, &value
);
650 g_assert(type
== LTTV_GOBJECT
);
651 tracefile_tree
= *((LttvAttribute
**)(value
.v_gobject
));
653 type
= lttv_attribute_get_by_name(tracefile_tree
, LTTV_STATE_EVENT
,
655 g_assert(type
== LTTV_POINTER
);
656 if(*(value
.v_pointer
) != NULL
) g_free(*(value
.v_pointer
));
658 g_object_unref(G_OBJECT(tracefiles_tree
));
662 static void free_saved_state(LttvTraceState
*self
)
666 LttvAttributeType type
;
668 LttvAttributeValue value
;
670 LttvAttributeName name
;
672 LttvAttribute
*saved_states
;
674 saved_states
= lttv_attribute_find_subdir(self
->parent
.t_a
,
675 LTTV_STATE_SAVED_STATES
);
677 nb
= lttv_attribute_get_number(saved_states
);
678 for(i
= 0 ; i
< nb
; i
++) {
679 type
= lttv_attribute_get(saved_states
, i
, &name
, &value
);
680 g_assert(type
== LTTV_GOBJECT
);
681 state_saved_free(self
, *((LttvAttribute
**)value
.v_gobject
));
684 lttv_attribute_remove_by_name(self
->parent
.t_a
, LTTV_STATE_SAVED_STATES
);
689 create_max_time(LttvTraceState
*tcs
)
691 LttvAttributeValue v
;
693 lttv_attribute_find(tcs
->parent
.t_a
, LTTV_STATE_SAVED_STATES_TIME
,
695 g_assert(*(v
.v_pointer
) == NULL
);
696 *(v
.v_pointer
) = g_new(LttTime
,1);
697 *((LttTime
*)*(v
.v_pointer
)) = ltt_time_zero
;
702 get_max_time(LttvTraceState
*tcs
)
704 LttvAttributeValue v
;
706 lttv_attribute_find(tcs
->parent
.t_a
, LTTV_STATE_SAVED_STATES_TIME
,
708 g_assert(*(v
.v_pointer
) != NULL
);
709 tcs
->max_time_state_recomputed_in_seek
= (LttTime
*)*(v
.v_pointer
);
714 free_max_time(LttvTraceState
*tcs
)
716 LttvAttributeValue v
;
718 lttv_attribute_find(tcs
->parent
.t_a
, LTTV_STATE_SAVED_STATES_TIME
,
720 g_free(*(v
.v_pointer
));
721 *(v
.v_pointer
) = NULL
;
725 typedef struct _LttvNameTables
{
726 // FIXME GQuark *eventtype_names;
727 GQuark
*syscall_names
;
734 create_name_tables(LttvTraceState
*tcs
)
738 GQuark f_name
, e_name
;
742 LttvTraceHookByFacility
*thf
;
748 GString
*fe_name
= g_string_new("");
750 LttvNameTables
*name_tables
= g_new(LttvNameTables
, 1);
752 LttvAttributeValue v
;
754 lttv_attribute_find(tcs
->parent
.t_a
, LTTV_STATE_NAME_TABLES
,
756 g_assert(*(v
.v_pointer
) == NULL
);
757 *(v
.v_pointer
) = name_tables
;
758 #if 0 // Use iteration over the facilities_by_name and then list all event
759 // types of each facility
760 nb
= ltt_trace_eventtype_number(tcs
->parent
.t
);
761 name_tables
->eventtype_names
= g_new(GQuark
, nb
);
762 for(i
= 0 ; i
< nb
; i
++) {
763 et
= ltt_trace_eventtype_get(tcs
->parent
.t
, i
);
764 e_name
= ltt_eventtype_name(et
);
765 f_name
= ltt_facility_name(ltt_eventtype_facility(et
));
766 g_string_printf(fe_name
, "%s.%s", f_name
, e_name
);
767 name_tables
->eventtype_names
[i
] = g_quark_from_string(fe_name
->str
);
770 if(lttv_trace_find_hook(tcs
->parent
.t
,
771 LTT_FACILITY_KERNEL
, LTT_EVENT_SYSCALL_ENTRY
,
772 LTT_FIELD_SYSCALL_ID
, 0, 0,
776 thf
= lttv_trace_hook_get_first(&h
);
778 t
= ltt_field_type(thf
->f1
);
779 //nb = ltt_type_element_number(t);
781 lttv_trace_hook_destroy(&h
);
783 /* CHECK syscalls should be an enum but currently are not!
784 name_tables->syscall_names = g_new(GQuark, nb);
786 for(i = 0 ; i < nb ; i++) {
787 name_tables->syscall_names[i] = g_quark_from_string(
788 ltt_enum_string_get(t, i));
792 name_tables
->syscall_names
= g_new(GQuark
, 256);
793 for(i
= 0 ; i
< 256 ; i
++) {
794 g_string_printf(fe_name
, "syscall %d", i
);
795 name_tables
->syscall_names
[i
] = g_quark_from_string(fe_name
->str
);
798 if(lttv_trace_find_hook(tcs
->parent
.t
, LTT_FACILITY_KERNEL
,
799 LTT_EVENT_TRAP_ENTRY
,
800 LTT_FIELD_TRAP_ID
, 0, 0,
804 thf
= lttv_trace_hook_get_first(&h
);
806 t
= ltt_field_type(thf
->f1
);
807 //nb = ltt_type_element_number(t);
809 lttv_trace_hook_destroy(&h
);
812 name_tables->trap_names = g_new(GQuark, nb);
813 for(i = 0 ; i < nb ; i++) {
814 name_tables->trap_names[i] = g_quark_from_string(
815 ltt_enum_string_get(t, i));
819 name_tables
->trap_names
= g_new(GQuark
, 256);
820 for(i
= 0 ; i
< 256 ; i
++) {
821 g_string_printf(fe_name
, "trap %d", i
);
822 name_tables
->trap_names
[i
] = g_quark_from_string(fe_name
->str
);
825 if(lttv_trace_find_hook(tcs
->parent
.t
,
826 LTT_FACILITY_KERNEL
, LTT_EVENT_IRQ_ENTRY
,
827 LTT_FIELD_IRQ_ID
, 0, 0,
831 thf
= lttv_trace_hook_get_first(&h
);
833 t
= ltt_field_type(thf
->f1
);
834 //nb = ltt_type_element_number(t);
836 lttv_trace_hook_destroy(&h
);
839 name_tables->irq_names = g_new(GQuark, nb);
840 for(i = 0 ; i < nb ; i++) {
841 name_tables->irq_names[i] = g_quark_from_string(ltt_enum_string_get(t, i));
845 name_tables
->irq_names
= g_new(GQuark
, 256);
846 for(i
= 0 ; i
< 256 ; i
++) {
847 g_string_printf(fe_name
, "irq %d", i
);
848 name_tables
->irq_names
[i
] = g_quark_from_string(fe_name
->str
);
851 g_string_free(fe_name
, TRUE
);
856 get_name_tables(LttvTraceState
*tcs
)
858 LttvNameTables
*name_tables
;
860 LttvAttributeValue v
;
862 lttv_attribute_find(tcs
->parent
.t_a
, LTTV_STATE_NAME_TABLES
,
864 g_assert(*(v
.v_pointer
) != NULL
);
865 name_tables
= (LttvNameTables
*)*(v
.v_pointer
);
866 //tcs->eventtype_names = name_tables->eventtype_names;
867 tcs
->syscall_names
= name_tables
->syscall_names
;
868 tcs
->trap_names
= name_tables
->trap_names
;
869 tcs
->irq_names
= name_tables
->irq_names
;
874 free_name_tables(LttvTraceState
*tcs
)
876 LttvNameTables
*name_tables
;
878 LttvAttributeValue v
;
880 lttv_attribute_find(tcs
->parent
.t_a
, LTTV_STATE_NAME_TABLES
,
882 name_tables
= (LttvNameTables
*)*(v
.v_pointer
);
883 *(v
.v_pointer
) = NULL
;
885 // g_free(name_tables->eventtype_names);
886 g_free(name_tables
->syscall_names
);
887 g_free(name_tables
->trap_names
);
888 g_free(name_tables
->irq_names
);
892 #ifdef HASH_TABLE_DEBUG
894 static void test_process(gpointer key
, gpointer value
, gpointer user_data
)
896 LttvProcessState
*process
= (LttvProcessState
*)value
;
898 /* Test for process corruption */
899 guint stack_len
= process
->execution_stack
->len
;
902 static void hash_table_check(GHashTable
*table
)
904 g_hash_table_foreach(table
, test_process
, NULL
);
911 static void push_state(LttvTracefileState
*tfs
, LttvExecutionMode t
,
914 LttvExecutionState
*es
;
916 guint cpu
= ltt_tracefile_num(tfs
->parent
.tf
);
917 LttvTraceState
*ts
= (LttvTraceState
*)tfs
->parent
.t_context
;
919 #ifdef HASH_TABLE_DEBUG
920 hash_table_check(ts
->processes
);
922 LttvProcessState
*process
= ts
->running_process
[cpu
];
924 guint depth
= process
->execution_stack
->len
;
926 process
->execution_stack
=
927 g_array_set_size(process
->execution_stack
, depth
+ 1);
930 &g_array_index(process
->execution_stack
, LttvExecutionState
, depth
- 1);
932 es
= &g_array_index(process
->execution_stack
, LttvExecutionState
, depth
);
935 es
->entry
= es
->change
= tfs
->parent
.timestamp
;
936 es
->s
= process
->state
->s
;
941 static void pop_state(LttvTracefileState
*tfs
, LttvExecutionMode t
)
943 guint cpu
= ltt_tracefile_num(tfs
->parent
.tf
);
944 LttvTraceState
*ts
= (LttvTraceState
*)tfs
->parent
.t_context
;
945 LttvProcessState
*process
= ts
->running_process
[cpu
];
947 guint depth
= process
->execution_stack
->len
;
949 if(process
->state
->t
!= t
){
950 g_info("Different execution mode type (%lu.%09lu): ignore it\n",
951 tfs
->parent
.timestamp
.tv_sec
, tfs
->parent
.timestamp
.tv_nsec
);
952 g_info("process state has %s when pop_int is %s\n",
953 g_quark_to_string(process
->state
->t
),
954 g_quark_to_string(t
));
955 g_info("{ %u, %u, %s, %s }\n",
958 g_quark_to_string(process
->name
),
959 g_quark_to_string(process
->state
->s
));
964 g_info("Trying to pop last state on stack (%lu.%09lu): ignore it\n",
965 tfs
->parent
.timestamp
.tv_sec
, tfs
->parent
.timestamp
.tv_nsec
);
969 process
->execution_stack
=
970 g_array_set_size(process
->execution_stack
, depth
- 1);
971 process
->state
= &g_array_index(process
->execution_stack
, LttvExecutionState
,
973 process
->state
->change
= tfs
->parent
.timestamp
;
978 lttv_state_create_process(LttvTraceState
*tcs
, LttvProcessState
*parent
,
979 guint cpu
, guint pid
, const LttTime
*timestamp
)
981 LttvProcessState
*process
= g_new(LttvProcessState
, 1);
983 LttvExecutionState
*es
;
985 LttvTraceContext
*tc
= (LttvTraceContext
*)tcs
;
991 //process->last_cpu = tfs->cpu_name;
992 //process->last_cpu_index = ltt_tracefile_num(((LttvTracefileContext*)tfs)->tf);
993 g_info("Process %u, core %p", process
->pid
, process
);
994 g_hash_table_insert(tcs
->processes
, process
, process
);
997 process
->ppid
= parent
->pid
;
998 process
->name
= parent
->name
;
999 process
->creation_time
= *timestamp
;
1002 /* No parent. This process exists but we are missing all information about
1003 its creation. The birth time is set to zero but we remember the time of
1008 process
->name
= LTTV_STATE_UNNAMED
;
1009 process
->creation_time
= ltt_time_zero
;
1012 process
->insertion_time
= *timestamp
;
1013 sprintf(buffer
,"%d-%lu.%lu",pid
, process
->creation_time
.tv_sec
,
1014 process
->creation_time
.tv_nsec
);
1015 process
->pid_time
= g_quark_from_string(buffer
);
1017 //process->last_cpu = tfs->cpu_name;
1018 //process->last_cpu_index = ltt_tracefile_num(((LttvTracefileContext*)tfs)->tf);
1019 process
->execution_stack
= g_array_sized_new(FALSE
, FALSE
,
1020 sizeof(LttvExecutionState
), PREALLOCATED_EXECUTION_STACK
);
1021 process
->execution_stack
= g_array_set_size(process
->execution_stack
, 2);
1022 es
= process
->state
= &g_array_index(process
->execution_stack
,
1023 LttvExecutionState
, 0);
1024 es
->t
= LTTV_STATE_USER_MODE
;
1025 es
->n
= LTTV_STATE_SUBMODE_NONE
;
1026 es
->entry
= *timestamp
;
1027 //g_assert(timestamp->tv_sec != 0);
1028 es
->change
= *timestamp
;
1029 es
->s
= LTTV_STATE_RUN
;
1031 es
= process
->state
= &g_array_index(process
->execution_stack
,
1032 LttvExecutionState
, 1);
1033 es
->t
= LTTV_STATE_SYSCALL
;
1034 es
->n
= LTTV_STATE_SUBMODE_NONE
;
1035 es
->entry
= *timestamp
;
1036 //g_assert(timestamp->tv_sec != 0);
1037 es
->change
= *timestamp
;
1038 es
->s
= LTTV_STATE_WAIT_FORK
;
1043 LttvProcessState
*lttv_state_find_process(LttvTraceState
*ts
, guint cpu
,
1046 LttvProcessState key
;
1047 LttvProcessState
*process
;
1051 process
= g_hash_table_lookup(ts
->processes
, &key
);
1056 lttv_state_find_process_or_create(LttvTraceState
*ts
, guint cpu
, guint pid
,
1059 LttvProcessState
*process
= lttv_state_find_process(ts
, cpu
, pid
);
1061 /* Put ltt_time_zero creation time for unexisting processes */
1062 if(unlikely(process
== NULL
)) process
= lttv_state_create_process(ts
,
1063 NULL
, cpu
, pid
, timestamp
);
1067 /* FIXME : this function should be called when we receive an event telling that
1068 * release_task has been called in the kernel. In happens generally when
1069 * the parent waits for its child terminaison, but may also happen in special
1070 * cases in the child's exit : when the parent ignores its children SIGCCHLD or
1071 * has the flag SA_NOCLDWAIT. It can also happen when the child is part
1072 * of a killed thread ground, but isn't the leader.
1074 static void exit_process(LttvTracefileState
*tfs
, LttvProcessState
*process
)
1076 LttvTraceState
*ts
= LTTV_TRACE_STATE(tfs
->parent
.t_context
);
1077 LttvProcessState key
;
1079 key
.pid
= process
->pid
;
1080 key
.cpu
= process
->cpu
;
1081 g_hash_table_remove(ts
->processes
, &key
);
1082 g_array_free(process
->execution_stack
, TRUE
);
1087 static void free_process_state(gpointer key
, gpointer value
,gpointer user_data
)
1089 g_array_free(((LttvProcessState
*)value
)->execution_stack
, TRUE
);
1094 static void lttv_state_free_process_table(GHashTable
*processes
)
1096 g_hash_table_foreach(processes
, free_process_state
, NULL
);
1097 g_hash_table_destroy(processes
);
1101 static gboolean
syscall_entry(void *hook_data
, void *call_data
)
1103 LttvTracefileState
*s
= (LttvTracefileState
*)call_data
;
1104 LttEvent
*e
= ltt_tracefile_get_event(s
->parent
.tf
);
1105 LttvTraceHookByFacility
*thf
= (LttvTraceHookByFacility
*)hook_data
;
1106 LttField
*f
= thf
->f1
;
1108 LttvExecutionSubmode submode
;
1110 submode
= ((LttvTraceState
*)(s
->parent
.t_context
))->syscall_names
[
1111 ltt_event_get_unsigned(e
, f
)];
1112 push_state(s
, LTTV_STATE_SYSCALL
, submode
);
1117 static gboolean
syscall_exit(void *hook_data
, void *call_data
)
1119 LttvTracefileState
*s
= (LttvTracefileState
*)call_data
;
1121 pop_state(s
, LTTV_STATE_SYSCALL
);
1126 static gboolean
trap_entry(void *hook_data
, void *call_data
)
1128 LttvTracefileState
*s
= (LttvTracefileState
*)call_data
;
1129 LttEvent
*e
= ltt_tracefile_get_event(s
->parent
.tf
);
1130 LttvTraceHookByFacility
*thf
= (LttvTraceHookByFacility
*)hook_data
;
1131 LttField
*f
= thf
->f1
;
1133 LttvExecutionSubmode submode
;
1135 submode
= ((LttvTraceState
*)(s
->parent
.t_context
))->trap_names
[
1136 ltt_event_get_unsigned(e
, f
)];
1137 push_state(s
, LTTV_STATE_TRAP
, submode
);
1142 static gboolean
trap_exit(void *hook_data
, void *call_data
)
1144 LttvTracefileState
*s
= (LttvTracefileState
*)call_data
;
1146 pop_state(s
, LTTV_STATE_TRAP
);
1151 static gboolean
irq_entry(void *hook_data
, void *call_data
)
1153 LttvTracefileState
*s
= (LttvTracefileState
*)call_data
;
1154 LttEvent
*e
= ltt_tracefile_get_event(s
->parent
.tf
);
1155 guint8 fac_id
= ltt_event_facility_id(e
);
1156 guint8 ev_id
= ltt_event_eventtype_id(e
);
1157 LttvTraceHookByFacility
*thf
= (LttvTraceHookByFacility
*)hook_data
;
1158 // g_assert(lttv_trace_hook_get_first((LttvTraceHook *)hook_data)->f1 != NULL);
1159 g_assert(thf
->f1
!= NULL
);
1160 // g_assert(thf == lttv_trace_hook_get_first((LttvTraceHook *)hook_data));
1161 LttField
*f
= thf
->f1
;
1163 LttvExecutionSubmode submode
;
1165 submode
= ((LttvTraceState
*)(s
->parent
.t_context
))->irq_names
[
1166 ltt_event_get_unsigned(e
, f
)];
1168 /* Do something with the info about being in user or system mode when int? */
1169 push_state(s
, LTTV_STATE_IRQ
, submode
);
1174 static gboolean
irq_exit(void *hook_data
, void *call_data
)
1176 LttvTracefileState
*s
= (LttvTracefileState
*)call_data
;
1178 pop_state(s
, LTTV_STATE_IRQ
);
1183 static gboolean
schedchange(void *hook_data
, void *call_data
)
1185 LttvTracefileState
*s
= (LttvTracefileState
*)call_data
;
1186 guint cpu
= ltt_tracefile_num(s
->parent
.tf
);
1187 LttvTraceState
*ts
= (LttvTraceState
*)s
->parent
.t_context
;
1188 LttvProcessState
*process
= ts
->running_process
[cpu
];
1190 LttEvent
*e
= ltt_tracefile_get_event(s
->parent
.tf
);
1191 LttvTraceHookByFacility
*thf
= (LttvTraceHookByFacility
*)hook_data
;
1192 guint pid_in
, pid_out
;
1195 pid_out
= ltt_event_get_unsigned(e
, thf
->f1
);
1196 pid_in
= ltt_event_get_unsigned(e
, thf
->f2
);
1197 state_out
= ltt_event_get_int(e
, thf
->f3
);
1199 if(likely(process
!= NULL
)) {
1201 /* We could not know but it was not the idle process executing.
1202 This should only happen at the beginning, before the first schedule
1203 event, and when the initial information (current process for each CPU)
1204 is missing. It is not obvious how we could, after the fact, compensate
1205 the wrongly attributed statistics. */
1207 //This test only makes sense once the state is known and if there is no
1209 //if(unlikely(process->pid != pid_out)) {
1210 // g_assert(process->pid == 0);
1213 if(unlikely(process
->state
->s
== LTTV_STATE_EXIT
)) {
1214 process
->state
->s
= LTTV_STATE_ZOMBIE
;
1215 process
->state
->change
= s
->parent
.timestamp
;
1217 if(unlikely(state_out
== 0)) process
->state
->s
= LTTV_STATE_WAIT_CPU
;
1218 else process
->state
->s
= LTTV_STATE_WAIT
;
1219 process
->state
->change
= s
->parent
.timestamp
;
1223 exit_process(s
, process
); /* EXIT_DEAD */
1224 /* see sched.h for states */
1226 process
= ts
->running_process
[cpu
] =
1227 lttv_state_find_process_or_create(
1228 (LttvTraceState
*)s
->parent
.t_context
,
1230 &s
->parent
.timestamp
);
1231 process
->state
->s
= LTTV_STATE_RUN
;
1233 // process->last_cpu_index = ltt_tracefile_num(((LttvTracefileContext*)s)->tf);
1234 process
->state
->change
= s
->parent
.timestamp
;
1238 static gboolean
process_fork(void *hook_data
, void *call_data
)
1240 LttvTracefileState
*s
= (LttvTracefileState
*)call_data
;
1241 LttEvent
*e
= ltt_tracefile_get_event(s
->parent
.tf
);
1242 LttvTraceHookByFacility
*thf
= (LttvTraceHookByFacility
*)hook_data
;
1246 LttvProcessState
*zombie_process
;
1247 guint cpu
= ltt_tracefile_num(s
->parent
.tf
);
1248 LttvTraceState
*ts
= (LttvTraceState
*)s
->parent
.t_context
;
1249 LttvProcessState
*process
= ts
->running_process
[cpu
];
1250 LttvProcessState
*child_process
;
1254 parent_pid
= ltt_event_get_unsigned(e
, f
);
1258 child_pid
= ltt_event_get_unsigned(e
, f
);
1260 /* Mathieu : it seems like the process might have been scheduled in before the
1261 * fork, and, in a rare case, might be the current process. This might happen
1262 * in a SMP case where we don't have enough precision on the clocks.
1264 * Test reenabled after precision fixes on time. (Mathieu) */
1266 zombie_process
= lttv_state_find_process(ts
, ANY_CPU
, child_pid
);
1268 if(unlikely(zombie_process
!= NULL
)) {
1269 /* Reutilisation of PID. Only now we are sure that the old PID
1270 * has been released. FIXME : should know when release_task happens instead.
1272 guint num_cpus
= ltt_trace_get_num_cpu(ts
->parent
.t
);
1274 for(i
=0; i
< num_cpus
; i
++) {
1275 g_assert(zombie_process
!= ts
->running_process
[i
]);
1278 exit_process(s
, zombie_process
);
1281 g_assert(process
->pid
!= child_pid
);
1282 // FIXME : Add this test in the "known state" section
1283 // g_assert(process->pid == parent_pid);
1284 child_process
= lttv_state_find_process(ts
, ANY_CPU
, child_pid
);
1285 if(child_process
== NULL
) {
1286 lttv_state_create_process(ts
, process
, cpu
,
1287 child_pid
, &s
->parent
.timestamp
);
1289 /* The process has already been created : due to time imprecision between
1290 * multiple CPUs : it has been scheduled in before creation. Note that we
1291 * shouldn't have this kind of imprecision.
1293 * Simply put a correct parent.
1295 g_assert(0); /* This is a problematic case : the process has been created
1296 before the fork event */
1297 child_process
->ppid
= process
->pid
;
1304 static gboolean
process_exit(void *hook_data
, void *call_data
)
1306 LttvTracefileState
*s
= (LttvTracefileState
*)call_data
;
1307 LttEvent
*e
= ltt_tracefile_get_event(s
->parent
.tf
);
1308 LttvTraceHookByFacility
*thf
= (LttvTraceHookByFacility
*)hook_data
;
1311 guint cpu
= ltt_tracefile_num(s
->parent
.tf
);
1312 LttvTraceState
*ts
= (LttvTraceState
*)s
->parent
.t_context
;
1313 LttvProcessState
*process
= ts
->running_process
[cpu
];
1315 pid
= ltt_event_get_unsigned(e
, thf
->f1
);
1317 // FIXME : Add this test in the "known state" section
1318 // g_assert(process->pid == pid);
1320 if(likely(process
!= NULL
)) {
1321 process
->state
->s
= LTTV_STATE_EXIT
;
1326 static gboolean
process_free(void *hook_data
, void *call_data
)
1328 LttvTracefileState
*s
= (LttvTracefileState
*)call_data
;
1329 LttvTraceState
*ts
= (LttvTraceState
*)s
->parent
.t_context
;
1330 LttEvent
*e
= ltt_tracefile_get_event(s
->parent
.tf
);
1331 LttvTraceHookByFacility
*thf
= (LttvTraceHookByFacility
*)hook_data
;
1333 LttvProcessState
*process
;
1335 /* PID of the process to release */
1336 release_pid
= ltt_event_get_unsigned(e
, thf
->f1
);
1338 g_assert(release_pid
!= 0);
1340 process
= lttv_state_find_process(ts
, ANY_CPU
, release_pid
);
1342 if(likely(process
!= NULL
)) {
1343 /* release_task is happening at kernel level : we can now safely release
1344 * the data structure of the process */
1345 //This test is fun, though, as it may happen that
1346 //at time t : CPU 0 : process_free
1347 //at time t+150ns : CPU 1 : schedule out
1348 //Clearly due to time imprecision, we disable it. (Mathieu)
1349 //If this weird case happen, we have no choice but to put the
1350 //Currently running process on the cpu to 0.
1351 //I re-enable it following time precision fixes. (Mathieu)
1352 //Well, in the case where an process is freed by a process on another CPU
1353 //and still scheduled, it happens that this is the schedchange that will
1354 //drop the last reference count. Do not free it here!
1355 guint num_cpus
= ltt_trace_get_num_cpu(ts
->parent
.t
);
1357 for(i
=0; i
< num_cpus
; i
++) {
1358 //g_assert(process != ts->running_process[i]);
1359 if(process
== ts
->running_process
[i
]) {
1360 //ts->running_process[i] = lttv_state_find_process(ts, i, 0);
1364 if(i
== num_cpus
) /* process is not scheduled */
1365 exit_process(s
, process
);
1372 static gboolean
process_exec(void *hook_data
, void *call_data
)
1374 LttvTracefileState
*s
= (LttvTracefileState
*)call_data
;
1375 LttvTraceState
*ts
= (LttvTraceState
*)s
->parent
.t_context
;
1376 LttEvent
*e
= ltt_tracefile_get_event(s
->parent
.tf
);
1377 LttvTraceHookByFacility
*thf
= (LttvTraceHookByFacility
*)hook_data
;
1379 guint cpu
= ltt_tracefile_num(s
->parent
.tf
);
1380 LttvProcessState
*process
= ts
->running_process
[cpu
];
1382 /* PID of the process to release */
1383 guint64 name_len
= ltt_event_field_element_number(e
, thf
->f1
);
1384 //name = ltt_event_get_string(e, thf->f1);
1385 gchar
*name_begin
= ltt_event_field_element_select(e
, thf
->f1
, 0);
1386 gchar
*null_term_name
= g_new(gchar
, name_len
+1);
1387 memcpy(null_term_name
, name_begin
, name_len
);
1388 null_term_name
[name_len
] = '\0';
1390 process
->name
= g_quark_from_string(null_term_name
);
1398 gint
lttv_state_hook_add_event_hooks(void *hook_data
, void *call_data
)
1400 LttvTracesetState
*tss
= (LttvTracesetState
*)(call_data
);
1402 lttv_state_add_event_hooks(tss
);
1407 void lttv_state_add_event_hooks(LttvTracesetState
*self
)
1409 LttvTraceset
*traceset
= self
->parent
.ts
;
1411 guint i
, j
, k
, l
, nb_trace
, nb_tracefile
;
1415 LttvTracefileState
*tfs
;
1419 LttvTraceHookByFacility
*thf
;
1421 LttvTraceHook
*hook
;
1423 LttvAttributeValue val
;
1427 nb_trace
= lttv_traceset_number(traceset
);
1428 for(i
= 0 ; i
< nb_trace
; i
++) {
1429 ts
= (LttvTraceState
*)self
->parent
.traces
[i
];
1431 /* Find the eventtype id for the following events and register the
1432 associated by id hooks. */
1434 hooks
= g_array_sized_new(FALSE
, FALSE
, sizeof(LttvTraceHook
), 11);
1435 hooks
= g_array_set_size(hooks
, 11);
1437 ret
= lttv_trace_find_hook(ts
->parent
.t
,
1438 LTT_FACILITY_KERNEL
, LTT_EVENT_SYSCALL_ENTRY
,
1439 LTT_FIELD_SYSCALL_ID
, 0, 0,
1440 syscall_entry
, NULL
, &g_array_index(hooks
, LttvTraceHook
, 0));
1443 ret
= lttv_trace_find_hook(ts
->parent
.t
,
1444 LTT_FACILITY_KERNEL
, LTT_EVENT_SYSCALL_EXIT
,
1446 syscall_exit
, NULL
, &g_array_index(hooks
, LttvTraceHook
, 1));
1449 ret
= lttv_trace_find_hook(ts
->parent
.t
,
1450 LTT_FACILITY_KERNEL
, LTT_EVENT_TRAP_ENTRY
,
1451 LTT_FIELD_TRAP_ID
, 0, 0,
1452 trap_entry
, NULL
, &g_array_index(hooks
, LttvTraceHook
, 2));
1455 ret
= lttv_trace_find_hook(ts
->parent
.t
,
1456 LTT_FACILITY_KERNEL
, LTT_EVENT_TRAP_EXIT
,
1458 trap_exit
, NULL
, &g_array_index(hooks
, LttvTraceHook
, 3));
1461 ret
= lttv_trace_find_hook(ts
->parent
.t
,
1462 LTT_FACILITY_KERNEL
, LTT_EVENT_IRQ_ENTRY
,
1463 LTT_FIELD_IRQ_ID
, 0, 0,
1464 irq_entry
, NULL
, &g_array_index(hooks
, LttvTraceHook
, 4));
1467 ret
= lttv_trace_find_hook(ts
->parent
.t
,
1468 LTT_FACILITY_KERNEL
, LTT_EVENT_IRQ_EXIT
,
1470 irq_exit
, NULL
, &g_array_index(hooks
, LttvTraceHook
, 5));
1473 ret
= lttv_trace_find_hook(ts
->parent
.t
,
1474 LTT_FACILITY_PROCESS
, LTT_EVENT_SCHEDCHANGE
,
1475 LTT_FIELD_OUT
, LTT_FIELD_IN
, LTT_FIELD_OUT_STATE
,
1476 schedchange
, NULL
, &g_array_index(hooks
, LttvTraceHook
, 6));
1479 ret
= lttv_trace_find_hook(ts
->parent
.t
,
1480 LTT_FACILITY_PROCESS
, LTT_EVENT_FORK
,
1481 LTT_FIELD_PARENT_PID
, LTT_FIELD_CHILD_PID
, 0,
1482 process_fork
, NULL
, &g_array_index(hooks
, LttvTraceHook
, 7));
1485 ret
= lttv_trace_find_hook(ts
->parent
.t
,
1486 LTT_FACILITY_PROCESS
, LTT_EVENT_EXIT
,
1487 LTT_FIELD_PID
, 0, 0,
1488 process_exit
, NULL
, &g_array_index(hooks
, LttvTraceHook
, 8));
1491 ret
= lttv_trace_find_hook(ts
->parent
.t
,
1492 LTT_FACILITY_PROCESS
, LTT_EVENT_FREE
,
1493 LTT_FIELD_PID
, 0, 0,
1494 process_free
, NULL
, &g_array_index(hooks
, LttvTraceHook
, 9));
1497 ret
= lttv_trace_find_hook(ts
->parent
.t
,
1498 LTT_FACILITY_FS
, LTT_EVENT_EXEC
,
1499 LTT_FIELD_FILENAME
, 0, 0,
1500 process_exec
, NULL
, &g_array_index(hooks
, LttvTraceHook
, 10));
1505 /* Add these hooks to each event_by_id hooks list */
1507 nb_tracefile
= ts
->parent
.tracefiles
->len
;
1509 for(j
= 0 ; j
< nb_tracefile
; j
++) {
1511 LTTV_TRACEFILE_STATE(g_array_index(ts
->parent
.tracefiles
,
1512 LttvTracefileContext
*, j
));
1514 for(k
= 0 ; k
< hooks
->len
; k
++) {
1515 hook
= &g_array_index(hooks
, LttvTraceHook
, k
);
1516 for(l
=0;l
<hook
->fac_list
->len
;l
++) {
1517 thf
= g_array_index(hook
->fac_list
, LttvTraceHookByFacility
*, l
);
1519 lttv_hooks_by_id_find(tfs
->parent
.event_by_id
, thf
->id
),
1526 lttv_attribute_find(self
->parent
.a
, LTTV_STATE_HOOKS
, LTTV_POINTER
, &val
);
1527 *(val
.v_pointer
) = hooks
;
1531 gint
lttv_state_hook_remove_event_hooks(void *hook_data
, void *call_data
)
1533 LttvTracesetState
*tss
= (LttvTracesetState
*)(call_data
);
1535 lttv_state_remove_event_hooks(tss
);
1540 void lttv_state_remove_event_hooks(LttvTracesetState
*self
)
1542 LttvTraceset
*traceset
= self
->parent
.ts
;
1544 guint i
, j
, k
, l
, nb_trace
, nb_tracefile
;
1548 LttvTracefileState
*tfs
;
1552 LttvTraceHook
*hook
;
1554 LttvTraceHookByFacility
*thf
;
1556 LttvAttributeValue val
;
1558 nb_trace
= lttv_traceset_number(traceset
);
1559 for(i
= 0 ; i
< nb_trace
; i
++) {
1560 ts
= LTTV_TRACE_STATE(self
->parent
.traces
[i
]);
1561 lttv_attribute_find(self
->parent
.a
, LTTV_STATE_HOOKS
, LTTV_POINTER
, &val
);
1562 hooks
= *(val
.v_pointer
);
1564 /* Remove these hooks from each event_by_id hooks list */
1566 nb_tracefile
= ts
->parent
.tracefiles
->len
;
1568 for(j
= 0 ; j
< nb_tracefile
; j
++) {
1570 LTTV_TRACEFILE_STATE(g_array_index(ts
->parent
.tracefiles
,
1571 LttvTracefileContext
*, j
));
1573 for(k
= 0 ; k
< hooks
->len
; k
++) {
1574 hook
= &g_array_index(hooks
, LttvTraceHook
, k
);
1575 for(l
=0;l
<hook
->fac_list
->len
;l
++) {
1576 thf
= g_array_index(hook
->fac_list
, LttvTraceHookByFacility
*, l
);
1578 lttv_hooks_remove_data(
1579 lttv_hooks_by_id_find(tfs
->parent
.event_by_id
, thf
->id
),
1585 for(k
= 0 ; k
< hooks
->len
; k
++)
1586 lttv_trace_hook_destroy(&g_array_index(hooks
, LttvTraceHook
, k
));
1587 g_array_free(hooks
, TRUE
);
1591 static gboolean
state_save_event_hook(void *hook_data
, void *call_data
)
1593 guint
*event_count
= (guint
*)hook_data
;
1595 /* Only save at LTTV_STATE_SAVE_INTERVAL */
1596 if(likely((*event_count
)++ < LTTV_STATE_SAVE_INTERVAL
))
1601 LttvTracefileState
*self
= (LttvTracefileState
*)call_data
;
1603 LttvTracefileState
*tfcs
;
1605 LttvTraceState
*tcs
= (LttvTraceState
*)(self
->parent
.t_context
);
1607 LttEventPosition
*ep
;
1613 LttvAttribute
*saved_states_tree
, *saved_state_tree
;
1615 LttvAttributeValue value
;
1617 saved_states_tree
= lttv_attribute_find_subdir(tcs
->parent
.t_a
,
1618 LTTV_STATE_SAVED_STATES
);
1619 saved_state_tree
= g_object_new(LTTV_ATTRIBUTE_TYPE
, NULL
);
1620 value
= lttv_attribute_add(saved_states_tree
,
1621 lttv_attribute_get_number(saved_states_tree
), LTTV_GOBJECT
);
1622 *(value
.v_gobject
) = (GObject
*)saved_state_tree
;
1623 value
= lttv_attribute_add(saved_state_tree
, LTTV_STATE_TIME
, LTTV_TIME
);
1624 *(value
.v_time
) = self
->parent
.timestamp
;
1625 lttv_state_save(tcs
, saved_state_tree
);
1626 g_debug("Saving state at time %lu.%lu", self
->parent
.timestamp
.tv_sec
,
1627 self
->parent
.timestamp
.tv_nsec
);
1629 *(tcs
->max_time_state_recomputed_in_seek
) = self
->parent
.timestamp
;
1634 static gboolean
state_save_after_trace_hook(void *hook_data
, void *call_data
)
1636 LttvTraceState
*tcs
= (LttvTraceState
*)(call_data
);
1638 *(tcs
->max_time_state_recomputed_in_seek
) = tcs
->parent
.time_span
.end_time
;
1644 static gboolean
block_start(void *hook_data
, void *call_data
)
1646 LttvTracefileState
*self
= (LttvTracefileState
*)call_data
;
1648 LttvTracefileState
*tfcs
;
1650 LttvTraceState
*tcs
= (LttvTraceState
*)(self
->parent
.t_context
);
1652 LttEventPosition
*ep
;
1654 guint i
, nb_block
, nb_event
, nb_tracefile
;
1658 LttvAttribute
*saved_states_tree
, *saved_state_tree
;
1660 LttvAttributeValue value
;
1662 ep
= ltt_event_position_new();
1664 nb_tracefile
= tcs
->parent
.tracefiles
->len
;
1666 /* Count the number of events added since the last block end in any
1669 for(i
= 0 ; i
< nb_tracefile
; i
++) {
1671 LTTV_TRACEFILE_STATE(&g_array_index(tcs
->parent
.tracefiles
,
1672 LttvTracefileContext
, i
));
1673 ltt_event_position(tfcs
->parent
.e
, ep
);
1674 ltt_event_position_get(ep
, &nb_block
, &nb_event
, &tf
);
1675 tcs
->nb_event
+= nb_event
- tfcs
->saved_position
;
1676 tfcs
->saved_position
= nb_event
;
1680 if(tcs
->nb_event
>= tcs
->save_interval
) {
1681 saved_states_tree
= lttv_attribute_find_subdir(tcs
->parent
.t_a
,
1682 LTTV_STATE_SAVED_STATES
);
1683 saved_state_tree
= g_object_new(LTTV_ATTRIBUTE_TYPE
, NULL
);
1684 value
= lttv_attribute_add(saved_states_tree
,
1685 lttv_attribute_get_number(saved_states_tree
), LTTV_GOBJECT
);
1686 *(value
.v_gobject
) = (GObject
*)saved_state_tree
;
1687 value
= lttv_attribute_add(saved_state_tree
, LTTV_STATE_TIME
, LTTV_TIME
);
1688 *(value
.v_time
) = self
->parent
.timestamp
;
1689 lttv_state_save(tcs
, saved_state_tree
);
1691 g_debug("Saving state at time %lu.%lu", self
->parent
.timestamp
.tv_sec
,
1692 self
->parent
.timestamp
.tv_nsec
);
1694 *(tcs
->max_time_state_recomputed_in_seek
) = self
->parent
.timestamp
;
1700 static gboolean
block_end(void *hook_data
, void *call_data
)
1702 LttvTracefileState
*self
= (LttvTracefileState
*)call_data
;
1704 LttvTraceState
*tcs
= (LttvTraceState
*)(self
->parent
.t_context
);
1708 LttEventPosition
*ep
;
1710 guint nb_block
, nb_event
;
1712 ep
= ltt_event_position_new();
1713 ltt_event_position(self
->parent
.e
, ep
);
1714 ltt_event_position_get(ep
, &nb_block
, &nb_event
, &tf
);
1715 tcs
->nb_event
+= nb_event
- self
->saved_position
+ 1;
1716 self
->saved_position
= 0;
1717 *(tcs
->max_time_state_recomputed_in_seek
) = self
->parent
.timestamp
;
1724 void lttv_state_save_add_event_hooks(LttvTracesetState
*self
)
1726 LttvTraceset
*traceset
= self
->parent
.ts
;
1728 guint i
, j
, nb_trace
, nb_tracefile
;
1732 LttvTracefileState
*tfs
;
1734 LttvTraceHook hook_start
, hook_end
;
1736 nb_trace
= lttv_traceset_number(traceset
);
1737 for(i
= 0 ; i
< nb_trace
; i
++) {
1738 ts
= (LttvTraceState
*)self
->parent
.traces
[i
];
1740 lttv_trace_find_hook(ts
->parent
.t
, "core","block_start",NULL
,
1741 NULL
, NULL
, block_start
, &hook_start
);
1742 lttv_trace_find_hook(ts
->parent
.t
, "core","block_end",NULL
,
1743 NULL
, NULL
, block_end
, &hook_end
);
1745 nb_tracefile
= ts
->parent
.tracefiles
->len
;
1747 for(j
= 0 ; j
< nb_tracefile
; j
++) {
1749 LTTV_TRACEFILE_STATE(&g_array_index(ts
->parent
.tracefiles
,
1750 LttvTracefileContext
, j
));
1751 lttv_hooks_add(lttv_hooks_by_id_find(tfs
->parent
.event_by_id
,
1752 hook_start
.id
), hook_start
.h
, NULL
, LTTV_PRIO_STATE
);
1753 lttv_hooks_add(lttv_hooks_by_id_find(tfs
->parent
.event_by_id
,
1754 hook_end
.id
), hook_end
.h
, NULL
, LTTV_PRIO_STATE
);
1760 void lttv_state_save_add_event_hooks(LttvTracesetState
*self
)
1762 LttvTraceset
*traceset
= self
->parent
.ts
;
1764 guint i
, j
, nb_trace
, nb_tracefile
;
1768 LttvTracefileState
*tfs
;
1771 nb_trace
= lttv_traceset_number(traceset
);
1772 for(i
= 0 ; i
< nb_trace
; i
++) {
1774 ts
= (LttvTraceState
*)self
->parent
.traces
[i
];
1775 nb_tracefile
= ts
->parent
.tracefiles
->len
;
1777 guint
*event_count
= g_new(guint
, 1);
1780 for(j
= 0 ; j
< nb_tracefile
; j
++) {
1782 LTTV_TRACEFILE_STATE(g_array_index(ts
->parent
.tracefiles
,
1783 LttvTracefileContext
*, j
));
1784 lttv_hooks_add(tfs
->parent
.event
,
1785 state_save_event_hook
,
1792 lttv_process_traceset_begin(&self
->parent
,
1793 NULL
, NULL
, NULL
, NULL
, NULL
);
1797 gint
lttv_state_save_hook_add_event_hooks(void *hook_data
, void *call_data
)
1799 LttvTracesetState
*tss
= (LttvTracesetState
*)(call_data
);
1801 lttv_state_save_add_event_hooks(tss
);
1808 void lttv_state_save_remove_event_hooks(LttvTracesetState
*self
)
1810 LttvTraceset
*traceset
= self
->parent
.ts
;
1812 guint i
, j
, nb_trace
, nb_tracefile
;
1816 LttvTracefileState
*tfs
;
1818 LttvTraceHook hook_start
, hook_end
;
1820 nb_trace
= lttv_traceset_number(traceset
);
1821 for(i
= 0 ; i
< nb_trace
; i
++) {
1822 ts
= LTTV_TRACE_STATE(self
->parent
.traces
[i
]);
1824 lttv_trace_find_hook(ts
->parent
.t
, "core","block_start",NULL
,
1825 NULL
, NULL
, block_start
, &hook_start
);
1827 lttv_trace_find_hook(ts
->parent
.t
, "core","block_end",NULL
,
1828 NULL
, NULL
, block_end
, &hook_end
);
1830 nb_tracefile
= ts
->parent
.tracefiles
->len
;
1832 for(j
= 0 ; j
< nb_tracefile
; j
++) {
1834 LTTV_TRACEFILE_STATE(&g_array_index(ts
->parent
.tracefiles
,
1835 LttvTracefileContext
, j
));
1836 lttv_hooks_remove_data(lttv_hooks_by_id_find(
1837 tfs
->parent
.event_by_id
, hook_start
.id
), hook_start
.h
, NULL
);
1838 lttv_hooks_remove_data(lttv_hooks_by_id_find(
1839 tfs
->parent
.event_by_id
, hook_end
.id
), hook_end
.h
, NULL
);
1845 void lttv_state_save_remove_event_hooks(LttvTracesetState
*self
)
1847 LttvTraceset
*traceset
= self
->parent
.ts
;
1849 guint i
, j
, nb_trace
, nb_tracefile
;
1853 LttvTracefileState
*tfs
;
1855 LttvHooks
*after_trace
= lttv_hooks_new();
1857 lttv_hooks_add(after_trace
,
1858 state_save_after_trace_hook
,
1863 lttv_process_traceset_end(&self
->parent
,
1864 NULL
, after_trace
, NULL
, NULL
, NULL
);
1866 lttv_hooks_destroy(after_trace
);
1868 nb_trace
= lttv_traceset_number(traceset
);
1869 for(i
= 0 ; i
< nb_trace
; i
++) {
1871 ts
= (LttvTraceState
*)self
->parent
.traces
[i
];
1872 nb_tracefile
= ts
->parent
.tracefiles
->len
;
1874 guint
*event_count
= NULL
;
1876 for(j
= 0 ; j
< nb_tracefile
; j
++) {
1878 LTTV_TRACEFILE_STATE(g_array_index(ts
->parent
.tracefiles
,
1879 LttvTracefileContext
*, j
));
1880 event_count
= lttv_hooks_remove(tfs
->parent
.event
,
1881 state_save_event_hook
);
1883 if(event_count
) g_free(event_count
);
1887 gint
lttv_state_save_hook_remove_event_hooks(void *hook_data
, void *call_data
)
1889 LttvTracesetState
*tss
= (LttvTracesetState
*)(call_data
);
1891 lttv_state_save_remove_event_hooks(tss
);
1896 void lttv_state_traceset_seek_time_closest(LttvTracesetState
*self
, LttTime t
)
1898 LttvTraceset
*traceset
= self
->parent
.ts
;
1902 int min_pos
, mid_pos
, max_pos
;
1904 guint call_rest
= 0;
1906 LttvTraceState
*tcs
;
1908 LttvAttributeValue value
;
1910 LttvAttributeType type
;
1912 LttvAttributeName name
;
1914 LttvAttribute
*saved_states_tree
, *saved_state_tree
, *closest_tree
;
1916 //g_tree_destroy(self->parent.pqueue);
1917 //self->parent.pqueue = g_tree_new(compare_tracefile);
1919 g_info("Entering seek_time_closest for time %lu.%lu", t
.tv_sec
, t
.tv_nsec
);
1921 nb_trace
= lttv_traceset_number(traceset
);
1922 for(i
= 0 ; i
< nb_trace
; i
++) {
1923 tcs
= (LttvTraceState
*)self
->parent
.traces
[i
];
1925 if(ltt_time_compare(t
, *(tcs
->max_time_state_recomputed_in_seek
)) < 0) {
1926 saved_states_tree
= lttv_attribute_find_subdir(tcs
->parent
.t_a
,
1927 LTTV_STATE_SAVED_STATES
);
1930 if(saved_states_tree
) {
1931 max_pos
= lttv_attribute_get_number(saved_states_tree
) - 1;
1932 mid_pos
= max_pos
/ 2;
1933 while(min_pos
< max_pos
) {
1934 type
= lttv_attribute_get(saved_states_tree
, mid_pos
, &name
, &value
);
1935 g_assert(type
== LTTV_GOBJECT
);
1936 saved_state_tree
= *((LttvAttribute
**)(value
.v_gobject
));
1937 type
= lttv_attribute_get_by_name(saved_state_tree
, LTTV_STATE_TIME
,
1939 g_assert(type
== LTTV_TIME
);
1940 if(ltt_time_compare(*(value
.v_time
), t
) < 0) {
1942 closest_tree
= saved_state_tree
;
1944 else max_pos
= mid_pos
- 1;
1946 mid_pos
= (min_pos
+ max_pos
+ 1) / 2;
1950 /* restore the closest earlier saved state */
1952 lttv_state_restore(tcs
, closest_tree
);
1956 /* There is no saved state, yet we want to have it. Restart at T0 */
1958 restore_init_state(tcs
);
1959 lttv_process_trace_seek_time(&(tcs
->parent
), ltt_time_zero
);
1962 /* We want to seek quickly without restoring/updating the state */
1964 restore_init_state(tcs
);
1965 lttv_process_trace_seek_time(&(tcs
->parent
), t
);
1968 if(!call_rest
) g_info("NOT Calling restore");
1973 traceset_state_instance_init (GTypeInstance
*instance
, gpointer g_class
)
1979 traceset_state_finalize (LttvTracesetState
*self
)
1981 G_OBJECT_CLASS(g_type_class_peek(LTTV_TRACESET_CONTEXT_TYPE
))->
1982 finalize(G_OBJECT(self
));
1987 traceset_state_class_init (LttvTracesetContextClass
*klass
)
1989 GObjectClass
*gobject_class
= G_OBJECT_CLASS(klass
);
1991 gobject_class
->finalize
= (void (*)(GObject
*self
)) traceset_state_finalize
;
1992 klass
->init
= (void (*)(LttvTracesetContext
*self
, LttvTraceset
*ts
))init
;
1993 klass
->fini
= (void (*)(LttvTracesetContext
*self
))fini
;
1994 klass
->new_traceset_context
= new_traceset_context
;
1995 klass
->new_trace_context
= new_trace_context
;
1996 klass
->new_tracefile_context
= new_tracefile_context
;
2001 lttv_traceset_state_get_type(void)
2003 static GType type
= 0;
2005 static const GTypeInfo info
= {
2006 sizeof (LttvTracesetStateClass
),
2007 NULL
, /* base_init */
2008 NULL
, /* base_finalize */
2009 (GClassInitFunc
) traceset_state_class_init
, /* class_init */
2010 NULL
, /* class_finalize */
2011 NULL
, /* class_data */
2012 sizeof (LttvTracesetState
),
2013 0, /* n_preallocs */
2014 (GInstanceInitFunc
) traceset_state_instance_init
, /* instance_init */
2015 NULL
/* value handling */
2018 type
= g_type_register_static (LTTV_TRACESET_CONTEXT_TYPE
, "LttvTracesetStateType",
2026 trace_state_instance_init (GTypeInstance
*instance
, gpointer g_class
)
2032 trace_state_finalize (LttvTraceState
*self
)
2034 G_OBJECT_CLASS(g_type_class_peek(LTTV_TRACE_CONTEXT_TYPE
))->
2035 finalize(G_OBJECT(self
));
2040 trace_state_class_init (LttvTraceStateClass
*klass
)
2042 GObjectClass
*gobject_class
= G_OBJECT_CLASS(klass
);
2044 gobject_class
->finalize
= (void (*)(GObject
*self
)) trace_state_finalize
;
2045 klass
->state_save
= state_save
;
2046 klass
->state_restore
= state_restore
;
2047 klass
->state_saved_free
= state_saved_free
;
2052 lttv_trace_state_get_type(void)
2054 static GType type
= 0;
2056 static const GTypeInfo info
= {
2057 sizeof (LttvTraceStateClass
),
2058 NULL
, /* base_init */
2059 NULL
, /* base_finalize */
2060 (GClassInitFunc
) trace_state_class_init
, /* class_init */
2061 NULL
, /* class_finalize */
2062 NULL
, /* class_data */
2063 sizeof (LttvTraceState
),
2064 0, /* n_preallocs */
2065 (GInstanceInitFunc
) trace_state_instance_init
, /* instance_init */
2066 NULL
/* value handling */
2069 type
= g_type_register_static (LTTV_TRACE_CONTEXT_TYPE
,
2070 "LttvTraceStateType", &info
, 0);
2077 tracefile_state_instance_init (GTypeInstance
*instance
, gpointer g_class
)
2083 tracefile_state_finalize (LttvTracefileState
*self
)
2085 G_OBJECT_CLASS(g_type_class_peek(LTTV_TRACEFILE_CONTEXT_TYPE
))->
2086 finalize(G_OBJECT(self
));
2091 tracefile_state_class_init (LttvTracefileStateClass
*klass
)
2093 GObjectClass
*gobject_class
= G_OBJECT_CLASS(klass
);
2095 gobject_class
->finalize
= (void (*)(GObject
*self
)) tracefile_state_finalize
;
2100 lttv_tracefile_state_get_type(void)
2102 static GType type
= 0;
2104 static const GTypeInfo info
= {
2105 sizeof (LttvTracefileStateClass
),
2106 NULL
, /* base_init */
2107 NULL
, /* base_finalize */
2108 (GClassInitFunc
) tracefile_state_class_init
, /* class_init */
2109 NULL
, /* class_finalize */
2110 NULL
, /* class_data */
2111 sizeof (LttvTracefileState
),
2112 0, /* n_preallocs */
2113 (GInstanceInitFunc
) tracefile_state_instance_init
, /* instance_init */
2114 NULL
/* value handling */
2117 type
= g_type_register_static (LTTV_TRACEFILE_CONTEXT_TYPE
,
2118 "LttvTracefileStateType", &info
, 0);
2124 static void module_init()
2126 LTTV_STATE_UNNAMED
= g_quark_from_string("unnamed");
2127 LTTV_STATE_MODE_UNKNOWN
= g_quark_from_string("unknown execution mode");
2128 LTTV_STATE_USER_MODE
= g_quark_from_string("user mode");
2129 LTTV_STATE_WAIT_FORK
= g_quark_from_string("wait fork");
2130 LTTV_STATE_SYSCALL
= g_quark_from_string("system call");
2131 LTTV_STATE_TRAP
= g_quark_from_string("trap");
2132 LTTV_STATE_IRQ
= g_quark_from_string("irq");
2133 LTTV_STATE_SUBMODE_UNKNOWN
= g_quark_from_string("unknown submode");
2134 LTTV_STATE_SUBMODE_NONE
= g_quark_from_string("(no submode)");
2135 LTTV_STATE_WAIT_CPU
= g_quark_from_string("wait for cpu");
2136 LTTV_STATE_EXIT
= g_quark_from_string("exiting");
2137 LTTV_STATE_ZOMBIE
= g_quark_from_string("zombie");
2138 LTTV_STATE_WAIT
= g_quark_from_string("wait for I/O");
2139 LTTV_STATE_RUN
= g_quark_from_string("running");
2140 LTTV_STATE_DEAD
= g_quark_from_string("dead");
2141 LTTV_STATE_TRACEFILES
= g_quark_from_string("tracefiles");
2142 LTTV_STATE_PROCESSES
= g_quark_from_string("processes");
2143 LTTV_STATE_PROCESS
= g_quark_from_string("process");
2144 LTTV_STATE_RUNNING_PROCESS
= g_quark_from_string("running_process");
2145 LTTV_STATE_EVENT
= g_quark_from_string("event");
2146 LTTV_STATE_SAVED_STATES
= g_quark_from_string("saved states");
2147 LTTV_STATE_SAVED_STATES_TIME
= g_quark_from_string("saved states time");
2148 LTTV_STATE_TIME
= g_quark_from_string("time");
2149 LTTV_STATE_HOOKS
= g_quark_from_string("saved state hooks");
2150 LTTV_STATE_NAME_TABLES
= g_quark_from_string("name tables");
2151 LTTV_STATE_TRACE_STATE_USE_COUNT
=
2152 g_quark_from_string("trace_state_use_count");
2155 LTT_FACILITY_KERNEL
= g_quark_from_string("kernel");
2156 LTT_FACILITY_PROCESS
= g_quark_from_string("process");
2157 LTT_FACILITY_FS
= g_quark_from_string("fs");
2160 LTT_EVENT_SYSCALL_ENTRY
= g_quark_from_string("syscall_entry");
2161 LTT_EVENT_SYSCALL_EXIT
= g_quark_from_string("syscall_exit");
2162 LTT_EVENT_TRAP_ENTRY
= g_quark_from_string("trap_entry");
2163 LTT_EVENT_TRAP_EXIT
= g_quark_from_string("trap_exit");
2164 LTT_EVENT_IRQ_ENTRY
= g_quark_from_string("irq_entry");
2165 LTT_EVENT_IRQ_EXIT
= g_quark_from_string("irq_exit");
2166 LTT_EVENT_SCHEDCHANGE
= g_quark_from_string("schedchange");
2167 LTT_EVENT_FORK
= g_quark_from_string("fork");
2168 LTT_EVENT_EXIT
= g_quark_from_string("exit");
2169 LTT_EVENT_FREE
= g_quark_from_string("free");
2170 LTT_EVENT_EXEC
= g_quark_from_string("exec");
2173 LTT_FIELD_SYSCALL_ID
= g_quark_from_string("syscall_id");
2174 LTT_FIELD_TRAP_ID
= g_quark_from_string("trap_id");
2175 LTT_FIELD_IRQ_ID
= g_quark_from_string("irq_id");
2176 LTT_FIELD_OUT
= g_quark_from_string("out");
2177 LTT_FIELD_IN
= g_quark_from_string("in");
2178 LTT_FIELD_OUT_STATE
= g_quark_from_string("out_state");
2179 LTT_FIELD_PARENT_PID
= g_quark_from_string("parent_pid");
2180 LTT_FIELD_CHILD_PID
= g_quark_from_string("child_pid");
2181 LTT_FIELD_PID
= g_quark_from_string("pid");
2182 LTT_FIELD_FILENAME
= g_quark_from_string("filename");
2186 static void module_destroy()
2191 LTTV_MODULE("state", "State computation", \
2192 "Update the system state, possibly saving it at intervals", \
2193 module_init
, module_destroy
)