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,
25 #include <lttv/lttv.h>
26 #include <lttv/module.h>
27 #include <lttv/state.h>
28 #include <ltt/trace.h>
29 #include <ltt/event.h>
31 #include <ltt/marker-desc.h>
34 #include <ltt/ltt-private.h>
39 * usertrace is there only to be able to update the current CPU of the
40 * usertraces when there is a schedchange. it is a way to link the ProcessState
41 * to the associated usertrace. Link only created upon thread creation.
43 * The cpu id is necessary : it gives us back the current ProcessState when we
44 * are considering data from the usertrace.
47 #define PREALLOCATED_EXECUTION_STACK 10
53 LTT_CHANNEL_GLOBAL_STATE
,
54 LTT_CHANNEL_IRQ_STATE
,
55 LTT_CHANNEL_MODULE_STATE
,
56 LTT_CHANNEL_NETIF_STATE
,
57 LTT_CHANNEL_SOFTIRQ_STATE
,
58 LTT_CHANNEL_SWAP_STATE
,
59 LTT_CHANNEL_SYSCALL_STATE
,
60 LTT_CHANNEL_TASK_STATE
,
62 LTT_CHANNEL_KPROBE_STATE
,
66 LTT_CHANNEL_USERSPACE
,
72 LTT_EVENT_SYSCALL_ENTRY
,
73 LTT_EVENT_SYSCALL_EXIT
,
74 LTT_EVENT_PAGE_FAULT_NOSEM_ENTRY
,
75 LTT_EVENT_PAGE_FAULT_NOSEM_EXIT
,
76 LTT_EVENT_PAGE_FAULT_ENTRY
,
77 LTT_EVENT_PAGE_FAULT_EXIT
,
82 LTT_EVENT_SOFT_IRQ_RAISE
,
83 LTT_EVENT_SOFT_IRQ_ENTRY
,
84 LTT_EVENT_SOFT_IRQ_EXIT
,
85 LTT_EVENT_SCHED_SCHEDULE
,
86 LTT_EVENT_PROCESS_FORK
,
87 LTT_EVENT_KTHREAD_CREATE
,
88 LTT_EVENT_PROCESS_EXIT
,
89 LTT_EVENT_PROCESS_FREE
,
91 LTT_EVENT_PROCESS_STATE
,
92 LTT_EVENT_STATEDUMP_END
,
93 LTT_EVENT_FUNCTION_ENTRY
,
94 LTT_EVENT_FUNCTION_EXIT
,
95 LTT_EVENT_THREAD_BRAND
,
96 LTT_EVENT_REQUEST_ISSUE
,
97 LTT_EVENT_REQUEST_COMPLETE
,
98 LTT_EVENT_LIST_INTERRUPT
,
99 LTT_EVENT_SYS_CALL_TABLE
,
100 LTT_EVENT_SOFTIRQ_VEC
,
101 LTT_EVENT_KPROBE_TABLE
,
107 LTT_FIELD_SYSCALL_ID
,
110 LTT_FIELD_SOFT_IRQ_ID
,
113 LTT_FIELD_PREV_STATE
,
114 LTT_FIELD_PARENT_PID
,
118 LTT_FIELD_CHILD_TGID
,
137 LTTV_STATE_MODE_UNKNOWN
,
138 LTTV_STATE_USER_MODE
,
145 LTTV_STATE_SUBMODE_UNKNOWN
,
146 LTTV_STATE_SUBMODE_NONE
;
150 LTTV_STATE_WAIT_FORK
,
159 LTTV_STATE_UNBRANDED
;
162 LTTV_STATE_USER_THREAD
,
163 LTTV_STATE_KERNEL_THREAD
;
181 LTTV_BDEV_BUSY_READING
,
182 LTTV_BDEV_BUSY_WRITING
;
185 LTTV_STATE_TRACEFILES
,
186 LTTV_STATE_PROCESSES
,
188 LTTV_STATE_RUNNING_PROCESS
,
190 LTTV_STATE_SAVED_STATES
,
191 LTTV_STATE_SAVED_STATES_TIME
,
194 LTTV_STATE_NAME_TABLES
,
195 LTTV_STATE_TRACE_STATE_USE_COUNT
,
196 LTTV_STATE_RESOURCE_CPUS
,
197 LTTV_STATE_RESOURCE_CPUS_COUNT
,
198 LTTV_STATE_RESOURCE_IRQS
,
199 LTTV_STATE_RESOURCE_SOFT_IRQS
,
200 LTTV_STATE_RESOURCE_TRAPS
,
201 LTTV_STATE_RESOURCE_BLKDEVS
;
203 static void create_max_time(LttvTraceState
*tcs
);
205 static void get_max_time(LttvTraceState
*tcs
);
207 static void free_max_time(LttvTraceState
*tcs
);
209 static void create_name_tables(LttvTraceState
*tcs
);
211 static void get_name_tables(LttvTraceState
*tcs
);
213 static void free_name_tables(LttvTraceState
*tcs
);
215 static void free_saved_state(LttvTraceState
*tcs
);
217 static void lttv_state_free_process_table(GHashTable
*processes
);
219 static void lttv_trace_states_read_raw(LttvTraceState
*tcs
, FILE *fp
,
220 GPtrArray
*quarktable
);
222 /* Resource function prototypes */
223 static LttvBdevState
*get_hashed_bdevstate(LttvTraceState
*ts
, guint16 devcode
);
224 static LttvBdevState
*bdevstate_new(void);
225 static void bdevstate_free(LttvBdevState
*);
226 static void bdevstate_free_cb(gpointer key
, gpointer value
, gpointer user_data
);
227 static LttvBdevState
*bdevstate_copy(LttvBdevState
*bds
);
230 #if (__SIZEOF_LONG__ == 4)
231 guint
guint64_hash(gconstpointer key
)
233 guint64 ukey
= *(const guint64
*)key
;
235 return (guint
)ukey
^ (guint
)(ukey
>> 32);
238 gboolean
guint64_equal(gconstpointer a
, gconstpointer b
)
240 guint64 ua
= *(const guint64
*)a
;
241 guint64 ub
= *(const guint64
*)b
;
247 void lttv_state_save(LttvTraceState
*self
, LttvAttribute
*container
)
249 LTTV_TRACE_STATE_GET_CLASS(self
)->state_save(self
, container
);
253 void lttv_state_restore(LttvTraceState
*self
, LttvAttribute
*container
)
255 LTTV_TRACE_STATE_GET_CLASS(self
)->state_restore(self
, container
);
259 void lttv_state_state_saved_free(LttvTraceState
*self
,
260 LttvAttribute
*container
)
262 LTTV_TRACE_STATE_GET_CLASS(self
)->state_saved_free(self
, container
);
266 guint
process_hash(gconstpointer key
)
268 guint pid
= ((const LttvProcessState
*)key
)->pid
;
269 return (pid
>>8 ^ pid
>>4 ^ pid
>>2 ^ pid
) ;
273 /* If the hash table hash function is well distributed,
274 * the process_equal should compare different pid */
275 gboolean
process_equal(gconstpointer a
, gconstpointer b
)
277 const LttvProcessState
*process_a
, *process_b
;
280 process_a
= (const LttvProcessState
*)a
;
281 process_b
= (const LttvProcessState
*)b
;
283 if(likely(process_a
->pid
!= process_b
->pid
)) ret
= FALSE
;
284 else if(likely(process_a
->pid
== 0 &&
285 process_a
->cpu
!= process_b
->cpu
)) ret
= FALSE
;
290 static void delete_usertrace(gpointer key
, gpointer value
, gpointer user_data
)
292 g_tree_destroy((GTree
*)value
);
295 static void lttv_state_free_usertraces(GHashTable
*usertraces
)
297 g_hash_table_foreach(usertraces
, delete_usertrace
, NULL
);
298 g_hash_table_destroy(usertraces
);
301 gboolean
rettrue(gpointer key
, gpointer value
, gpointer user_data
)
306 static guint
check_expand(nb
, id
)
311 return max(id
+ 1, nb
* 2);
314 static void expand_name_table(LttvTraceState
*ts
, GQuark
**table
,
315 guint nb
, guint new_nb
)
317 /* Expand an incomplete table */
318 GQuark
*old_table
= *table
;
319 *table
= g_new(GQuark
, new_nb
);
320 memcpy(*table
, old_table
, nb
* sizeof(GQuark
));
323 static void fill_name_table(LttvTraceState
*ts
, GQuark
*table
, guint nb
,
324 guint new_nb
, const char *def_string
)
327 GString
*fe_name
= g_string_new("");
328 for(i
= nb
; i
< new_nb
; i
++) {
329 g_string_printf(fe_name
, "%s %d", def_string
, i
);
330 table
[i
] = g_quark_from_string(fe_name
->str
);
332 g_string_free(fe_name
, TRUE
);
335 static void expand_syscall_table(LttvTraceState
*ts
, int id
)
337 guint new_nb
= check_expand(ts
->nb_syscalls
, id
);
338 if(likely(new_nb
== ts
->nb_syscalls
))
340 expand_name_table(ts
, &ts
->syscall_names
, ts
->nb_syscalls
, new_nb
);
341 fill_name_table(ts
, ts
->syscall_names
, ts
->nb_syscalls
, new_nb
, "syscall");
342 /* Update the table size */
343 ts
->nb_syscalls
= new_nb
;
346 static void expand_kprobe_table(LttvTraceState
*ts
, guint64 ip
, char *symbol
)
348 #if (__SIZEOF_LONG__ == 4)
349 guint64
*ip_ptr
= g_new(guint64
, 1);
350 g_hash_table_insert(ts
->kprobe_hash
, ip_ptr
,
351 (gpointer
)(glong
)g_quark_from_string(symbol
));
353 g_hash_table_insert(ts
->kprobe_hash
, (gpointer
)ip
,
354 (gpointer
)(glong
)g_quark_from_string(symbol
));
358 static void expand_trap_table(LttvTraceState
*ts
, int id
)
360 guint new_nb
= check_expand(ts
->nb_traps
, id
);
362 if(likely(new_nb
== ts
->nb_traps
))
364 expand_name_table(ts
, &ts
->trap_names
, ts
->nb_traps
, new_nb
);
365 fill_name_table(ts
, ts
->trap_names
, ts
->nb_traps
, new_nb
, "trap");
366 /* Update the table size */
367 ts
->nb_traps
= new_nb
;
369 LttvTrapState
*old_table
= ts
->trap_states
;
370 ts
->trap_states
= g_new(LttvTrapState
, new_nb
);
371 memcpy(ts
->trap_states
, old_table
,
372 ts
->nb_traps
* sizeof(LttvTrapState
));
373 for(i
= ts
->nb_traps
; i
< new_nb
; i
++)
374 ts
->trap_states
[i
].running
= 0;
377 static void expand_irq_table(LttvTraceState
*ts
, int id
)
379 guint new_nb
= check_expand(ts
->nb_irqs
, id
);
381 if(likely(new_nb
== ts
->nb_irqs
))
383 expand_name_table(ts
, &ts
->irq_names
, ts
->nb_irqs
, new_nb
);
384 fill_name_table(ts
, ts
->irq_names
, ts
->nb_irqs
, new_nb
, "irq");
386 LttvIRQState
*old_table
= ts
->irq_states
;
387 ts
->irq_states
= g_new(LttvIRQState
, new_nb
);
388 memcpy(ts
->irq_states
, old_table
, ts
->nb_irqs
* sizeof(LttvIRQState
));
389 for(i
= ts
->nb_irqs
; i
< new_nb
; i
++) {
390 ts
->irq_states
[i
].mode_stack
= g_array_new(FALSE
, FALSE
, sizeof(LttvIRQMode
));
393 /* Update the table size */
394 ts
->nb_irqs
= new_nb
;
397 static void expand_soft_irq_table(LttvTraceState
*ts
, int id
)
399 guint new_nb
= check_expand(ts
->nb_soft_irqs
, id
);
401 if(likely(new_nb
== ts
->nb_soft_irqs
))
403 expand_name_table(ts
, &ts
->soft_irq_names
, ts
->nb_soft_irqs
, new_nb
);
404 fill_name_table(ts
, ts
->soft_irq_names
, ts
->nb_soft_irqs
, new_nb
, "softirq");
406 LttvSoftIRQState
*old_table
= ts
->soft_irq_states
;
407 ts
->soft_irq_states
= g_new(LttvSoftIRQState
, new_nb
);
408 memcpy(ts
->soft_irq_states
, old_table
,
409 ts
->nb_soft_irqs
* sizeof(LttvSoftIRQState
));
410 for(i
= ts
->nb_soft_irqs
; i
< new_nb
; i
++)
411 ts
->soft_irq_states
[i
].running
= 0;
413 /* Update the table size */
414 ts
->nb_soft_irqs
= new_nb
;
418 restore_init_state(LttvTraceState
*self
)
420 guint i
, nb_cpus
, nb_irqs
, nb_soft_irqs
, nb_traps
;
422 //LttvTracefileState *tfcs;
424 LttTime start_time
, end_time
;
426 /* Free the process tables */
427 if(self
->processes
!= NULL
) lttv_state_free_process_table(self
->processes
);
428 if(self
->usertraces
!= NULL
) lttv_state_free_usertraces(self
->usertraces
);
429 self
->processes
= g_hash_table_new(process_hash
, process_equal
);
430 self
->usertraces
= g_hash_table_new(g_direct_hash
, g_direct_equal
);
433 /* Seek time to beginning */
434 // Mathieu : fix : don't seek traceset here : causes inconsistency in seek
435 // closest. It's the tracecontext job to seek the trace to the beginning
436 // anyway : the init state might be used at the middle of the trace as well...
437 //g_tree_destroy(self->parent.ts_context->pqueue);
438 //self->parent.ts_context->pqueue = g_tree_new(compare_tracefile);
440 ltt_trace_time_span_get(self
->parent
.t
, &start_time
, &end_time
);
442 //lttv_process_trace_seek_time(&self->parent, ltt_time_zero);
444 nb_cpus
= ltt_trace_get_num_cpu(self
->parent
.t
);
445 nb_irqs
= self
->nb_irqs
;
446 nb_soft_irqs
= self
->nb_soft_irqs
;
447 nb_traps
= self
->nb_traps
;
449 /* Put the per cpu running_process to beginning state : process 0. */
450 for(i
=0; i
< nb_cpus
; i
++) {
451 LttvExecutionState
*es
;
452 self
->running_process
[i
] = lttv_state_create_process(self
, NULL
, i
, 0, 0,
453 LTTV_STATE_UNNAMED
, &start_time
);
454 /* We are not sure is it's a kernel thread or normal thread, put the
455 * bottom stack state to unknown */
456 self
->running_process
[i
]->execution_stack
=
457 g_array_set_size(self
->running_process
[i
]->execution_stack
, 1);
458 es
= self
->running_process
[i
]->state
=
459 &g_array_index(self
->running_process
[i
]->execution_stack
,
460 LttvExecutionState
, 0);
461 es
->t
= LTTV_STATE_MODE_UNKNOWN
;
462 es
->s
= LTTV_STATE_UNNAMED
;
464 //self->running_process[i]->state->s = LTTV_STATE_RUN;
465 self
->running_process
[i
]->cpu
= i
;
467 /* reset cpu states */
468 if(self
->cpu_states
[i
].mode_stack
->len
> 0) {
469 g_array_remove_range(self
->cpu_states
[i
].mode_stack
, 0, self
->cpu_states
[i
].mode_stack
->len
);
470 self
->cpu_states
[i
].last_irq
= -1;
471 self
->cpu_states
[i
].last_soft_irq
= -1;
472 self
->cpu_states
[i
].last_trap
= -1;
476 /* reset irq states */
477 for(i
=0; i
<nb_irqs
; i
++) {
478 if(self
->irq_states
[i
].mode_stack
->len
> 0)
479 g_array_remove_range(self
->irq_states
[i
].mode_stack
, 0, self
->irq_states
[i
].mode_stack
->len
);
482 /* reset softirq states */
483 for(i
=0; i
<nb_soft_irqs
; i
++) {
484 self
->soft_irq_states
[i
].pending
= 0;
485 self
->soft_irq_states
[i
].running
= 0;
488 /* reset trap states */
489 for(i
=0; i
<nb_traps
; i
++) {
490 self
->trap_states
[i
].running
= 0;
493 /* reset bdev states */
494 g_hash_table_foreach(self
->bdev_states
, bdevstate_free_cb
, NULL
);
495 //g_hash_table_steal_all(self->bdev_states);
496 g_hash_table_foreach_steal(self
->bdev_states
, rettrue
, NULL
);
499 nb_tracefile
= self
->parent
.tracefiles
->len
;
501 for(i
= 0 ; i
< nb_tracefile
; i
++) {
503 LTTV_TRACEFILE_STATE(g_array_index(self
->parent
.tracefiles
,
504 LttvTracefileContext
*, i
));
505 ltt_trace_time_span_get(self
->parent
.t
, &tfcs
->parent
.timestamp
, NULL
);
506 // tfcs->saved_position = 0;
507 tfcs
->process
= lttv_state_create_process(tfcs
, NULL
,0);
508 tfcs
->process
->state
->s
= LTTV_STATE_RUN
;
509 tfcs
->process
->last_cpu
= tfcs
->cpu_name
;
510 tfcs
->process
->last_cpu_index
= ltt_tracefile_num(((LttvTracefileContext
*)tfcs
)->tf
);
515 //static LttTime time_zero = {0,0};
517 static gint
compare_usertraces(gconstpointer a
, gconstpointer b
,
520 const LttTime
*t1
= (const LttTime
*)a
;
521 const LttTime
*t2
= (const LttTime
*)b
;
523 return ltt_time_compare(*t1
, *t2
);
526 static void free_usertrace_key(gpointer data
)
531 #define MAX_STRING_LEN 4096
534 state_load_saved_states(LttvTraceState
*tcs
)
537 GPtrArray
*quarktable
;
538 const char *trace_path
;
542 tcs
->has_precomputed_states
= FALSE
;
546 gchar buf
[MAX_STRING_LEN
];
549 trace_path
= g_quark_to_string(ltt_trace_name(tcs
->parent
.t
));
550 strncpy(path
, trace_path
, PATH_MAX
-1);
551 count
= strnlen(trace_path
, PATH_MAX
-1);
552 // quarktable : open, test
553 strncat(path
, "/precomputed/quarktable", PATH_MAX
-count
-1);
554 fp
= fopen(path
, "r");
556 quarktable
= g_ptr_array_sized_new(4096);
558 /* Index 0 is null */
560 if(hdr
== EOF
) return;
561 g_assert(hdr
== HDR_QUARKS
);
565 if(hdr
== EOF
) break;
566 g_assert(hdr
== HDR_QUARK
);
567 g_ptr_array_set_size(quarktable
, q
+1);
570 fread(&buf
[i
], sizeof(gchar
), 1, fp
);
571 if(buf
[i
] == '\0' || feof(fp
)) break;
574 len
= strnlen(buf
, MAX_STRING_LEN
-1);
575 g_ptr_array_index (quarktable
, q
) = g_new(gchar
, len
+1);
576 strncpy(g_ptr_array_index (quarktable
, q
), buf
, len
+1);
582 // saved_states : open, test
583 strncpy(path
, trace_path
, PATH_MAX
-1);
584 count
= strnlen(trace_path
, PATH_MAX
-1);
585 strncat(path
, "/precomputed/states", PATH_MAX
-count
-1);
586 fp
= fopen(path
, "r");
590 if(hdr
!= HDR_TRACE
) goto end
;
592 lttv_trace_states_read_raw(tcs
, fp
, quarktable
);
594 tcs
->has_precomputed_states
= TRUE
;
599 /* Free the quarktable */
600 for(i
=0; i
<quarktable
->len
; i
++) {
601 string
= g_ptr_array_index (quarktable
, i
);
604 g_ptr_array_free(quarktable
, TRUE
);
609 init(LttvTracesetState
*self
, LttvTraceset
*ts
)
611 guint i
, j
, nb_trace
, nb_tracefile
, nb_cpu
;
614 LttvTraceContext
*tc
;
618 LttvTracefileState
*tfcs
;
620 LttvAttributeValue v
;
622 LTTV_TRACESET_CONTEXT_CLASS(g_type_class_peek(LTTV_TRACESET_CONTEXT_TYPE
))->
623 init((LttvTracesetContext
*)self
, ts
);
625 nb_trace
= lttv_traceset_number(ts
);
626 for(i
= 0 ; i
< nb_trace
; i
++) {
627 tc
= self
->parent
.traces
[i
];
628 tcs
= LTTV_TRACE_STATE(tc
);
629 tcs
->save_interval
= LTTV_STATE_SAVE_INTERVAL
;
630 lttv_attribute_find(tcs
->parent
.t_a
, LTTV_STATE_TRACE_STATE_USE_COUNT
,
634 if(*(v
.v_uint
) == 1) {
635 create_name_tables(tcs
);
636 create_max_time(tcs
);
638 get_name_tables(tcs
);
641 nb_tracefile
= tc
->tracefiles
->len
;
642 nb_cpu
= ltt_trace_get_num_cpu(tc
->t
);
643 nb_irq
= tcs
->nb_irqs
;
644 tcs
->processes
= NULL
;
645 tcs
->usertraces
= NULL
;
646 tcs
->running_process
= g_new(LttvProcessState
*, nb_cpu
);
648 /* init cpu resource stuff */
649 tcs
->cpu_states
= g_new(LttvCPUState
, nb_cpu
);
650 for(j
= 0; j
<nb_cpu
; j
++) {
651 tcs
->cpu_states
[j
].mode_stack
= g_array_new(FALSE
, FALSE
, sizeof(LttvCPUMode
));
652 tcs
->cpu_states
[j
].last_irq
= -1;
653 tcs
->cpu_states
[j
].last_soft_irq
= -1;
654 tcs
->cpu_states
[j
].last_trap
= -1;
655 g_assert(tcs
->cpu_states
[j
].mode_stack
!= NULL
);
658 /* init irq resource stuff */
659 tcs
->irq_states
= g_new(LttvIRQState
, nb_irq
);
660 for(j
= 0; j
<nb_irq
; j
++) {
661 tcs
->irq_states
[j
].mode_stack
= g_array_new(FALSE
, FALSE
, sizeof(LttvIRQMode
));
662 g_assert(tcs
->irq_states
[j
].mode_stack
!= NULL
);
665 /* init soft irq stuff */
666 /* the kernel has a statically fixed max of 32 softirqs */
667 tcs
->soft_irq_states
= g_new(LttvSoftIRQState
, tcs
->nb_soft_irqs
);
669 /* init trap stuff */
670 tcs
->trap_states
= g_new(LttvTrapState
, tcs
->nb_traps
);
672 /* init bdev resource stuff */
673 tcs
->bdev_states
= g_hash_table_new(g_int_hash
, g_int_equal
);
675 restore_init_state(tcs
);
676 for(j
= 0 ; j
< nb_tracefile
; j
++) {
678 LTTV_TRACEFILE_STATE(g_array_index(tc
->tracefiles
,
679 LttvTracefileContext
*, j
));
680 tfcs
->tracefile_name
= ltt_tracefile_name(tfcs
->parent
.tf
);
681 tfcs
->cpu
= ltt_tracefile_cpu(tfcs
->parent
.tf
);
682 tfcs
->cpu_state
= &(tcs
->cpu_states
[tfcs
->cpu
]);
683 if(ltt_tracefile_tid(tfcs
->parent
.tf
) != 0) {
684 /* It's a Usertrace */
685 guint tid
= ltt_tracefile_tid(tfcs
->parent
.tf
);
686 GTree
*usertrace_tree
= (GTree
*)g_hash_table_lookup(tcs
->usertraces
,
687 GUINT_TO_POINTER(tid
));
688 if(!usertrace_tree
) {
689 usertrace_tree
= g_tree_new_full(compare_usertraces
,
690 NULL
, free_usertrace_key
, NULL
);
691 g_hash_table_insert(tcs
->usertraces
,
692 GUINT_TO_POINTER(tid
), usertrace_tree
);
694 LttTime
*timestamp
= g_new(LttTime
, 1);
695 *timestamp
= ltt_interpolate_time_from_tsc(tfcs
->parent
.tf
,
696 ltt_tracefile_creation(tfcs
->parent
.tf
));
697 g_tree_insert(usertrace_tree
, timestamp
, tfcs
);
701 /* See if the trace has saved states */
702 state_load_saved_states(tcs
);
707 fini(LttvTracesetState
*self
)
713 //LttvTracefileState *tfcs;
715 LttvAttributeValue v
;
717 nb_trace
= lttv_traceset_number(LTTV_TRACESET_CONTEXT(self
)->ts
);
718 for(i
= 0 ; i
< nb_trace
; i
++) {
719 tcs
= (LttvTraceState
*)(LTTV_TRACESET_CONTEXT(self
)->traces
[i
]);
720 lttv_attribute_find(tcs
->parent
.t_a
, LTTV_STATE_TRACE_STATE_USE_COUNT
,
723 g_assert(*(v
.v_uint
) != 0);
726 if(*(v
.v_uint
) == 0) {
727 free_name_tables(tcs
);
729 free_saved_state(tcs
);
731 g_free(tcs
->running_process
);
732 tcs
->running_process
= NULL
;
733 lttv_state_free_process_table(tcs
->processes
);
734 lttv_state_free_usertraces(tcs
->usertraces
);
735 tcs
->processes
= NULL
;
736 tcs
->usertraces
= NULL
;
738 LTTV_TRACESET_CONTEXT_CLASS(g_type_class_peek(LTTV_TRACESET_CONTEXT_TYPE
))->
739 fini((LttvTracesetContext
*)self
);
743 static LttvTracesetContext
*
744 new_traceset_context(LttvTracesetContext
*self
)
746 return LTTV_TRACESET_CONTEXT(g_object_new(LTTV_TRACESET_STATE_TYPE
, NULL
));
750 static LttvTraceContext
*
751 new_trace_context(LttvTracesetContext
*self
)
753 return LTTV_TRACE_CONTEXT(g_object_new(LTTV_TRACE_STATE_TYPE
, NULL
));
757 static LttvTracefileContext
*
758 new_tracefile_context(LttvTracesetContext
*self
)
760 return LTTV_TRACEFILE_CONTEXT(g_object_new(LTTV_TRACEFILE_STATE_TYPE
, NULL
));
764 /* Write the process state of the trace */
766 static void write_process_state(gpointer key
, gpointer value
,
769 LttvProcessState
*process
;
771 LttvExecutionState
*es
;
773 FILE *fp
= (FILE *)user_data
;
778 process
= (LttvProcessState
*)value
;
780 " <PROCESS CORE=%p PID=%u TGID=%u PPID=%u TYPE=\"%s\" CTIME_S=%lu CTIME_NS=%lu ITIME_S=%lu ITIME_NS=%lu NAME=\"%s\" BRAND=\"%s\" CPU=\"%u\" FREE_EVENTS=\"%u\">\n",
781 process
, process
->pid
, process
->tgid
, process
->ppid
,
782 g_quark_to_string(process
->type
),
783 process
->creation_time
.tv_sec
,
784 process
->creation_time
.tv_nsec
,
785 process
->insertion_time
.tv_sec
,
786 process
->insertion_time
.tv_nsec
,
787 g_quark_to_string(process
->name
),
788 g_quark_to_string(process
->brand
),
789 process
->cpu
, process
->free_events
);
791 for(i
= 0 ; i
< process
->execution_stack
->len
; i
++) {
792 es
= &g_array_index(process
->execution_stack
, LttvExecutionState
, i
);
793 fprintf(fp
, " <ES MODE=\"%s\" SUBMODE=\"%s\" ENTRY_S=%lu ENTRY_NS=%lu",
794 g_quark_to_string(es
->t
), g_quark_to_string(es
->n
),
795 es
->entry
.tv_sec
, es
->entry
.tv_nsec
);
796 fprintf(fp
, " CHANGE_S=%lu CHANGE_NS=%lu STATUS=\"%s\"/>\n",
797 es
->change
.tv_sec
, es
->change
.tv_nsec
, g_quark_to_string(es
->s
));
800 for(i
= 0 ; i
< process
->user_stack
->len
; i
++) {
801 address
= g_array_index(process
->user_stack
, guint64
, i
);
802 fprintf(fp
, " <USER_STACK ADDRESS=\"%" PRIu64
"\"/>\n",
806 if(process
->usertrace
) {
807 fprintf(fp
, " <USERTRACE NAME=\"%s\" CPU=%u\n/>",
808 g_quark_to_string(process
->usertrace
->tracefile_name
),
809 process
->usertrace
->cpu
);
813 fprintf(fp
, " </PROCESS>\n");
817 void lttv_state_write(LttvTraceState
*self
, LttTime t
, FILE *fp
)
819 guint i
, nb_tracefile
, nb_block
, offset
;
822 LttvTracefileState
*tfcs
;
826 LttEventPosition
*ep
;
830 ep
= ltt_event_position_new();
832 fprintf(fp
,"<PROCESS_STATE TIME_S=%lu TIME_NS=%lu>\n", t
.tv_sec
, t
.tv_nsec
);
834 g_hash_table_foreach(self
->processes
, write_process_state
, fp
);
836 nb_cpus
= ltt_trace_get_num_cpu(self
->parent
.t
);
837 for(i
=0;i
<nb_cpus
;i
++) {
838 fprintf(fp
," <CPU NUM=%u RUNNING_PROCESS=%u>\n",
839 i
, self
->running_process
[i
]->pid
);
842 nb_tracefile
= self
->parent
.tracefiles
->len
;
844 for(i
= 0 ; i
< nb_tracefile
; i
++) {
846 LTTV_TRACEFILE_STATE(g_array_index(self
->parent
.tracefiles
,
847 LttvTracefileContext
*, i
));
848 fprintf(fp
, " <TRACEFILE TIMESTAMP_S=%lu TIMESTAMP_NS=%lu",
849 tfcs
->parent
.timestamp
.tv_sec
,
850 tfcs
->parent
.timestamp
.tv_nsec
);
851 LttEvent
*e
= ltt_tracefile_get_event(tfcs
->parent
.tf
);
852 if(e
== NULL
) fprintf(fp
,"/>\n");
854 ltt_event_position(e
, ep
);
855 ltt_event_position_get(ep
, &tf
, &nb_block
, &offset
, &tsc
);
856 fprintf(fp
, " BLOCK=%u OFFSET=%u TSC=%" PRIu64
"/>\n", nb_block
, offset
,
861 fprintf(fp
,"</PROCESS_STATE>\n");
865 static void write_process_state_raw(gpointer key
, gpointer value
,
868 LttvProcessState
*process
;
870 LttvExecutionState
*es
;
872 FILE *fp
= (FILE *)user_data
;
877 process
= (LttvProcessState
*)value
;
878 fputc(HDR_PROCESS
, fp
);
879 //fwrite(&header, sizeof(header), 1, fp);
880 //fprintf(fp, "%s", g_quark_to_string(process->type));
882 fwrite(&process
->type
, sizeof(process
->type
), 1, fp
);
883 //fprintf(fp, "%s", g_quark_to_string(process->name));
885 fwrite(&process
->name
, sizeof(process
->name
), 1, fp
);
886 //fprintf(fp, "%s", g_quark_to_string(process->brand));
888 fwrite(&process
->brand
, sizeof(process
->brand
), 1, fp
);
889 fwrite(&process
->pid
, sizeof(process
->pid
), 1, fp
);
890 fwrite(&process
->free_events
, sizeof(process
->free_events
), 1, fp
);
891 fwrite(&process
->tgid
, sizeof(process
->tgid
), 1, fp
);
892 fwrite(&process
->ppid
, sizeof(process
->ppid
), 1, fp
);
893 fwrite(&process
->cpu
, sizeof(process
->cpu
), 1, fp
);
894 fwrite(&process
->creation_time
, sizeof(process
->creation_time
), 1, fp
);
895 fwrite(&process
->insertion_time
, sizeof(process
->insertion_time
), 1, fp
);
899 " <PROCESS CORE=%p PID=%u TGID=%u PPID=%u TYPE=\"%s\" CTIME_S=%lu CTIME_NS=%lu ITIME_S=%lu ITIME_NS=%lu NAME=\"%s\" BRAND=\"%s\" CPU=\"%u\" PROCESS_TYPE=%u>\n",
900 process
, process
->pid
, process
->tgid
, process
->ppid
,
901 g_quark_to_string(process
->type
),
902 process
->creation_time
.tv_sec
,
903 process
->creation_time
.tv_nsec
,
904 process
->insertion_time
.tv_sec
,
905 process
->insertion_time
.tv_nsec
,
906 g_quark_to_string(process
->name
),
907 g_quark_to_string(process
->brand
),
911 for(i
= 0 ; i
< process
->execution_stack
->len
; i
++) {
912 es
= &g_array_index(process
->execution_stack
, LttvExecutionState
, i
);
915 //fprintf(fp, "%s", g_quark_to_string(es->t));
917 fwrite(&es
->t
, sizeof(es
->t
), 1, fp
);
918 //fprintf(fp, "%s", g_quark_to_string(es->n));
920 fwrite(&es
->n
, sizeof(es
->n
), 1, fp
);
921 //fprintf(fp, "%s", g_quark_to_string(es->s));
923 fwrite(&es
->s
, sizeof(es
->s
), 1, fp
);
924 fwrite(&es
->entry
, sizeof(es
->entry
), 1, fp
);
925 fwrite(&es
->change
, sizeof(es
->change
), 1, fp
);
926 fwrite(&es
->cum_cpu_time
, sizeof(es
->cum_cpu_time
), 1, fp
);
928 fprintf(fp
, " <ES MODE=\"%s\" SUBMODE=\"%s\" ENTRY_S=%lu ENTRY_NS=%lu",
929 g_quark_to_string(es
->t
), g_quark_to_string(es
->n
),
930 es
->entry
.tv_sec
, es
->entry
.tv_nsec
);
931 fprintf(fp
, " CHANGE_S=%lu CHANGE_NS=%lu STATUS=\"%s\"/>\n",
932 es
->change
.tv_sec
, es
->change
.tv_nsec
, g_quark_to_string(es
->s
));
936 for(i
= 0 ; i
< process
->user_stack
->len
; i
++) {
937 address
= g_array_index(process
->user_stack
, guint64
, i
);
938 fputc(HDR_USER_STACK
, fp
);
939 fwrite(&address
, sizeof(address
), 1, fp
);
941 fprintf(fp
, " <USER_STACK ADDRESS=\"%llu\"/>\n",
946 if(process
->usertrace
) {
947 fputc(HDR_USERTRACE
, fp
);
948 //fprintf(fp, "%s", g_quark_to_string(process->usertrace->tracefile_name));
950 fwrite(&process
->usertrace
->tracefile_name
,
951 sizeof(process
->usertrace
->tracefile_name
), 1, fp
);
952 fwrite(&process
->usertrace
->cpu
, sizeof(process
->usertrace
->cpu
), 1, fp
);
954 fprintf(fp
, " <USERTRACE NAME=\"%s\" CPU=%u\n/>",
955 g_quark_to_string(process
->usertrace
->tracefile_name
),
956 process
->usertrace
->cpu
);
963 void lttv_state_write_raw(LttvTraceState
*self
, LttTime t
, FILE *fp
)
965 guint i
, nb_tracefile
, nb_block
, offset
;
968 LttvTracefileState
*tfcs
;
972 LttEventPosition
*ep
;
976 ep
= ltt_event_position_new();
978 //fprintf(fp,"<PROCESS_STATE TIME_S=%lu TIME_NS=%lu>\n", t.tv_sec, t.tv_nsec);
979 fputc(HDR_PROCESS_STATE
, fp
);
980 fwrite(&t
, sizeof(t
), 1, fp
);
982 g_hash_table_foreach(self
->processes
, write_process_state_raw
, fp
);
984 nb_cpus
= ltt_trace_get_num_cpu(self
->parent
.t
);
985 for(i
=0;i
<nb_cpus
;i
++) {
987 fwrite(&i
, sizeof(i
), 1, fp
); /* cpu number */
988 fwrite(&self
->running_process
[i
]->pid
,
989 sizeof(self
->running_process
[i
]->pid
), 1, fp
);
990 //fprintf(fp," <CPU NUM=%u RUNNING_PROCESS=%u>\n",
991 // i, self->running_process[i]->pid);
994 nb_tracefile
= self
->parent
.tracefiles
->len
;
996 for(i
= 0 ; i
< nb_tracefile
; i
++) {
998 LTTV_TRACEFILE_STATE(g_array_index(self
->parent
.tracefiles
,
999 LttvTracefileContext
*, i
));
1000 // fprintf(fp, " <TRACEFILE TIMESTAMP_S=%lu TIMESTAMP_NS=%lu",
1001 // tfcs->parent.timestamp.tv_sec,
1002 // tfcs->parent.timestamp.tv_nsec);
1003 fputc(HDR_TRACEFILE
, fp
);
1004 fwrite(&tfcs
->parent
.timestamp
, sizeof(tfcs
->parent
.timestamp
), 1, fp
);
1005 /* Note : if timestamp if LTT_TIME_INFINITE, there will be no
1006 * position following : end of trace */
1007 LttEvent
*e
= ltt_tracefile_get_event(tfcs
->parent
.tf
);
1009 ltt_event_position(e
, ep
);
1010 ltt_event_position_get(ep
, &tf
, &nb_block
, &offset
, &tsc
);
1011 //fprintf(fp, " BLOCK=%u OFFSET=%u TSC=%llu/>\n", nb_block, offset,
1013 fwrite(&nb_block
, sizeof(nb_block
), 1, fp
);
1014 fwrite(&offset
, sizeof(offset
), 1, fp
);
1015 fwrite(&tsc
, sizeof(tsc
), 1, fp
);
1022 /* Read process state from a file */
1024 /* Called because a HDR_PROCESS was found */
1025 static void read_process_state_raw(LttvTraceState
*self
, FILE *fp
,
1026 GPtrArray
*quarktable
)
1028 LttvExecutionState
*es
;
1029 LttvProcessState
*process
, *parent_process
;
1030 LttvProcessState tmp
;
1035 /* TODO : check return value */
1036 fread(&tmp
.type
, sizeof(tmp
.type
), 1, fp
);
1037 fread(&tmp
.name
, sizeof(tmp
.name
), 1, fp
);
1038 fread(&tmp
.brand
, sizeof(tmp
.brand
), 1, fp
);
1039 fread(&tmp
.pid
, sizeof(tmp
.pid
), 1, fp
);
1040 fread(&tmp
.free_events
, sizeof(tmp
.free_events
), 1, fp
);
1041 fread(&tmp
.tgid
, sizeof(tmp
.tgid
), 1, fp
);
1042 fread(&tmp
.ppid
, sizeof(tmp
.ppid
), 1, fp
);
1043 fread(&tmp
.cpu
, sizeof(tmp
.cpu
), 1, fp
);
1044 fread(&tmp
.creation_time
, sizeof(tmp
.creation_time
), 1, fp
);
1045 fread(&tmp
.insertion_time
, sizeof(tmp
.insertion_time
), 1, fp
);
1048 process
= lttv_state_find_process(self
, tmp
.cpu
, tmp
.pid
);
1050 /* We must link to the parent */
1051 parent_process
= lttv_state_find_process_or_create(self
, ANY_CPU
, tmp
.ppid
,
1053 process
= lttv_state_find_process(self
, ANY_CPU
, tmp
.pid
);
1054 if(process
== NULL
) {
1055 process
= lttv_state_create_process(self
, parent_process
, tmp
.cpu
,
1057 g_quark_from_string((gchar
*)g_ptr_array_index(quarktable
, tmp
.name
)),
1058 &tmp
.creation_time
);
1061 process
->insertion_time
= tmp
.insertion_time
;
1062 process
->creation_time
= tmp
.creation_time
;
1063 process
->type
= g_quark_from_string(
1064 (gchar
*)g_ptr_array_index(quarktable
, tmp
.type
));
1065 process
->tgid
= tmp
.tgid
;
1066 process
->ppid
= tmp
.ppid
;
1067 process
->brand
= g_quark_from_string(
1068 (gchar
*)g_ptr_array_index(quarktable
, tmp
.brand
));
1070 g_quark_from_string((gchar
*)g_ptr_array_index(quarktable
, tmp
.name
));
1071 process
->free_events
= tmp
.free_events
;
1074 if(feof(fp
) || ferror(fp
)) goto end_loop
;
1076 gint hdr
= fgetc(fp
);
1077 if(hdr
== EOF
) goto end_loop
;
1081 process
->execution_stack
=
1082 g_array_set_size(process
->execution_stack
,
1083 process
->execution_stack
->len
+ 1);
1084 es
= &g_array_index(process
->execution_stack
, LttvExecutionState
,
1085 process
->execution_stack
->len
-1);
1086 process
->state
= es
;
1088 fread(&es
->t
, sizeof(es
->t
), 1, fp
);
1089 es
->t
= g_quark_from_string(
1090 (gchar
*)g_ptr_array_index(quarktable
, es
->t
));
1091 fread(&es
->n
, sizeof(es
->n
), 1, fp
);
1092 es
->n
= g_quark_from_string(
1093 (gchar
*)g_ptr_array_index(quarktable
, es
->n
));
1094 fread(&es
->s
, sizeof(es
->s
), 1, fp
);
1095 es
->s
= g_quark_from_string(
1096 (gchar
*)g_ptr_array_index(quarktable
, es
->s
));
1097 fread(&es
->entry
, sizeof(es
->entry
), 1, fp
);
1098 fread(&es
->change
, sizeof(es
->change
), 1, fp
);
1099 fread(&es
->cum_cpu_time
, sizeof(es
->cum_cpu_time
), 1, fp
);
1101 case HDR_USER_STACK
:
1102 process
->user_stack
= g_array_set_size(process
->user_stack
,
1103 process
->user_stack
->len
+ 1);
1104 address
= &g_array_index(process
->user_stack
, guint64
,
1105 process
->user_stack
->len
-1);
1106 fread(address
, sizeof(address
), 1, fp
);
1107 process
->current_function
= *address
;
1110 fread(&tmpq
, sizeof(tmpq
), 1, fp
);
1111 fread(&process
->usertrace
->cpu
, sizeof(process
->usertrace
->cpu
), 1, fp
);
1123 /* Called because a HDR_PROCESS_STATE was found */
1124 /* Append a saved state to the trace states */
1125 void lttv_state_read_raw(LttvTraceState
*self
, FILE *fp
, GPtrArray
*quarktable
)
1127 guint i
, nb_tracefile
, nb_block
, offset
;
1129 LttvTracefileState
*tfcs
;
1131 LttEventPosition
*ep
;
1139 LttvAttribute
*saved_states_tree
, *saved_state_tree
;
1141 LttvAttributeValue value
;
1142 GTree
*pqueue
= self
->parent
.ts_context
->pqueue
;
1143 ep
= ltt_event_position_new();
1145 restore_init_state(self
);
1147 fread(&t
, sizeof(t
), 1, fp
);
1150 if(feof(fp
) || ferror(fp
)) goto end_loop
;
1152 if(hdr
== EOF
) goto end_loop
;
1156 /* Call read_process_state_raw */
1157 read_process_state_raw(self
, fp
, quarktable
);
1165 case HDR_USER_STACK
:
1167 case HDR_PROCESS_STATE
:
1173 g_error("Error while parsing saved state file : unknown data header %d",
1179 nb_cpus
= ltt_trace_get_num_cpu(self
->parent
.t
);
1180 for(i
=0;i
<nb_cpus
;i
++) {
1183 g_assert(hdr
== HDR_CPU
);
1184 fread(&cpu_num
, sizeof(cpu_num
), 1, fp
); /* cpu number */
1185 g_assert(i
== cpu_num
);
1186 fread(&self
->running_process
[i
]->pid
,
1187 sizeof(self
->running_process
[i
]->pid
), 1, fp
);
1190 nb_tracefile
= self
->parent
.tracefiles
->len
;
1192 for(i
= 0 ; i
< nb_tracefile
; i
++) {
1194 LTTV_TRACEFILE_STATE(g_array_index(self
->parent
.tracefiles
,
1195 LttvTracefileContext
*, i
));
1196 // fprintf(fp, " <TRACEFILE TIMESTAMP_S=%lu TIMESTAMP_NS=%lu",
1197 // tfcs->parent.timestamp.tv_sec,
1198 // tfcs->parent.timestamp.tv_nsec);
1199 g_tree_remove(pqueue
, &tfcs
->parent
);
1201 g_assert(hdr
== HDR_TRACEFILE
);
1202 fread(&tfcs
->parent
.timestamp
, sizeof(tfcs
->parent
.timestamp
), 1, fp
);
1203 /* Note : if timestamp if LTT_TIME_INFINITE, there will be no
1204 * position following : end of trace */
1205 if(ltt_time_compare(tfcs
->parent
.timestamp
, ltt_time_infinite
) != 0) {
1206 fread(&nb_block
, sizeof(nb_block
), 1, fp
);
1207 fread(&offset
, sizeof(offset
), 1, fp
);
1208 fread(&tsc
, sizeof(tsc
), 1, fp
);
1209 ltt_event_position_set(ep
, tfcs
->parent
.tf
, nb_block
, offset
, tsc
);
1210 gint ret
= ltt_tracefile_seek_position(tfcs
->parent
.tf
, ep
);
1212 g_tree_insert(pqueue
, &tfcs
->parent
, &tfcs
->parent
);
1217 saved_states_tree
= lttv_attribute_find_subdir(self
->parent
.t_a
,
1218 LTTV_STATE_SAVED_STATES
);
1219 saved_state_tree
= g_object_new(LTTV_ATTRIBUTE_TYPE
, NULL
);
1220 value
= lttv_attribute_add(saved_states_tree
,
1221 lttv_attribute_get_number(saved_states_tree
), LTTV_GOBJECT
);
1222 *(value
.v_gobject
) = (GObject
*)saved_state_tree
;
1223 value
= lttv_attribute_add(saved_state_tree
, LTTV_STATE_TIME
, LTTV_TIME
);
1224 *(value
.v_time
) = t
;
1225 lttv_state_save(self
, saved_state_tree
);
1226 g_debug("Saving state at time %lu.%lu", t
.tv_sec
,
1229 *(self
->max_time_state_recomputed_in_seek
) = t
;
1233 /* Called when a HDR_TRACE is found */
1234 void lttv_trace_states_read_raw(LttvTraceState
*tcs
, FILE *fp
,
1235 GPtrArray
*quarktable
)
1240 if(feof(fp
) || ferror(fp
)) goto end_loop
;
1242 if(hdr
== EOF
) goto end_loop
;
1245 case HDR_PROCESS_STATE
:
1246 /* Call read_process_state_raw */
1247 lttv_state_read_raw(tcs
, fp
, quarktable
);
1255 case HDR_USER_STACK
:
1259 g_error("Error while parsing saved state file :"
1260 " unexpected data header %d",
1264 g_error("Error while parsing saved state file : unknown data header %d",
1269 *(tcs
->max_time_state_recomputed_in_seek
) = tcs
->parent
.time_span
.end_time
;
1270 restore_init_state(tcs
);
1271 lttv_process_trace_seek_time(&tcs
->parent
, ltt_time_zero
);
1277 /* Copy each process from an existing hash table to a new one */
1279 static void copy_process_state(gpointer key
, gpointer value
,gpointer user_data
)
1281 LttvProcessState
*process
, *new_process
;
1283 GHashTable
*new_processes
= (GHashTable
*)user_data
;
1287 process
= (LttvProcessState
*)value
;
1288 new_process
= g_new(LttvProcessState
, 1);
1289 *new_process
= *process
;
1290 new_process
->execution_stack
= g_array_sized_new(FALSE
, FALSE
,
1291 sizeof(LttvExecutionState
), PREALLOCATED_EXECUTION_STACK
);
1292 new_process
->execution_stack
=
1293 g_array_set_size(new_process
->execution_stack
,
1294 process
->execution_stack
->len
);
1295 for(i
= 0 ; i
< process
->execution_stack
->len
; i
++) {
1296 g_array_index(new_process
->execution_stack
, LttvExecutionState
, i
) =
1297 g_array_index(process
->execution_stack
, LttvExecutionState
, i
);
1299 new_process
->state
= &g_array_index(new_process
->execution_stack
,
1300 LttvExecutionState
, new_process
->execution_stack
->len
- 1);
1301 new_process
->user_stack
= g_array_sized_new(FALSE
, FALSE
,
1302 sizeof(guint64
), 0);
1303 new_process
->user_stack
=
1304 g_array_set_size(new_process
->user_stack
,
1305 process
->user_stack
->len
);
1306 for(i
= 0 ; i
< process
->user_stack
->len
; i
++) {
1307 g_array_index(new_process
->user_stack
, guint64
, i
) =
1308 g_array_index(process
->user_stack
, guint64
, i
);
1310 new_process
->current_function
= process
->current_function
;
1311 g_hash_table_insert(new_processes
, new_process
, new_process
);
1315 static GHashTable
*lttv_state_copy_process_table(GHashTable
*processes
)
1317 GHashTable
*new_processes
= g_hash_table_new(process_hash
, process_equal
);
1319 g_hash_table_foreach(processes
, copy_process_state
, new_processes
);
1320 return new_processes
;
1323 static LttvCPUState
*lttv_state_copy_cpu_states(LttvCPUState
*states
, guint n
)
1326 LttvCPUState
*retval
;
1328 retval
= g_new(LttvCPUState
, n
);
1330 for(i
=0; i
<n
; i
++) {
1331 retval
[i
].mode_stack
= g_array_new(FALSE
, FALSE
, sizeof(LttvCPUMode
));
1332 retval
[i
].last_irq
= states
[i
].last_irq
;
1333 retval
[i
].last_soft_irq
= states
[i
].last_soft_irq
;
1334 retval
[i
].last_trap
= states
[i
].last_trap
;
1335 g_array_set_size(retval
[i
].mode_stack
, states
[i
].mode_stack
->len
);
1336 for(j
=0; j
<states
[i
].mode_stack
->len
; j
++) {
1337 g_array_index(retval
[i
].mode_stack
, GQuark
, j
) = g_array_index(states
[i
].mode_stack
, GQuark
, j
);
1344 static void lttv_state_free_cpu_states(LttvCPUState
*states
, guint n
)
1348 for(i
=0; i
<n
; i
++) {
1349 g_array_free(states
[i
].mode_stack
, TRUE
);
1355 static LttvIRQState
*lttv_state_copy_irq_states(LttvIRQState
*states
, guint n
)
1358 LttvIRQState
*retval
;
1360 retval
= g_new(LttvIRQState
, n
);
1362 for(i
=0; i
<n
; i
++) {
1363 retval
[i
].mode_stack
= g_array_new(FALSE
, FALSE
, sizeof(LttvIRQMode
));
1364 g_array_set_size(retval
[i
].mode_stack
, states
[i
].mode_stack
->len
);
1365 for(j
=0; j
<states
[i
].mode_stack
->len
; j
++) {
1366 g_array_index(retval
[i
].mode_stack
, GQuark
, j
) = g_array_index(states
[i
].mode_stack
, GQuark
, j
);
1373 static void lttv_state_free_irq_states(LttvIRQState
*states
, guint n
)
1377 for(i
=0; i
<n
; i
++) {
1378 g_array_free(states
[i
].mode_stack
, TRUE
);
1384 static LttvSoftIRQState
*lttv_state_copy_soft_irq_states(LttvSoftIRQState
*states
, guint n
)
1387 LttvSoftIRQState
*retval
;
1389 retval
= g_new(LttvSoftIRQState
, n
);
1391 for(i
=0; i
<n
; i
++) {
1392 retval
[i
].pending
= states
[i
].pending
;
1393 retval
[i
].running
= states
[i
].running
;
1399 static void lttv_state_free_soft_irq_states(LttvSoftIRQState
*states
, guint n
)
1404 static LttvTrapState
*lttv_state_copy_trap_states(LttvTrapState
*states
, guint n
)
1407 LttvTrapState
*retval
;
1409 retval
= g_new(LttvTrapState
, n
);
1411 for(i
=0; i
<n
; i
++) {
1412 retval
[i
].running
= states
[i
].running
;
1418 static void lttv_state_free_trap_states(LttvTrapState
*states
, guint n
)
1423 /* bdevstate stuff */
1425 static LttvBdevState
*get_hashed_bdevstate(LttvTraceState
*ts
, guint16 devcode
)
1427 gint devcode_gint
= devcode
;
1428 gpointer bdev
= g_hash_table_lookup(ts
->bdev_states
, &devcode_gint
);
1430 LttvBdevState
*bdevstate
= g_new(LttvBdevState
, 1);
1431 bdevstate
->mode_stack
= g_array_new(FALSE
, FALSE
, sizeof(GQuark
));
1433 gint
* key
= g_new(gint
, 1);
1435 g_hash_table_insert(ts
->bdev_states
, key
, bdevstate
);
1443 static LttvBdevState
*bdevstate_new(void)
1445 LttvBdevState
*retval
;
1446 retval
= g_new(LttvBdevState
, 1);
1447 retval
->mode_stack
= g_array_new(FALSE
, FALSE
, sizeof(GQuark
));
1452 static void bdevstate_free(LttvBdevState
*bds
)
1454 g_array_free(bds
->mode_stack
, TRUE
);
1458 static void bdevstate_free_cb(gpointer key
, gpointer value
, gpointer user_data
)
1460 LttvBdevState
*bds
= (LttvBdevState
*) value
;
1462 bdevstate_free(bds
);
1465 static LttvBdevState
*bdevstate_copy(LttvBdevState
*bds
)
1467 LttvBdevState
*retval
;
1469 retval
= bdevstate_new();
1470 g_array_insert_vals(retval
->mode_stack
, 0, bds
->mode_stack
->data
, bds
->mode_stack
->len
);
1475 static void insert_and_copy_bdev_state(gpointer k
, gpointer v
, gpointer u
)
1477 //GHashTable *ht = (GHashTable *)u;
1478 LttvBdevState
*bds
= (LttvBdevState
*)v
;
1479 LttvBdevState
*newbds
;
1481 newbds
= bdevstate_copy(bds
);
1483 g_hash_table_insert(u
, k
, newbds
);
1486 static GHashTable
*lttv_state_copy_blkdev_hashtable(GHashTable
*ht
)
1490 retval
= g_hash_table_new(g_int_hash
, g_int_equal
);
1492 g_hash_table_foreach(ht
, insert_and_copy_bdev_state
, retval
);
1497 /* Free a hashtable and the LttvBdevState structures its values
1500 static void lttv_state_free_blkdev_hashtable(GHashTable
*ht
)
1502 g_hash_table_foreach(ht
, bdevstate_free_cb
, NULL
);
1503 g_hash_table_destroy(ht
);
1506 /* The saved state for each trace contains a member "processes", which
1507 stores a copy of the process table, and a member "tracefiles" with
1508 one entry per tracefile. Each tracefile has a "process" member pointing
1509 to the current process and a "position" member storing the tracefile
1510 position (needed to seek to the current "next" event. */
1512 static void state_save(LttvTraceState
*self
, LttvAttribute
*container
)
1514 guint i
, nb_tracefile
, nb_cpus
, nb_irqs
, nb_soft_irqs
, nb_traps
;
1516 LttvTracefileState
*tfcs
;
1518 LttvAttribute
*tracefiles_tree
, *tracefile_tree
;
1520 guint
*running_process
;
1522 LttvAttributeValue value
;
1524 LttEventPosition
*ep
;
1526 tracefiles_tree
= lttv_attribute_find_subdir(container
,
1527 LTTV_STATE_TRACEFILES
);
1529 value
= lttv_attribute_add(container
, LTTV_STATE_PROCESSES
,
1531 *(value
.v_pointer
) = lttv_state_copy_process_table(self
->processes
);
1533 /* Add the currently running processes array */
1534 nb_cpus
= ltt_trace_get_num_cpu(self
->parent
.t
);
1535 running_process
= g_new(guint
, nb_cpus
);
1536 for(i
=0;i
<nb_cpus
;i
++) {
1537 running_process
[i
] = self
->running_process
[i
]->pid
;
1539 value
= lttv_attribute_add(container
, LTTV_STATE_RUNNING_PROCESS
,
1541 *(value
.v_pointer
) = running_process
;
1543 g_info("State save");
1545 nb_tracefile
= self
->parent
.tracefiles
->len
;
1547 for(i
= 0 ; i
< nb_tracefile
; i
++) {
1549 LTTV_TRACEFILE_STATE(g_array_index(self
->parent
.tracefiles
,
1550 LttvTracefileContext
*, i
));
1551 tracefile_tree
= g_object_new(LTTV_ATTRIBUTE_TYPE
, NULL
);
1552 value
= lttv_attribute_add(tracefiles_tree
, i
,
1554 *(value
.v_gobject
) = (GObject
*)tracefile_tree
;
1556 value
= lttv_attribute_add(tracefile_tree
, LTTV_STATE_PROCESS
,
1558 *(value
.v_uint
) = tfcs
->process
->pid
;
1560 value
= lttv_attribute_add(tracefile_tree
, LTTV_STATE_EVENT
,
1562 /* Only save the position if the tfs has not infinite time. */
1563 //if(!g_tree_lookup(self->parent.ts_context->pqueue, &tfcs->parent)
1564 // && current_tfcs != tfcs) {
1565 if(ltt_time_compare(tfcs
->parent
.timestamp
, ltt_time_infinite
) == 0) {
1566 *(value
.v_pointer
) = NULL
;
1568 LttEvent
*e
= ltt_tracefile_get_event(tfcs
->parent
.tf
);
1569 ep
= ltt_event_position_new();
1570 ltt_event_position(e
, ep
);
1571 *(value
.v_pointer
) = ep
;
1573 guint nb_block
, offset
;
1576 ltt_event_position_get(ep
, &tf
, &nb_block
, &offset
, &tsc
);
1577 g_info("Block %u offset %u tsc %" PRIu64
" time %lu.%lu", nb_block
, offset
,
1579 tfcs
->parent
.timestamp
.tv_sec
, tfcs
->parent
.timestamp
.tv_nsec
);
1583 /* save the cpu state */
1585 value
= lttv_attribute_add(container
, LTTV_STATE_RESOURCE_CPUS_COUNT
,
1587 *(value
.v_uint
) = nb_cpus
;
1589 value
= lttv_attribute_add(container
, LTTV_STATE_RESOURCE_CPUS
,
1591 *(value
.v_pointer
) = lttv_state_copy_cpu_states(self
->cpu_states
, nb_cpus
);
1594 /* save the irq state */
1595 nb_irqs
= self
->nb_irqs
;
1597 value
= lttv_attribute_add(container
, LTTV_STATE_RESOURCE_IRQS
,
1599 *(value
.v_pointer
) = lttv_state_copy_irq_states(self
->irq_states
, nb_irqs
);
1602 /* save the soft irq state */
1603 nb_soft_irqs
= self
->nb_soft_irqs
;
1605 value
= lttv_attribute_add(container
, LTTV_STATE_RESOURCE_SOFT_IRQS
,
1607 *(value
.v_pointer
) = lttv_state_copy_soft_irq_states(self
->soft_irq_states
, nb_soft_irqs
);
1610 /* save the trap state */
1611 nb_traps
= self
->nb_traps
;
1613 value
= lttv_attribute_add(container
, LTTV_STATE_RESOURCE_TRAPS
,
1615 *(value
.v_pointer
) = lttv_state_copy_trap_states(self
->trap_states
, nb_traps
);
1618 /* save the blkdev states */
1619 value
= lttv_attribute_add(container
, LTTV_STATE_RESOURCE_BLKDEVS
,
1621 *(value
.v_pointer
) = lttv_state_copy_blkdev_hashtable(self
->bdev_states
);
1625 static void state_restore(LttvTraceState
*self
, LttvAttribute
*container
)
1627 guint i
, nb_tracefile
, pid
, nb_cpus
, nb_irqs
, nb_soft_irqs
, nb_traps
;
1629 LttvTracefileState
*tfcs
;
1631 LttvAttribute
*tracefiles_tree
, *tracefile_tree
;
1633 guint
*running_process
;
1635 LttvAttributeType type
;
1637 LttvAttributeValue value
;
1639 LttvAttributeName name
;
1643 LttEventPosition
*ep
;
1645 LttvTracesetContext
*tsc
= self
->parent
.ts_context
;
1647 tracefiles_tree
= lttv_attribute_find_subdir(container
,
1648 LTTV_STATE_TRACEFILES
);
1650 type
= lttv_attribute_get_by_name(container
, LTTV_STATE_PROCESSES
,
1652 g_assert(type
== LTTV_POINTER
);
1653 lttv_state_free_process_table(self
->processes
);
1654 self
->processes
= lttv_state_copy_process_table(*(value
.v_pointer
));
1656 /* Add the currently running processes array */
1657 nb_cpus
= ltt_trace_get_num_cpu(self
->parent
.t
);
1658 type
= lttv_attribute_get_by_name(container
, LTTV_STATE_RUNNING_PROCESS
,
1660 g_assert(type
== LTTV_POINTER
);
1661 running_process
= *(value
.v_pointer
);
1662 for(i
=0;i
<nb_cpus
;i
++) {
1663 pid
= running_process
[i
];
1664 self
->running_process
[i
] = lttv_state_find_process(self
, i
, pid
);
1665 g_assert(self
->running_process
[i
] != NULL
);
1668 nb_tracefile
= self
->parent
.tracefiles
->len
;
1670 //g_tree_destroy(tsc->pqueue);
1671 //tsc->pqueue = g_tree_new(compare_tracefile);
1673 /* restore cpu resource states */
1674 type
= lttv_attribute_get_by_name(container
, LTTV_STATE_RESOURCE_CPUS
, &value
);
1675 g_assert(type
== LTTV_POINTER
);
1676 lttv_state_free_cpu_states(self
->cpu_states
, nb_cpus
);
1677 self
->cpu_states
= lttv_state_copy_cpu_states(*(value
.v_pointer
), nb_cpus
);
1679 /* restore irq resource states */
1680 nb_irqs
= self
->nb_irqs
;
1681 type
= lttv_attribute_get_by_name(container
, LTTV_STATE_RESOURCE_IRQS
, &value
);
1682 g_assert(type
== LTTV_POINTER
);
1683 lttv_state_free_irq_states(self
->irq_states
, nb_irqs
);
1684 self
->irq_states
= lttv_state_copy_irq_states(*(value
.v_pointer
), nb_irqs
);
1686 /* restore soft irq resource states */
1687 nb_soft_irqs
= self
->nb_soft_irqs
;
1688 type
= lttv_attribute_get_by_name(container
, LTTV_STATE_RESOURCE_SOFT_IRQS
, &value
);
1689 g_assert(type
== LTTV_POINTER
);
1690 lttv_state_free_soft_irq_states(self
->soft_irq_states
, nb_soft_irqs
);
1691 self
->soft_irq_states
= lttv_state_copy_soft_irq_states(*(value
.v_pointer
), nb_soft_irqs
);
1693 /* restore trap resource states */
1694 nb_traps
= self
->nb_traps
;
1695 type
= lttv_attribute_get_by_name(container
, LTTV_STATE_RESOURCE_TRAPS
, &value
);
1696 g_assert(type
== LTTV_POINTER
);
1697 lttv_state_free_trap_states(self
->trap_states
, nb_traps
);
1698 self
->trap_states
= lttv_state_copy_trap_states(*(value
.v_pointer
), nb_traps
);
1700 /* restore the blkdev states */
1701 type
= lttv_attribute_get_by_name(container
, LTTV_STATE_RESOURCE_BLKDEVS
, &value
);
1702 g_assert(type
== LTTV_POINTER
);
1703 lttv_state_free_blkdev_hashtable(self
->bdev_states
);
1704 self
->bdev_states
= lttv_state_copy_blkdev_hashtable(*(value
.v_pointer
));
1706 for(i
= 0 ; i
< nb_tracefile
; i
++) {
1708 LTTV_TRACEFILE_STATE(g_array_index(self
->parent
.tracefiles
,
1709 LttvTracefileContext
*, i
));
1710 type
= lttv_attribute_get(tracefiles_tree
, i
, &name
, &value
, &is_named
);
1711 g_assert(type
== LTTV_GOBJECT
);
1712 tracefile_tree
= *((LttvAttribute
**)(value
.v_gobject
));
1714 type
= lttv_attribute_get_by_name(tracefile_tree
, LTTV_STATE_PROCESS
,
1716 g_assert(type
== LTTV_UINT
);
1717 pid
= *(value
.v_uint
);
1718 tfcs
->process
= lttv_state_find_process_or_create(tfcs
, pid
);
1720 type
= lttv_attribute_get_by_name(tracefile_tree
, LTTV_STATE_EVENT
,
1722 g_assert(type
== LTTV_POINTER
);
1723 //g_assert(*(value.v_pointer) != NULL);
1724 ep
= *(value
.v_pointer
);
1725 g_assert(tfcs
->parent
.t_context
!= NULL
);
1727 tfcs
->cpu_state
= &self
->cpu_states
[tfcs
->cpu
];
1729 LttvTracefileContext
*tfc
= LTTV_TRACEFILE_CONTEXT(tfcs
);
1730 g_tree_remove(tsc
->pqueue
, tfc
);
1733 g_assert(ltt_tracefile_seek_position(tfc
->tf
, ep
) == 0);
1734 tfc
->timestamp
= ltt_event_time(ltt_tracefile_get_event(tfc
->tf
));
1735 g_assert(ltt_time_compare(tfc
->timestamp
, ltt_time_infinite
) != 0);
1736 g_tree_insert(tsc
->pqueue
, tfc
, tfc
);
1737 g_info("Restoring state for a tf at time %lu.%lu", tfc
->timestamp
.tv_sec
, tfc
->timestamp
.tv_nsec
);
1739 tfc
->timestamp
= ltt_time_infinite
;
1745 static void state_saved_free(LttvTraceState
*self
, LttvAttribute
*container
)
1747 guint i
, nb_tracefile
, nb_cpus
, nb_irqs
, nb_softirqs
;
1749 LttvTracefileState
*tfcs
;
1751 LttvAttribute
*tracefiles_tree
, *tracefile_tree
;
1753 guint
*running_process
;
1755 LttvAttributeType type
;
1757 LttvAttributeValue value
;
1759 LttvAttributeName name
;
1763 tracefiles_tree
= lttv_attribute_find_subdir(container
,
1764 LTTV_STATE_TRACEFILES
);
1765 g_object_ref(G_OBJECT(tracefiles_tree
));
1766 lttv_attribute_remove_by_name(container
, LTTV_STATE_TRACEFILES
);
1768 type
= lttv_attribute_get_by_name(container
, LTTV_STATE_PROCESSES
,
1770 g_assert(type
== LTTV_POINTER
);
1771 lttv_state_free_process_table(*(value
.v_pointer
));
1772 *(value
.v_pointer
) = NULL
;
1773 lttv_attribute_remove_by_name(container
, LTTV_STATE_PROCESSES
);
1775 /* Free running processes array */
1776 type
= lttv_attribute_get_by_name(container
, LTTV_STATE_RUNNING_PROCESS
,
1778 g_assert(type
== LTTV_POINTER
);
1779 running_process
= *(value
.v_pointer
);
1780 g_free(running_process
);
1782 /* free cpu resource states */
1783 type
= lttv_attribute_get_by_name(container
, LTTV_STATE_RESOURCE_CPUS_COUNT
, &value
);
1784 g_assert(type
== LTTV_UINT
);
1785 nb_cpus
= *value
.v_uint
;
1786 type
= lttv_attribute_get_by_name(container
, LTTV_STATE_RESOURCE_CPUS
, &value
);
1787 g_assert(type
== LTTV_POINTER
);
1788 lttv_state_free_cpu_states(*(value
.v_pointer
), nb_cpus
);
1790 /* free irq resource states */
1791 nb_irqs
= self
->nb_irqs
;
1792 type
= lttv_attribute_get_by_name(container
, LTTV_STATE_RESOURCE_IRQS
, &value
);
1793 g_assert(type
== LTTV_POINTER
);
1794 lttv_state_free_irq_states(*(value
.v_pointer
), nb_irqs
);
1796 /* free softirq resource states */
1797 nb_softirqs
= self
->nb_irqs
;
1798 type
= lttv_attribute_get_by_name(container
, LTTV_STATE_RESOURCE_SOFT_IRQS
, &value
);
1799 g_assert(type
== LTTV_POINTER
);
1800 lttv_state_free_soft_irq_states(*(value
.v_pointer
), nb_softirqs
);
1802 /* free the blkdev states */
1803 type
= lttv_attribute_get_by_name(container
, LTTV_STATE_RESOURCE_BLKDEVS
, &value
);
1804 g_assert(type
== LTTV_POINTER
);
1805 lttv_state_free_blkdev_hashtable(*(value
.v_pointer
));
1807 nb_tracefile
= self
->parent
.tracefiles
->len
;
1809 for(i
= 0 ; i
< nb_tracefile
; i
++) {
1811 LTTV_TRACEFILE_STATE(g_array_index(self
->parent
.tracefiles
,
1812 LttvTracefileContext
*, i
));
1813 type
= lttv_attribute_get(tracefiles_tree
, i
, &name
, &value
, &is_named
);
1814 g_assert(type
== LTTV_GOBJECT
);
1815 tracefile_tree
= *((LttvAttribute
**)(value
.v_gobject
));
1817 type
= lttv_attribute_get_by_name(tracefile_tree
, LTTV_STATE_EVENT
,
1819 g_assert(type
== LTTV_POINTER
);
1820 if(*(value
.v_pointer
) != NULL
) g_free(*(value
.v_pointer
));
1822 g_object_unref(G_OBJECT(tracefiles_tree
));
1826 static void free_saved_state(LttvTraceState
*self
)
1830 LttvAttributeType type
;
1832 LttvAttributeValue value
;
1834 LttvAttributeName name
;
1838 LttvAttribute
*saved_states
;
1840 saved_states
= lttv_attribute_find_subdir(self
->parent
.t_a
,
1841 LTTV_STATE_SAVED_STATES
);
1843 nb
= lttv_attribute_get_number(saved_states
);
1844 for(i
= 0 ; i
< nb
; i
++) {
1845 type
= lttv_attribute_get(saved_states
, i
, &name
, &value
, &is_named
);
1846 g_assert(type
== LTTV_GOBJECT
);
1847 state_saved_free(self
, *((LttvAttribute
**)value
.v_gobject
));
1850 lttv_attribute_remove_by_name(self
->parent
.t_a
, LTTV_STATE_SAVED_STATES
);
1855 create_max_time(LttvTraceState
*tcs
)
1857 LttvAttributeValue v
;
1859 lttv_attribute_find(tcs
->parent
.t_a
, LTTV_STATE_SAVED_STATES_TIME
,
1861 g_assert(*(v
.v_pointer
) == NULL
);
1862 *(v
.v_pointer
) = g_new(LttTime
,1);
1863 *((LttTime
*)*(v
.v_pointer
)) = ltt_time_zero
;
1868 get_max_time(LttvTraceState
*tcs
)
1870 LttvAttributeValue v
;
1872 lttv_attribute_find(tcs
->parent
.t_a
, LTTV_STATE_SAVED_STATES_TIME
,
1874 g_assert(*(v
.v_pointer
) != NULL
);
1875 tcs
->max_time_state_recomputed_in_seek
= (LttTime
*)*(v
.v_pointer
);
1880 free_max_time(LttvTraceState
*tcs
)
1882 LttvAttributeValue v
;
1884 lttv_attribute_find(tcs
->parent
.t_a
, LTTV_STATE_SAVED_STATES_TIME
,
1886 g_free(*(v
.v_pointer
));
1887 *(v
.v_pointer
) = NULL
;
1891 typedef struct _LttvNameTables
{
1892 // FIXME GQuark *eventtype_names;
1893 GQuark
*syscall_names
;
1899 GQuark
*soft_irq_names
;
1901 GHashTable
*kprobe_hash
;
1906 create_name_tables(LttvTraceState
*tcs
)
1910 GString
*fe_name
= g_string_new("");
1912 LttvNameTables
*name_tables
= g_new(LttvNameTables
, 1);
1914 LttvAttributeValue v
;
1918 lttv_attribute_find(tcs
->parent
.t_a
, LTTV_STATE_NAME_TABLES
,
1920 g_assert(*(v
.v_pointer
) == NULL
);
1921 *(v
.v_pointer
) = name_tables
;
1923 hooks
= g_array_sized_new(FALSE
, FALSE
, sizeof(LttvTraceHook
), 1);
1925 if(!lttv_trace_find_hook(tcs
->parent
.t
,
1927 LTT_EVENT_SYSCALL_ENTRY
,
1928 FIELD_ARRAY(LTT_FIELD_SYSCALL_ID
),
1929 NULL
, NULL
, &hooks
)) {
1931 // th = lttv_trace_hook_get_first(&th);
1933 // t = ltt_field_type(lttv_trace_get_hook_field(th, 0));
1934 // nb = ltt_type_element_number(t);
1936 // name_tables->syscall_names = g_new(GQuark, nb);
1937 // name_tables->nb_syscalls = nb;
1939 // for(i = 0 ; i < nb ; i++) {
1940 // name_tables->syscall_names[i] = ltt_enum_string_get(t, i);
1941 // if(!name_tables->syscall_names[i]) {
1942 // GString *string = g_string_new("");
1943 // g_string_printf(string, "syscall %u", i);
1944 // name_tables->syscall_names[i] = g_quark_from_string(string->str);
1945 // g_string_free(string, TRUE);
1949 name_tables
->nb_syscalls
= 256;
1950 name_tables
->syscall_names
= g_new(GQuark
, 256);
1951 for(i
= 0 ; i
< 256 ; i
++) {
1952 g_string_printf(fe_name
, "syscall %d", i
);
1953 name_tables
->syscall_names
[i
] = g_quark_from_string(fe_name
->str
);
1956 name_tables
->syscall_names
= NULL
;
1957 name_tables
->nb_syscalls
= 0;
1959 lttv_trace_hook_remove_all(&hooks
);
1961 if(!lttv_trace_find_hook(tcs
->parent
.t
,
1963 LTT_EVENT_TRAP_ENTRY
,
1964 FIELD_ARRAY(LTT_FIELD_TRAP_ID
),
1965 NULL
, NULL
, &hooks
) ||
1966 !lttv_trace_find_hook(tcs
->parent
.t
,
1968 LTT_EVENT_PAGE_FAULT_ENTRY
,
1969 FIELD_ARRAY(LTT_FIELD_TRAP_ID
),
1970 NULL
, NULL
, &hooks
)) {
1972 // th = lttv_trace_hook_get_first(&th);
1974 // t = ltt_field_type(lttv_trace_get_hook_field(th, 0));
1975 // //nb = ltt_type_element_number(t);
1977 // name_tables->trap_names = g_new(GQuark, nb);
1978 // for(i = 0 ; i < nb ; i++) {
1979 // name_tables->trap_names[i] = g_quark_from_string(
1980 // ltt_enum_string_get(t, i));
1983 name_tables
->nb_traps
= 256;
1984 name_tables
->trap_names
= g_new(GQuark
, 256);
1985 for(i
= 0 ; i
< 256 ; i
++) {
1986 g_string_printf(fe_name
, "trap %d", i
);
1987 name_tables
->trap_names
[i
] = g_quark_from_string(fe_name
->str
);
1990 name_tables
->trap_names
= NULL
;
1991 name_tables
->nb_traps
= 0;
1993 lttv_trace_hook_remove_all(&hooks
);
1995 if(!lttv_trace_find_hook(tcs
->parent
.t
,
1997 LTT_EVENT_IRQ_ENTRY
,
1998 FIELD_ARRAY(LTT_FIELD_IRQ_ID
),
1999 NULL
, NULL
, &hooks
)) {
2002 name_tables->irq_names = g_new(GQuark, nb);
2003 for(i = 0 ; i < nb ; i++) {
2004 name_tables->irq_names[i] = g_quark_from_string(ltt_enum_string_get(t, i));
2008 name_tables
->nb_irqs
= 256;
2009 name_tables
->irq_names
= g_new(GQuark
, 256);
2010 for(i
= 0 ; i
< 256 ; i
++) {
2011 g_string_printf(fe_name
, "irq %d", i
);
2012 name_tables
->irq_names
[i
] = g_quark_from_string(fe_name
->str
);
2015 name_tables
->nb_irqs
= 0;
2016 name_tables
->irq_names
= NULL
;
2018 lttv_trace_hook_remove_all(&hooks
);
2020 name_tables->soft_irq_names = g_new(GQuark, nb);
2021 for(i = 0 ; i < nb ; i++) {
2022 name_tables->soft_irq_names[i] = g_quark_from_string(ltt_enum_string_get(t, i));
2026 /* the kernel is limited to 32 statically defined softirqs */
2027 name_tables
->nb_softirqs
= 32;
2028 name_tables
->soft_irq_names
= g_new(GQuark
, name_tables
->nb_softirqs
);
2029 for(i
= 0 ; i
< name_tables
->nb_softirqs
; i
++) {
2030 g_string_printf(fe_name
, "softirq %d", i
);
2031 name_tables
->soft_irq_names
[i
] = g_quark_from_string(fe_name
->str
);
2033 g_array_free(hooks
, TRUE
);
2035 g_string_free(fe_name
, TRUE
);
2037 #if (__SIZEOF_LONG__ == 4)
2038 name_tables
->kprobe_hash
= g_hash_table_new_full(guint64_hash
, guint64_equal
,
2041 name_tables
->kprobe_hash
= g_hash_table_new(g_direct_hash
, g_direct_equal
);
2047 get_name_tables(LttvTraceState
*tcs
)
2049 LttvNameTables
*name_tables
;
2051 LttvAttributeValue v
;
2053 lttv_attribute_find(tcs
->parent
.t_a
, LTTV_STATE_NAME_TABLES
,
2055 g_assert(*(v
.v_pointer
) != NULL
);
2056 name_tables
= (LttvNameTables
*)*(v
.v_pointer
);
2057 //tcs->eventtype_names = name_tables->eventtype_names;
2058 tcs
->syscall_names
= name_tables
->syscall_names
;
2059 tcs
->nb_syscalls
= name_tables
->nb_syscalls
;
2060 tcs
->trap_names
= name_tables
->trap_names
;
2061 tcs
->nb_traps
= name_tables
->nb_traps
;
2062 tcs
->irq_names
= name_tables
->irq_names
;
2063 tcs
->soft_irq_names
= name_tables
->soft_irq_names
;
2064 tcs
->nb_irqs
= name_tables
->nb_irqs
;
2065 tcs
->nb_soft_irqs
= name_tables
->nb_softirqs
;
2066 tcs
->kprobe_hash
= name_tables
->kprobe_hash
;
2071 free_name_tables(LttvTraceState
*tcs
)
2073 LttvNameTables
*name_tables
;
2075 LttvAttributeValue v
;
2077 lttv_attribute_find(tcs
->parent
.t_a
, LTTV_STATE_NAME_TABLES
,
2079 name_tables
= (LttvNameTables
*)*(v
.v_pointer
);
2080 *(v
.v_pointer
) = NULL
;
2082 // g_free(name_tables->eventtype_names);
2083 if(name_tables
->syscall_names
) g_free(name_tables
->syscall_names
);
2084 if(name_tables
->trap_names
) g_free(name_tables
->trap_names
);
2085 if(name_tables
->irq_names
) g_free(name_tables
->irq_names
);
2086 if(name_tables
->soft_irq_names
) g_free(name_tables
->soft_irq_names
);
2087 if(name_tables
) g_free(name_tables
);
2088 if(name_tables
) g_hash_table_destroy(name_tables
->kprobe_hash
);
2091 #ifdef HASH_TABLE_DEBUG
2093 static void test_process(gpointer key
, gpointer value
, gpointer user_data
)
2095 LttvProcessState
*process
= (LttvProcessState
*)value
;
2097 /* Test for process corruption */
2098 guint stack_len
= process
->execution_stack
->len
;
2101 static void hash_table_check(GHashTable
*table
)
2103 g_hash_table_foreach(table
, test_process
, NULL
);
2109 /* clears the stack and sets the state passed as argument */
2110 static void cpu_set_base_mode(LttvCPUState
*cpust
, LttvCPUMode state
)
2112 g_array_set_size(cpust
->mode_stack
, 1);
2113 ((GQuark
*)cpust
->mode_stack
->data
)[0] = state
;
2116 static void cpu_push_mode(LttvCPUState
*cpust
, LttvCPUMode state
)
2118 g_array_set_size(cpust
->mode_stack
, cpust
->mode_stack
->len
+ 1);
2119 ((GQuark
*)cpust
->mode_stack
->data
)[cpust
->mode_stack
->len
- 1] = state
;
2122 static void cpu_pop_mode(LttvCPUState
*cpust
)
2124 if(cpust
->mode_stack
->len
<= 1)
2125 cpu_set_base_mode(cpust
, LTTV_CPU_UNKNOWN
);
2127 g_array_set_size(cpust
->mode_stack
, cpust
->mode_stack
->len
- 1);
2130 /* clears the stack and sets the state passed as argument */
2131 static void bdev_set_base_mode(LttvBdevState
*bdevst
, LttvBdevMode state
)
2133 g_array_set_size(bdevst
->mode_stack
, 1);
2134 ((GQuark
*)bdevst
->mode_stack
->data
)[0] = state
;
2137 static void bdev_push_mode(LttvBdevState
*bdevst
, LttvBdevMode state
)
2139 g_array_set_size(bdevst
->mode_stack
, bdevst
->mode_stack
->len
+ 1);
2140 ((GQuark
*)bdevst
->mode_stack
->data
)[bdevst
->mode_stack
->len
- 1] = state
;
2143 static void bdev_pop_mode(LttvBdevState
*bdevst
)
2145 if(bdevst
->mode_stack
->len
<= 1)
2146 bdev_set_base_mode(bdevst
, LTTV_BDEV_UNKNOWN
);
2148 g_array_set_size(bdevst
->mode_stack
, bdevst
->mode_stack
->len
- 1);
2151 static void irq_set_base_mode(LttvIRQState
*irqst
, LttvIRQMode state
)
2153 g_array_set_size(irqst
->mode_stack
, 1);
2154 ((GQuark
*)irqst
->mode_stack
->data
)[0] = state
;
2157 static void irq_push_mode(LttvIRQState
*irqst
, LttvIRQMode state
)
2159 g_array_set_size(irqst
->mode_stack
, irqst
->mode_stack
->len
+ 1);
2160 ((GQuark
*)irqst
->mode_stack
->data
)[irqst
->mode_stack
->len
- 1] = state
;
2163 static void irq_pop_mode(LttvIRQState
*irqst
)
2165 if(irqst
->mode_stack
->len
<= 1)
2166 irq_set_base_mode(irqst
, LTTV_IRQ_UNKNOWN
);
2168 g_array_set_size(irqst
->mode_stack
, irqst
->mode_stack
->len
- 1);
2171 static void push_state(LttvTracefileState
*tfs
, LttvExecutionMode t
,
2174 LttvExecutionState
*es
;
2176 LttvTraceState
*ts
= (LttvTraceState
*)tfs
->parent
.t_context
;
2177 guint cpu
= tfs
->cpu
;
2179 #ifdef HASH_TABLE_DEBUG
2180 hash_table_check(ts
->processes
);
2182 LttvProcessState
*process
= ts
->running_process
[cpu
];
2184 guint depth
= process
->execution_stack
->len
;
2186 process
->execution_stack
=
2187 g_array_set_size(process
->execution_stack
, depth
+ 1);
2190 &g_array_index(process
->execution_stack
, LttvExecutionState
, depth
- 1);
2192 es
= &g_array_index(process
->execution_stack
, LttvExecutionState
, depth
);
2195 es
->entry
= es
->change
= tfs
->parent
.timestamp
;
2196 es
->cum_cpu_time
= ltt_time_zero
;
2197 es
->s
= process
->state
->s
;
2198 process
->state
= es
;
2202 * return 1 when empty, else 0 */
2203 int lttv_state_pop_state_cleanup(LttvProcessState
*process
,
2204 LttvTracefileState
*tfs
)
2206 guint depth
= process
->execution_stack
->len
;
2212 process
->execution_stack
=
2213 g_array_set_size(process
->execution_stack
, depth
- 1);
2214 process
->state
= &g_array_index(process
->execution_stack
, LttvExecutionState
,
2216 process
->state
->change
= tfs
->parent
.timestamp
;
2221 static void pop_state(LttvTracefileState
*tfs
, LttvExecutionMode t
)
2223 guint cpu
= tfs
->cpu
;
2224 LttvTraceState
*ts
= (LttvTraceState
*)tfs
->parent
.t_context
;
2225 LttvProcessState
*process
= ts
->running_process
[cpu
];
2227 guint depth
= process
->execution_stack
->len
;
2229 if(process
->state
->t
!= t
){
2230 g_info("Different execution mode type (%lu.%09lu): ignore it\n",
2231 tfs
->parent
.timestamp
.tv_sec
, tfs
->parent
.timestamp
.tv_nsec
);
2232 g_info("process state has %s when pop_int is %s\n",
2233 g_quark_to_string(process
->state
->t
),
2234 g_quark_to_string(t
));
2235 g_info("{ %u, %u, %s, %s, %s }\n",
2238 g_quark_to_string(process
->name
),
2239 g_quark_to_string(process
->brand
),
2240 g_quark_to_string(process
->state
->s
));
2245 g_info("Trying to pop last state on stack (%lu.%09lu): ignore it\n",
2246 tfs
->parent
.timestamp
.tv_sec
, tfs
->parent
.timestamp
.tv_nsec
);
2250 process
->execution_stack
=
2251 g_array_set_size(process
->execution_stack
, depth
- 1);
2252 process
->state
= &g_array_index(process
->execution_stack
, LttvExecutionState
,
2254 process
->state
->change
= tfs
->parent
.timestamp
;
2257 struct search_result
{
2258 const LttTime
*time
; /* Requested time */
2259 LttTime
*best
; /* Best result */
2262 static gint
search_usertrace(gconstpointer a
, gconstpointer b
)
2264 const LttTime
*elem_time
= (const LttTime
*)a
;
2265 /* Explicit non const cast */
2266 struct search_result
*res
= (struct search_result
*)b
;
2268 if(ltt_time_compare(*elem_time
, *(res
->time
)) < 0) {
2269 /* The usertrace was created before the schedchange */
2270 /* Get larger keys */
2272 } else if(ltt_time_compare(*elem_time
, *(res
->time
)) >= 0) {
2273 /* The usertrace was created after the schedchange time */
2274 /* Get smaller keys */
2276 if(ltt_time_compare(*elem_time
, *res
->best
) < 0) {
2277 res
->best
= (LttTime
*)elem_time
;
2280 res
->best
= (LttTime
*)elem_time
;
2287 static LttvTracefileState
*ltt_state_usertrace_find(LttvTraceState
*tcs
,
2288 guint pid
, const LttTime
*timestamp
)
2290 LttvTracefileState
*tfs
= NULL
;
2291 struct search_result res
;
2292 /* Find the usertrace associated with a pid and time interval.
2293 * Search in the usertraces by PID (within a hash) and then, for each
2294 * corresponding element of the array, find the first one with creation
2295 * timestamp the lowest, but higher or equal to "timestamp". */
2296 res
.time
= timestamp
;
2298 GTree
*usertrace_tree
= g_hash_table_lookup(tcs
->usertraces
,
2299 GUINT_TO_POINTER(pid
));
2300 if(usertrace_tree
) {
2301 g_tree_search(usertrace_tree
, search_usertrace
, &res
);
2303 tfs
= g_tree_lookup(usertrace_tree
, res
.best
);
2311 lttv_state_create_process(LttvTraceState
*tcs
, LttvProcessState
*parent
,
2312 guint cpu
, guint pid
, guint tgid
, GQuark name
, const LttTime
*timestamp
)
2314 LttvProcessState
*process
= g_new(LttvProcessState
, 1);
2316 LttvExecutionState
*es
;
2321 process
->tgid
= tgid
;
2323 process
->name
= name
;
2324 process
->brand
= LTTV_STATE_UNBRANDED
;
2325 //process->last_cpu = tfs->cpu_name;
2326 //process->last_cpu_index = ltt_tracefile_num(((LttvTracefileContext*)tfs)->tf);
2327 process
->type
= LTTV_STATE_USER_THREAD
;
2328 process
->usertrace
= ltt_state_usertrace_find(tcs
, pid
, timestamp
);
2329 process
->current_function
= 0; //function 0x0 by default.
2331 g_info("Process %u, core %p", process
->pid
, process
);
2332 g_hash_table_insert(tcs
->processes
, process
, process
);
2335 process
->ppid
= parent
->pid
;
2336 process
->creation_time
= *timestamp
;
2339 /* No parent. This process exists but we are missing all information about
2340 its creation. The birth time is set to zero but we remember the time of
2345 process
->creation_time
= ltt_time_zero
;
2348 process
->insertion_time
= *timestamp
;
2349 sprintf(buffer
,"%d-%lu.%lu",pid
, process
->creation_time
.tv_sec
,
2350 process
->creation_time
.tv_nsec
);
2351 process
->pid_time
= g_quark_from_string(buffer
);
2353 process
->free_events
= 0;
2354 //process->last_cpu = tfs->cpu_name;
2355 //process->last_cpu_index = ltt_tracefile_num(((LttvTracefileContext*)tfs)->tf);
2356 process
->execution_stack
= g_array_sized_new(FALSE
, FALSE
,
2357 sizeof(LttvExecutionState
), PREALLOCATED_EXECUTION_STACK
);
2358 process
->execution_stack
= g_array_set_size(process
->execution_stack
, 2);
2359 es
= process
->state
= &g_array_index(process
->execution_stack
,
2360 LttvExecutionState
, 0);
2361 es
->t
= LTTV_STATE_USER_MODE
;
2362 es
->n
= LTTV_STATE_SUBMODE_NONE
;
2363 es
->entry
= *timestamp
;
2364 //g_assert(timestamp->tv_sec != 0);
2365 es
->change
= *timestamp
;
2366 es
->cum_cpu_time
= ltt_time_zero
;
2367 es
->s
= LTTV_STATE_RUN
;
2369 es
= process
->state
= &g_array_index(process
->execution_stack
,
2370 LttvExecutionState
, 1);
2371 es
->t
= LTTV_STATE_SYSCALL
;
2372 es
->n
= LTTV_STATE_SUBMODE_NONE
;
2373 es
->entry
= *timestamp
;
2374 //g_assert(timestamp->tv_sec != 0);
2375 es
->change
= *timestamp
;
2376 es
->cum_cpu_time
= ltt_time_zero
;
2377 es
->s
= LTTV_STATE_WAIT_FORK
;
2379 /* Allocate an empty function call stack. If it's empty, use 0x0. */
2380 process
->user_stack
= g_array_sized_new(FALSE
, FALSE
,
2381 sizeof(guint64
), 0);
2386 LttvProcessState
*lttv_state_find_process(LttvTraceState
*ts
, guint cpu
,
2389 LttvProcessState key
;
2390 LttvProcessState
*process
;
2394 process
= g_hash_table_lookup(ts
->processes
, &key
);
2399 lttv_state_find_process_or_create(LttvTraceState
*ts
, guint cpu
, guint pid
,
2400 const LttTime
*timestamp
)
2402 LttvProcessState
*process
= lttv_state_find_process(ts
, cpu
, pid
);
2403 LttvExecutionState
*es
;
2405 /* Put ltt_time_zero creation time for unexisting processes */
2406 if(unlikely(process
== NULL
)) {
2407 process
= lttv_state_create_process(ts
,
2408 NULL
, cpu
, pid
, 0, LTTV_STATE_UNNAMED
, timestamp
);
2409 /* We are not sure is it's a kernel thread or normal thread, put the
2410 * bottom stack state to unknown */
2411 process
->execution_stack
=
2412 g_array_set_size(process
->execution_stack
, 1);
2413 process
->state
= es
=
2414 &g_array_index(process
->execution_stack
, LttvExecutionState
, 0);
2415 es
->t
= LTTV_STATE_MODE_UNKNOWN
;
2416 es
->s
= LTTV_STATE_UNNAMED
;
2421 /* FIXME : this function should be called when we receive an event telling that
2422 * release_task has been called in the kernel. In happens generally when
2423 * the parent waits for its child terminaison, but may also happen in special
2424 * cases in the child's exit : when the parent ignores its children SIGCCHLD or
2425 * has the flag SA_NOCLDWAIT. It can also happen when the child is part
2426 * of a killed thread group, but isn't the leader.
2428 static int exit_process(LttvTracefileState
*tfs
, LttvProcessState
*process
)
2430 LttvTraceState
*ts
= LTTV_TRACE_STATE(tfs
->parent
.t_context
);
2431 LttvProcessState key
;
2433 /* Wait for both schedule with exit dead and process free to happen.
2434 * They can happen in any order. */
2435 if (++(process
->free_events
) < 2)
2438 key
.pid
= process
->pid
;
2439 key
.cpu
= process
->cpu
;
2440 g_hash_table_remove(ts
->processes
, &key
);
2441 g_array_free(process
->execution_stack
, TRUE
);
2442 g_array_free(process
->user_stack
, TRUE
);
2448 static void free_process_state(gpointer key
, gpointer value
,gpointer user_data
)
2450 g_array_free(((LttvProcessState
*)value
)->execution_stack
, TRUE
);
2451 g_array_free(((LttvProcessState
*)value
)->user_stack
, TRUE
);
2456 static void lttv_state_free_process_table(GHashTable
*processes
)
2458 g_hash_table_foreach(processes
, free_process_state
, NULL
);
2459 g_hash_table_destroy(processes
);
2463 static gboolean
syscall_entry(void *hook_data
, void *call_data
)
2465 LttvTracefileState
*s
= (LttvTracefileState
*)call_data
;
2467 LttvTraceState
*ts
= (LttvTraceState
*)s
->parent
.t_context
;
2468 LttvProcessState
*process
= ts
->running_process
[cpu
];
2469 LttEvent
*e
= ltt_tracefile_get_event(s
->parent
.tf
);
2470 LttvTraceHook
*th
= (LttvTraceHook
*)hook_data
;
2471 struct marker_field
*f
= lttv_trace_get_hook_field(th
, 0);
2472 LttvExecutionSubmode submode
;
2474 guint syscall
= ltt_event_get_unsigned(e
, f
);
2475 expand_syscall_table(ts
, syscall
);
2476 submode
= ((LttvTraceState
*)(s
->parent
.t_context
))->syscall_names
[syscall
];
2477 /* There can be no system call from PID 0 : unknown state */
2478 if(process
->pid
!= 0)
2479 push_state(s
, LTTV_STATE_SYSCALL
, submode
);
2484 static gboolean
syscall_exit(void *hook_data
, void *call_data
)
2486 LttvTracefileState
*s
= (LttvTracefileState
*)call_data
;
2488 LttvTraceState
*ts
= (LttvTraceState
*)s
->parent
.t_context
;
2489 LttvProcessState
*process
= ts
->running_process
[cpu
];
2491 /* There can be no system call from PID 0 : unknown state */
2492 if(process
->pid
!= 0)
2493 pop_state(s
, LTTV_STATE_SYSCALL
);
2498 static gboolean
trap_entry(void *hook_data
, void *call_data
)
2500 LttvTracefileState
*s
= (LttvTracefileState
*)call_data
;
2501 LttvTraceState
*ts
= (LttvTraceState
*)s
->parent
.t_context
;
2502 LttEvent
*e
= ltt_tracefile_get_event(s
->parent
.tf
);
2503 LttvTraceHook
*th
= (LttvTraceHook
*)hook_data
;
2504 struct marker_field
*f
= lttv_trace_get_hook_field(th
, 0);
2506 LttvExecutionSubmode submode
;
2508 guint64 trap
= ltt_event_get_long_unsigned(e
, f
);
2510 expand_trap_table(ts
, trap
);
2512 submode
= ((LttvTraceState
*)(s
->parent
.t_context
))->trap_names
[trap
];
2514 push_state(s
, LTTV_STATE_TRAP
, submode
);
2516 /* update cpu status */
2517 cpu_push_mode(s
->cpu_state
, LTTV_CPU_TRAP
);
2519 /* update trap status */
2520 s
->cpu_state
->last_trap
= trap
;
2521 ts
->trap_states
[trap
].running
++;
2526 static gboolean
trap_exit(void *hook_data
, void *call_data
)
2528 LttvTracefileState
*s
= (LttvTracefileState
*)call_data
;
2529 LttvTraceState
*ts
= (LttvTraceState
*)s
->parent
.t_context
;
2530 gint trap
= s
->cpu_state
->last_trap
;
2532 pop_state(s
, LTTV_STATE_TRAP
);
2534 /* update cpu status */
2535 cpu_pop_mode(s
->cpu_state
);
2537 /* update trap status */
2539 if(ts
->trap_states
[trap
].running
)
2540 ts
->trap_states
[trap
].running
--;
2545 static gboolean
irq_entry(void *hook_data
, void *call_data
)
2547 LttvTracefileState
*s
= (LttvTracefileState
*)call_data
;
2548 LttvTraceState
*ts
= (LttvTraceState
*)s
->parent
.t_context
;
2549 LttEvent
*e
= ltt_tracefile_get_event(s
->parent
.tf
);
2550 //guint8 ev_id = ltt_event_eventtype_id(e);
2551 LttvTraceHook
*th
= (LttvTraceHook
*)hook_data
;
2552 struct marker_field
*f
= lttv_trace_get_hook_field(th
, 0);
2554 LttvExecutionSubmode submode
;
2555 guint64 irq
= ltt_event_get_long_unsigned(e
, f
);
2557 expand_irq_table(ts
, irq
);
2559 submode
= ((LttvTraceState
*)(s
->parent
.t_context
))->irq_names
[irq
];
2561 /* Do something with the info about being in user or system mode when int? */
2562 push_state(s
, LTTV_STATE_IRQ
, submode
);
2564 /* update cpu status */
2565 cpu_push_mode(s
->cpu_state
, LTTV_CPU_IRQ
);
2567 /* update irq status */
2568 s
->cpu_state
->last_irq
= irq
;
2569 irq_push_mode(&ts
->irq_states
[irq
], LTTV_IRQ_BUSY
);
2574 static gboolean
soft_irq_exit(void *hook_data
, void *call_data
)
2576 LttvTracefileState
*s
= (LttvTracefileState
*)call_data
;
2577 LttvTraceState
*ts
= (LttvTraceState
*)s
->parent
.t_context
;
2578 gint softirq
= s
->cpu_state
->last_soft_irq
;
2580 pop_state(s
, LTTV_STATE_SOFT_IRQ
);
2582 /* update softirq status */
2584 if(ts
->soft_irq_states
[softirq
].running
)
2585 ts
->soft_irq_states
[softirq
].running
--;
2587 /* update cpu status */
2588 cpu_pop_mode(s
->cpu_state
);
2593 static gboolean
irq_exit(void *hook_data
, void *call_data
)
2595 LttvTracefileState
*s
= (LttvTracefileState
*)call_data
;
2596 LttvTraceState
*ts
= (LttvTraceState
*)s
->parent
.t_context
;
2598 pop_state(s
, LTTV_STATE_IRQ
);
2600 /* update cpu status */
2601 cpu_pop_mode(s
->cpu_state
);
2603 /* update irq status */
2604 if (s
->cpu_state
->last_irq
!= -1)
2605 irq_pop_mode(&ts
->irq_states
[s
->cpu_state
->last_irq
]);
2610 static gboolean
soft_irq_raise(void *hook_data
, void *call_data
)
2612 LttvTracefileState
*s
= (LttvTracefileState
*)call_data
;
2613 LttvTraceState
*ts
= (LttvTraceState
*)s
->parent
.t_context
;
2614 LttEvent
*e
= ltt_tracefile_get_event(s
->parent
.tf
);
2615 //guint8 ev_id = ltt_event_eventtype_id(e);
2616 LttvTraceHook
*th
= (LttvTraceHook
*)hook_data
;
2617 struct marker_field
*f
= lttv_trace_get_hook_field(th
, 0);
2619 LttvExecutionSubmode submode
;
2620 guint64 softirq
= ltt_event_get_long_unsigned(e
, f
);
2621 guint64 nb_softirqs
= ((LttvTraceState
*)(s
->parent
.t_context
))->nb_soft_irqs
;
2623 if(softirq
< nb_softirqs
) {
2624 submode
= ((LttvTraceState
*)(s
->parent
.t_context
))->soft_irq_names
[softirq
];
2626 /* Fixup an incomplete irq table */
2627 GString
*string
= g_string_new("");
2628 g_string_printf(string
, "softirq %" PRIu64
, softirq
);
2629 submode
= g_quark_from_string(string
->str
);
2630 g_string_free(string
, TRUE
);
2633 /* update softirq status */
2634 /* a soft irq raises are not cumulative */
2635 ts
->soft_irq_states
[softirq
].pending
=1;
2640 static gboolean
soft_irq_entry(void *hook_data
, void *call_data
)
2642 LttvTracefileState
*s
= (LttvTracefileState
*)call_data
;
2643 LttvTraceState
*ts
= (LttvTraceState
*)s
->parent
.t_context
;
2644 LttEvent
*e
= ltt_tracefile_get_event(s
->parent
.tf
);
2645 //guint8 ev_id = ltt_event_eventtype_id(e);
2646 LttvTraceHook
*th
= (LttvTraceHook
*)hook_data
;
2647 struct marker_field
*f
= lttv_trace_get_hook_field(th
, 0);
2648 LttvExecutionSubmode submode
;
2649 guint64 softirq
= ltt_event_get_long_unsigned(e
, f
);
2650 expand_soft_irq_table(ts
, softirq
);
2651 submode
= ((LttvTraceState
*)(s
->parent
.t_context
))->soft_irq_names
[softirq
];
2653 /* Do something with the info about being in user or system mode when int? */
2654 push_state(s
, LTTV_STATE_SOFT_IRQ
, submode
);
2656 /* update cpu status */
2657 cpu_push_mode(s
->cpu_state
, LTTV_CPU_SOFT_IRQ
);
2659 /* update softirq status */
2660 s
->cpu_state
->last_soft_irq
= softirq
;
2661 if(ts
->soft_irq_states
[softirq
].pending
)
2662 ts
->soft_irq_states
[softirq
].pending
--;
2663 ts
->soft_irq_states
[softirq
].running
++;
2668 static gboolean
enum_interrupt(void *hook_data
, void *call_data
)
2670 LttvTracefileState
*s
= (LttvTracefileState
*)call_data
;
2671 LttvTraceState
*ts
= (LttvTraceState
*)s
->parent
.t_context
;
2672 LttEvent
*e
= ltt_tracefile_get_event(s
->parent
.tf
);
2673 //guint8 ev_id = ltt_event_eventtype_id(e);
2674 LttvTraceHook
*th
= (LttvTraceHook
*)hook_data
;
2676 GQuark action
= g_quark_from_string(ltt_event_get_string(e
,
2677 lttv_trace_get_hook_field(th
, 0)));
2678 guint irq
= ltt_event_get_long_unsigned(e
, lttv_trace_get_hook_field(th
, 1));
2680 expand_irq_table(ts
, irq
);
2681 ts
->irq_names
[irq
] = action
;
2687 static gboolean
bdev_request_issue(void *hook_data
, void *call_data
)
2689 LttvTracefileState
*s
= (LttvTracefileState
*)call_data
;
2690 LttvTraceState
*ts
= (LttvTraceState
*)s
->parent
.t_context
;
2691 LttEvent
*e
= ltt_tracefile_get_event(s
->parent
.tf
);
2692 //guint8 ev_id = ltt_event_eventtype_id(e);
2693 LttvTraceHook
*th
= (LttvTraceHook
*)hook_data
;
2695 guint major
= ltt_event_get_long_unsigned(e
,
2696 lttv_trace_get_hook_field(th
, 0));
2697 guint minor
= ltt_event_get_long_unsigned(e
,
2698 lttv_trace_get_hook_field(th
, 1));
2699 guint oper
= ltt_event_get_long_unsigned(e
,
2700 lttv_trace_get_hook_field(th
, 2));
2701 guint16 devcode
= MKDEV(major
,minor
);
2703 /* have we seen this block device before? */
2704 gpointer bdev
= get_hashed_bdevstate(ts
, devcode
);
2707 bdev_push_mode(bdev
, LTTV_BDEV_BUSY_READING
);
2709 bdev_push_mode(bdev
, LTTV_BDEV_BUSY_WRITING
);
2714 static gboolean
bdev_request_complete(void *hook_data
, void *call_data
)
2716 LttvTracefileState
*s
= (LttvTracefileState
*)call_data
;
2717 LttvTraceState
*ts
= (LttvTraceState
*)s
->parent
.t_context
;
2718 LttEvent
*e
= ltt_tracefile_get_event(s
->parent
.tf
);
2719 LttvTraceHook
*th
= (LttvTraceHook
*)hook_data
;
2721 guint major
= ltt_event_get_long_unsigned(e
,
2722 lttv_trace_get_hook_field(th
, 0));
2723 guint minor
= ltt_event_get_long_unsigned(e
,
2724 lttv_trace_get_hook_field(th
, 1));
2725 //guint oper = ltt_event_get_long_unsigned(e,
2726 // lttv_trace_get_hook_field(th, 2));
2727 guint16 devcode
= MKDEV(major
,minor
);
2729 /* have we seen this block device before? */
2730 gpointer bdev
= get_hashed_bdevstate(ts
, devcode
);
2732 /* update block device */
2733 bdev_pop_mode(bdev
);
2738 static void push_function(LttvTracefileState
*tfs
, guint64 funcptr
)
2742 LttvTraceState
*ts
= (LttvTraceState
*)tfs
->parent
.t_context
;
2743 guint cpu
= tfs
->cpu
;
2744 LttvProcessState
*process
= ts
->running_process
[cpu
];
2746 guint depth
= process
->user_stack
->len
;
2748 process
->user_stack
=
2749 g_array_set_size(process
->user_stack
, depth
+ 1);
2751 new_func
= &g_array_index(process
->user_stack
, guint64
, depth
);
2752 *new_func
= funcptr
;
2753 process
->current_function
= funcptr
;
2756 static void pop_function(LttvTracefileState
*tfs
, guint64 funcptr
)
2758 guint cpu
= tfs
->cpu
;
2759 LttvTraceState
*ts
= (LttvTraceState
*)tfs
->parent
.t_context
;
2760 LttvProcessState
*process
= ts
->running_process
[cpu
];
2762 if(process
->current_function
!= funcptr
){
2763 g_info("Different functions (%lu.%09lu): ignore it\n",
2764 tfs
->parent
.timestamp
.tv_sec
, tfs
->parent
.timestamp
.tv_nsec
);
2765 g_info("process state has %" PRIu64
" when pop_function is %" PRIu64
"\n",
2766 process
->current_function
, funcptr
);
2767 g_info("{ %u, %u, %s, %s, %s }\n",
2770 g_quark_to_string(process
->name
),
2771 g_quark_to_string(process
->brand
),
2772 g_quark_to_string(process
->state
->s
));
2775 guint depth
= process
->user_stack
->len
;
2778 g_info("Trying to pop last function on stack (%lu.%09lu): ignore it\n",
2779 tfs
->parent
.timestamp
.tv_sec
, tfs
->parent
.timestamp
.tv_nsec
);
2783 process
->user_stack
=
2784 g_array_set_size(process
->user_stack
, depth
- 1);
2785 process
->current_function
=
2786 g_array_index(process
->user_stack
, guint64
, depth
- 2);
2790 static gboolean
function_entry(void *hook_data
, void *call_data
)
2792 LttvTracefileState
*s
= (LttvTracefileState
*)call_data
;
2793 LttEvent
*e
= ltt_tracefile_get_event(s
->parent
.tf
);
2794 //guint8 ev_id = ltt_event_eventtype_id(e);
2795 LttvTraceHook
*th
= (LttvTraceHook
*)hook_data
;
2796 struct marker_field
*f
= lttv_trace_get_hook_field(th
, 0);
2797 guint64 funcptr
= ltt_event_get_long_unsigned(e
, f
);
2799 push_function(s
, funcptr
);
2803 static gboolean
function_exit(void *hook_data
, void *call_data
)
2805 LttvTracefileState
*s
= (LttvTracefileState
*)call_data
;
2806 LttEvent
*e
= ltt_tracefile_get_event(s
->parent
.tf
);
2807 //guint8 ev_id = ltt_event_eventtype_id(e);
2808 LttvTraceHook
*th
= (LttvTraceHook
*)hook_data
;
2809 struct marker_field
*f
= lttv_trace_get_hook_field(th
, 0);
2810 guint64 funcptr
= ltt_event_get_long_unsigned(e
, f
);
2812 pop_function(s
, funcptr
);
2816 static gboolean
dump_syscall(void *hook_data
, void *call_data
)
2818 LttvTracefileState
*s
= (LttvTracefileState
*)call_data
;
2819 LttvTraceState
*ts
= (LttvTraceState
*)s
->parent
.t_context
;
2820 LttEvent
*e
= ltt_tracefile_get_event(s
->parent
.tf
);
2821 LttvTraceHook
*th
= (LttvTraceHook
*)hook_data
;
2826 id
= ltt_event_get_unsigned(e
, lttv_trace_get_hook_field(th
, 0));
2827 address
= ltt_event_get_long_unsigned(e
, lttv_trace_get_hook_field(th
, 1));
2828 symbol
= ltt_event_get_string(e
, lttv_trace_get_hook_field(th
, 2));
2830 expand_syscall_table(ts
, id
);
2831 ts
->syscall_names
[id
] = g_quark_from_string(symbol
);
2836 static gboolean
dump_kprobe(void *hook_data
, void *call_data
)
2838 LttvTracefileState
*s
= (LttvTracefileState
*)call_data
;
2839 LttvTraceState
*ts
= (LttvTraceState
*)s
->parent
.t_context
;
2840 LttEvent
*e
= ltt_tracefile_get_event(s
->parent
.tf
);
2841 LttvTraceHook
*th
= (LttvTraceHook
*)hook_data
;
2845 ip
= ltt_event_get_long_unsigned(e
, lttv_trace_get_hook_field(th
, 0));
2846 symbol
= ltt_event_get_string(e
, lttv_trace_get_hook_field(th
, 1));
2848 expand_kprobe_table(ts
, ip
, symbol
);
2853 static gboolean
dump_softirq(void *hook_data
, void *call_data
)
2855 LttvTracefileState
*s
= (LttvTracefileState
*)call_data
;
2856 LttvTraceState
*ts
= (LttvTraceState
*)s
->parent
.t_context
;
2857 LttEvent
*e
= ltt_tracefile_get_event(s
->parent
.tf
);
2858 LttvTraceHook
*th
= (LttvTraceHook
*)hook_data
;
2863 id
= ltt_event_get_unsigned(e
, lttv_trace_get_hook_field(th
, 0));
2864 address
= ltt_event_get_long_unsigned(e
, lttv_trace_get_hook_field(th
, 1));
2865 symbol
= ltt_event_get_string(e
, lttv_trace_get_hook_field(th
, 2));
2867 expand_soft_irq_table(ts
, id
);
2868 ts
->soft_irq_names
[id
] = g_quark_from_string(symbol
);
2873 static gboolean
schedchange(void *hook_data
, void *call_data
)
2875 LttvTracefileState
*s
= (LttvTracefileState
*)call_data
;
2877 LttvTraceState
*ts
= (LttvTraceState
*)s
->parent
.t_context
;
2878 LttvProcessState
*process
= ts
->running_process
[cpu
];
2879 //LttvProcessState *old_process = ts->running_process[cpu];
2881 LttEvent
*e
= ltt_tracefile_get_event(s
->parent
.tf
);
2882 LttvTraceHook
*th
= (LttvTraceHook
*)hook_data
;
2883 guint pid_in
, pid_out
;
2886 pid_out
= ltt_event_get_unsigned(e
, lttv_trace_get_hook_field(th
, 0));
2887 pid_in
= ltt_event_get_unsigned(e
, lttv_trace_get_hook_field(th
, 1));
2888 state_out
= ltt_event_get_long_int(e
, lttv_trace_get_hook_field(th
, 2));
2890 if(likely(process
!= NULL
)) {
2892 /* We could not know but it was not the idle process executing.
2893 This should only happen at the beginning, before the first schedule
2894 event, and when the initial information (current process for each CPU)
2895 is missing. It is not obvious how we could, after the fact, compensate
2896 the wrongly attributed statistics. */
2898 //This test only makes sense once the state is known and if there is no
2899 //missing events. We need to silently ignore schedchange coming after a
2900 //process_free, or it causes glitches. (FIXME)
2901 //if(unlikely(process->pid != pid_out)) {
2902 // g_assert(process->pid == 0);
2904 if(process
->pid
== 0
2905 && process
->state
->t
== LTTV_STATE_MODE_UNKNOWN
) {
2907 /* Scheduling out of pid 0 at beginning of the trace :
2908 * we know for sure it is in syscall mode at this point. */
2909 g_assert(process
->execution_stack
->len
== 1);
2910 process
->state
->t
= LTTV_STATE_SYSCALL
;
2911 process
->state
->s
= LTTV_STATE_WAIT
;
2912 process
->state
->change
= s
->parent
.timestamp
;
2913 process
->state
->entry
= s
->parent
.timestamp
;
2916 if(unlikely(process
->state
->s
== LTTV_STATE_EXIT
)) {
2917 process
->state
->s
= LTTV_STATE_ZOMBIE
;
2918 process
->state
->change
= s
->parent
.timestamp
;
2920 if(unlikely(state_out
== 0)) process
->state
->s
= LTTV_STATE_WAIT_CPU
;
2921 else process
->state
->s
= LTTV_STATE_WAIT
;
2922 process
->state
->change
= s
->parent
.timestamp
;
2925 if(state_out
== 32 || state_out
== 64) { /* EXIT_DEAD || TASK_DEAD */
2926 /* see sched.h for states */
2927 if (!exit_process(s
, process
)) {
2928 process
->state
->s
= LTTV_STATE_DEAD
;
2929 process
->state
->change
= s
->parent
.timestamp
;
2934 process
= ts
->running_process
[cpu
] =
2935 lttv_state_find_process_or_create(
2936 (LttvTraceState
*)s
->parent
.t_context
,
2938 &s
->parent
.timestamp
);
2939 process
->state
->s
= LTTV_STATE_RUN
;
2941 if(process
->usertrace
)
2942 process
->usertrace
->cpu
= cpu
;
2943 // process->last_cpu_index = ltt_tracefile_num(((LttvTracefileContext*)s)->tf);
2944 process
->state
->change
= s
->parent
.timestamp
;
2946 /* update cpu status */
2948 /* going to idle task */
2949 cpu_set_base_mode(s
->cpu_state
, LTTV_CPU_IDLE
);
2951 /* scheduling a real task.
2952 * we must be careful here:
2953 * if we just schedule()'ed to a process that is
2954 * in a trap, we must put the cpu in trap mode
2956 cpu_set_base_mode(s
->cpu_state
, LTTV_CPU_BUSY
);
2957 if(process
->state
->t
== LTTV_STATE_TRAP
)
2958 cpu_push_mode(s
->cpu_state
, LTTV_CPU_TRAP
);
2964 static gboolean
process_fork(void *hook_data
, void *call_data
)
2966 LttvTracefileState
*s
= (LttvTracefileState
*)call_data
;
2967 LttEvent
*e
= ltt_tracefile_get_event(s
->parent
.tf
);
2968 LttvTraceHook
*th
= (LttvTraceHook
*)hook_data
;
2970 guint child_pid
; /* In the Linux Kernel, there is one PID per thread. */
2971 guint child_tgid
; /* tgid in the Linux kernel is the "real" POSIX PID. */
2972 //LttvProcessState *zombie_process;
2974 LttvTraceState
*ts
= (LttvTraceState
*)s
->parent
.t_context
;
2975 LttvProcessState
*process
= ts
->running_process
[cpu
];
2976 LttvProcessState
*child_process
;
2977 struct marker_field
*f
;
2980 parent_pid
= ltt_event_get_unsigned(e
, lttv_trace_get_hook_field(th
, 0));
2983 child_pid
= ltt_event_get_unsigned(e
, lttv_trace_get_hook_field(th
, 1));
2984 s
->parent
.target_pid
= child_pid
;
2987 f
= lttv_trace_get_hook_field(th
, 2);
2989 child_tgid
= ltt_event_get_unsigned(e
, f
);
2993 /* Mathieu : it seems like the process might have been scheduled in before the
2994 * fork, and, in a rare case, might be the current process. This might happen
2995 * in a SMP case where we don't have enough precision on the clocks.
2997 * Test reenabled after precision fixes on time. (Mathieu) */
2999 zombie_process
= lttv_state_find_process(ts
, ANY_CPU
, child_pid
);
3001 if(unlikely(zombie_process
!= NULL
)) {
3002 /* Reutilisation of PID. Only now we are sure that the old PID
3003 * has been released. FIXME : should know when release_task happens instead.
3005 guint num_cpus
= ltt_trace_get_num_cpu(ts
->parent
.t
);
3007 for(i
=0; i
< num_cpus
; i
++) {
3008 g_assert(zombie_process
!= ts
->running_process
[i
]);
3011 exit_process(s
, zombie_process
);
3014 g_assert(process
->pid
!= child_pid
);
3015 // FIXME : Add this test in the "known state" section
3016 // g_assert(process->pid == parent_pid);
3017 child_process
= lttv_state_find_process(ts
, ANY_CPU
, child_pid
);
3018 if(child_process
== NULL
) {
3019 child_process
= lttv_state_create_process(ts
, process
, cpu
,
3020 child_pid
, child_tgid
,
3021 LTTV_STATE_UNNAMED
, &s
->parent
.timestamp
);
3023 /* The process has already been created : due to time imprecision between
3024 * multiple CPUs : it has been scheduled in before creation. Note that we
3025 * shouldn't have this kind of imprecision.
3027 * Simply put a correct parent.
3029 g_error("Process %u has been created at [%lu.%09lu] "
3030 "and inserted at [%lu.%09lu] before \n"
3031 "fork on cpu %u[%lu.%09lu].\n"
3032 "Probably an unsynchronized TSC problem on the traced machine.",
3034 child_process
->creation_time
.tv_sec
,
3035 child_process
->creation_time
.tv_nsec
,
3036 child_process
->insertion_time
.tv_sec
,
3037 child_process
->insertion_time
.tv_nsec
,
3038 cpu
, ltt_event_time(e
).tv_sec
, ltt_event_time(e
).tv_nsec
);
3039 //g_assert(0); /* This is a problematic case : the process has been created
3040 // before the fork event */
3041 child_process
->ppid
= process
->pid
;
3042 child_process
->tgid
= child_tgid
;
3044 g_assert(child_process
->name
== LTTV_STATE_UNNAMED
);
3045 child_process
->name
= process
->name
;
3046 child_process
->brand
= process
->brand
;
3051 /* We stamp a newly created process as kernel_thread.
3052 * The thread should not be running yet. */
3053 static gboolean
process_kernel_thread(void *hook_data
, void *call_data
)
3055 LttvTracefileState
*s
= (LttvTracefileState
*)call_data
;
3056 LttEvent
*e
= ltt_tracefile_get_event(s
->parent
.tf
);
3057 LttvTraceHook
*th
= (LttvTraceHook
*)hook_data
;
3059 LttvTraceState
*ts
= (LttvTraceState
*)s
->parent
.t_context
;
3060 LttvProcessState
*process
;
3061 LttvExecutionState
*es
;
3064 pid
= (guint
)ltt_event_get_long_unsigned(e
, lttv_trace_get_hook_field(th
, 0));
3065 s
->parent
.target_pid
= pid
;
3067 process
= lttv_state_find_process_or_create(ts
, ANY_CPU
, pid
,
3069 if (process
->state
->s
!= LTTV_STATE_DEAD
) {
3070 process
->execution_stack
=
3071 g_array_set_size(process
->execution_stack
, 1);
3072 es
= process
->state
=
3073 &g_array_index(process
->execution_stack
, LttvExecutionState
, 0);
3074 es
->t
= LTTV_STATE_SYSCALL
;
3076 process
->type
= LTTV_STATE_KERNEL_THREAD
;
3081 static gboolean
process_exit(void *hook_data
, void *call_data
)
3083 LttvTracefileState
*s
= (LttvTracefileState
*)call_data
;
3084 LttEvent
*e
= ltt_tracefile_get_event(s
->parent
.tf
);
3085 LttvTraceHook
*th
= (LttvTraceHook
*)hook_data
;
3087 LttvTraceState
*ts
= (LttvTraceState
*)s
->parent
.t_context
;
3088 LttvProcessState
*process
; // = ts->running_process[cpu];
3090 pid
= ltt_event_get_unsigned(e
, lttv_trace_get_hook_field(th
, 0));
3091 s
->parent
.target_pid
= pid
;
3093 // FIXME : Add this test in the "known state" section
3094 // g_assert(process->pid == pid);
3096 process
= lttv_state_find_process(ts
, ANY_CPU
, pid
);
3097 if(likely(process
!= NULL
)) {
3098 process
->state
->s
= LTTV_STATE_EXIT
;
3103 static gboolean
process_free(void *hook_data
, void *call_data
)
3105 LttvTracefileState
*s
= (LttvTracefileState
*)call_data
;
3106 LttvTraceState
*ts
= (LttvTraceState
*)s
->parent
.t_context
;
3107 LttEvent
*e
= ltt_tracefile_get_event(s
->parent
.tf
);
3108 LttvTraceHook
*th
= (LttvTraceHook
*)hook_data
;
3110 LttvProcessState
*process
;
3112 /* PID of the process to release */
3113 release_pid
= ltt_event_get_unsigned(e
, lttv_trace_get_hook_field(th
, 0));
3114 s
->parent
.target_pid
= release_pid
;
3116 g_assert(release_pid
!= 0);
3118 process
= lttv_state_find_process(ts
, ANY_CPU
, release_pid
);
3119 if(likely(process
!= NULL
))
3120 exit_process(s
, process
);
3123 if(likely(process
!= NULL
)) {
3124 /* release_task is happening at kernel level : we can now safely release
3125 * the data structure of the process */
3126 //This test is fun, though, as it may happen that
3127 //at time t : CPU 0 : process_free
3128 //at time t+150ns : CPU 1 : schedule out
3129 //Clearly due to time imprecision, we disable it. (Mathieu)
3130 //If this weird case happen, we have no choice but to put the
3131 //Currently running process on the cpu to 0.
3132 //I re-enable it following time precision fixes. (Mathieu)
3133 //Well, in the case where an process is freed by a process on another CPU
3134 //and still scheduled, it happens that this is the schedchange that will
3135 //drop the last reference count. Do not free it here!
3136 guint num_cpus
= ltt_trace_get_num_cpu(ts
->parent
.t
);
3138 for(i
=0; i
< num_cpus
; i
++) {
3139 //g_assert(process != ts->running_process[i]);
3140 if(process
== ts
->running_process
[i
]) {
3141 //ts->running_process[i] = lttv_state_find_process(ts, i, 0);
3145 if(i
== num_cpus
) /* process is not scheduled */
3146 exit_process(s
, process
);
3153 static gboolean
process_exec(void *hook_data
, void *call_data
)
3155 LttvTracefileState
*s
= (LttvTracefileState
*)call_data
;
3156 LttvTraceState
*ts
= (LttvTraceState
*)s
->parent
.t_context
;
3157 LttEvent
*e
= ltt_tracefile_get_event(s
->parent
.tf
);
3158 LttvTraceHook
*th
= (LttvTraceHook
*)hook_data
;
3161 LttvProcessState
*process
= ts
->running_process
[cpu
];
3163 #if 0//how to use a sequence that must be transformed in a string
3164 /* PID of the process to release */
3165 guint64 name_len
= ltt_event_field_element_number(e
,
3166 lttv_trace_get_hook_field(th
, 0));
3167 //name = ltt_event_get_string(e, lttv_trace_get_hook_field(th, 0));
3168 LttField
*child
= ltt_event_field_element_select(e
,
3169 lttv_trace_get_hook_field(th
, 0), 0);
3171 (gchar
*)(ltt_event_data(e
)+ltt_event_field_offset(e
, child
));
3172 gchar
*null_term_name
= g_new(gchar
, name_len
+1);
3173 memcpy(null_term_name
, name_begin
, name_len
);
3174 null_term_name
[name_len
] = '\0';
3175 process
->name
= g_quark_from_string(null_term_name
);
3178 process
->name
= g_quark_from_string(ltt_event_get_string(e
,
3179 lttv_trace_get_hook_field(th
, 0)));
3180 process
->brand
= LTTV_STATE_UNBRANDED
;
3181 //g_free(null_term_name);
3185 static gboolean
thread_brand(void *hook_data
, void *call_data
)
3187 LttvTracefileState
*s
= (LttvTracefileState
*)call_data
;
3188 LttvTraceState
*ts
= (LttvTraceState
*)s
->parent
.t_context
;
3189 LttEvent
*e
= ltt_tracefile_get_event(s
->parent
.tf
);
3190 LttvTraceHook
*th
= (LttvTraceHook
*)hook_data
;
3193 LttvProcessState
*process
= ts
->running_process
[cpu
];
3195 name
= ltt_event_get_string(e
, lttv_trace_get_hook_field(th
, 0));
3196 process
->brand
= g_quark_from_string(name
);
3201 static void fix_process(gpointer key
, gpointer value
,
3204 LttvProcessState
*process
;
3205 LttvExecutionState
*es
;
3206 process
= (LttvProcessState
*)value
;
3207 LttTime
*timestamp
= (LttTime
*)user_data
;
3209 if(process
->type
== LTTV_STATE_KERNEL_THREAD
) {
3210 es
= &g_array_index(process
->execution_stack
, LttvExecutionState
, 0);
3211 if(es
->t
== LTTV_STATE_MODE_UNKNOWN
) {
3212 es
->t
= LTTV_STATE_SYSCALL
;
3213 es
->n
= LTTV_STATE_SUBMODE_NONE
;
3214 es
->entry
= *timestamp
;
3215 es
->change
= *timestamp
;
3216 es
->cum_cpu_time
= ltt_time_zero
;
3217 if(es
->s
== LTTV_STATE_UNNAMED
)
3218 es
->s
= LTTV_STATE_WAIT
;
3221 es
= &g_array_index(process
->execution_stack
, LttvExecutionState
, 0);
3222 if(es
->t
== LTTV_STATE_MODE_UNKNOWN
) {
3223 es
->t
= LTTV_STATE_USER_MODE
;
3224 es
->n
= LTTV_STATE_SUBMODE_NONE
;
3225 es
->entry
= *timestamp
;
3226 //g_assert(timestamp->tv_sec != 0);
3227 es
->change
= *timestamp
;
3228 es
->cum_cpu_time
= ltt_time_zero
;
3229 if(es
->s
== LTTV_STATE_UNNAMED
)
3230 es
->s
= LTTV_STATE_RUN
;
3232 if(process
->execution_stack
->len
== 1) {
3233 /* Still in bottom unknown mode, means never did a system call
3234 * May be either in user mode, syscall mode, running or waiting.*/
3235 /* FIXME : we may be tagging syscall mode when being user mode */
3236 process
->execution_stack
=
3237 g_array_set_size(process
->execution_stack
, 2);
3238 es
= process
->state
= &g_array_index(process
->execution_stack
,
3239 LttvExecutionState
, 1);
3240 es
->t
= LTTV_STATE_SYSCALL
;
3241 es
->n
= LTTV_STATE_SUBMODE_NONE
;
3242 es
->entry
= *timestamp
;
3243 //g_assert(timestamp->tv_sec != 0);
3244 es
->change
= *timestamp
;
3245 es
->cum_cpu_time
= ltt_time_zero
;
3246 if(es
->s
== LTTV_STATE_WAIT_FORK
)
3247 es
->s
= LTTV_STATE_WAIT
;
3253 static gboolean
statedump_end(void *hook_data
, void *call_data
)
3255 LttvTracefileState
*s
= (LttvTracefileState
*)call_data
;
3256 LttvTraceState
*ts
= (LttvTraceState
*)s
->parent
.t_context
;
3257 LttvTracefileContext
*tfc
= (LttvTracefileContext
*)call_data
;
3258 //LttEvent *e = ltt_tracefile_get_event(s->parent.tf);
3259 //LttvTraceHook *th = (LttvTraceHook *)hook_data;
3261 /* For all processes */
3262 /* if kernel thread, if stack[0] is unknown, set to syscall mode, wait */
3263 /* else, if stack[0] is unknown, set to user mode, running */
3265 g_hash_table_foreach(ts
->processes
, fix_process
, &tfc
->timestamp
);
3270 static gboolean
enum_process_state(void *hook_data
, void *call_data
)
3272 LttvTracefileState
*s
= (LttvTracefileState
*)call_data
;
3273 LttEvent
*e
= ltt_tracefile_get_event(s
->parent
.tf
);
3274 //It's slow : optimise later by doing this before reading trace.
3275 LttvTraceHook
*th
= (LttvTraceHook
*)hook_data
;
3281 LttvTraceState
*ts
= (LttvTraceState
*)s
->parent
.t_context
;
3282 LttvProcessState
*process
= ts
->running_process
[cpu
];
3283 LttvProcessState
*parent_process
;
3284 struct marker_field
*f
;
3285 GQuark type
, mode
, submode
, status
;
3286 LttvExecutionState
*es
;
3290 pid
= ltt_event_get_unsigned(e
, lttv_trace_get_hook_field(th
, 0));
3291 s
->parent
.target_pid
= pid
;
3294 parent_pid
= ltt_event_get_unsigned(e
, lttv_trace_get_hook_field(th
, 1));
3297 command
= ltt_event_get_string(e
, lttv_trace_get_hook_field(th
, 2));
3300 f
= lttv_trace_get_hook_field(th
, 3);
3301 type
= ltt_enum_string_get(f
, ltt_event_get_unsigned(e
, f
));
3303 //FIXME: type is rarely used, enum must match possible types.
3306 f
= lttv_trace_get_hook_field(th
, 4);
3307 mode
= ltt_enum_string_get(f
,ltt_event_get_unsigned(e
, f
));
3310 f
= lttv_trace_get_hook_field(th
, 5);
3311 submode
= ltt_enum_string_get(f
, ltt_event_get_unsigned(e
, f
));
3314 f
= lttv_trace_get_hook_field(th
, 6);
3315 status
= ltt_enum_string_get(f
, ltt_event_get_unsigned(e
, f
));
3318 f
= lttv_trace_get_hook_field(th
, 7);
3320 tgid
= ltt_event_get_unsigned(e
, f
);
3325 nb_cpus
= ltt_trace_get_num_cpu(ts
->parent
.t
);
3326 for(i
=0; i
<nb_cpus
; i
++) {
3327 process
= lttv_state_find_process(ts
, i
, pid
);
3328 g_assert(process
!= NULL
);
3330 process
->ppid
= parent_pid
;
3331 process
->tgid
= tgid
;
3332 process
->name
= g_quark_from_string(command
);
3334 &g_array_index(process
->execution_stack
, LttvExecutionState
, 0);
3335 process
->type
= LTTV_STATE_KERNEL_THREAD
;
3339 /* The process might exist if a process was forked while performing the
3341 process
= lttv_state_find_process(ts
, ANY_CPU
, pid
);
3342 if(process
== NULL
) {
3343 parent_process
= lttv_state_find_process(ts
, ANY_CPU
, parent_pid
);
3344 process
= lttv_state_create_process(ts
, parent_process
, cpu
,
3345 pid
, tgid
, g_quark_from_string(command
),
3346 &s
->parent
.timestamp
);
3348 /* Keep the stack bottom : a running user mode */
3349 /* Disabled because of inconsistencies in the current statedump states. */
3350 if(type
== LTTV_STATE_KERNEL_THREAD
) {
3351 /* Only keep the bottom
3352 * FIXME Kernel thread : can be in syscall or interrupt or trap. */
3353 /* Will cause expected trap when in fact being syscall (even after end of
3355 * Will cause expected interrupt when being syscall. (only before end of
3356 * statedump event) */
3357 // This will cause a "popping last state on stack, ignoring it."
3358 process
->execution_stack
= g_array_set_size(process
->execution_stack
, 1);
3359 es
= process
->state
= &g_array_index(process
->execution_stack
,
3360 LttvExecutionState
, 0);
3361 process
->type
= LTTV_STATE_KERNEL_THREAD
;
3362 es
->t
= LTTV_STATE_MODE_UNKNOWN
;
3363 es
->s
= LTTV_STATE_UNNAMED
;
3364 es
->n
= LTTV_STATE_SUBMODE_UNKNOWN
;
3366 es
->t
= LTTV_STATE_SYSCALL
;
3371 /* User space process :
3372 * bottom : user mode
3373 * either currently running or scheduled out.
3374 * can be scheduled out because interrupted in (user mode or in syscall)
3375 * or because of an explicit call to the scheduler in syscall. Note that
3376 * the scheduler call comes after the irq_exit, so never in interrupt
3378 // temp workaround : set size to 1 : only have user mode bottom of stack.
3379 // will cause g_info message of expected syscall mode when in fact being
3380 // in user mode. Can also cause expected trap when in fact being user
3381 // mode in the event of a page fault reenabling interrupts in the handler.
3382 // Expected syscall and trap can also happen after the end of statedump
3383 // This will cause a "popping last state on stack, ignoring it."
3384 process
->execution_stack
= g_array_set_size(process
->execution_stack
, 1);
3385 es
= process
->state
= &g_array_index(process
->execution_stack
,
3386 LttvExecutionState
, 0);
3387 es
->t
= LTTV_STATE_MODE_UNKNOWN
;
3388 es
->s
= LTTV_STATE_UNNAMED
;
3389 es
->n
= LTTV_STATE_SUBMODE_UNKNOWN
;
3391 es
->t
= LTTV_STATE_USER_MODE
;
3399 es
= process
->state
= &g_array_index(process
->execution_stack
,
3400 LttvExecutionState
, 1);
3401 es
->t
= LTTV_STATE_MODE_UNKNOWN
;
3402 es
->s
= LTTV_STATE_UNNAMED
;
3403 es
->n
= LTTV_STATE_SUBMODE_UNKNOWN
;
3407 /* The process has already been created :
3408 * Probably was forked while dumping the process state or
3409 * was simply scheduled in prior to get the state dump event.
3411 process
->ppid
= parent_pid
;
3412 process
->tgid
= tgid
;
3413 process
->name
= g_quark_from_string(command
);
3414 process
->type
= type
;
3416 &g_array_index(process
->execution_stack
, LttvExecutionState
, 0);
3418 if(es
->t
== LTTV_STATE_MODE_UNKNOWN
) {
3419 if(type
== LTTV_STATE_KERNEL_THREAD
)
3420 es
->t
= LTTV_STATE_SYSCALL
;
3422 es
->t
= LTTV_STATE_USER_MODE
;
3425 /* Don't mess around with the stack, it will eventually become
3426 * ok after the end of state dump. */
3433 gint
lttv_state_hook_add_event_hooks(void *hook_data
, void *call_data
)
3435 LttvTracesetState
*tss
= (LttvTracesetState
*)(call_data
);
3437 lttv_state_add_event_hooks(tss
);
3442 void lttv_state_add_event_hooks(LttvTracesetState
*self
)
3444 LttvTraceset
*traceset
= self
->parent
.ts
;
3446 guint i
, j
, k
, nb_trace
, nb_tracefile
;
3450 LttvTracefileState
*tfs
;
3456 LttvAttributeValue val
;
3458 nb_trace
= lttv_traceset_number(traceset
);
3459 for(i
= 0 ; i
< nb_trace
; i
++) {
3460 ts
= (LttvTraceState
*)self
->parent
.traces
[i
];
3462 /* Find the eventtype id for the following events and register the
3463 associated by id hooks. */
3465 hooks
= g_array_sized_new(FALSE
, FALSE
, sizeof(LttvTraceHook
), 20);
3466 //hooks = g_array_set_size(hooks, 19); // Max possible number of hooks.
3469 lttv_trace_find_hook(ts
->parent
.t
,
3471 LTT_EVENT_SYSCALL_ENTRY
,
3472 FIELD_ARRAY(LTT_FIELD_SYSCALL_ID
),
3473 syscall_entry
, NULL
, &hooks
);
3475 lttv_trace_find_hook(ts
->parent
.t
,
3477 LTT_EVENT_SYSCALL_EXIT
,
3479 syscall_exit
, NULL
, &hooks
);
3481 lttv_trace_find_hook(ts
->parent
.t
,
3483 LTT_EVENT_TRAP_ENTRY
,
3484 FIELD_ARRAY(LTT_FIELD_TRAP_ID
),
3485 trap_entry
, NULL
, &hooks
);
3487 lttv_trace_find_hook(ts
->parent
.t
,
3489 LTT_EVENT_TRAP_EXIT
,
3491 trap_exit
, NULL
, &hooks
);
3493 lttv_trace_find_hook(ts
->parent
.t
,
3495 LTT_EVENT_PAGE_FAULT_ENTRY
,
3496 FIELD_ARRAY(LTT_FIELD_TRAP_ID
),
3497 trap_entry
, NULL
, &hooks
);
3499 lttv_trace_find_hook(ts
->parent
.t
,
3501 LTT_EVENT_PAGE_FAULT_EXIT
,
3503 trap_exit
, NULL
, &hooks
);
3505 lttv_trace_find_hook(ts
->parent
.t
,
3507 LTT_EVENT_PAGE_FAULT_NOSEM_ENTRY
,
3508 FIELD_ARRAY(LTT_FIELD_TRAP_ID
),
3509 trap_entry
, NULL
, &hooks
);
3511 lttv_trace_find_hook(ts
->parent
.t
,
3513 LTT_EVENT_PAGE_FAULT_NOSEM_EXIT
,
3515 trap_exit
, NULL
, &hooks
);
3517 lttv_trace_find_hook(ts
->parent
.t
,
3519 LTT_EVENT_IRQ_ENTRY
,
3520 FIELD_ARRAY(LTT_FIELD_IRQ_ID
),
3521 irq_entry
, NULL
, &hooks
);
3523 lttv_trace_find_hook(ts
->parent
.t
,
3527 irq_exit
, NULL
, &hooks
);
3529 lttv_trace_find_hook(ts
->parent
.t
,
3531 LTT_EVENT_SOFT_IRQ_RAISE
,
3532 FIELD_ARRAY(LTT_FIELD_SOFT_IRQ_ID
),
3533 soft_irq_raise
, NULL
, &hooks
);
3535 lttv_trace_find_hook(ts
->parent
.t
,
3537 LTT_EVENT_SOFT_IRQ_ENTRY
,
3538 FIELD_ARRAY(LTT_FIELD_SOFT_IRQ_ID
),
3539 soft_irq_entry
, NULL
, &hooks
);
3541 lttv_trace_find_hook(ts
->parent
.t
,
3543 LTT_EVENT_SOFT_IRQ_EXIT
,
3545 soft_irq_exit
, NULL
, &hooks
);
3547 lttv_trace_find_hook(ts
->parent
.t
,
3549 LTT_EVENT_SCHED_SCHEDULE
,
3550 FIELD_ARRAY(LTT_FIELD_PREV_PID
, LTT_FIELD_NEXT_PID
,
3551 LTT_FIELD_PREV_STATE
),
3552 schedchange
, NULL
, &hooks
);
3554 lttv_trace_find_hook(ts
->parent
.t
,
3556 LTT_EVENT_PROCESS_FORK
,
3557 FIELD_ARRAY(LTT_FIELD_PARENT_PID
, LTT_FIELD_CHILD_PID
,
3558 LTT_FIELD_CHILD_TGID
),
3559 process_fork
, NULL
, &hooks
);
3561 lttv_trace_find_hook(ts
->parent
.t
,
3563 LTT_EVENT_KTHREAD_CREATE
,
3564 FIELD_ARRAY(LTT_FIELD_PID
),
3565 process_kernel_thread
, NULL
, &hooks
);
3567 lttv_trace_find_hook(ts
->parent
.t
,
3569 LTT_EVENT_PROCESS_EXIT
,
3570 FIELD_ARRAY(LTT_FIELD_PID
),
3571 process_exit
, NULL
, &hooks
);
3573 lttv_trace_find_hook(ts
->parent
.t
,
3575 LTT_EVENT_PROCESS_FREE
,
3576 FIELD_ARRAY(LTT_FIELD_PID
),
3577 process_free
, NULL
, &hooks
);
3579 lttv_trace_find_hook(ts
->parent
.t
,
3582 FIELD_ARRAY(LTT_FIELD_FILENAME
),
3583 process_exec
, NULL
, &hooks
);
3585 lttv_trace_find_hook(ts
->parent
.t
,
3586 LTT_CHANNEL_USERSPACE
,
3587 LTT_EVENT_THREAD_BRAND
,
3588 FIELD_ARRAY(LTT_FIELD_NAME
),
3589 thread_brand
, NULL
, &hooks
);
3591 /* statedump-related hooks */
3592 lttv_trace_find_hook(ts
->parent
.t
,
3593 LTT_CHANNEL_TASK_STATE
,
3594 LTT_EVENT_PROCESS_STATE
,
3595 FIELD_ARRAY(LTT_FIELD_PID
, LTT_FIELD_PARENT_PID
, LTT_FIELD_NAME
,
3596 LTT_FIELD_TYPE
, LTT_FIELD_MODE
, LTT_FIELD_SUBMODE
,
3597 LTT_FIELD_STATUS
, LTT_FIELD_TGID
),
3598 enum_process_state
, NULL
, &hooks
);
3600 lttv_trace_find_hook(ts
->parent
.t
,
3601 LTT_CHANNEL_GLOBAL_STATE
,
3602 LTT_EVENT_STATEDUMP_END
,
3604 statedump_end
, NULL
, &hooks
);
3606 lttv_trace_find_hook(ts
->parent
.t
,
3607 LTT_CHANNEL_IRQ_STATE
,
3608 LTT_EVENT_LIST_INTERRUPT
,
3609 FIELD_ARRAY(LTT_FIELD_ACTION
, LTT_FIELD_IRQ_ID
),
3610 enum_interrupt
, NULL
, &hooks
);
3612 lttv_trace_find_hook(ts
->parent
.t
,
3614 LTT_EVENT_REQUEST_ISSUE
,
3615 FIELD_ARRAY(LTT_FIELD_MAJOR
, LTT_FIELD_MINOR
, LTT_FIELD_OPERATION
),
3616 bdev_request_issue
, NULL
, &hooks
);
3618 lttv_trace_find_hook(ts
->parent
.t
,
3620 LTT_EVENT_REQUEST_COMPLETE
,
3621 FIELD_ARRAY(LTT_FIELD_MAJOR
, LTT_FIELD_MINOR
, LTT_FIELD_OPERATION
),
3622 bdev_request_complete
, NULL
, &hooks
);
3624 lttv_trace_find_hook(ts
->parent
.t
,
3625 LTT_CHANNEL_USERSPACE
,
3626 LTT_EVENT_FUNCTION_ENTRY
,
3627 FIELD_ARRAY(LTT_FIELD_THIS_FN
, LTT_FIELD_CALL_SITE
),
3628 function_entry
, NULL
, &hooks
);
3630 lttv_trace_find_hook(ts
->parent
.t
,
3631 LTT_CHANNEL_USERSPACE
,
3632 LTT_EVENT_FUNCTION_EXIT
,
3633 FIELD_ARRAY(LTT_FIELD_THIS_FN
, LTT_FIELD_CALL_SITE
),
3634 function_exit
, NULL
, &hooks
);
3636 lttv_trace_find_hook(ts
->parent
.t
,
3637 LTT_CHANNEL_SYSCALL_STATE
,
3638 LTT_EVENT_SYS_CALL_TABLE
,
3639 FIELD_ARRAY(LTT_FIELD_ID
, LTT_FIELD_ADDRESS
, LTT_FIELD_SYMBOL
),
3640 dump_syscall
, NULL
, &hooks
);
3642 lttv_trace_find_hook(ts
->parent
.t
,
3643 LTT_CHANNEL_KPROBE_STATE
,
3644 LTT_EVENT_KPROBE_TABLE
,
3645 FIELD_ARRAY(LTT_FIELD_IP
, LTT_FIELD_SYMBOL
),
3646 dump_kprobe
, NULL
, &hooks
);
3648 lttv_trace_find_hook(ts
->parent
.t
,
3649 LTT_CHANNEL_SOFTIRQ_STATE
,
3650 LTT_EVENT_SOFTIRQ_VEC
,
3651 FIELD_ARRAY(LTT_FIELD_ID
, LTT_FIELD_ADDRESS
, LTT_FIELD_SYMBOL
),
3652 dump_softirq
, NULL
, &hooks
);
3654 /* Add these hooks to each event_by_id hooks list */
3656 nb_tracefile
= ts
->parent
.tracefiles
->len
;
3658 for(j
= 0 ; j
< nb_tracefile
; j
++) {
3660 LTTV_TRACEFILE_STATE(g_array_index(ts
->parent
.tracefiles
,
3661 LttvTracefileContext
*, j
));
3663 for(k
= 0 ; k
< hooks
->len
; k
++) {
3664 th
= &g_array_index(hooks
, LttvTraceHook
, k
);
3665 if (th
->mdata
== tfs
->parent
.tf
->mdata
)
3667 lttv_hooks_by_id_find(tfs
->parent
.event_by_id
, th
->id
),
3673 lttv_attribute_find(ts
->parent
.a
, LTTV_STATE_HOOKS
, LTTV_POINTER
, &val
);
3674 *(val
.v_pointer
) = hooks
;
3678 gint
lttv_state_hook_remove_event_hooks(void *hook_data
, void *call_data
)
3680 LttvTracesetState
*tss
= (LttvTracesetState
*)(call_data
);
3682 lttv_state_remove_event_hooks(tss
);
3687 void lttv_state_remove_event_hooks(LttvTracesetState
*self
)
3689 LttvTraceset
*traceset
= self
->parent
.ts
;
3691 guint i
, j
, k
, nb_trace
, nb_tracefile
;
3695 LttvTracefileState
*tfs
;
3701 LttvAttributeValue val
;
3703 nb_trace
= lttv_traceset_number(traceset
);
3704 for(i
= 0 ; i
< nb_trace
; i
++) {
3705 ts
= LTTV_TRACE_STATE(self
->parent
.traces
[i
]);
3707 lttv_attribute_find(ts
->parent
.a
, LTTV_STATE_HOOKS
, LTTV_POINTER
, &val
);
3708 hooks
= *(val
.v_pointer
);
3710 /* Remove these hooks from each event_by_id hooks list */
3712 nb_tracefile
= ts
->parent
.tracefiles
->len
;
3714 for(j
= 0 ; j
< nb_tracefile
; j
++) {
3716 LTTV_TRACEFILE_STATE(g_array_index(ts
->parent
.tracefiles
,
3717 LttvTracefileContext
*, j
));
3719 for(k
= 0 ; k
< hooks
->len
; k
++) {
3720 th
= &g_array_index(hooks
, LttvTraceHook
, k
);
3721 if (th
->mdata
== tfs
->parent
.tf
->mdata
)
3722 lttv_hooks_remove_data(
3723 lttv_hooks_by_id_find(tfs
->parent
.event_by_id
, th
->id
),
3728 lttv_trace_hook_remove_all(&hooks
);
3729 g_array_free(hooks
, TRUE
);
3733 static gboolean
state_save_event_hook(void *hook_data
, void *call_data
)
3735 guint
*event_count
= (guint
*)hook_data
;
3737 /* Only save at LTTV_STATE_SAVE_INTERVAL */
3738 if(likely((*event_count
)++ < LTTV_STATE_SAVE_INTERVAL
))
3743 LttvTracefileState
*self
= (LttvTracefileState
*)call_data
;
3745 LttvTraceState
*tcs
= (LttvTraceState
*)(self
->parent
.t_context
);
3747 LttvAttribute
*saved_states_tree
, *saved_state_tree
;
3749 LttvAttributeValue value
;
3751 saved_states_tree
= lttv_attribute_find_subdir(tcs
->parent
.t_a
,
3752 LTTV_STATE_SAVED_STATES
);
3753 saved_state_tree
= g_object_new(LTTV_ATTRIBUTE_TYPE
, NULL
);
3754 value
= lttv_attribute_add(saved_states_tree
,
3755 lttv_attribute_get_number(saved_states_tree
), LTTV_GOBJECT
);
3756 *(value
.v_gobject
) = (GObject
*)saved_state_tree
;
3757 value
= lttv_attribute_add(saved_state_tree
, LTTV_STATE_TIME
, LTTV_TIME
);
3758 *(value
.v_time
) = self
->parent
.timestamp
;
3759 lttv_state_save(tcs
, saved_state_tree
);
3760 g_debug("Saving state at time %lu.%lu", self
->parent
.timestamp
.tv_sec
,
3761 self
->parent
.timestamp
.tv_nsec
);
3763 *(tcs
->max_time_state_recomputed_in_seek
) = self
->parent
.timestamp
;
3768 static gboolean
state_save_after_trace_hook(void *hook_data
, void *call_data
)
3770 LttvTraceState
*tcs
= (LttvTraceState
*)(call_data
);
3772 *(tcs
->max_time_state_recomputed_in_seek
) = tcs
->parent
.time_span
.end_time
;
3777 guint
lttv_state_current_cpu(LttvTracefileState
*tfs
)
3785 static gboolean
block_start(void *hook_data
, void *call_data
)
3787 LttvTracefileState
*self
= (LttvTracefileState
*)call_data
;
3789 LttvTracefileState
*tfcs
;
3791 LttvTraceState
*tcs
= (LttvTraceState
*)(self
->parent
.t_context
);
3793 LttEventPosition
*ep
;
3795 guint i
, nb_block
, nb_event
, nb_tracefile
;
3799 LttvAttribute
*saved_states_tree
, *saved_state_tree
;
3801 LttvAttributeValue value
;
3803 ep
= ltt_event_position_new();
3805 nb_tracefile
= tcs
->parent
.tracefiles
->len
;
3807 /* Count the number of events added since the last block end in any
3810 for(i
= 0 ; i
< nb_tracefile
; i
++) {
3812 LTTV_TRACEFILE_STATE(&g_array_index(tcs
->parent
.tracefiles
,
3813 LttvTracefileContext
, i
));
3814 ltt_event_position(tfcs
->parent
.e
, ep
);
3815 ltt_event_position_get(ep
, &nb_block
, &nb_event
, &tf
);
3816 tcs
->nb_event
+= nb_event
- tfcs
->saved_position
;
3817 tfcs
->saved_position
= nb_event
;
3821 if(tcs
->nb_event
>= tcs
->save_interval
) {
3822 saved_states_tree
= lttv_attribute_find_subdir(tcs
->parent
.t_a
,
3823 LTTV_STATE_SAVED_STATES
);
3824 saved_state_tree
= g_object_new(LTTV_ATTRIBUTE_TYPE
, NULL
);
3825 value
= lttv_attribute_add(saved_states_tree
,
3826 lttv_attribute_get_number(saved_states_tree
), LTTV_GOBJECT
);
3827 *(value
.v_gobject
) = (GObject
*)saved_state_tree
;
3828 value
= lttv_attribute_add(saved_state_tree
, LTTV_STATE_TIME
, LTTV_TIME
);
3829 *(value
.v_time
) = self
->parent
.timestamp
;
3830 lttv_state_save(tcs
, saved_state_tree
);
3832 g_debug("Saving state at time %lu.%lu", self
->parent
.timestamp
.tv_sec
,
3833 self
->parent
.timestamp
.tv_nsec
);
3835 *(tcs
->max_time_state_recomputed_in_seek
) = self
->parent
.timestamp
;
3841 static gboolean
block_end(void *hook_data
, void *call_data
)
3843 LttvTracefileState
*self
= (LttvTracefileState
*)call_data
;
3845 LttvTraceState
*tcs
= (LttvTraceState
*)(self
->parent
.t_context
);
3849 LttEventPosition
*ep
;
3851 guint nb_block
, nb_event
;
3853 ep
= ltt_event_position_new();
3854 ltt_event_position(self
->parent
.e
, ep
);
3855 ltt_event_position_get(ep
, &nb_block
, &nb_event
, &tf
);
3856 tcs
->nb_event
+= nb_event
- self
->saved_position
+ 1;
3857 self
->saved_position
= 0;
3858 *(tcs
->max_time_state_recomputed_in_seek
) = self
->parent
.timestamp
;
3865 void lttv_state_save_add_event_hooks(LttvTracesetState
*self
)
3867 LttvTraceset
*traceset
= self
->parent
.ts
;
3869 guint i
, j
, nb_trace
, nb_tracefile
;
3873 LttvTracefileState
*tfs
;
3875 LttvTraceHook hook_start
, hook_end
;
3877 nb_trace
= lttv_traceset_number(traceset
);
3878 for(i
= 0 ; i
< nb_trace
; i
++) {
3879 ts
= (LttvTraceState
*)self
->parent
.traces
[i
];
3881 lttv_trace_find_hook(ts
->parent
.t
, "core","block_start",NULL
,
3882 NULL
, NULL
, block_start
, &hook_start
);
3883 lttv_trace_find_hook(ts
->parent
.t
, "core","block_end",NULL
,
3884 NULL
, NULL
, block_end
, &hook_end
);
3886 nb_tracefile
= ts
->parent
.tracefiles
->len
;
3888 for(j
= 0 ; j
< nb_tracefile
; j
++) {
3890 LTTV_TRACEFILE_STATE(&g_array_index(ts
->parent
.tracefiles
,
3891 LttvTracefileContext
, j
));
3892 lttv_hooks_add(lttv_hooks_by_id_find(tfs
->parent
.event_by_id
,
3893 hook_start
.id
), hook_start
.h
, NULL
, LTTV_PRIO_STATE
);
3894 lttv_hooks_add(lttv_hooks_by_id_find(tfs
->parent
.event_by_id
,
3895 hook_end
.id
), hook_end
.h
, NULL
, LTTV_PRIO_STATE
);
3901 void lttv_state_save_add_event_hooks(LttvTracesetState
*self
)
3903 LttvTraceset
*traceset
= self
->parent
.ts
;
3905 guint i
, j
, nb_trace
, nb_tracefile
;
3909 LttvTracefileState
*tfs
;
3912 nb_trace
= lttv_traceset_number(traceset
);
3913 for(i
= 0 ; i
< nb_trace
; i
++) {
3915 ts
= (LttvTraceState
*)self
->parent
.traces
[i
];
3916 nb_tracefile
= ts
->parent
.tracefiles
->len
;
3918 if(ts
->has_precomputed_states
) continue;
3920 guint
*event_count
= g_new(guint
, 1);
3923 for(j
= 0 ; j
< nb_tracefile
; j
++) {
3925 LTTV_TRACEFILE_STATE(g_array_index(ts
->parent
.tracefiles
,
3926 LttvTracefileContext
*, j
));
3927 lttv_hooks_add(tfs
->parent
.event
,
3928 state_save_event_hook
,
3935 lttv_process_traceset_begin(&self
->parent
,
3936 NULL
, NULL
, NULL
, NULL
, NULL
);
3940 gint
lttv_state_save_hook_add_event_hooks(void *hook_data
, void *call_data
)
3942 LttvTracesetState
*tss
= (LttvTracesetState
*)(call_data
);
3944 lttv_state_save_add_event_hooks(tss
);
3951 void lttv_state_save_remove_event_hooks(LttvTracesetState
*self
)
3953 LttvTraceset
*traceset
= self
->parent
.ts
;
3955 guint i
, j
, nb_trace
, nb_tracefile
;
3959 LttvTracefileState
*tfs
;
3961 LttvTraceHook hook_start
, hook_end
;
3963 nb_trace
= lttv_traceset_number(traceset
);
3964 for(i
= 0 ; i
< nb_trace
; i
++) {
3965 ts
= LTTV_TRACE_STATE(self
->parent
.traces
[i
]);
3967 lttv_trace_find_hook(ts
->parent
.t
, "core","block_start",NULL
,
3968 NULL
, NULL
, block_start
, &hook_start
);
3970 lttv_trace_find_hook(ts
->parent
.t
, "core","block_end",NULL
,
3971 NULL
, NULL
, block_end
, &hook_end
);
3973 nb_tracefile
= ts
->parent
.tracefiles
->len
;
3975 for(j
= 0 ; j
< nb_tracefile
; j
++) {
3977 LTTV_TRACEFILE_STATE(&g_array_index(ts
->parent
.tracefiles
,
3978 LttvTracefileContext
, j
));
3979 lttv_hooks_remove_data(lttv_hooks_by_id_find(
3980 tfs
->parent
.event_by_id
, hook_start
.id
), hook_start
.h
, NULL
);
3981 lttv_hooks_remove_data(lttv_hooks_by_id_find(
3982 tfs
->parent
.event_by_id
, hook_end
.id
), hook_end
.h
, NULL
);
3988 void lttv_state_save_remove_event_hooks(LttvTracesetState
*self
)
3990 LttvTraceset
*traceset
= self
->parent
.ts
;
3992 guint i
, j
, nb_trace
, nb_tracefile
;
3996 LttvTracefileState
*tfs
;
3998 LttvHooks
*after_trace
= lttv_hooks_new();
4000 lttv_hooks_add(after_trace
,
4001 state_save_after_trace_hook
,
4006 lttv_process_traceset_end(&self
->parent
,
4007 NULL
, after_trace
, NULL
, NULL
, NULL
);
4009 lttv_hooks_destroy(after_trace
);
4011 nb_trace
= lttv_traceset_number(traceset
);
4012 for(i
= 0 ; i
< nb_trace
; i
++) {
4014 ts
= (LttvTraceState
*)self
->parent
.traces
[i
];
4015 nb_tracefile
= ts
->parent
.tracefiles
->len
;
4017 if(ts
->has_precomputed_states
) continue;
4019 guint
*event_count
= NULL
;
4021 for(j
= 0 ; j
< nb_tracefile
; j
++) {
4023 LTTV_TRACEFILE_STATE(g_array_index(ts
->parent
.tracefiles
,
4024 LttvTracefileContext
*, j
));
4025 event_count
= lttv_hooks_remove(tfs
->parent
.event
,
4026 state_save_event_hook
);
4028 if(event_count
) g_free(event_count
);
4032 gint
lttv_state_save_hook_remove_event_hooks(void *hook_data
, void *call_data
)
4034 LttvTracesetState
*tss
= (LttvTracesetState
*)(call_data
);
4036 lttv_state_save_remove_event_hooks(tss
);
4041 void lttv_state_traceset_seek_time_closest(LttvTracesetState
*self
, LttTime t
)
4043 LttvTraceset
*traceset
= self
->parent
.ts
;
4047 int min_pos
, mid_pos
, max_pos
;
4049 guint call_rest
= 0;
4051 LttvTraceState
*tcs
;
4053 LttvAttributeValue value
;
4055 LttvAttributeType type
;
4057 LttvAttributeName name
;
4061 LttvAttribute
*saved_states_tree
, *saved_state_tree
, *closest_tree
= NULL
;
4063 //g_tree_destroy(self->parent.pqueue);
4064 //self->parent.pqueue = g_tree_new(compare_tracefile);
4066 g_info("Entering seek_time_closest for time %lu.%lu", t
.tv_sec
, t
.tv_nsec
);
4068 nb_trace
= lttv_traceset_number(traceset
);
4069 for(i
= 0 ; i
< nb_trace
; i
++) {
4070 tcs
= (LttvTraceState
*)self
->parent
.traces
[i
];
4072 if(ltt_time_compare(t
, *(tcs
->max_time_state_recomputed_in_seek
)) < 0) {
4073 saved_states_tree
= lttv_attribute_find_subdir(tcs
->parent
.t_a
,
4074 LTTV_STATE_SAVED_STATES
);
4077 if(saved_states_tree
) {
4078 max_pos
= lttv_attribute_get_number(saved_states_tree
) - 1;
4079 mid_pos
= max_pos
/ 2;
4080 while(min_pos
< max_pos
) {
4081 type
= lttv_attribute_get(saved_states_tree
, mid_pos
, &name
, &value
,
4083 g_assert(type
== LTTV_GOBJECT
);
4084 saved_state_tree
= *((LttvAttribute
**)(value
.v_gobject
));
4085 type
= lttv_attribute_get_by_name(saved_state_tree
, LTTV_STATE_TIME
,
4087 g_assert(type
== LTTV_TIME
);
4088 if(ltt_time_compare(*(value
.v_time
), t
) < 0) {
4090 closest_tree
= saved_state_tree
;
4092 else max_pos
= mid_pos
- 1;
4094 mid_pos
= (min_pos
+ max_pos
+ 1) / 2;
4098 /* restore the closest earlier saved state */
4100 lttv_state_restore(tcs
, closest_tree
);
4104 /* There is no saved state, yet we want to have it. Restart at T0 */
4106 restore_init_state(tcs
);
4107 lttv_process_trace_seek_time(&(tcs
->parent
), ltt_time_zero
);
4110 /* We want to seek quickly without restoring/updating the state */
4112 restore_init_state(tcs
);
4113 lttv_process_trace_seek_time(&(tcs
->parent
), t
);
4116 if(!call_rest
) g_info("NOT Calling restore");
4121 traceset_state_instance_init (GTypeInstance
*instance
, gpointer g_class
)
4127 traceset_state_finalize (LttvTracesetState
*self
)
4129 G_OBJECT_CLASS(g_type_class_peek(LTTV_TRACESET_CONTEXT_TYPE
))->
4130 finalize(G_OBJECT(self
));
4135 traceset_state_class_init (LttvTracesetContextClass
*klass
)
4137 GObjectClass
*gobject_class
= G_OBJECT_CLASS(klass
);
4139 gobject_class
->finalize
= (void (*)(GObject
*self
)) traceset_state_finalize
;
4140 klass
->init
= (void (*)(LttvTracesetContext
*self
, LttvTraceset
*ts
))init
;
4141 klass
->fini
= (void (*)(LttvTracesetContext
*self
))fini
;
4142 klass
->new_traceset_context
= new_traceset_context
;
4143 klass
->new_trace_context
= new_trace_context
;
4144 klass
->new_tracefile_context
= new_tracefile_context
;
4149 lttv_traceset_state_get_type(void)
4151 static GType type
= 0;
4153 static const GTypeInfo info
= {
4154 sizeof (LttvTracesetStateClass
),
4155 NULL
, /* base_init */
4156 NULL
, /* base_finalize */
4157 (GClassInitFunc
) traceset_state_class_init
, /* class_init */
4158 NULL
, /* class_finalize */
4159 NULL
, /* class_data */
4160 sizeof (LttvTracesetState
),
4161 0, /* n_preallocs */
4162 (GInstanceInitFunc
) traceset_state_instance_init
, /* instance_init */
4163 NULL
/* value handling */
4166 type
= g_type_register_static (LTTV_TRACESET_CONTEXT_TYPE
, "LttvTracesetStateType",
4174 trace_state_instance_init (GTypeInstance
*instance
, gpointer g_class
)
4180 trace_state_finalize (LttvTraceState
*self
)
4182 G_OBJECT_CLASS(g_type_class_peek(LTTV_TRACE_CONTEXT_TYPE
))->
4183 finalize(G_OBJECT(self
));
4188 trace_state_class_init (LttvTraceStateClass
*klass
)
4190 GObjectClass
*gobject_class
= G_OBJECT_CLASS(klass
);
4192 gobject_class
->finalize
= (void (*)(GObject
*self
)) trace_state_finalize
;
4193 klass
->state_save
= state_save
;
4194 klass
->state_restore
= state_restore
;
4195 klass
->state_saved_free
= state_saved_free
;
4200 lttv_trace_state_get_type(void)
4202 static GType type
= 0;
4204 static const GTypeInfo info
= {
4205 sizeof (LttvTraceStateClass
),
4206 NULL
, /* base_init */
4207 NULL
, /* base_finalize */
4208 (GClassInitFunc
) trace_state_class_init
, /* class_init */
4209 NULL
, /* class_finalize */
4210 NULL
, /* class_data */
4211 sizeof (LttvTraceState
),
4212 0, /* n_preallocs */
4213 (GInstanceInitFunc
) trace_state_instance_init
, /* instance_init */
4214 NULL
/* value handling */
4217 type
= g_type_register_static (LTTV_TRACE_CONTEXT_TYPE
,
4218 "LttvTraceStateType", &info
, 0);
4225 tracefile_state_instance_init (GTypeInstance
*instance
, gpointer g_class
)
4231 tracefile_state_finalize (LttvTracefileState
*self
)
4233 G_OBJECT_CLASS(g_type_class_peek(LTTV_TRACEFILE_CONTEXT_TYPE
))->
4234 finalize(G_OBJECT(self
));
4239 tracefile_state_class_init (LttvTracefileStateClass
*klass
)
4241 GObjectClass
*gobject_class
= G_OBJECT_CLASS(klass
);
4243 gobject_class
->finalize
= (void (*)(GObject
*self
)) tracefile_state_finalize
;
4248 lttv_tracefile_state_get_type(void)
4250 static GType type
= 0;
4252 static const GTypeInfo info
= {
4253 sizeof (LttvTracefileStateClass
),
4254 NULL
, /* base_init */
4255 NULL
, /* base_finalize */
4256 (GClassInitFunc
) tracefile_state_class_init
, /* class_init */
4257 NULL
, /* class_finalize */
4258 NULL
, /* class_data */
4259 sizeof (LttvTracefileState
),
4260 0, /* n_preallocs */
4261 (GInstanceInitFunc
) tracefile_state_instance_init
, /* instance_init */
4262 NULL
/* value handling */
4265 type
= g_type_register_static (LTTV_TRACEFILE_CONTEXT_TYPE
,
4266 "LttvTracefileStateType", &info
, 0);
4272 static void module_init()
4274 LTTV_STATE_UNNAMED
= g_quark_from_string("");
4275 LTTV_STATE_UNBRANDED
= g_quark_from_string("");
4276 LTTV_STATE_MODE_UNKNOWN
= g_quark_from_string("MODE_UNKNOWN");
4277 LTTV_STATE_USER_MODE
= g_quark_from_string("USER_MODE");
4278 LTTV_STATE_SYSCALL
= g_quark_from_string("SYSCALL");
4279 LTTV_STATE_TRAP
= g_quark_from_string("TRAP");
4280 LTTV_STATE_IRQ
= g_quark_from_string("IRQ");
4281 LTTV_STATE_SOFT_IRQ
= g_quark_from_string("SOFTIRQ");
4282 LTTV_STATE_SUBMODE_UNKNOWN
= g_quark_from_string("UNKNOWN");
4283 LTTV_STATE_SUBMODE_NONE
= g_quark_from_string("NONE");
4284 LTTV_STATE_WAIT_FORK
= g_quark_from_string("WAIT_FORK");
4285 LTTV_STATE_WAIT_CPU
= g_quark_from_string("WAIT_CPU");
4286 LTTV_STATE_EXIT
= g_quark_from_string("EXIT");
4287 LTTV_STATE_ZOMBIE
= g_quark_from_string("ZOMBIE");
4288 LTTV_STATE_WAIT
= g_quark_from_string("WAIT");
4289 LTTV_STATE_RUN
= g_quark_from_string("RUN");
4290 LTTV_STATE_DEAD
= g_quark_from_string("DEAD");
4291 LTTV_STATE_USER_THREAD
= g_quark_from_string("USER_THREAD");
4292 LTTV_STATE_KERNEL_THREAD
= g_quark_from_string("KERNEL_THREAD");
4293 LTTV_STATE_TRACEFILES
= g_quark_from_string("tracefiles");
4294 LTTV_STATE_PROCESSES
= g_quark_from_string("processes");
4295 LTTV_STATE_PROCESS
= g_quark_from_string("process");
4296 LTTV_STATE_RUNNING_PROCESS
= g_quark_from_string("running_process");
4297 LTTV_STATE_EVENT
= g_quark_from_string("event");
4298 LTTV_STATE_SAVED_STATES
= g_quark_from_string("saved states");
4299 LTTV_STATE_SAVED_STATES_TIME
= g_quark_from_string("saved states time");
4300 LTTV_STATE_TIME
= g_quark_from_string("time");
4301 LTTV_STATE_HOOKS
= g_quark_from_string("saved state hooks");
4302 LTTV_STATE_NAME_TABLES
= g_quark_from_string("name tables");
4303 LTTV_STATE_TRACE_STATE_USE_COUNT
=
4304 g_quark_from_string("trace_state_use_count");
4305 LTTV_STATE_RESOURCE_CPUS
= g_quark_from_string("cpu resource states");
4306 LTTV_STATE_RESOURCE_CPUS
= g_quark_from_string("cpu count");
4307 LTTV_STATE_RESOURCE_IRQS
= g_quark_from_string("irq resource states");
4308 LTTV_STATE_RESOURCE_SOFT_IRQS
= g_quark_from_string("soft irq resource states");
4309 LTTV_STATE_RESOURCE_TRAPS
= g_quark_from_string("trap resource states");
4310 LTTV_STATE_RESOURCE_BLKDEVS
= g_quark_from_string("blkdevs resource states");
4312 LTT_CHANNEL_FD_STATE
= g_quark_from_string("fd_state");
4313 LTT_CHANNEL_GLOBAL_STATE
= g_quark_from_string("global_state");
4314 LTT_CHANNEL_IRQ_STATE
= g_quark_from_string("irq_state");
4315 LTT_CHANNEL_MODULE_STATE
= g_quark_from_string("module_state");
4316 LTT_CHANNEL_NETIF_STATE
= g_quark_from_string("netif_state");
4317 LTT_CHANNEL_SOFTIRQ_STATE
= g_quark_from_string("softirq_state");
4318 LTT_CHANNEL_SWAP_STATE
= g_quark_from_string("swap_state");
4319 LTT_CHANNEL_SYSCALL_STATE
= g_quark_from_string("syscall_state");
4320 LTT_CHANNEL_TASK_STATE
= g_quark_from_string("task_state");
4321 LTT_CHANNEL_VM_STATE
= g_quark_from_string("vm_state");
4322 LTT_CHANNEL_KPROBE_STATE
= g_quark_from_string("kprobe_state");
4323 LTT_CHANNEL_FS
= g_quark_from_string("fs");
4324 LTT_CHANNEL_KERNEL
= g_quark_from_string("kernel");
4325 LTT_CHANNEL_MM
= g_quark_from_string("mm");
4326 LTT_CHANNEL_USERSPACE
= g_quark_from_string("userspace");
4327 LTT_CHANNEL_BLOCK
= g_quark_from_string("block");
4329 LTT_EVENT_SYSCALL_ENTRY
= g_quark_from_string("syscall_entry");
4330 LTT_EVENT_SYSCALL_EXIT
= g_quark_from_string("syscall_exit");
4331 LTT_EVENT_TRAP_ENTRY
= g_quark_from_string("trap_entry");
4332 LTT_EVENT_TRAP_EXIT
= g_quark_from_string("trap_exit");
4333 LTT_EVENT_PAGE_FAULT_ENTRY
= g_quark_from_string("page_fault_entry");
4334 LTT_EVENT_PAGE_FAULT_EXIT
= g_quark_from_string("page_fault_exit");
4335 LTT_EVENT_PAGE_FAULT_NOSEM_ENTRY
= g_quark_from_string("page_fault_nosem_entry");
4336 LTT_EVENT_PAGE_FAULT_NOSEM_EXIT
= g_quark_from_string("page_fault_nosem_exit");
4337 LTT_EVENT_IRQ_ENTRY
= g_quark_from_string("irq_entry");
4338 LTT_EVENT_IRQ_EXIT
= g_quark_from_string("irq_exit");
4339 LTT_EVENT_SOFT_IRQ_RAISE
= g_quark_from_string("softirq_raise");
4340 LTT_EVENT_SOFT_IRQ_ENTRY
= g_quark_from_string("softirq_entry");
4341 LTT_EVENT_SOFT_IRQ_EXIT
= g_quark_from_string("softirq_exit");
4342 LTT_EVENT_SCHED_SCHEDULE
= g_quark_from_string("sched_schedule");
4343 LTT_EVENT_PROCESS_FORK
= g_quark_from_string("process_fork");
4344 LTT_EVENT_KTHREAD_CREATE
= g_quark_from_string("kthread_create");
4345 LTT_EVENT_PROCESS_EXIT
= g_quark_from_string("process_exit");
4346 LTT_EVENT_PROCESS_FREE
= g_quark_from_string("process_free");
4347 LTT_EVENT_EXEC
= g_quark_from_string("exec");
4348 LTT_EVENT_PROCESS_STATE
= g_quark_from_string("process_state");
4349 LTT_EVENT_STATEDUMP_END
= g_quark_from_string("statedump_end");
4350 LTT_EVENT_FUNCTION_ENTRY
= g_quark_from_string("function_entry");
4351 LTT_EVENT_FUNCTION_EXIT
= g_quark_from_string("function_exit");
4352 LTT_EVENT_THREAD_BRAND
= g_quark_from_string("thread_brand");
4353 LTT_EVENT_REQUEST_ISSUE
= g_quark_from_string("_blk_request_issue");
4354 LTT_EVENT_REQUEST_COMPLETE
= g_quark_from_string("_blk_request_complete");
4355 LTT_EVENT_LIST_INTERRUPT
= g_quark_from_string("interrupt");
4356 LTT_EVENT_SYS_CALL_TABLE
= g_quark_from_string("sys_call_table");
4357 LTT_EVENT_SOFTIRQ_VEC
= g_quark_from_string("softirq_vec");
4358 LTT_EVENT_KPROBE_TABLE
= g_quark_from_string("kprobe_table");
4359 LTT_EVENT_KPROBE
= g_quark_from_string("kprobe");
4361 LTT_FIELD_SYSCALL_ID
= g_quark_from_string("syscall_id");
4362 LTT_FIELD_TRAP_ID
= g_quark_from_string("trap_id");
4363 LTT_FIELD_IRQ_ID
= g_quark_from_string("irq_id");
4364 LTT_FIELD_SOFT_IRQ_ID
= g_quark_from_string("softirq_id");
4365 LTT_FIELD_PREV_PID
= g_quark_from_string("prev_pid");
4366 LTT_FIELD_NEXT_PID
= g_quark_from_string("next_pid");
4367 LTT_FIELD_PREV_STATE
= g_quark_from_string("prev_state");
4368 LTT_FIELD_PARENT_PID
= g_quark_from_string("parent_pid");
4369 LTT_FIELD_CHILD_PID
= g_quark_from_string("child_pid");
4370 LTT_FIELD_PID
= g_quark_from_string("pid");
4371 LTT_FIELD_TGID
= g_quark_from_string("tgid");
4372 LTT_FIELD_CHILD_TGID
= g_quark_from_string("child_tgid");
4373 LTT_FIELD_FILENAME
= g_quark_from_string("filename");
4374 LTT_FIELD_NAME
= g_quark_from_string("name");
4375 LTT_FIELD_TYPE
= g_quark_from_string("type");
4376 LTT_FIELD_MODE
= g_quark_from_string("mode");
4377 LTT_FIELD_SUBMODE
= g_quark_from_string("submode");
4378 LTT_FIELD_STATUS
= g_quark_from_string("status");
4379 LTT_FIELD_THIS_FN
= g_quark_from_string("this_fn");
4380 LTT_FIELD_CALL_SITE
= g_quark_from_string("call_site");
4381 LTT_FIELD_MAJOR
= g_quark_from_string("major");
4382 LTT_FIELD_MINOR
= g_quark_from_string("minor");
4383 LTT_FIELD_OPERATION
= g_quark_from_string("direction");
4384 LTT_FIELD_ACTION
= g_quark_from_string("action");
4385 LTT_FIELD_ID
= g_quark_from_string("id");
4386 LTT_FIELD_ADDRESS
= g_quark_from_string("address");
4387 LTT_FIELD_SYMBOL
= g_quark_from_string("symbol");
4388 LTT_FIELD_IP
= g_quark_from_string("ip");
4390 LTTV_CPU_UNKNOWN
= g_quark_from_string("unknown");
4391 LTTV_CPU_IDLE
= g_quark_from_string("idle");
4392 LTTV_CPU_BUSY
= g_quark_from_string("busy");
4393 LTTV_CPU_IRQ
= g_quark_from_string("irq");
4394 LTTV_CPU_SOFT_IRQ
= g_quark_from_string("softirq");
4395 LTTV_CPU_TRAP
= g_quark_from_string("trap");
4397 LTTV_IRQ_UNKNOWN
= g_quark_from_string("unknown");
4398 LTTV_IRQ_IDLE
= g_quark_from_string("idle");
4399 LTTV_IRQ_BUSY
= g_quark_from_string("busy");
4401 LTTV_BDEV_UNKNOWN
= g_quark_from_string("unknown");
4402 LTTV_BDEV_IDLE
= g_quark_from_string("idle");
4403 LTTV_BDEV_BUSY_READING
= g_quark_from_string("busy_reading");
4404 LTTV_BDEV_BUSY_WRITING
= g_quark_from_string("busy_writing");
4407 static void module_destroy()
4412 LTTV_MODULE("state", "State computation", \
4413 "Update the system state, possibly saving it at intervals", \
4414 module_init
, module_destroy
)