2 #include <lttv/state.h>
6 init(LttvTracesetState
*self
, LttvTraceset
*ts
)
8 guint i
, j
, nb_trace
, nb_tracefile
;
12 LttvTracefileState
*tfc
;
14 LTTV_TRACESET_CONTEXT_CLASS(g_type_class_peek_parent(LTTV_TRACESET_STATE_TYPE
))->init(self
, ts
);
16 nb_trace
= lttv_traceset_number(ts
);
17 for(i
= 0 ; i
< nb_trace
; i
++) {
18 tc
= (LttvTraceState
*)self
->traces
[i
];
19 tc
->processes
= g_hash_table_new(g_direct_hash
, g_direct_equal
);
21 nb_tracefile
= ltt_trace_control_tracefile_number(tc
->t
);
22 for(j
= 0 ; j
< nb_tracefile
; j
++) {
23 tfc
= tc
->control_tracefiles
[j
];
27 nb_tracefile
= ltt_trace_per_cpu_tracefile_number(tc
->t
);
28 for(j
= 0 ; j
< nb_tracefile
; j
++) {
29 tfc
= tc
->per_cpu_tracefiles
[j
];
37 fini(LttvTracesetState
*self
)
39 guint i
, j
, nb_trace
, nb_tracefile
;
43 LttvTracefileState
*tfc
;
45 nb_trace
= lttv_traceset_number(ts
);
46 for(i
= 0 ; i
< nb_trace
; i
++) {
47 tc
= (LttvTraceState
*)self
->traces
[i
];
48 remove_all_processes(tc
->processes
);
49 g_hash_table_destroy(tc
->processes
);
51 LTTV_TRACESET_CONTEXT_CLASS(g_type_class_peek_parent(LTTV_TRACESET_STATE_TYPE
))->fini(self
);
56 new_traceset_context(LttvTracesetContext
*self
)
58 return LTTV_TRACESET_CONTEXT(g_object_new(LTTV_TRACESET_STATE_TYPE
));
63 new_trace_context(LttvTracesetContext
*self
)
65 return LTTV_TRACE_CONTEXT(g_object_new(LTTV_TRACE_STATE_TYPE
));
69 LttvTracefileContext
*
70 new_tracefile_context(LttvTracesetContext
*self
)
72 return LTTV_TRACEFILE_CONTEXT(g_object_new(LTTV_TRACEFILE_STATE_TYPE
));
77 lttv_traceset_state_get_type(void)
79 static GType type
= 0;
81 static const GTypeInfo info
= {
82 sizeof (LttvTracesetStateClass
),
84 NULL
, /* base_finalize */
85 traceset_state_class_init
, /* class_init */
86 NULL
, /* class_finalize */
87 NULL
, /* class_data */
88 sizeof (LttvTracesetContext
),
90 traceset_state_instance_init
/* instance_init */
93 type
= g_type_register_static (LTTV_TRACESET_CONTEXT_TYPE
, "LttvTracesetStateType",
101 traceset_state_instance_init (GTypeInstance
*instance
, gpointer g_class
)
107 traceset_context_finalize (LttvTracesetContext
*self
)
109 G_OBJECT_CLASS(g_type_class_peek_parent(LTTV_TRACESET_STATE_TYPE
))->finalize(self
);
114 traceset_state_class_init (LttvTracesetContextClass
*klass
)
116 GObjectClass
*gobject_class
= G_OBJECT_CLASS(klass
);
118 gobject_class
->finalize
= traceset_state_finalize
;
121 klass
->new_traceset_context
= new_traceset_context
;
122 klass
->new_trace_context
= new_trace_context
;
123 klass
->new_tracefile_context
= new_tracefile_context
;
128 lttv_trace_state_get_type(void)
130 static GType type
= 0;
132 static const GTypeInfo info
= {
133 sizeof (LttvTraceStateClass
),
134 NULL
, /* base_init */
135 NULL
, /* base_finalize */
136 trace_state_class_init
, /* class_init */
137 NULL
, /* class_finalize */
138 NULL
, /* class_data */
139 sizeof (LttvTracesetState
),
141 trace_state_instance_init
/* instance_init */
144 type
= g_type_register_static (LTTV_TRACE_CONTEXT_TYPE
,
145 "LttvTraceStateType", &info
, 0);
152 trace_state_instance_init (GTypeInstance
*instance
, gpointer g_class
)
158 trace_state_finalize (LttvTraceContext
*self
)
160 G_OBJECT_CLASS(g_type_class_peek_parent(LTTV_TRACE_STATE_TYPE
))->finalize(self
);
165 trace_state_class_init (LttvTraceContextClass
*klass
)
167 GObjectClass
*gobject_class
= G_OBJECT_CLASS(klass
);
169 gobject_class
->finalize
= trace_state_finalize
;
174 lttv_tracefile_state_get_type(void)
176 static GType type
= 0;
178 static const GTypeInfo info
= {
179 sizeof (LttvTracefileStateClass
),
180 NULL
, /* base_init */
181 NULL
, /* base_finalize */
182 tracefile_state_class_init
, /* class_init */
183 NULL
, /* class_finalize */
184 NULL
, /* class_data */
185 sizeof (LttvTracefileState
),
187 tracefile_state_instance_init
/* instance_init */
190 type
= g_type_register_static (LTTV_TRACEFILE_CONTEXT_TYPE
,
191 "LttvTracefileStateType", &info
, 0);
198 tracefile_state_instance_init (GTypeInstance
*instance
, gpointer g_class
)
204 tracefile_state_finalize (LttvTracefileState
*self
)
206 G_OBJECT_CLASS(g_type_class_peek_parent(LTTV_TRACEFILE_STATE_TYPE
))->finalize(self
);
211 tracefile_state_class_init (LttvTracefileStateClass
*klass
)
213 GObjectClass
*gobject_class
= G_OBJECT_CLASS(klass
);
215 gobject_class
->finalize
= tracefile_state_finalize
;
230 gboolean free_hook_data
;
234 void push_state(LttvTracefileState
*tfs
, LttvInterruptType t
, guint state_id
)
236 LttvInterruptState intr
;
238 LttvProcessState
*process
= tfs
->process
;
240 guint depth
= process
->interrupt_stack
->len
;
242 g_array_set_size(process
->interrupt_stack
, depth
+ 1);
243 intr
= &g_array_index(process
->interrupt_stack
, LttvInterruptState
, depth
);
246 intr
->entry
= tfs
->time
;
247 intr
->last_change
= tfs
->time
;
248 intr
->s
= process
->state
->s
;
252 void pop_state(LttvTracefileState
*tfs
, LttvInterruptType t
)
254 LttvProcessState
*process
= tfs
->process
;
256 guint depth
= process
->interrupt_stack
->len
- 1;
258 g_assert(process
->state
->t
== t
);
259 g_array_remove_index(process
->interrupt_stack
, depth
);
261 process
->state
= &g_array_index(process
->interrupt_stack
, LttvInterruptState
,
266 LttvProcessState
*create_process(LttvTraceState
*tfs
, LttvProcessState
*parent
,
269 LttvProcessState
*process
= g_new(LttvProcessState
, 1);
271 LttvInterruptState
*intr
;
273 g_hash_table_insert(tfs
->ts
->processes
, pid
, process
);
275 process
->birth
= tfs
->time
;
276 process
->name
= LTTV_STATE_UNNAMED
;
277 process
->interrupt_stack
= g_array_new(FALSE
, FALSE
,
278 sizeof(LttvInterruptState
));
279 g_array_set_size(process
->interrupt_stack
, 1);
280 intr
= process
->state
= process
->interrupt_stack
->data
;
281 intr
->t
= LTTV_STATE_USER_MODE
283 intr
->entry
= tfs
->time
;
284 intr
->last_change
= tfs
->time
;
285 intr
->s
= LTTV_STATE_WAIT_FORK
;
289 LttvProcessState
*find_process(LttvTraceState
*tfs
, guint pid
)
291 LttvProcessState
*process
= g_hash_table_lookup(tfs
->processes
, pid
);
292 if(process
== NULL
) process
= create_process(tfs
, NULL
, pid
);
297 void exit_process(LttvTraceState
*ts
, LttvProcessState
*process
)
299 g_hash_table_remove(tfs
-ts
->processes
, process
->pid
);
300 g_array_free(process
->interrupt_stack
, TRUE
);
305 void free_process_state(gpointer key
, gpointer value
, gpointer user_data
)
307 g_array_free(((LttvProcessState
*)value
)->interrupt_stack
, TRUE
);
312 void remove_all_processes(GHashTable
*processes
)
314 g_hash_table_foreach(processes
, free_process_state
, NULL
);
318 gboolean
syscall_entry(void *hook_data
, void *call_data
)
320 LttField
*f
= (LttField
*)hook_data
;
322 struct LttvTracefileState
*s
= (LttvTraceFileState
*)call_data
;
324 push_state(s
, STATE_SYSCALL
, ltt_event_get_unsigned(s
->e
, f
));
329 gboolean
syscall_exit(void *hook_data
, void *call_data
)
331 struct LttvTracefileState
*s
= (LttvTraceFileState
*)call_data
;
333 pop_state(s
, STATE_SYSCALL
);
338 gboolean
trap_entry(void *hook_data
, void *call_data
)
340 LttField
*f
= (LttField
*)hook_data
;
342 struct LttvTracefileState
*s
= (LttvTraceFileState
*)call_data
;
344 push_state(s
, STATE_TRAP
, ltt_event_get_unsigned(s
->e
, f
));
349 gboolean
trap_exit(void *hook_data
, void *call_data
)
351 struct LttvTracefileState
*s
= (LttvTraceFileState
*)call_data
;
353 pop_state(s
, STATE_TRAP
);
358 gboolean
irq_entry(void *hook_data
, void *call_data
)
360 LttField
*f
= (LttField
*)hook_data
;
362 struct LttvTracefileState
*s
= (LttvTraceFileState
*)call_data
;
364 /* Do something with the info about being in user or system mode when int? */
365 push_state(s
, STATE_IRQ
, ltt_event_get_unsigned(s
->e
, f
));
370 gboolean
irq_exit(void *hook_data
, void *call_data
)
372 struct LttvTracefileState
*s
= (LttvTraceFileState
*)call_data
;
374 pop_state(s
, STATE_IRQ
);
379 gboolean
schedchange(void *hook_data
, void *call_data
)
381 struct HookData
*h
= (struct HookData
*)hook_data
;
383 struct LttvTracefileState
*s
= (LttvTraceFileState
*)call_data
;
385 guint pid_in
, pid_out
, state_out
;
387 pid_in
= ltt_event_get_int(s
->e
, h
->f1
);
388 pid_out
= ltt_event_get_int(s
->e
, h
->f2
);
389 state_out
= ltt_event_get_int(s
->e
, h
->f3
);
390 if(s
->process
!= NULL
) {
391 if(state_out
== 0) s
->process
->state
->s
= STATE_WAIT_CPU
;
392 else if(s
->process
->state
->s
== STATE_EXIT
)
393 exit_process(s
->tc
, s
->process
);
394 else s
->process
->state
->s
= STATE_WAIT
;
396 s
->process
= find_process(s
->tc
, pid_in
);
397 s
->process
->state
->s
= STATE_RUN
;
402 gboolean
process_fork(void *hook_data
, void *call_data
)
404 LttField
*f
= (LttField
*)hook_data
;
406 struct LttvTracefileState
*s
= (LttvTraceFileState
*)call_data
;
410 child_pid
= ltt_event_get_int(s
->e
, f
);
411 create_process(s
->tc
, s
->process
, child_pid
);
416 gboolean
process_exit(void *hook_data
, void *call_data
)
418 struct LttvTracefileState
*s
= (LttvTraceFileState
*)call_data
;
420 if(s
->process
!= NULL
) {
421 s
->process
->state
->s
= STATE_EXIT
;
428 find_field(LttEventType
*et
, const char *field
)
438 if(field
== NULL
) return NULL
;
440 f
= ltt_eventtype_field(et
);
441 t
= ltt_eventtype_type(et
);
442 g_assert(ltt_type_class(t
) == LTT_STRUCT
);
443 nb
= ltt_type_member_number(t
);
444 for(i
= 0 ; i
< nb
; i
++) {
445 ltt_type_member_type(t
, i
, &name
);
446 if(strcmp(name
, field
) == 0) break;
449 return ltt_field_member(f
, i
);
454 find_hook(LttTrace
*t
, const char *facility
, const char *event
,
455 const char *field1
, *field2
, *field3
, LttHook h
)
463 struct HookId hook_id
;
465 struct HookData hook_data
, *phook_data
;
469 nb
= ltt_trace_facility_find(t
, facility
, &pos
);
470 if(nb
< 1) g_error("No %s facility", facility
);
471 f
= ltt_facility_get(t
, pos
);
472 et
= ltt_facility_get_by_name(f
, event
);
473 if(et
== NULL
) g_error("Event %s does not exist", event
);
475 hook_id
.id
= ltt_eventtype_id(et
);
477 hook_id
.free_hook_data
= FALSE
;
478 hook_data
.f1
= find_field(et
, field1
);
479 hook_data
.f2
= find_field(et
, field2
);
480 hook_data
.f3
= find_field(et
, field3
);
481 if(hook_data
->f1
== NULL
) hook_id
->hook_data
= NULL
;
482 else if(hook_data
->f2
== NULL
) hook_id
->hook_data
= hook_data
->f1
;
484 phook_data
= g_new(struct HookData
, 1);
485 *phook_data
= hook_data
;
486 hook_id
.hook_data
= phook_data
;
487 hook_id
.free_hook_data
= TRUE
;
493 lttv_state_add_event_hooks(LttvTracesetState
*self
)
495 LttvTraceset
*ts
= self
->ts
;
497 guint i
, j
, nb_trace
, nb_control
, nb_per_cpu
, nb_tracefile
;
505 LttvTracefileState
*tfc
;
511 struct HookId hook_id
;
513 LttvAttributeValue val
;
515 nb_trace
= lttv_traceset_number(ts
);
516 for(i
= 0 ; i
< nb_trace
; i
++) {
517 tc
= (LttvTraceState
*)self
->traces
[i
];
519 /* Find the eventtype id for the following events and register the
520 associated by id hooks. */
522 hooks
= g_array_new(FALSE
, FALSE
, struct HookId
);
523 g_array_add(hooks
, find_hook(tc
->t
, "core","syscall_entry", "syscall_id",
524 NULL
, NULL
, syscall_entry
));
525 g_array_add(hooks
, find_hook(tc
->t
, "core", "syscall_exit", NULL
, NULL
,
526 NULL
, syscall_exit
));
527 g_array_add(hooks
, find_hook(tc
->t
, "core", "trap_entry", "trap_id",
529 g_array_add(hooks
, find_hook(tc
->t
, "core", "trap_exit", NULL
, NULL
,
531 g_array_add(hooks
, find_hook(tc
->t
, "core", "irq_entry", "irq_id",
533 g_array_add(hooks
, find_hook(tc
->t
, "core", "irq_exit", NULL
, NULL
,
535 g_array_add(hooks
, find_hook(tc
->t
, "core", "schedchange", "in", "out",
536 "out_state", schedchange
));
537 g_array_add(hooks
, find_hook(tc
->t
, "core", "process_fork", "child_pid",
538 NULL
, NULL
, process_fork
));
539 g_array_add(hooks
, find_hook(tc
->t
, "core", "process_exit", NULL
, NULL
,
540 NULL
, process_exit
));
542 /* Add these hooks to each before_event_by_id hooks list */
544 nb_control
= ltt_trace_control_tracefile_number(tc
->t
);
545 nb_per_cpu
= ltt_trace_control_tracefile_number(tc
->t
);
546 nb_tracefile
= nb_control
+ nb_per_cpu
;
547 for(j
= 0 ; j
< nb_tracefile
; j
++) {
549 tfc
= tc
->control_tracefiles
[j
];
552 tfc
= tc
->per_cpu_tracefiles
[j
];
555 for(k
= 0 ; k
< hooks
->len
; k
++) {
556 hook_id
= g_array_index(hooks
, struct HookId
, k
);
557 lttv_hooks_add(lttv_hooks_by_id_find(tfc
->before_event_by_id
,
558 hook_id
->id
), hook_id
->h
, hook_id
->hook_data
);
560 lttv_attribute_find(self
->a
, STATE_HOOKS
, LTTV_POINTER
, val
);
561 val
->v_pointer
= hooks
;
566 lttv_state_remove_event_hooks(LttvTracesetState
*self
)
568 LttvTraceset
*ts
= self
->ts
;
570 guint i
, j
, nb_trace
, nb_control
, nb_per_cpu
, nb_tracefile
;
574 LttvTracefileState
*tfc
;
580 struct HookId hook_id
;
582 LttvAttributeValue val
;
584 nb_trace
= lttv_traceset_number(ts
);
585 for(i
= 0 ; i
< nb_trace
; i
++) {
586 tc
= (LttvTraceState
*)self
->traces
[i
];
587 lttv_attribute_find(self
->a
, STATE_HOOKS
, LTTV_POINTER
, val
);
588 hooks
= val
->v_pointer
;
590 /* Add these hooks to each before_event_by_id hooks list */
592 nb_control
= ltt_trace_control_tracefile_number(tc
->t
);
593 nb_per_cpu
= ltt_trace_control_tracefile_number(tc
->t
);
594 nb_tracefile
= nb_control
+ nb_per_cpu
;
595 for(j
= 0 ; j
< nb_tracefile
; j
++) {
597 tfc
= tc
->control_tracefiles
[j
];
600 tfc
= tc
->per_cpu_tracefiles
[j
];
603 for(k
= 0 ; k
< hooks
->len
; k
++) {
604 hook_id
= g_array_index(hooks
, struct HookId
, k
);
605 lttv_hooks_remove_data(lttv_hooks_by_id_find(tfc
->before_event_by_id
,
606 hook_id
->id
), hook_id
->h
, hook_id
->hook_data
);
608 for(k
= 0 ; k
< hooks
->len
; k
++) {
609 hook_id
= g_array_index(hooks
, struct HookId
, k
);
610 if(hook_id
->free_hook_data
) g_free(hook_id
->hook_data
);
612 g_array_free(hooks
, TRUE
);