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_SCHED_TRY_WAKEUP
,
87 LTT_EVENT_PROCESS_FORK
,
88 LTT_EVENT_KTHREAD_CREATE
,
89 LTT_EVENT_PROCESS_EXIT
,
90 LTT_EVENT_PROCESS_FREE
,
92 LTT_EVENT_PROCESS_STATE
,
93 LTT_EVENT_STATEDUMP_END
,
94 LTT_EVENT_FUNCTION_ENTRY
,
95 LTT_EVENT_FUNCTION_EXIT
,
96 LTT_EVENT_THREAD_BRAND
,
97 LTT_EVENT_REQUEST_ISSUE
,
98 LTT_EVENT_REQUEST_COMPLETE
,
99 LTT_EVENT_LIST_INTERRUPT
,
100 LTT_EVENT_SYS_CALL_TABLE
,
101 LTT_EVENT_SOFTIRQ_VEC
,
102 LTT_EVENT_KPROBE_TABLE
,
106 LTT_EVENT_POLL_EVENT
;
111 LTT_FIELD_SYSCALL_ID
,
114 LTT_FIELD_SOFT_IRQ_ID
,
117 LTT_FIELD_PREV_STATE
,
118 LTT_FIELD_PARENT_PID
,
122 LTT_FIELD_CHILD_TGID
,
142 LTTV_STATE_MODE_UNKNOWN
,
143 LTTV_STATE_USER_MODE
,
150 LTTV_STATE_SUBMODE_UNKNOWN
,
151 LTTV_STATE_SUBMODE_NONE
;
155 LTTV_STATE_WAIT_FORK
,
164 LTTV_STATE_UNBRANDED
;
167 LTTV_STATE_USER_THREAD
,
168 LTTV_STATE_KERNEL_THREAD
;
186 LTTV_BDEV_BUSY_READING
,
187 LTTV_BDEV_BUSY_WRITING
;
190 LTTV_STATE_TRACEFILES
,
191 LTTV_STATE_PROCESSES
,
193 LTTV_STATE_RUNNING_PROCESS
,
195 LTTV_STATE_SAVED_STATES
,
196 LTTV_STATE_SAVED_STATES_TIME
,
199 LTTV_STATE_NAME_TABLES
,
200 LTTV_STATE_TRACE_STATE_USE_COUNT
,
201 LTTV_STATE_RESOURCE_CPUS
,
202 LTTV_STATE_RESOURCE_CPUS_COUNT
,
203 LTTV_STATE_RESOURCE_IRQS
,
204 LTTV_STATE_RESOURCE_SOFT_IRQS
,
205 LTTV_STATE_RESOURCE_TRAPS
,
206 LTTV_STATE_RESOURCE_BLKDEVS
;
208 static void create_max_time(LttvTraceState
*tcs
);
210 static void get_max_time(LttvTraceState
*tcs
);
212 static void free_max_time(LttvTraceState
*tcs
);
214 static void create_name_tables(LttvTraceState
*tcs
);
216 static void get_name_tables(LttvTraceState
*tcs
);
218 static void free_name_tables(LttvTraceState
*tcs
);
220 static void free_saved_state(LttvTraceState
*tcs
);
222 static void lttv_state_free_process_table(GHashTable
*processes
);
224 static void lttv_trace_states_read_raw(LttvTraceState
*tcs
, FILE *fp
,
225 GPtrArray
*quarktable
);
227 /* Resource function prototypes */
228 static LttvBdevState
*get_hashed_bdevstate(LttvTraceState
*ts
, guint16 devcode
);
229 static LttvBdevState
*bdevstate_new(void);
230 static void bdevstate_free(LttvBdevState
*);
231 static void bdevstate_free_cb(gpointer key
, gpointer value
, gpointer user_data
);
232 static LttvBdevState
*bdevstate_copy(LttvBdevState
*bds
);
235 #if (__SIZEOF_LONG__ == 4)
236 guint
guint64_hash(gconstpointer key
)
238 guint64 ukey
= *(const guint64
*)key
;
240 return (guint
)ukey
^ (guint
)(ukey
>> 32);
243 gboolean
guint64_equal(gconstpointer a
, gconstpointer b
)
245 guint64 ua
= *(const guint64
*)a
;
246 guint64 ub
= *(const guint64
*)b
;
252 void lttv_state_save(LttvTraceState
*self
, LttvAttribute
*container
)
254 LTTV_TRACE_STATE_GET_CLASS(self
)->state_save(self
, container
);
258 void lttv_state_restore(LttvTraceState
*self
, LttvAttribute
*container
)
260 LTTV_TRACE_STATE_GET_CLASS(self
)->state_restore(self
, container
);
264 void lttv_state_state_saved_free(LttvTraceState
*self
,
265 LttvAttribute
*container
)
267 LTTV_TRACE_STATE_GET_CLASS(self
)->state_saved_free(self
, container
);
271 guint
process_hash(gconstpointer key
)
273 guint pid
= ((const LttvProcessState
*)key
)->pid
;
274 return (pid
>>8 ^ pid
>>4 ^ pid
>>2 ^ pid
) ;
278 /* If the hash table hash function is well distributed,
279 * the process_equal should compare different pid */
280 gboolean
process_equal(gconstpointer a
, gconstpointer b
)
282 const LttvProcessState
*process_a
, *process_b
;
285 process_a
= (const LttvProcessState
*)a
;
286 process_b
= (const LttvProcessState
*)b
;
288 if(likely(process_a
->pid
!= process_b
->pid
)) ret
= FALSE
;
289 else if(likely(process_a
->pid
== 0 &&
290 process_a
->cpu
!= process_b
->cpu
)) ret
= FALSE
;
295 static void delete_usertrace(gpointer key
, gpointer value
, gpointer user_data
)
297 g_tree_destroy((GTree
*)value
);
300 static void lttv_state_free_usertraces(GHashTable
*usertraces
)
302 g_hash_table_foreach(usertraces
, delete_usertrace
, NULL
);
303 g_hash_table_destroy(usertraces
);
306 gboolean
rettrue(gpointer key
, gpointer value
, gpointer user_data
)
311 static guint
check_expand(nb
, id
)
316 return max(id
+ 1, nb
* 2);
319 static void expand_name_table(LttvTraceState
*ts
, GQuark
**table
,
320 guint nb
, guint new_nb
)
322 /* Expand an incomplete table */
323 GQuark
*old_table
= *table
;
324 *table
= g_new(GQuark
, new_nb
);
325 memcpy(*table
, old_table
, nb
* sizeof(GQuark
));
329 static void fill_name_table(LttvTraceState
*ts
, GQuark
*table
, guint nb
,
330 guint new_nb
, const char *def_string
)
333 GString
*fe_name
= g_string_new("");
334 for(i
= nb
; i
< new_nb
; i
++) {
335 g_string_printf(fe_name
, "%s %d", def_string
, i
);
336 table
[i
] = g_quark_from_string(fe_name
->str
);
338 g_string_free(fe_name
, TRUE
);
341 static void expand_syscall_table(LttvTraceState
*ts
, int id
)
343 LttvNameTables
*nt
= ts
->name_tables
;
346 new_nb
= check_expand(nt
->nb_syscalls
, id
);
347 if(likely(new_nb
== nt
->nb_syscalls
))
349 expand_name_table(ts
, &nt
->syscall_names
, nt
->nb_syscalls
, new_nb
);
350 fill_name_table(ts
, nt
->syscall_names
, nt
->nb_syscalls
, new_nb
, "syscall");
351 /* Update the table size */
352 nt
->nb_syscalls
= new_nb
;
355 static void expand_kprobe_table(LttvTraceState
*ts
, guint64 ip
, char *symbol
)
357 LttvNameTables
*nt
= ts
->name_tables
;
358 #if (__SIZEOF_LONG__ == 4)
359 guint64
*ip_ptr
= g_new(guint64
, 1);
360 g_hash_table_insert(nt
->kprobe_hash
, ip_ptr
,
361 (gpointer
)(glong
)g_quark_from_string(symbol
));
363 g_hash_table_insert(nt
->kprobe_hash
, (gpointer
)ip
,
364 (gpointer
)(glong
)g_quark_from_string(symbol
));
368 static void expand_trap_table(LttvTraceState
*ts
, int id
)
370 LttvNameTables
*nt
= ts
->name_tables
;
371 LttvTrapState
*old_table
;
374 new_nb
= check_expand(nt
->nb_traps
, id
);
375 if(likely(new_nb
== nt
->nb_traps
))
378 expand_name_table(ts
, &nt
->trap_names
, nt
->nb_traps
, new_nb
);
379 fill_name_table(ts
, nt
->trap_names
, nt
->nb_traps
, new_nb
, "trap");
381 old_table
= ts
->trap_states
;
382 ts
->trap_states
= g_new(LttvTrapState
, new_nb
);
383 memcpy(ts
->trap_states
, old_table
, nt
->nb_traps
* sizeof(LttvTrapState
));
385 for(i
= nt
->nb_traps
; i
< new_nb
; i
++)
386 ts
->trap_states
[i
].running
= 0;
388 /* Update the table size */
389 nt
->nb_traps
= new_nb
;
392 static void expand_irq_table(LttvTraceState
*ts
, int id
)
394 LttvNameTables
*nt
= ts
->name_tables
;
395 LttvIRQState
*old_table
;
398 new_nb
= check_expand(nt
->nb_irqs
, id
);
399 if(likely(new_nb
== nt
->nb_irqs
))
402 expand_name_table(ts
, &nt
->irq_names
, nt
->nb_irqs
, new_nb
);
403 fill_name_table(ts
, nt
->irq_names
, nt
->nb_irqs
, new_nb
, "irq");
405 old_table
= ts
->irq_states
;
406 ts
->irq_states
= g_new(LttvIRQState
, new_nb
);
407 memcpy(ts
->irq_states
, old_table
, nt
->nb_irqs
* sizeof(LttvIRQState
));
409 for(i
= nt
->nb_irqs
; i
< new_nb
; i
++)
410 ts
->irq_states
[i
].mode_stack
=
411 g_array_new(FALSE
, FALSE
, sizeof(LttvIRQMode
));
413 /* Update the table size */
414 nt
->nb_irqs
= new_nb
;
417 static void expand_soft_irq_table(LttvTraceState
*ts
, int id
)
419 LttvNameTables
*nt
= ts
->name_tables
;
420 LttvSoftIRQState
*old_table
;
423 new_nb
= check_expand(nt
->nb_soft_irqs
, id
);
424 if(likely(new_nb
== nt
->nb_soft_irqs
))
427 expand_name_table(ts
, &nt
->soft_irq_names
, nt
->nb_soft_irqs
, new_nb
);
428 fill_name_table(ts
, nt
->soft_irq_names
, nt
->nb_soft_irqs
, new_nb
, "softirq");
430 old_table
= ts
->soft_irq_states
;
431 ts
->soft_irq_states
= g_new(LttvSoftIRQState
, new_nb
);
432 memcpy(ts
->soft_irq_states
, old_table
,
433 nt
->nb_soft_irqs
* sizeof(LttvSoftIRQState
));
435 for(i
= nt
->nb_soft_irqs
; i
< new_nb
; i
++)
436 ts
->soft_irq_states
[i
].running
= 0;
438 /* Update the table size */
439 nt
->nb_soft_irqs
= new_nb
;
443 restore_init_state(LttvTraceState
*self
)
445 guint i
, nb_cpus
, nb_irqs
, nb_soft_irqs
, nb_traps
;
447 //LttvTracefileState *tfcs;
449 LttTime start_time
, end_time
;
451 /* Free the process tables */
452 if(self
->processes
!= NULL
) lttv_state_free_process_table(self
->processes
);
453 if(self
->usertraces
!= NULL
) lttv_state_free_usertraces(self
->usertraces
);
454 self
->processes
= g_hash_table_new(process_hash
, process_equal
);
455 self
->usertraces
= g_hash_table_new(g_direct_hash
, g_direct_equal
);
458 /* Seek time to beginning */
459 // Mathieu : fix : don't seek traceset here : causes inconsistency in seek
460 // closest. It's the tracecontext job to seek the trace to the beginning
461 // anyway : the init state might be used at the middle of the trace as well...
462 //g_tree_destroy(self->parent.ts_context->pqueue);
463 //self->parent.ts_context->pqueue = g_tree_new(compare_tracefile);
465 ltt_trace_time_span_get(self
->parent
.t
, &start_time
, &end_time
);
467 //lttv_process_trace_seek_time(&self->parent, ltt_time_zero);
469 nb_cpus
= ltt_trace_get_num_cpu(self
->parent
.t
);
470 nb_irqs
= self
->name_tables
->nb_irqs
;
471 nb_soft_irqs
= self
->name_tables
->nb_soft_irqs
;
472 nb_traps
= self
->name_tables
->nb_traps
;
474 /* Put the per cpu running_process to beginning state : process 0. */
475 for(i
=0; i
< nb_cpus
; i
++) {
476 LttvExecutionState
*es
;
477 self
->running_process
[i
] = lttv_state_create_process(self
, NULL
, i
, 0, 0,
478 LTTV_STATE_UNNAMED
, &start_time
);
479 /* We are not sure is it's a kernel thread or normal thread, put the
480 * bottom stack state to unknown */
481 self
->running_process
[i
]->execution_stack
=
482 g_array_set_size(self
->running_process
[i
]->execution_stack
, 1);
483 es
= self
->running_process
[i
]->state
=
484 &g_array_index(self
->running_process
[i
]->execution_stack
,
485 LttvExecutionState
, 0);
486 es
->t
= LTTV_STATE_MODE_UNKNOWN
;
487 es
->s
= LTTV_STATE_UNNAMED
;
489 //self->running_process[i]->state->s = LTTV_STATE_RUN;
490 self
->running_process
[i
]->cpu
= i
;
492 /* reset cpu states */
493 if(self
->cpu_states
[i
].mode_stack
->len
> 0) {
494 g_array_remove_range(self
->cpu_states
[i
].mode_stack
, 0, self
->cpu_states
[i
].mode_stack
->len
);
495 if(self
->cpu_states
[i
].irq_stack
->len
)
496 g_array_remove_range(self
->cpu_states
[i
].irq_stack
, 0, self
->cpu_states
[i
].irq_stack
->len
);
497 if(self
->cpu_states
[i
].softirq_stack
->len
)
498 g_array_remove_range(self
->cpu_states
[i
].softirq_stack
, 0, self
->cpu_states
[i
].softirq_stack
->len
);
499 if(self
->cpu_states
[i
].trap_stack
->len
)
500 g_array_remove_range(self
->cpu_states
[i
].trap_stack
, 0, self
->cpu_states
[i
].trap_stack
->len
);
504 /* reset irq states */
505 for(i
=0; i
<nb_irqs
; i
++) {
506 if(self
->irq_states
[i
].mode_stack
->len
> 0)
507 g_array_remove_range(self
->irq_states
[i
].mode_stack
, 0, self
->irq_states
[i
].mode_stack
->len
);
510 /* reset softirq states */
511 for(i
=0; i
<nb_soft_irqs
; i
++) {
512 self
->soft_irq_states
[i
].pending
= 0;
513 self
->soft_irq_states
[i
].running
= 0;
516 /* reset trap states */
517 for(i
=0; i
<nb_traps
; i
++) {
518 self
->trap_states
[i
].running
= 0;
521 /* reset bdev states */
522 g_hash_table_foreach(self
->bdev_states
, bdevstate_free_cb
, NULL
);
523 //g_hash_table_steal_all(self->bdev_states);
524 g_hash_table_foreach_steal(self
->bdev_states
, rettrue
, NULL
);
527 nb_tracefile
= self
->parent
.tracefiles
->len
;
529 for(i
= 0 ; i
< nb_tracefile
; i
++) {
531 LTTV_TRACEFILE_STATE(g_array_index(self
->parent
.tracefiles
,
532 LttvTracefileContext
*, i
));
533 ltt_trace_time_span_get(self
->parent
.t
, &tfcs
->parent
.timestamp
, NULL
);
534 // tfcs->saved_position = 0;
535 tfcs
->process
= lttv_state_create_process(tfcs
, NULL
,0);
536 tfcs
->process
->state
->s
= LTTV_STATE_RUN
;
537 tfcs
->process
->last_cpu
= tfcs
->cpu_name
;
538 tfcs
->process
->last_cpu_index
= ltt_tracefile_num(((LttvTracefileContext
*)tfcs
)->tf
);
543 //static LttTime time_zero = {0,0};
545 static gint
compare_usertraces(gconstpointer a
, gconstpointer b
,
548 const LttTime
*t1
= (const LttTime
*)a
;
549 const LttTime
*t2
= (const LttTime
*)b
;
551 return ltt_time_compare(*t1
, *t2
);
554 static void free_usertrace_key(gpointer data
)
559 #define MAX_STRING_LEN 4096
562 state_load_saved_states(LttvTraceState
*tcs
)
565 GPtrArray
*quarktable
;
566 const char *trace_path
;
570 tcs
->has_precomputed_states
= FALSE
;
574 gchar buf
[MAX_STRING_LEN
];
577 trace_path
= g_quark_to_string(ltt_trace_name(tcs
->parent
.t
));
578 strncpy(path
, trace_path
, PATH_MAX
-1);
579 count
= strnlen(trace_path
, PATH_MAX
-1);
580 // quarktable : open, test
581 strncat(path
, "/precomputed/quarktable", PATH_MAX
-count
-1);
582 fp
= fopen(path
, "r");
584 quarktable
= g_ptr_array_sized_new(4096);
586 /* Index 0 is null */
588 if(hdr
== EOF
) return;
589 g_assert(hdr
== HDR_QUARKS
);
593 if(hdr
== EOF
) break;
594 g_assert(hdr
== HDR_QUARK
);
595 g_ptr_array_set_size(quarktable
, q
+1);
598 fread(&buf
[i
], sizeof(gchar
), 1, fp
);
599 if(buf
[i
] == '\0' || feof(fp
)) break;
602 len
= strnlen(buf
, MAX_STRING_LEN
-1);
603 g_ptr_array_index (quarktable
, q
) = g_new(gchar
, len
+1);
604 strncpy(g_ptr_array_index (quarktable
, q
), buf
, len
+1);
610 // saved_states : open, test
611 strncpy(path
, trace_path
, PATH_MAX
-1);
612 count
= strnlen(trace_path
, PATH_MAX
-1);
613 strncat(path
, "/precomputed/states", PATH_MAX
-count
-1);
614 fp
= fopen(path
, "r");
618 if(hdr
!= HDR_TRACE
) goto end
;
620 lttv_trace_states_read_raw(tcs
, fp
, quarktable
);
622 tcs
->has_precomputed_states
= TRUE
;
627 /* Free the quarktable */
628 for(i
=0; i
<quarktable
->len
; i
++) {
629 string
= g_ptr_array_index (quarktable
, i
);
632 g_ptr_array_free(quarktable
, TRUE
);
637 init(LttvTracesetState
*self
, LttvTraceset
*ts
)
639 guint i
, j
, nb_trace
, nb_tracefile
, nb_cpu
;
642 LttvTraceContext
*tc
;
646 LttvTracefileState
*tfcs
;
648 LttvAttributeValue v
;
650 LTTV_TRACESET_CONTEXT_CLASS(g_type_class_peek(LTTV_TRACESET_CONTEXT_TYPE
))->
651 init((LttvTracesetContext
*)self
, ts
);
653 nb_trace
= lttv_traceset_number(ts
);
654 for(i
= 0 ; i
< nb_trace
; i
++) {
655 tc
= self
->parent
.traces
[i
];
656 tcs
= LTTV_TRACE_STATE(tc
);
657 tcs
->save_interval
= LTTV_STATE_SAVE_INTERVAL
;
658 lttv_attribute_find(tcs
->parent
.t_a
, LTTV_STATE_TRACE_STATE_USE_COUNT
,
662 if(*(v
.v_uint
) == 1) {
663 create_name_tables(tcs
);
664 create_max_time(tcs
);
666 get_name_tables(tcs
);
669 nb_tracefile
= tc
->tracefiles
->len
;
670 nb_cpu
= ltt_trace_get_num_cpu(tc
->t
);
671 nb_irq
= tcs
->name_tables
->nb_irqs
;
672 tcs
->processes
= NULL
;
673 tcs
->usertraces
= NULL
;
674 tcs
->running_process
= g_new(LttvProcessState
*, nb_cpu
);
676 /* init cpu resource stuff */
677 tcs
->cpu_states
= g_new(LttvCPUState
, nb_cpu
);
678 for(j
= 0; j
<nb_cpu
; j
++) {
679 tcs
->cpu_states
[j
].mode_stack
= g_array_new(FALSE
, FALSE
, sizeof(LttvCPUMode
));
680 tcs
->cpu_states
[j
].irq_stack
= g_array_new(FALSE
, FALSE
, sizeof(gint
));
681 tcs
->cpu_states
[j
].softirq_stack
= g_array_new(FALSE
, FALSE
, sizeof(gint
));
682 tcs
->cpu_states
[j
].trap_stack
= g_array_new(FALSE
, FALSE
, sizeof(gint
));
683 g_assert(tcs
->cpu_states
[j
].mode_stack
!= NULL
);
686 /* init irq resource stuff */
687 tcs
->irq_states
= g_new(LttvIRQState
, nb_irq
);
688 for(j
= 0; j
<nb_irq
; j
++) {
689 tcs
->irq_states
[j
].mode_stack
= g_array_new(FALSE
, FALSE
, sizeof(LttvIRQMode
));
690 g_assert(tcs
->irq_states
[j
].mode_stack
!= NULL
);
693 /* init soft irq stuff */
694 /* the kernel has a statically fixed max of 32 softirqs */
695 tcs
->soft_irq_states
= g_new(LttvSoftIRQState
, tcs
->name_tables
->nb_soft_irqs
);
697 /* init trap stuff */
698 tcs
->trap_states
= g_new(LttvTrapState
, tcs
->name_tables
->nb_traps
);
700 /* init bdev resource stuff */
701 tcs
->bdev_states
= g_hash_table_new(g_int_hash
, g_int_equal
);
703 restore_init_state(tcs
);
704 for(j
= 0 ; j
< nb_tracefile
; j
++) {
706 LTTV_TRACEFILE_STATE(g_array_index(tc
->tracefiles
,
707 LttvTracefileContext
*, j
));
708 tfcs
->tracefile_name
= ltt_tracefile_name(tfcs
->parent
.tf
);
709 tfcs
->cpu
= ltt_tracefile_cpu(tfcs
->parent
.tf
);
710 tfcs
->cpu_state
= &(tcs
->cpu_states
[tfcs
->cpu
]);
711 if(ltt_tracefile_tid(tfcs
->parent
.tf
) != 0) {
712 /* It's a Usertrace */
713 guint tid
= ltt_tracefile_tid(tfcs
->parent
.tf
);
714 GTree
*usertrace_tree
= (GTree
*)g_hash_table_lookup(tcs
->usertraces
,
715 GUINT_TO_POINTER(tid
));
716 if(!usertrace_tree
) {
717 usertrace_tree
= g_tree_new_full(compare_usertraces
,
718 NULL
, free_usertrace_key
, NULL
);
719 g_hash_table_insert(tcs
->usertraces
,
720 GUINT_TO_POINTER(tid
), usertrace_tree
);
722 LttTime
*timestamp
= g_new(LttTime
, 1);
723 *timestamp
= ltt_interpolate_time_from_tsc(tfcs
->parent
.tf
,
724 ltt_tracefile_creation(tfcs
->parent
.tf
));
725 g_tree_insert(usertrace_tree
, timestamp
, tfcs
);
729 /* See if the trace has saved states */
730 state_load_saved_states(tcs
);
735 fini(LttvTracesetState
*self
)
741 //LttvTracefileState *tfcs;
743 LttvAttributeValue v
;
745 nb_trace
= lttv_traceset_number(LTTV_TRACESET_CONTEXT(self
)->ts
);
746 for(i
= 0 ; i
< nb_trace
; i
++) {
747 tcs
= (LttvTraceState
*)(LTTV_TRACESET_CONTEXT(self
)->traces
[i
]);
748 lttv_attribute_find(tcs
->parent
.t_a
, LTTV_STATE_TRACE_STATE_USE_COUNT
,
751 g_assert(*(v
.v_uint
) != 0);
754 if(*(v
.v_uint
) == 0) {
755 free_name_tables(tcs
);
757 free_saved_state(tcs
);
759 g_free(tcs
->running_process
);
760 tcs
->running_process
= NULL
;
761 lttv_state_free_process_table(tcs
->processes
);
762 lttv_state_free_usertraces(tcs
->usertraces
);
763 tcs
->processes
= NULL
;
764 tcs
->usertraces
= NULL
;
766 LTTV_TRACESET_CONTEXT_CLASS(g_type_class_peek(LTTV_TRACESET_CONTEXT_TYPE
))->
767 fini((LttvTracesetContext
*)self
);
771 static LttvTracesetContext
*
772 new_traceset_context(LttvTracesetContext
*self
)
774 return LTTV_TRACESET_CONTEXT(g_object_new(LTTV_TRACESET_STATE_TYPE
, NULL
));
778 static LttvTraceContext
*
779 new_trace_context(LttvTracesetContext
*self
)
781 return LTTV_TRACE_CONTEXT(g_object_new(LTTV_TRACE_STATE_TYPE
, NULL
));
785 static LttvTracefileContext
*
786 new_tracefile_context(LttvTracesetContext
*self
)
788 return LTTV_TRACEFILE_CONTEXT(g_object_new(LTTV_TRACEFILE_STATE_TYPE
, NULL
));
792 /* Write the process state of the trace */
794 static void write_process_state(gpointer key
, gpointer value
,
797 LttvProcessState
*process
;
799 LttvExecutionState
*es
;
801 FILE *fp
= (FILE *)user_data
;
806 process
= (LttvProcessState
*)value
;
808 " <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",
809 process
, process
->pid
, process
->tgid
, process
->ppid
,
810 g_quark_to_string(process
->type
),
811 process
->creation_time
.tv_sec
,
812 process
->creation_time
.tv_nsec
,
813 process
->insertion_time
.tv_sec
,
814 process
->insertion_time
.tv_nsec
,
815 g_quark_to_string(process
->name
),
816 g_quark_to_string(process
->brand
),
817 process
->cpu
, process
->free_events
);
819 for(i
= 0 ; i
< process
->execution_stack
->len
; i
++) {
820 es
= &g_array_index(process
->execution_stack
, LttvExecutionState
, i
);
821 fprintf(fp
, " <ES MODE=\"%s\" SUBMODE=\"%s\" ENTRY_S=%lu ENTRY_NS=%lu",
822 g_quark_to_string(es
->t
), g_quark_to_string(es
->n
),
823 es
->entry
.tv_sec
, es
->entry
.tv_nsec
);
824 fprintf(fp
, " CHANGE_S=%lu CHANGE_NS=%lu STATUS=\"%s\"/>\n",
825 es
->change
.tv_sec
, es
->change
.tv_nsec
, g_quark_to_string(es
->s
));
828 for(i
= 0 ; i
< process
->user_stack
->len
; i
++) {
829 address
= g_array_index(process
->user_stack
, guint64
, i
);
830 fprintf(fp
, " <USER_STACK ADDRESS=\"%" PRIu64
"\"/>\n",
834 if(process
->usertrace
) {
835 fprintf(fp
, " <USERTRACE NAME=\"%s\" CPU=%u\n/>",
836 g_quark_to_string(process
->usertrace
->tracefile_name
),
837 process
->usertrace
->cpu
);
841 fprintf(fp
, " </PROCESS>\n");
845 void lttv_state_write(LttvTraceState
*self
, LttTime t
, FILE *fp
)
847 guint i
, nb_tracefile
, nb_block
, offset
;
850 LttvTracefileState
*tfcs
;
854 LttEventPosition
*ep
;
858 ep
= ltt_event_position_new();
860 fprintf(fp
,"<PROCESS_STATE TIME_S=%lu TIME_NS=%lu>\n", t
.tv_sec
, t
.tv_nsec
);
862 g_hash_table_foreach(self
->processes
, write_process_state
, fp
);
864 nb_cpus
= ltt_trace_get_num_cpu(self
->parent
.t
);
865 for(i
=0;i
<nb_cpus
;i
++) {
866 fprintf(fp
," <CPU NUM=%u RUNNING_PROCESS=%u>\n",
867 i
, self
->running_process
[i
]->pid
);
870 nb_tracefile
= self
->parent
.tracefiles
->len
;
872 for(i
= 0 ; i
< nb_tracefile
; i
++) {
874 LTTV_TRACEFILE_STATE(g_array_index(self
->parent
.tracefiles
,
875 LttvTracefileContext
*, i
));
876 fprintf(fp
, " <TRACEFILE TIMESTAMP_S=%lu TIMESTAMP_NS=%lu",
877 tfcs
->parent
.timestamp
.tv_sec
,
878 tfcs
->parent
.timestamp
.tv_nsec
);
879 LttEvent
*e
= ltt_tracefile_get_event(tfcs
->parent
.tf
);
880 if(e
== NULL
) fprintf(fp
,"/>\n");
882 ltt_event_position(e
, ep
);
883 ltt_event_position_get(ep
, &tf
, &nb_block
, &offset
, &tsc
);
884 fprintf(fp
, " BLOCK=%u OFFSET=%u TSC=%" PRIu64
"/>\n", nb_block
, offset
,
889 fprintf(fp
,"</PROCESS_STATE>\n");
893 static void write_process_state_raw(gpointer key
, gpointer value
,
896 LttvProcessState
*process
;
898 LttvExecutionState
*es
;
900 FILE *fp
= (FILE *)user_data
;
905 process
= (LttvProcessState
*)value
;
906 fputc(HDR_PROCESS
, fp
);
907 //fwrite(&header, sizeof(header), 1, fp);
908 //fprintf(fp, "%s", g_quark_to_string(process->type));
910 fwrite(&process
->type
, sizeof(process
->type
), 1, fp
);
911 //fprintf(fp, "%s", g_quark_to_string(process->name));
913 fwrite(&process
->name
, sizeof(process
->name
), 1, fp
);
914 //fprintf(fp, "%s", g_quark_to_string(process->brand));
916 fwrite(&process
->brand
, sizeof(process
->brand
), 1, fp
);
917 fwrite(&process
->pid
, sizeof(process
->pid
), 1, fp
);
918 fwrite(&process
->free_events
, sizeof(process
->free_events
), 1, fp
);
919 fwrite(&process
->tgid
, sizeof(process
->tgid
), 1, fp
);
920 fwrite(&process
->ppid
, sizeof(process
->ppid
), 1, fp
);
921 fwrite(&process
->cpu
, sizeof(process
->cpu
), 1, fp
);
922 fwrite(&process
->creation_time
, sizeof(process
->creation_time
), 1, fp
);
923 fwrite(&process
->insertion_time
, sizeof(process
->insertion_time
), 1, fp
);
927 " <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",
928 process
, process
->pid
, process
->tgid
, process
->ppid
,
929 g_quark_to_string(process
->type
),
930 process
->creation_time
.tv_sec
,
931 process
->creation_time
.tv_nsec
,
932 process
->insertion_time
.tv_sec
,
933 process
->insertion_time
.tv_nsec
,
934 g_quark_to_string(process
->name
),
935 g_quark_to_string(process
->brand
),
939 for(i
= 0 ; i
< process
->execution_stack
->len
; i
++) {
940 es
= &g_array_index(process
->execution_stack
, LttvExecutionState
, i
);
943 //fprintf(fp, "%s", g_quark_to_string(es->t));
945 fwrite(&es
->t
, sizeof(es
->t
), 1, fp
);
946 //fprintf(fp, "%s", g_quark_to_string(es->n));
948 fwrite(&es
->n
, sizeof(es
->n
), 1, fp
);
949 //fprintf(fp, "%s", g_quark_to_string(es->s));
951 fwrite(&es
->s
, sizeof(es
->s
), 1, fp
);
952 fwrite(&es
->entry
, sizeof(es
->entry
), 1, fp
);
953 fwrite(&es
->change
, sizeof(es
->change
), 1, fp
);
954 fwrite(&es
->cum_cpu_time
, sizeof(es
->cum_cpu_time
), 1, fp
);
956 fprintf(fp
, " <ES MODE=\"%s\" SUBMODE=\"%s\" ENTRY_S=%lu ENTRY_NS=%lu",
957 g_quark_to_string(es
->t
), g_quark_to_string(es
->n
),
958 es
->entry
.tv_sec
, es
->entry
.tv_nsec
);
959 fprintf(fp
, " CHANGE_S=%lu CHANGE_NS=%lu STATUS=\"%s\"/>\n",
960 es
->change
.tv_sec
, es
->change
.tv_nsec
, g_quark_to_string(es
->s
));
964 for(i
= 0 ; i
< process
->user_stack
->len
; i
++) {
965 address
= g_array_index(process
->user_stack
, guint64
, i
);
966 fputc(HDR_USER_STACK
, fp
);
967 fwrite(&address
, sizeof(address
), 1, fp
);
969 fprintf(fp
, " <USER_STACK ADDRESS=\"%llu\"/>\n",
974 if(process
->usertrace
) {
975 fputc(HDR_USERTRACE
, fp
);
976 //fprintf(fp, "%s", g_quark_to_string(process->usertrace->tracefile_name));
978 fwrite(&process
->usertrace
->tracefile_name
,
979 sizeof(process
->usertrace
->tracefile_name
), 1, fp
);
980 fwrite(&process
->usertrace
->cpu
, sizeof(process
->usertrace
->cpu
), 1, fp
);
982 fprintf(fp
, " <USERTRACE NAME=\"%s\" CPU=%u\n/>",
983 g_quark_to_string(process
->usertrace
->tracefile_name
),
984 process
->usertrace
->cpu
);
991 void lttv_state_write_raw(LttvTraceState
*self
, LttTime t
, FILE *fp
)
993 guint i
, nb_tracefile
, nb_block
, offset
;
996 LttvTracefileState
*tfcs
;
1000 LttEventPosition
*ep
;
1004 ep
= ltt_event_position_new();
1006 //fprintf(fp,"<PROCESS_STATE TIME_S=%lu TIME_NS=%lu>\n", t.tv_sec, t.tv_nsec);
1007 fputc(HDR_PROCESS_STATE
, fp
);
1008 fwrite(&t
, sizeof(t
), 1, fp
);
1010 g_hash_table_foreach(self
->processes
, write_process_state_raw
, fp
);
1012 nb_cpus
= ltt_trace_get_num_cpu(self
->parent
.t
);
1013 for(i
=0;i
<nb_cpus
;i
++) {
1015 fwrite(&i
, sizeof(i
), 1, fp
); /* cpu number */
1016 fwrite(&self
->running_process
[i
]->pid
,
1017 sizeof(self
->running_process
[i
]->pid
), 1, fp
);
1018 //fprintf(fp," <CPU NUM=%u RUNNING_PROCESS=%u>\n",
1019 // i, self->running_process[i]->pid);
1022 nb_tracefile
= self
->parent
.tracefiles
->len
;
1024 for(i
= 0 ; i
< nb_tracefile
; i
++) {
1026 LTTV_TRACEFILE_STATE(g_array_index(self
->parent
.tracefiles
,
1027 LttvTracefileContext
*, i
));
1028 // fprintf(fp, " <TRACEFILE TIMESTAMP_S=%lu TIMESTAMP_NS=%lu",
1029 // tfcs->parent.timestamp.tv_sec,
1030 // tfcs->parent.timestamp.tv_nsec);
1031 fputc(HDR_TRACEFILE
, fp
);
1032 fwrite(&tfcs
->parent
.timestamp
, sizeof(tfcs
->parent
.timestamp
), 1, fp
);
1033 /* Note : if timestamp if LTT_TIME_INFINITE, there will be no
1034 * position following : end of trace */
1035 LttEvent
*e
= ltt_tracefile_get_event(tfcs
->parent
.tf
);
1037 ltt_event_position(e
, ep
);
1038 ltt_event_position_get(ep
, &tf
, &nb_block
, &offset
, &tsc
);
1039 //fprintf(fp, " BLOCK=%u OFFSET=%u TSC=%llu/>\n", nb_block, offset,
1041 fwrite(&nb_block
, sizeof(nb_block
), 1, fp
);
1042 fwrite(&offset
, sizeof(offset
), 1, fp
);
1043 fwrite(&tsc
, sizeof(tsc
), 1, fp
);
1050 /* Read process state from a file */
1052 /* Called because a HDR_PROCESS was found */
1053 static void read_process_state_raw(LttvTraceState
*self
, FILE *fp
,
1054 GPtrArray
*quarktable
)
1056 LttvExecutionState
*es
;
1057 LttvProcessState
*process
, *parent_process
;
1058 LttvProcessState tmp
;
1063 /* TODO : check return value */
1064 fread(&tmp
.type
, sizeof(tmp
.type
), 1, fp
);
1065 fread(&tmp
.name
, sizeof(tmp
.name
), 1, fp
);
1066 fread(&tmp
.brand
, sizeof(tmp
.brand
), 1, fp
);
1067 fread(&tmp
.pid
, sizeof(tmp
.pid
), 1, fp
);
1068 fread(&tmp
.free_events
, sizeof(tmp
.free_events
), 1, fp
);
1069 fread(&tmp
.tgid
, sizeof(tmp
.tgid
), 1, fp
);
1070 fread(&tmp
.ppid
, sizeof(tmp
.ppid
), 1, fp
);
1071 fread(&tmp
.cpu
, sizeof(tmp
.cpu
), 1, fp
);
1072 fread(&tmp
.creation_time
, sizeof(tmp
.creation_time
), 1, fp
);
1073 fread(&tmp
.insertion_time
, sizeof(tmp
.insertion_time
), 1, fp
);
1076 process
= lttv_state_find_process(self
, tmp
.cpu
, tmp
.pid
);
1078 /* We must link to the parent */
1079 parent_process
= lttv_state_find_process_or_create(self
, ANY_CPU
, tmp
.ppid
,
1081 process
= lttv_state_find_process(self
, ANY_CPU
, tmp
.pid
);
1082 if(process
== NULL
) {
1083 process
= lttv_state_create_process(self
, parent_process
, tmp
.cpu
,
1085 g_quark_from_string((gchar
*)g_ptr_array_index(quarktable
, tmp
.name
)),
1086 &tmp
.creation_time
);
1089 process
->insertion_time
= tmp
.insertion_time
;
1090 process
->creation_time
= tmp
.creation_time
;
1091 process
->type
= g_quark_from_string(
1092 (gchar
*)g_ptr_array_index(quarktable
, tmp
.type
));
1093 process
->tgid
= tmp
.tgid
;
1094 process
->ppid
= tmp
.ppid
;
1095 process
->brand
= g_quark_from_string(
1096 (gchar
*)g_ptr_array_index(quarktable
, tmp
.brand
));
1098 g_quark_from_string((gchar
*)g_ptr_array_index(quarktable
, tmp
.name
));
1099 process
->free_events
= tmp
.free_events
;
1102 if(feof(fp
) || ferror(fp
)) goto end_loop
;
1104 gint hdr
= fgetc(fp
);
1105 if(hdr
== EOF
) goto end_loop
;
1109 process
->execution_stack
=
1110 g_array_set_size(process
->execution_stack
,
1111 process
->execution_stack
->len
+ 1);
1112 es
= &g_array_index(process
->execution_stack
, LttvExecutionState
,
1113 process
->execution_stack
->len
-1);
1114 process
->state
= es
;
1116 fread(&es
->t
, sizeof(es
->t
), 1, fp
);
1117 es
->t
= g_quark_from_string(
1118 (gchar
*)g_ptr_array_index(quarktable
, es
->t
));
1119 fread(&es
->n
, sizeof(es
->n
), 1, fp
);
1120 es
->n
= g_quark_from_string(
1121 (gchar
*)g_ptr_array_index(quarktable
, es
->n
));
1122 fread(&es
->s
, sizeof(es
->s
), 1, fp
);
1123 es
->s
= g_quark_from_string(
1124 (gchar
*)g_ptr_array_index(quarktable
, es
->s
));
1125 fread(&es
->entry
, sizeof(es
->entry
), 1, fp
);
1126 fread(&es
->change
, sizeof(es
->change
), 1, fp
);
1127 fread(&es
->cum_cpu_time
, sizeof(es
->cum_cpu_time
), 1, fp
);
1129 case HDR_USER_STACK
:
1130 process
->user_stack
= g_array_set_size(process
->user_stack
,
1131 process
->user_stack
->len
+ 1);
1132 address
= &g_array_index(process
->user_stack
, guint64
,
1133 process
->user_stack
->len
-1);
1134 fread(address
, sizeof(address
), 1, fp
);
1135 process
->current_function
= *address
;
1138 fread(&tmpq
, sizeof(tmpq
), 1, fp
);
1139 fread(&process
->usertrace
->cpu
, sizeof(process
->usertrace
->cpu
), 1, fp
);
1151 /* Called because a HDR_PROCESS_STATE was found */
1152 /* Append a saved state to the trace states */
1153 void lttv_state_read_raw(LttvTraceState
*self
, FILE *fp
, GPtrArray
*quarktable
)
1155 guint i
, nb_tracefile
, nb_block
, offset
;
1157 LttvTracefileState
*tfcs
;
1159 LttEventPosition
*ep
;
1167 LttvAttribute
*saved_states_tree
, *saved_state_tree
;
1169 LttvAttributeValue value
;
1170 GTree
*pqueue
= self
->parent
.ts_context
->pqueue
;
1171 ep
= ltt_event_position_new();
1173 restore_init_state(self
);
1175 fread(&t
, sizeof(t
), 1, fp
);
1178 if(feof(fp
) || ferror(fp
)) goto end_loop
;
1180 if(hdr
== EOF
) goto end_loop
;
1184 /* Call read_process_state_raw */
1185 read_process_state_raw(self
, fp
, quarktable
);
1193 case HDR_USER_STACK
:
1195 case HDR_PROCESS_STATE
:
1201 g_error("Error while parsing saved state file : unknown data header %d",
1207 nb_cpus
= ltt_trace_get_num_cpu(self
->parent
.t
);
1208 for(i
=0;i
<nb_cpus
;i
++) {
1211 g_assert(hdr
== HDR_CPU
);
1212 fread(&cpu_num
, sizeof(cpu_num
), 1, fp
); /* cpu number */
1213 g_assert(i
== cpu_num
);
1214 fread(&self
->running_process
[i
]->pid
,
1215 sizeof(self
->running_process
[i
]->pid
), 1, fp
);
1218 nb_tracefile
= self
->parent
.tracefiles
->len
;
1220 for(i
= 0 ; i
< nb_tracefile
; i
++) {
1222 LTTV_TRACEFILE_STATE(g_array_index(self
->parent
.tracefiles
,
1223 LttvTracefileContext
*, i
));
1224 // fprintf(fp, " <TRACEFILE TIMESTAMP_S=%lu TIMESTAMP_NS=%lu",
1225 // tfcs->parent.timestamp.tv_sec,
1226 // tfcs->parent.timestamp.tv_nsec);
1227 g_tree_remove(pqueue
, &tfcs
->parent
);
1229 g_assert(hdr
== HDR_TRACEFILE
);
1230 fread(&tfcs
->parent
.timestamp
, sizeof(tfcs
->parent
.timestamp
), 1, fp
);
1231 /* Note : if timestamp if LTT_TIME_INFINITE, there will be no
1232 * position following : end of trace */
1233 if(ltt_time_compare(tfcs
->parent
.timestamp
, ltt_time_infinite
) != 0) {
1234 fread(&nb_block
, sizeof(nb_block
), 1, fp
);
1235 fread(&offset
, sizeof(offset
), 1, fp
);
1236 fread(&tsc
, sizeof(tsc
), 1, fp
);
1237 ltt_event_position_set(ep
, tfcs
->parent
.tf
, nb_block
, offset
, tsc
);
1238 gint ret
= ltt_tracefile_seek_position(tfcs
->parent
.tf
, ep
);
1240 g_tree_insert(pqueue
, &tfcs
->parent
, &tfcs
->parent
);
1245 saved_states_tree
= lttv_attribute_find_subdir(self
->parent
.t_a
,
1246 LTTV_STATE_SAVED_STATES
);
1247 saved_state_tree
= g_object_new(LTTV_ATTRIBUTE_TYPE
, NULL
);
1248 value
= lttv_attribute_add(saved_states_tree
,
1249 lttv_attribute_get_number(saved_states_tree
), LTTV_GOBJECT
);
1250 *(value
.v_gobject
) = (GObject
*)saved_state_tree
;
1251 value
= lttv_attribute_add(saved_state_tree
, LTTV_STATE_TIME
, LTTV_TIME
);
1252 *(value
.v_time
) = t
;
1253 lttv_state_save(self
, saved_state_tree
);
1254 g_debug("Saving state at time %lu.%lu", t
.tv_sec
,
1257 *(self
->max_time_state_recomputed_in_seek
) = t
;
1261 /* Called when a HDR_TRACE is found */
1262 void lttv_trace_states_read_raw(LttvTraceState
*tcs
, FILE *fp
,
1263 GPtrArray
*quarktable
)
1268 if(feof(fp
) || ferror(fp
)) goto end_loop
;
1270 if(hdr
== EOF
) goto end_loop
;
1273 case HDR_PROCESS_STATE
:
1274 /* Call read_process_state_raw */
1275 lttv_state_read_raw(tcs
, fp
, quarktable
);
1283 case HDR_USER_STACK
:
1287 g_error("Error while parsing saved state file :"
1288 " unexpected data header %d",
1292 g_error("Error while parsing saved state file : unknown data header %d",
1297 *(tcs
->max_time_state_recomputed_in_seek
) = tcs
->parent
.time_span
.end_time
;
1298 restore_init_state(tcs
);
1299 lttv_process_trace_seek_time(&tcs
->parent
, ltt_time_zero
);
1305 /* Copy each process from an existing hash table to a new one */
1307 static void copy_process_state(gpointer key
, gpointer value
,gpointer user_data
)
1309 LttvProcessState
*process
, *new_process
;
1311 GHashTable
*new_processes
= (GHashTable
*)user_data
;
1315 process
= (LttvProcessState
*)value
;
1316 new_process
= g_new(LttvProcessState
, 1);
1317 *new_process
= *process
;
1318 new_process
->execution_stack
= g_array_sized_new(FALSE
, FALSE
,
1319 sizeof(LttvExecutionState
), PREALLOCATED_EXECUTION_STACK
);
1320 new_process
->execution_stack
=
1321 g_array_set_size(new_process
->execution_stack
,
1322 process
->execution_stack
->len
);
1323 for(i
= 0 ; i
< process
->execution_stack
->len
; i
++) {
1324 g_array_index(new_process
->execution_stack
, LttvExecutionState
, i
) =
1325 g_array_index(process
->execution_stack
, LttvExecutionState
, i
);
1327 new_process
->state
= &g_array_index(new_process
->execution_stack
,
1328 LttvExecutionState
, new_process
->execution_stack
->len
- 1);
1329 new_process
->user_stack
= g_array_sized_new(FALSE
, FALSE
,
1330 sizeof(guint64
), 0);
1331 new_process
->user_stack
=
1332 g_array_set_size(new_process
->user_stack
,
1333 process
->user_stack
->len
);
1334 for(i
= 0 ; i
< process
->user_stack
->len
; i
++) {
1335 g_array_index(new_process
->user_stack
, guint64
, i
) =
1336 g_array_index(process
->user_stack
, guint64
, i
);
1338 new_process
->current_function
= process
->current_function
;
1340 /* fd hash table stuff */
1346 /* copy every item in the hash table */
1347 new_process
->fds
= g_hash_table_new(g_direct_hash
, g_direct_equal
);
1349 g_hash_table_iter_init(&it
, process
->fds
);
1350 while (g_hash_table_iter_next (&it
, (void *)&key
, (void *)&value
)) {
1351 g_hash_table_insert(new_process
->fds
, key
, value
);
1355 /* When done creating the new process state, insert it in the
1357 g_hash_table_insert(new_processes
, new_process
, new_process
);
1361 static GHashTable
*lttv_state_copy_process_table(GHashTable
*processes
)
1363 GHashTable
*new_processes
= g_hash_table_new(process_hash
, process_equal
);
1365 g_hash_table_foreach(processes
, copy_process_state
, new_processes
);
1366 return new_processes
;
1369 static LttvCPUState
*lttv_state_copy_cpu_states(LttvCPUState
*states
, guint n
)
1372 LttvCPUState
*retval
;
1374 retval
= g_new(LttvCPUState
, n
);
1376 for(i
=0; i
<n
; i
++) {
1377 retval
[i
].irq_stack
= g_array_new(FALSE
, FALSE
, sizeof(gint
));
1378 g_array_set_size(retval
[i
].irq_stack
, states
[i
].irq_stack
->len
);
1379 for(j
=0; j
<states
[i
].irq_stack
->len
; j
++) {
1380 g_array_index(retval
[i
].irq_stack
, gint
, j
) = g_array_index(states
[i
].irq_stack
, gint
, j
);
1383 retval
[i
].softirq_stack
= g_array_new(FALSE
, FALSE
, sizeof(gint
));
1384 g_array_set_size(retval
[i
].softirq_stack
, states
[i
].softirq_stack
->len
);
1385 for(j
=0; j
<states
[i
].softirq_stack
->len
; j
++) {
1386 g_array_index(retval
[i
].softirq_stack
, gint
, j
) = g_array_index(states
[i
].softirq_stack
, gint
, j
);
1389 retval
[i
].trap_stack
= g_array_new(FALSE
, FALSE
, sizeof(gint
));
1390 g_array_set_size(retval
[i
].trap_stack
, states
[i
].trap_stack
->len
);
1391 for(j
=0; j
<states
[i
].trap_stack
->len
; j
++) {
1392 g_array_index(retval
[i
].trap_stack
, gint
, j
) = g_array_index(states
[i
].trap_stack
, gint
, j
);
1395 retval
[i
].mode_stack
= g_array_new(FALSE
, FALSE
, sizeof(LttvCPUMode
));
1396 g_array_set_size(retval
[i
].mode_stack
, states
[i
].mode_stack
->len
);
1397 for(j
=0; j
<states
[i
].mode_stack
->len
; j
++) {
1398 g_array_index(retval
[i
].mode_stack
, GQuark
, j
) = g_array_index(states
[i
].mode_stack
, GQuark
, j
);
1405 static void lttv_state_free_cpu_states(LttvCPUState
*states
, guint n
)
1409 for(i
=0; i
<n
; i
++) {
1410 g_array_free(states
[i
].mode_stack
, TRUE
);
1411 g_array_free(states
[i
].irq_stack
, TRUE
);
1412 g_array_free(states
[i
].softirq_stack
, TRUE
);
1413 g_array_free(states
[i
].trap_stack
, TRUE
);
1419 static LttvIRQState
*lttv_state_copy_irq_states(LttvIRQState
*states
, guint n
)
1422 LttvIRQState
*retval
;
1424 retval
= g_new(LttvIRQState
, n
);
1426 for(i
=0; i
<n
; i
++) {
1427 retval
[i
].mode_stack
= g_array_new(FALSE
, FALSE
, sizeof(LttvIRQMode
));
1428 g_array_set_size(retval
[i
].mode_stack
, states
[i
].mode_stack
->len
);
1429 for(j
=0; j
<states
[i
].mode_stack
->len
; j
++) {
1430 g_array_index(retval
[i
].mode_stack
, GQuark
, j
) = g_array_index(states
[i
].mode_stack
, GQuark
, j
);
1437 static void lttv_state_free_irq_states(LttvIRQState
*states
, guint n
)
1441 for(i
=0; i
<n
; i
++) {
1442 g_array_free(states
[i
].mode_stack
, TRUE
);
1448 static LttvSoftIRQState
*lttv_state_copy_soft_irq_states(LttvSoftIRQState
*states
, guint n
)
1451 LttvSoftIRQState
*retval
;
1453 retval
= g_new(LttvSoftIRQState
, n
);
1455 for(i
=0; i
<n
; i
++) {
1456 retval
[i
].pending
= states
[i
].pending
;
1457 retval
[i
].running
= states
[i
].running
;
1463 static void lttv_state_free_soft_irq_states(LttvSoftIRQState
*states
, guint n
)
1468 static LttvTrapState
*lttv_state_copy_trap_states(LttvTrapState
*states
, guint n
)
1471 LttvTrapState
*retval
;
1473 retval
= g_new(LttvTrapState
, n
);
1475 for(i
=0; i
<n
; i
++) {
1476 retval
[i
].running
= states
[i
].running
;
1482 static void lttv_state_free_trap_states(LttvTrapState
*states
, guint n
)
1487 /* bdevstate stuff */
1489 static LttvBdevState
*get_hashed_bdevstate(LttvTraceState
*ts
, guint16 devcode
)
1491 gint devcode_gint
= devcode
;
1492 gpointer bdev
= g_hash_table_lookup(ts
->bdev_states
, &devcode_gint
);
1494 LttvBdevState
*bdevstate
= g_new(LttvBdevState
, 1);
1495 bdevstate
->mode_stack
= g_array_new(FALSE
, FALSE
, sizeof(GQuark
));
1497 gint
* key
= g_new(gint
, 1);
1499 g_hash_table_insert(ts
->bdev_states
, key
, bdevstate
);
1507 static LttvBdevState
*bdevstate_new(void)
1509 LttvBdevState
*retval
;
1510 retval
= g_new(LttvBdevState
, 1);
1511 retval
->mode_stack
= g_array_new(FALSE
, FALSE
, sizeof(GQuark
));
1516 static void bdevstate_free(LttvBdevState
*bds
)
1518 g_array_free(bds
->mode_stack
, TRUE
);
1522 static void bdevstate_free_cb(gpointer key
, gpointer value
, gpointer user_data
)
1524 LttvBdevState
*bds
= (LttvBdevState
*) value
;
1526 bdevstate_free(bds
);
1529 static LttvBdevState
*bdevstate_copy(LttvBdevState
*bds
)
1531 LttvBdevState
*retval
;
1533 retval
= bdevstate_new();
1534 g_array_insert_vals(retval
->mode_stack
, 0, bds
->mode_stack
->data
, bds
->mode_stack
->len
);
1539 static void insert_and_copy_bdev_state(gpointer k
, gpointer v
, gpointer u
)
1541 //GHashTable *ht = (GHashTable *)u;
1542 LttvBdevState
*bds
= (LttvBdevState
*)v
;
1543 LttvBdevState
*newbds
;
1545 newbds
= bdevstate_copy(bds
);
1547 g_hash_table_insert(u
, k
, newbds
);
1550 static GHashTable
*lttv_state_copy_blkdev_hashtable(GHashTable
*ht
)
1554 retval
= g_hash_table_new(g_int_hash
, g_int_equal
);
1556 g_hash_table_foreach(ht
, insert_and_copy_bdev_state
, retval
);
1561 /* Free a hashtable and the LttvBdevState structures its values
1564 static void lttv_state_free_blkdev_hashtable(GHashTable
*ht
)
1566 g_hash_table_foreach(ht
, bdevstate_free_cb
, NULL
);
1567 g_hash_table_destroy(ht
);
1570 /* The saved state for each trace contains a member "processes", which
1571 stores a copy of the process table, and a member "tracefiles" with
1572 one entry per tracefile. Each tracefile has a "process" member pointing
1573 to the current process and a "position" member storing the tracefile
1574 position (needed to seek to the current "next" event. */
1576 static void state_save(LttvTraceState
*self
, LttvAttribute
*container
)
1578 guint i
, nb_tracefile
, nb_cpus
, nb_irqs
, nb_soft_irqs
, nb_traps
;
1580 LttvTracefileState
*tfcs
;
1582 LttvAttribute
*tracefiles_tree
, *tracefile_tree
;
1584 guint
*running_process
;
1586 LttvAttributeValue value
;
1588 LttEventPosition
*ep
;
1590 tracefiles_tree
= lttv_attribute_find_subdir(container
,
1591 LTTV_STATE_TRACEFILES
);
1593 value
= lttv_attribute_add(container
, LTTV_STATE_PROCESSES
,
1595 *(value
.v_pointer
) = lttv_state_copy_process_table(self
->processes
);
1597 /* Add the currently running processes array */
1598 nb_cpus
= ltt_trace_get_num_cpu(self
->parent
.t
);
1599 running_process
= g_new(guint
, nb_cpus
);
1600 for(i
=0;i
<nb_cpus
;i
++) {
1601 running_process
[i
] = self
->running_process
[i
]->pid
;
1603 value
= lttv_attribute_add(container
, LTTV_STATE_RUNNING_PROCESS
,
1605 *(value
.v_pointer
) = running_process
;
1607 g_info("State save");
1609 nb_tracefile
= self
->parent
.tracefiles
->len
;
1611 for(i
= 0 ; i
< nb_tracefile
; i
++) {
1613 LTTV_TRACEFILE_STATE(g_array_index(self
->parent
.tracefiles
,
1614 LttvTracefileContext
*, i
));
1615 tracefile_tree
= g_object_new(LTTV_ATTRIBUTE_TYPE
, NULL
);
1616 value
= lttv_attribute_add(tracefiles_tree
, i
,
1618 *(value
.v_gobject
) = (GObject
*)tracefile_tree
;
1620 value
= lttv_attribute_add(tracefile_tree
, LTTV_STATE_PROCESS
,
1622 *(value
.v_uint
) = tfcs
->process
->pid
;
1624 value
= lttv_attribute_add(tracefile_tree
, LTTV_STATE_EVENT
,
1626 /* Only save the position if the tfs has not infinite time. */
1627 //if(!g_tree_lookup(self->parent.ts_context->pqueue, &tfcs->parent)
1628 // && current_tfcs != tfcs) {
1629 if(ltt_time_compare(tfcs
->parent
.timestamp
, ltt_time_infinite
) == 0) {
1630 *(value
.v_pointer
) = NULL
;
1632 LttEvent
*e
= ltt_tracefile_get_event(tfcs
->parent
.tf
);
1633 ep
= ltt_event_position_new();
1634 ltt_event_position(e
, ep
);
1635 *(value
.v_pointer
) = ep
;
1637 guint nb_block
, offset
;
1640 ltt_event_position_get(ep
, &tf
, &nb_block
, &offset
, &tsc
);
1641 g_info("Block %u offset %u tsc %" PRIu64
" time %lu.%lu", nb_block
, offset
,
1643 tfcs
->parent
.timestamp
.tv_sec
, tfcs
->parent
.timestamp
.tv_nsec
);
1647 /* save the cpu state */
1649 value
= lttv_attribute_add(container
, LTTV_STATE_RESOURCE_CPUS_COUNT
,
1651 *(value
.v_uint
) = nb_cpus
;
1653 value
= lttv_attribute_add(container
, LTTV_STATE_RESOURCE_CPUS
,
1655 *(value
.v_pointer
) = lttv_state_copy_cpu_states(self
->cpu_states
, nb_cpus
);
1658 /* save the irq state */
1659 nb_irqs
= self
->name_tables
->nb_irqs
;
1661 value
= lttv_attribute_add(container
, LTTV_STATE_RESOURCE_IRQS
,
1663 *(value
.v_pointer
) = lttv_state_copy_irq_states(self
->irq_states
, nb_irqs
);
1666 /* save the soft irq state */
1667 nb_soft_irqs
= self
->name_tables
->nb_soft_irqs
;
1669 value
= lttv_attribute_add(container
, LTTV_STATE_RESOURCE_SOFT_IRQS
,
1671 *(value
.v_pointer
) = lttv_state_copy_soft_irq_states(self
->soft_irq_states
, nb_soft_irqs
);
1674 /* save the trap state */
1675 nb_traps
= self
->name_tables
->nb_traps
;
1677 value
= lttv_attribute_add(container
, LTTV_STATE_RESOURCE_TRAPS
,
1679 *(value
.v_pointer
) = lttv_state_copy_trap_states(self
->trap_states
, nb_traps
);
1682 /* save the blkdev states */
1683 value
= lttv_attribute_add(container
, LTTV_STATE_RESOURCE_BLKDEVS
,
1685 *(value
.v_pointer
) = lttv_state_copy_blkdev_hashtable(self
->bdev_states
);
1689 static void state_restore(LttvTraceState
*self
, LttvAttribute
*container
)
1691 guint i
, nb_tracefile
, pid
, nb_cpus
, nb_irqs
, nb_soft_irqs
, nb_traps
;
1693 LttvTracefileState
*tfcs
;
1695 LttvAttribute
*tracefiles_tree
, *tracefile_tree
;
1697 guint
*running_process
;
1699 LttvAttributeType type
;
1701 LttvAttributeValue value
;
1703 LttvAttributeName name
;
1707 LttEventPosition
*ep
;
1709 LttvTracesetContext
*tsc
= self
->parent
.ts_context
;
1711 tracefiles_tree
= lttv_attribute_find_subdir(container
,
1712 LTTV_STATE_TRACEFILES
);
1714 type
= lttv_attribute_get_by_name(container
, LTTV_STATE_PROCESSES
,
1716 g_assert(type
== LTTV_POINTER
);
1717 lttv_state_free_process_table(self
->processes
);
1718 self
->processes
= lttv_state_copy_process_table(*(value
.v_pointer
));
1720 /* Add the currently running processes array */
1721 nb_cpus
= ltt_trace_get_num_cpu(self
->parent
.t
);
1722 type
= lttv_attribute_get_by_name(container
, LTTV_STATE_RUNNING_PROCESS
,
1724 g_assert(type
== LTTV_POINTER
);
1725 running_process
= *(value
.v_pointer
);
1726 for(i
=0;i
<nb_cpus
;i
++) {
1727 pid
= running_process
[i
];
1728 self
->running_process
[i
] = lttv_state_find_process(self
, i
, pid
);
1729 g_assert(self
->running_process
[i
] != NULL
);
1732 nb_tracefile
= self
->parent
.tracefiles
->len
;
1734 //g_tree_destroy(tsc->pqueue);
1735 //tsc->pqueue = g_tree_new(compare_tracefile);
1737 /* restore cpu resource states */
1738 type
= lttv_attribute_get_by_name(container
, LTTV_STATE_RESOURCE_CPUS
, &value
);
1739 g_assert(type
== LTTV_POINTER
);
1740 lttv_state_free_cpu_states(self
->cpu_states
, nb_cpus
);
1741 self
->cpu_states
= lttv_state_copy_cpu_states(*(value
.v_pointer
), nb_cpus
);
1743 /* restore irq resource states */
1744 nb_irqs
= self
->name_tables
->nb_irqs
;
1745 type
= lttv_attribute_get_by_name(container
, LTTV_STATE_RESOURCE_IRQS
, &value
);
1746 g_assert(type
== LTTV_POINTER
);
1747 lttv_state_free_irq_states(self
->irq_states
, nb_irqs
);
1748 self
->irq_states
= lttv_state_copy_irq_states(*(value
.v_pointer
), nb_irqs
);
1750 /* restore soft irq resource states */
1751 nb_soft_irqs
= self
->name_tables
->nb_soft_irqs
;
1752 type
= lttv_attribute_get_by_name(container
, LTTV_STATE_RESOURCE_SOFT_IRQS
, &value
);
1753 g_assert(type
== LTTV_POINTER
);
1754 lttv_state_free_soft_irq_states(self
->soft_irq_states
, nb_soft_irqs
);
1755 self
->soft_irq_states
= lttv_state_copy_soft_irq_states(*(value
.v_pointer
), nb_soft_irqs
);
1757 /* restore trap resource states */
1758 nb_traps
= self
->name_tables
->nb_traps
;
1759 type
= lttv_attribute_get_by_name(container
, LTTV_STATE_RESOURCE_TRAPS
, &value
);
1760 g_assert(type
== LTTV_POINTER
);
1761 lttv_state_free_trap_states(self
->trap_states
, nb_traps
);
1762 self
->trap_states
= lttv_state_copy_trap_states(*(value
.v_pointer
), nb_traps
);
1764 /* restore the blkdev states */
1765 type
= lttv_attribute_get_by_name(container
, LTTV_STATE_RESOURCE_BLKDEVS
, &value
);
1766 g_assert(type
== LTTV_POINTER
);
1767 lttv_state_free_blkdev_hashtable(self
->bdev_states
);
1768 self
->bdev_states
= lttv_state_copy_blkdev_hashtable(*(value
.v_pointer
));
1770 for(i
= 0 ; i
< nb_tracefile
; i
++) {
1772 LTTV_TRACEFILE_STATE(g_array_index(self
->parent
.tracefiles
,
1773 LttvTracefileContext
*, i
));
1774 type
= lttv_attribute_get(tracefiles_tree
, i
, &name
, &value
, &is_named
);
1775 g_assert(type
== LTTV_GOBJECT
);
1776 tracefile_tree
= *((LttvAttribute
**)(value
.v_gobject
));
1778 type
= lttv_attribute_get_by_name(tracefile_tree
, LTTV_STATE_PROCESS
,
1780 g_assert(type
== LTTV_UINT
);
1781 pid
= *(value
.v_uint
);
1782 tfcs
->process
= lttv_state_find_process_or_create(tfcs
, pid
);
1784 type
= lttv_attribute_get_by_name(tracefile_tree
, LTTV_STATE_EVENT
,
1786 g_assert(type
== LTTV_POINTER
);
1787 //g_assert(*(value.v_pointer) != NULL);
1788 ep
= *(value
.v_pointer
);
1789 g_assert(tfcs
->parent
.t_context
!= NULL
);
1791 tfcs
->cpu_state
= &self
->cpu_states
[tfcs
->cpu
];
1793 LttvTracefileContext
*tfc
= LTTV_TRACEFILE_CONTEXT(tfcs
);
1794 g_tree_remove(tsc
->pqueue
, tfc
);
1797 g_assert(ltt_tracefile_seek_position(tfc
->tf
, ep
) == 0);
1798 tfc
->timestamp
= ltt_event_time(ltt_tracefile_get_event(tfc
->tf
));
1799 g_assert(ltt_time_compare(tfc
->timestamp
, ltt_time_infinite
) != 0);
1800 g_tree_insert(tsc
->pqueue
, tfc
, tfc
);
1801 g_info("Restoring state for a tf at time %lu.%lu", tfc
->timestamp
.tv_sec
, tfc
->timestamp
.tv_nsec
);
1803 tfc
->timestamp
= ltt_time_infinite
;
1809 static void state_saved_free(LttvTraceState
*self
, LttvAttribute
*container
)
1811 guint i
, nb_tracefile
, nb_cpus
, nb_irqs
, nb_soft_irqs
;
1813 LttvTracefileState
*tfcs
;
1815 LttvAttribute
*tracefiles_tree
, *tracefile_tree
;
1817 guint
*running_process
;
1819 LttvAttributeType type
;
1821 LttvAttributeValue value
;
1823 LttvAttributeName name
;
1827 tracefiles_tree
= lttv_attribute_find_subdir(container
,
1828 LTTV_STATE_TRACEFILES
);
1829 g_object_ref(G_OBJECT(tracefiles_tree
));
1830 lttv_attribute_remove_by_name(container
, LTTV_STATE_TRACEFILES
);
1832 type
= lttv_attribute_get_by_name(container
, LTTV_STATE_PROCESSES
,
1834 g_assert(type
== LTTV_POINTER
);
1835 lttv_state_free_process_table(*(value
.v_pointer
));
1836 *(value
.v_pointer
) = NULL
;
1837 lttv_attribute_remove_by_name(container
, LTTV_STATE_PROCESSES
);
1839 /* Free running processes array */
1840 type
= lttv_attribute_get_by_name(container
, LTTV_STATE_RUNNING_PROCESS
,
1842 g_assert(type
== LTTV_POINTER
);
1843 running_process
= *(value
.v_pointer
);
1844 g_free(running_process
);
1846 /* free cpu resource states */
1847 type
= lttv_attribute_get_by_name(container
, LTTV_STATE_RESOURCE_CPUS_COUNT
, &value
);
1848 g_assert(type
== LTTV_UINT
);
1849 nb_cpus
= *value
.v_uint
;
1850 type
= lttv_attribute_get_by_name(container
, LTTV_STATE_RESOURCE_CPUS
, &value
);
1851 g_assert(type
== LTTV_POINTER
);
1852 lttv_state_free_cpu_states(*(value
.v_pointer
), nb_cpus
);
1854 /* free irq resource states */
1855 nb_irqs
= self
->name_tables
->nb_irqs
;
1856 type
= lttv_attribute_get_by_name(container
, LTTV_STATE_RESOURCE_IRQS
, &value
);
1857 g_assert(type
== LTTV_POINTER
);
1858 lttv_state_free_irq_states(*(value
.v_pointer
), nb_irqs
);
1860 /* free softirq resource states */
1861 nb_soft_irqs
= self
->name_tables
->nb_soft_irqs
;
1862 type
= lttv_attribute_get_by_name(container
, LTTV_STATE_RESOURCE_SOFT_IRQS
, &value
);
1863 g_assert(type
== LTTV_POINTER
);
1864 lttv_state_free_soft_irq_states(*(value
.v_pointer
), nb_soft_irqs
);
1866 /* free the blkdev states */
1867 type
= lttv_attribute_get_by_name(container
, LTTV_STATE_RESOURCE_BLKDEVS
, &value
);
1868 g_assert(type
== LTTV_POINTER
);
1869 lttv_state_free_blkdev_hashtable(*(value
.v_pointer
));
1871 nb_tracefile
= self
->parent
.tracefiles
->len
;
1873 for(i
= 0 ; i
< nb_tracefile
; i
++) {
1875 LTTV_TRACEFILE_STATE(g_array_index(self
->parent
.tracefiles
,
1876 LttvTracefileContext
*, i
));
1877 type
= lttv_attribute_get(tracefiles_tree
, i
, &name
, &value
, &is_named
);
1878 g_assert(type
== LTTV_GOBJECT
);
1879 tracefile_tree
= *((LttvAttribute
**)(value
.v_gobject
));
1881 type
= lttv_attribute_get_by_name(tracefile_tree
, LTTV_STATE_EVENT
,
1883 g_assert(type
== LTTV_POINTER
);
1884 if(*(value
.v_pointer
) != NULL
) g_free(*(value
.v_pointer
));
1886 g_object_unref(G_OBJECT(tracefiles_tree
));
1890 static void free_saved_state(LttvTraceState
*self
)
1894 LttvAttributeType type
;
1896 LttvAttributeValue value
;
1898 LttvAttributeName name
;
1902 LttvAttribute
*saved_states
;
1904 saved_states
= lttv_attribute_find_subdir(self
->parent
.t_a
,
1905 LTTV_STATE_SAVED_STATES
);
1907 nb
= lttv_attribute_get_number(saved_states
);
1908 for(i
= 0 ; i
< nb
; i
++) {
1909 type
= lttv_attribute_get(saved_states
, i
, &name
, &value
, &is_named
);
1910 g_assert(type
== LTTV_GOBJECT
);
1911 state_saved_free(self
, *((LttvAttribute
**)value
.v_gobject
));
1914 lttv_attribute_remove_by_name(self
->parent
.t_a
, LTTV_STATE_SAVED_STATES
);
1919 create_max_time(LttvTraceState
*tcs
)
1921 LttvAttributeValue v
;
1923 lttv_attribute_find(tcs
->parent
.t_a
, LTTV_STATE_SAVED_STATES_TIME
,
1925 g_assert(*(v
.v_pointer
) == NULL
);
1926 *(v
.v_pointer
) = g_new(LttTime
,1);
1927 *((LttTime
*)*(v
.v_pointer
)) = ltt_time_zero
;
1932 get_max_time(LttvTraceState
*tcs
)
1934 LttvAttributeValue v
;
1936 lttv_attribute_find(tcs
->parent
.t_a
, LTTV_STATE_SAVED_STATES_TIME
,
1938 g_assert(*(v
.v_pointer
) != NULL
);
1939 tcs
->max_time_state_recomputed_in_seek
= (LttTime
*)*(v
.v_pointer
);
1944 free_max_time(LttvTraceState
*tcs
)
1946 LttvAttributeValue v
;
1948 lttv_attribute_find(tcs
->parent
.t_a
, LTTV_STATE_SAVED_STATES_TIME
,
1950 g_free(*(v
.v_pointer
));
1951 *(v
.v_pointer
) = NULL
;
1955 create_name_tables(LttvTraceState
*tcs
)
1959 GString
*fe_name
= g_string_new("");
1961 LttvNameTables
*name_tables
= g_new(LttvNameTables
, 1);
1963 LttvAttributeValue v
;
1967 lttv_attribute_find(tcs
->parent
.t_a
, LTTV_STATE_NAME_TABLES
,
1969 g_assert(*(v
.v_pointer
) == NULL
);
1970 *(v
.v_pointer
) = name_tables
;
1972 hooks
= g_array_sized_new(FALSE
, FALSE
, sizeof(LttvTraceHook
), 1);
1974 if(!lttv_trace_find_hook(tcs
->parent
.t
,
1976 LTT_EVENT_SYSCALL_ENTRY
,
1977 FIELD_ARRAY(LTT_FIELD_SYSCALL_ID
),
1978 NULL
, NULL
, &hooks
)) {
1980 // th = lttv_trace_hook_get_first(&th);
1982 // t = ltt_field_type(lttv_trace_get_hook_field(th, 0));
1983 // nb = ltt_type_element_number(t);
1985 // name_tables->syscall_names = g_new(GQuark, nb);
1986 // name_tables->nb_syscalls = nb;
1988 // for(i = 0 ; i < nb ; i++) {
1989 // name_tables->syscall_names[i] = ltt_enum_string_get(t, i);
1990 // if(!name_tables->syscall_names[i]) {
1991 // GString *string = g_string_new("");
1992 // g_string_printf(string, "syscall %u", i);
1993 // name_tables->syscall_names[i] = g_quark_from_string(string->str);
1994 // g_string_free(string, TRUE);
1998 name_tables
->nb_syscalls
= 256;
1999 name_tables
->syscall_names
= g_new(GQuark
, 256);
2000 for(i
= 0 ; i
< 256 ; i
++) {
2001 g_string_printf(fe_name
, "syscall %d", i
);
2002 name_tables
->syscall_names
[i
] = g_quark_from_string(fe_name
->str
);
2005 name_tables
->syscall_names
= NULL
;
2006 name_tables
->nb_syscalls
= 0;
2008 lttv_trace_hook_remove_all(&hooks
);
2010 if(!lttv_trace_find_hook(tcs
->parent
.t
,
2012 LTT_EVENT_TRAP_ENTRY
,
2013 FIELD_ARRAY(LTT_FIELD_TRAP_ID
),
2014 NULL
, NULL
, &hooks
) ||
2015 !lttv_trace_find_hook(tcs
->parent
.t
,
2017 LTT_EVENT_PAGE_FAULT_ENTRY
,
2018 FIELD_ARRAY(LTT_FIELD_TRAP_ID
),
2019 NULL
, NULL
, &hooks
)) {
2021 // th = lttv_trace_hook_get_first(&th);
2023 // t = ltt_field_type(lttv_trace_get_hook_field(th, 0));
2024 // //nb = ltt_type_element_number(t);
2026 // name_tables->trap_names = g_new(GQuark, nb);
2027 // for(i = 0 ; i < nb ; i++) {
2028 // name_tables->trap_names[i] = g_quark_from_string(
2029 // ltt_enum_string_get(t, i));
2032 name_tables
->nb_traps
= 256;
2033 name_tables
->trap_names
= g_new(GQuark
, 256);
2034 for(i
= 0 ; i
< 256 ; i
++) {
2035 g_string_printf(fe_name
, "trap %d", i
);
2036 name_tables
->trap_names
[i
] = g_quark_from_string(fe_name
->str
);
2039 name_tables
->trap_names
= NULL
;
2040 name_tables
->nb_traps
= 0;
2042 lttv_trace_hook_remove_all(&hooks
);
2044 if(!lttv_trace_find_hook(tcs
->parent
.t
,
2046 LTT_EVENT_IRQ_ENTRY
,
2047 FIELD_ARRAY(LTT_FIELD_IRQ_ID
),
2048 NULL
, NULL
, &hooks
)) {
2051 name_tables->irq_names = g_new(GQuark, nb);
2052 for(i = 0 ; i < nb ; i++) {
2053 name_tables->irq_names[i] = g_quark_from_string(ltt_enum_string_get(t, i));
2057 name_tables
->nb_irqs
= 256;
2058 name_tables
->irq_names
= g_new(GQuark
, 256);
2059 for(i
= 0 ; i
< 256 ; i
++) {
2060 g_string_printf(fe_name
, "irq %d", i
);
2061 name_tables
->irq_names
[i
] = g_quark_from_string(fe_name
->str
);
2064 name_tables
->nb_irqs
= 0;
2065 name_tables
->irq_names
= NULL
;
2067 lttv_trace_hook_remove_all(&hooks
);
2069 name_tables->soft_irq_names = g_new(GQuark, nb);
2070 for(i = 0 ; i < nb ; i++) {
2071 name_tables->soft_irq_names[i] = g_quark_from_string(ltt_enum_string_get(t, i));
2075 /* the kernel is limited to 32 statically defined softirqs */
2076 name_tables
->nb_soft_irqs
= 32;
2077 name_tables
->soft_irq_names
= g_new(GQuark
, name_tables
->nb_soft_irqs
);
2078 for(i
= 0 ; i
< name_tables
->nb_soft_irqs
; i
++) {
2079 g_string_printf(fe_name
, "softirq %d", i
);
2080 name_tables
->soft_irq_names
[i
] = g_quark_from_string(fe_name
->str
);
2082 g_array_free(hooks
, TRUE
);
2084 g_string_free(fe_name
, TRUE
);
2086 #if (__SIZEOF_LONG__ == 4)
2087 name_tables
->kprobe_hash
= g_hash_table_new_full(guint64_hash
, guint64_equal
,
2090 name_tables
->kprobe_hash
= g_hash_table_new(g_direct_hash
, g_direct_equal
);
2096 get_name_tables(LttvTraceState
*tcs
)
2098 LttvAttributeValue v
;
2100 lttv_attribute_find(tcs
->parent
.t_a
, LTTV_STATE_NAME_TABLES
,
2102 g_assert(*(v
.v_pointer
) != NULL
);
2103 tcs
->name_tables
= (LttvNameTables
*)*(v
.v_pointer
);
2108 free_name_tables(LttvTraceState
*tcs
)
2110 LttvNameTables
*name_tables
;
2112 LttvAttributeValue v
;
2114 lttv_attribute_find(tcs
->parent
.t_a
, LTTV_STATE_NAME_TABLES
,
2116 name_tables
= (LttvNameTables
*)*(v
.v_pointer
);
2117 *(v
.v_pointer
) = NULL
;
2119 // g_free(name_tables->eventtype_names);
2120 if(name_tables
->syscall_names
) g_free(name_tables
->syscall_names
);
2121 if(name_tables
->trap_names
) g_free(name_tables
->trap_names
);
2122 if(name_tables
->irq_names
) g_free(name_tables
->irq_names
);
2123 if(name_tables
->soft_irq_names
) g_free(name_tables
->soft_irq_names
);
2124 g_hash_table_destroy(name_tables
->kprobe_hash
);
2125 g_free(name_tables
);
2128 #ifdef HASH_TABLE_DEBUG
2130 static void test_process(gpointer key
, gpointer value
, gpointer user_data
)
2132 LttvProcessState
*process
= (LttvProcessState
*)value
;
2134 /* Test for process corruption */
2135 guint stack_len
= process
->execution_stack
->len
;
2138 static void hash_table_check(GHashTable
*table
)
2140 g_hash_table_foreach(table
, test_process
, NULL
);
2146 /* clears the stack and sets the state passed as argument */
2147 static void cpu_set_base_mode(LttvCPUState
*cpust
, LttvCPUMode state
)
2149 g_array_set_size(cpust
->mode_stack
, 1);
2150 ((GQuark
*)cpust
->mode_stack
->data
)[0] = state
;
2153 static void cpu_push_mode(LttvCPUState
*cpust
, LttvCPUMode state
)
2155 g_array_set_size(cpust
->mode_stack
, cpust
->mode_stack
->len
+ 1);
2156 ((GQuark
*)cpust
->mode_stack
->data
)[cpust
->mode_stack
->len
- 1] = state
;
2159 static void cpu_pop_mode(LttvCPUState
*cpust
)
2161 if(cpust
->mode_stack
->len
<= 1)
2162 cpu_set_base_mode(cpust
, LTTV_CPU_UNKNOWN
);
2164 g_array_set_size(cpust
->mode_stack
, cpust
->mode_stack
->len
- 1);
2167 /* clears the stack and sets the state passed as argument */
2168 static void bdev_set_base_mode(LttvBdevState
*bdevst
, LttvBdevMode state
)
2170 g_array_set_size(bdevst
->mode_stack
, 1);
2171 ((GQuark
*)bdevst
->mode_stack
->data
)[0] = state
;
2174 static void bdev_push_mode(LttvBdevState
*bdevst
, LttvBdevMode state
)
2176 g_array_set_size(bdevst
->mode_stack
, bdevst
->mode_stack
->len
+ 1);
2177 ((GQuark
*)bdevst
->mode_stack
->data
)[bdevst
->mode_stack
->len
- 1] = state
;
2180 static void bdev_pop_mode(LttvBdevState
*bdevst
)
2182 if(bdevst
->mode_stack
->len
<= 1)
2183 bdev_set_base_mode(bdevst
, LTTV_BDEV_UNKNOWN
);
2185 g_array_set_size(bdevst
->mode_stack
, bdevst
->mode_stack
->len
- 1);
2188 static void irq_set_base_mode(LttvIRQState
*irqst
, LttvIRQMode state
)
2190 g_array_set_size(irqst
->mode_stack
, 1);
2191 ((GQuark
*)irqst
->mode_stack
->data
)[0] = state
;
2194 static void irq_push_mode(LttvIRQState
*irqst
, LttvIRQMode state
)
2196 g_array_set_size(irqst
->mode_stack
, irqst
->mode_stack
->len
+ 1);
2197 ((GQuark
*)irqst
->mode_stack
->data
)[irqst
->mode_stack
->len
- 1] = state
;
2200 static void irq_pop_mode(LttvIRQState
*irqst
)
2202 if(irqst
->mode_stack
->len
<= 1)
2203 irq_set_base_mode(irqst
, LTTV_IRQ_UNKNOWN
);
2205 g_array_set_size(irqst
->mode_stack
, irqst
->mode_stack
->len
- 1);
2208 static void push_state(LttvTracefileState
*tfs
, LttvExecutionMode t
,
2211 LttvExecutionState
*es
;
2213 LttvTraceState
*ts
= (LttvTraceState
*)tfs
->parent
.t_context
;
2214 guint cpu
= tfs
->cpu
;
2216 #ifdef HASH_TABLE_DEBUG
2217 hash_table_check(ts
->processes
);
2219 LttvProcessState
*process
= ts
->running_process
[cpu
];
2221 guint depth
= process
->execution_stack
->len
;
2223 process
->execution_stack
=
2224 g_array_set_size(process
->execution_stack
, depth
+ 1);
2227 &g_array_index(process
->execution_stack
, LttvExecutionState
, depth
- 1);
2229 es
= &g_array_index(process
->execution_stack
, LttvExecutionState
, depth
);
2232 es
->entry
= es
->change
= tfs
->parent
.timestamp
;
2233 es
->cum_cpu_time
= ltt_time_zero
;
2234 es
->s
= process
->state
->s
;
2235 process
->state
= es
;
2239 * return 1 when empty, else 0 */
2240 int lttv_state_pop_state_cleanup(LttvProcessState
*process
,
2241 LttvTracefileState
*tfs
)
2243 guint depth
= process
->execution_stack
->len
;
2249 process
->execution_stack
=
2250 g_array_set_size(process
->execution_stack
, depth
- 1);
2251 process
->state
= &g_array_index(process
->execution_stack
, LttvExecutionState
,
2253 process
->state
->change
= tfs
->parent
.timestamp
;
2258 static void pop_state(LttvTracefileState
*tfs
, LttvExecutionMode t
)
2260 guint cpu
= tfs
->cpu
;
2261 LttvTraceState
*ts
= (LttvTraceState
*)tfs
->parent
.t_context
;
2262 LttvProcessState
*process
= ts
->running_process
[cpu
];
2264 guint depth
= process
->execution_stack
->len
;
2266 if(process
->state
->t
!= t
){
2267 g_info("Different execution mode type (%lu.%09lu): ignore it\n",
2268 tfs
->parent
.timestamp
.tv_sec
, tfs
->parent
.timestamp
.tv_nsec
);
2269 g_info("process state has %s when pop_int is %s\n",
2270 g_quark_to_string(process
->state
->t
),
2271 g_quark_to_string(t
));
2272 g_info("{ %u, %u, %s, %s, %s }\n",
2275 g_quark_to_string(process
->name
),
2276 g_quark_to_string(process
->brand
),
2277 g_quark_to_string(process
->state
->s
));
2282 g_info("Trying to pop last state on stack (%lu.%09lu): ignore it\n",
2283 tfs
->parent
.timestamp
.tv_sec
, tfs
->parent
.timestamp
.tv_nsec
);
2287 process
->execution_stack
=
2288 g_array_set_size(process
->execution_stack
, depth
- 1);
2289 process
->state
= &g_array_index(process
->execution_stack
, LttvExecutionState
,
2291 process
->state
->change
= tfs
->parent
.timestamp
;
2294 struct search_result
{
2295 const LttTime
*time
; /* Requested time */
2296 LttTime
*best
; /* Best result */
2299 static gint
search_usertrace(gconstpointer a
, gconstpointer b
)
2301 const LttTime
*elem_time
= (const LttTime
*)a
;
2302 /* Explicit non const cast */
2303 struct search_result
*res
= (struct search_result
*)b
;
2305 if(ltt_time_compare(*elem_time
, *(res
->time
)) < 0) {
2306 /* The usertrace was created before the schedchange */
2307 /* Get larger keys */
2309 } else if(ltt_time_compare(*elem_time
, *(res
->time
)) >= 0) {
2310 /* The usertrace was created after the schedchange time */
2311 /* Get smaller keys */
2313 if(ltt_time_compare(*elem_time
, *res
->best
) < 0) {
2314 res
->best
= (LttTime
*)elem_time
;
2317 res
->best
= (LttTime
*)elem_time
;
2324 static LttvTracefileState
*ltt_state_usertrace_find(LttvTraceState
*tcs
,
2325 guint pid
, const LttTime
*timestamp
)
2327 LttvTracefileState
*tfs
= NULL
;
2328 struct search_result res
;
2329 /* Find the usertrace associated with a pid and time interval.
2330 * Search in the usertraces by PID (within a hash) and then, for each
2331 * corresponding element of the array, find the first one with creation
2332 * timestamp the lowest, but higher or equal to "timestamp". */
2333 res
.time
= timestamp
;
2335 GTree
*usertrace_tree
= g_hash_table_lookup(tcs
->usertraces
,
2336 GUINT_TO_POINTER(pid
));
2337 if(usertrace_tree
) {
2338 g_tree_search(usertrace_tree
, search_usertrace
, &res
);
2340 tfs
= g_tree_lookup(usertrace_tree
, res
.best
);
2346 /* Return a new and initialized LttvProcessState structure */
2349 lttv_state_create_process(LttvTraceState
*tcs
, LttvProcessState
*parent
,
2350 guint cpu
, guint pid
, guint tgid
, GQuark name
, const LttTime
*timestamp
)
2352 LttvProcessState
*process
= g_new(LttvProcessState
, 1);
2354 LttvExecutionState
*es
;
2359 process
->tgid
= tgid
;
2361 process
->name
= name
;
2362 process
->brand
= LTTV_STATE_UNBRANDED
;
2363 //process->last_cpu = tfs->cpu_name;
2364 //process->last_cpu_index = ltt_tracefile_num(((LttvTracefileContext*)tfs)->tf);
2365 process
->type
= LTTV_STATE_USER_THREAD
;
2366 process
->usertrace
= ltt_state_usertrace_find(tcs
, pid
, timestamp
);
2367 process
->current_function
= 0; //function 0x0 by default.
2369 g_info("Process %u, core %p", process
->pid
, process
);
2370 g_hash_table_insert(tcs
->processes
, process
, process
);
2373 process
->ppid
= parent
->pid
;
2374 process
->creation_time
= *timestamp
;
2377 /* No parent. This process exists but we are missing all information about
2378 its creation. The birth time is set to zero but we remember the time of
2383 process
->creation_time
= ltt_time_zero
;
2386 process
->insertion_time
= *timestamp
;
2387 sprintf(buffer
,"%d-%lu.%lu",pid
, process
->creation_time
.tv_sec
,
2388 process
->creation_time
.tv_nsec
);
2389 process
->pid_time
= g_quark_from_string(buffer
);
2391 process
->free_events
= 0;
2392 //process->last_cpu = tfs->cpu_name;
2393 //process->last_cpu_index = ltt_tracefile_num(((LttvTracefileContext*)tfs)->tf);
2394 process
->execution_stack
= g_array_sized_new(FALSE
, FALSE
,
2395 sizeof(LttvExecutionState
), PREALLOCATED_EXECUTION_STACK
);
2396 process
->execution_stack
= g_array_set_size(process
->execution_stack
, 2);
2397 es
= process
->state
= &g_array_index(process
->execution_stack
,
2398 LttvExecutionState
, 0);
2399 es
->t
= LTTV_STATE_USER_MODE
;
2400 es
->n
= LTTV_STATE_SUBMODE_NONE
;
2401 es
->entry
= *timestamp
;
2402 //g_assert(timestamp->tv_sec != 0);
2403 es
->change
= *timestamp
;
2404 es
->cum_cpu_time
= ltt_time_zero
;
2405 es
->s
= LTTV_STATE_RUN
;
2407 es
= process
->state
= &g_array_index(process
->execution_stack
,
2408 LttvExecutionState
, 1);
2409 es
->t
= LTTV_STATE_SYSCALL
;
2410 es
->n
= LTTV_STATE_SUBMODE_NONE
;
2411 es
->entry
= *timestamp
;
2412 //g_assert(timestamp->tv_sec != 0);
2413 es
->change
= *timestamp
;
2414 es
->cum_cpu_time
= ltt_time_zero
;
2415 es
->s
= LTTV_STATE_WAIT_FORK
;
2417 /* Allocate an empty function call stack. If it's empty, use 0x0. */
2418 process
->user_stack
= g_array_sized_new(FALSE
, FALSE
,
2419 sizeof(guint64
), 0);
2421 process
->fds
= g_hash_table_new(g_direct_hash
, g_direct_equal
);
2426 LttvProcessState
*lttv_state_find_process(LttvTraceState
*ts
, guint cpu
,
2429 LttvProcessState key
;
2430 LttvProcessState
*process
;
2434 process
= g_hash_table_lookup(ts
->processes
, &key
);
2439 lttv_state_find_process_or_create(LttvTraceState
*ts
, guint cpu
, guint pid
,
2440 const LttTime
*timestamp
)
2442 LttvProcessState
*process
= lttv_state_find_process(ts
, cpu
, pid
);
2443 LttvExecutionState
*es
;
2445 /* Put ltt_time_zero creation time for unexisting processes */
2446 if(unlikely(process
== NULL
)) {
2447 process
= lttv_state_create_process(ts
,
2448 NULL
, cpu
, pid
, 0, LTTV_STATE_UNNAMED
, timestamp
);
2449 /* We are not sure is it's a kernel thread or normal thread, put the
2450 * bottom stack state to unknown */
2451 process
->execution_stack
=
2452 g_array_set_size(process
->execution_stack
, 1);
2453 process
->state
= es
=
2454 &g_array_index(process
->execution_stack
, LttvExecutionState
, 0);
2455 es
->t
= LTTV_STATE_MODE_UNKNOWN
;
2456 es
->s
= LTTV_STATE_UNNAMED
;
2461 /* FIXME : this function should be called when we receive an event telling that
2462 * release_task has been called in the kernel. In happens generally when
2463 * the parent waits for its child termination, but may also happens in special
2464 * cases in the child's exit : when the parent ignores its children SIGCCHLD or
2465 * has the flag SA_NOCLDWAIT. It can also happen when the child is part
2466 * of a killed thread group, but isn't the leader.
2468 static int exit_process(LttvTracefileState
*tfs
, LttvProcessState
*process
)
2470 LttvTraceState
*ts
= LTTV_TRACE_STATE(tfs
->parent
.t_context
);
2471 LttvProcessState key
;
2473 /* Wait for both schedule with exit dead and process free to happen.
2474 * They can happen in any order. */
2475 if (++(process
->free_events
) < 2)
2478 key
.pid
= process
->pid
;
2479 key
.cpu
= process
->cpu
;
2480 g_hash_table_remove(ts
->processes
, &key
);
2481 g_array_free(process
->execution_stack
, TRUE
);
2482 g_array_free(process
->user_stack
, TRUE
);
2484 /* the following also clears the content */
2485 g_hash_table_destroy(process
->fds
);
2492 static void free_process_state(gpointer key
, gpointer value
,gpointer user_data
)
2494 g_array_free(((LttvProcessState
*)value
)->execution_stack
, TRUE
);
2495 g_array_free(((LttvProcessState
*)value
)->user_stack
, TRUE
);
2497 /* the following also clears the content */
2498 g_hash_table_destroy(((LttvProcessState
*)value
)->fds
);
2504 static void lttv_state_free_process_table(GHashTable
*processes
)
2506 g_hash_table_foreach(processes
, free_process_state
, NULL
);
2507 g_hash_table_destroy(processes
);
2511 static gboolean
syscall_entry(void *hook_data
, void *call_data
)
2513 LttvTracefileState
*s
= (LttvTracefileState
*)call_data
;
2515 LttvTraceState
*ts
= (LttvTraceState
*)s
->parent
.t_context
;
2516 LttvProcessState
*process
= ts
->running_process
[cpu
];
2517 LttEvent
*e
= ltt_tracefile_get_event(s
->parent
.tf
);
2518 LttvTraceHook
*th
= (LttvTraceHook
*)hook_data
;
2519 struct marker_field
*f
= lttv_trace_get_hook_field(th
, 0);
2520 LttvExecutionSubmode submode
;
2521 LttvNameTables
*nt
= ((LttvTraceState
*)(s
->parent
.t_context
))->name_tables
;
2523 guint syscall
= ltt_event_get_unsigned(e
, f
);
2524 expand_syscall_table(ts
, syscall
);
2525 submode
= nt
->syscall_names
[syscall
];
2526 /* There can be no system call from PID 0 : unknown state */
2527 if(process
->pid
!= 0)
2528 push_state(s
, LTTV_STATE_SYSCALL
, submode
);
2533 static gboolean
syscall_exit(void *hook_data
, void *call_data
)
2535 LttvTracefileState
*s
= (LttvTracefileState
*)call_data
;
2537 LttvTraceState
*ts
= (LttvTraceState
*)s
->parent
.t_context
;
2538 LttvProcessState
*process
= ts
->running_process
[cpu
];
2540 /* There can be no system call from PID 0 : unknown state */
2541 if(process
->pid
!= 0)
2542 pop_state(s
, LTTV_STATE_SYSCALL
);
2547 static gboolean
trap_entry(void *hook_data
, void *call_data
)
2549 LttvTracefileState
*s
= (LttvTracefileState
*)call_data
;
2550 LttvTraceState
*ts
= (LttvTraceState
*)s
->parent
.t_context
;
2551 LttEvent
*e
= ltt_tracefile_get_event(s
->parent
.tf
);
2552 LttvTraceHook
*th
= (LttvTraceHook
*)hook_data
;
2553 struct marker_field
*f
= lttv_trace_get_hook_field(th
, 0);
2554 LttvNameTables
*nt
= ((LttvTraceState
*)(s
->parent
.t_context
))->name_tables
;
2556 LttvExecutionSubmode submode
;
2558 guint64 trap
= ltt_event_get_long_unsigned(e
, f
);
2560 expand_trap_table(ts
, trap
);
2562 submode
= nt
->trap_names
[trap
];
2564 push_state(s
, LTTV_STATE_TRAP
, submode
);
2566 /* update cpu status */
2567 cpu_push_mode(s
->cpu_state
, LTTV_CPU_TRAP
);
2569 /* update trap status */
2570 g_array_append_val(s
->cpu_state
->trap_stack
, trap
);
2571 ts
->trap_states
[trap
].running
++;
2576 static gboolean
trap_exit(void *hook_data
, void *call_data
)
2578 LttvTracefileState
*s
= (LttvTracefileState
*)call_data
;
2579 LttvTraceState
*ts
= (LttvTraceState
*)s
->parent
.t_context
;
2581 pop_state(s
, LTTV_STATE_TRAP
);
2583 /* update cpu status */
2584 cpu_pop_mode(s
->cpu_state
);
2586 /* update trap status */
2587 if (s
->cpu_state
->trap_stack
->len
> 0) {
2588 gint last
= g_array_index(s
->cpu_state
->trap_stack
, gint
, s
->cpu_state
->trap_stack
->len
-1);
2589 if(ts
->trap_states
[last
].running
)
2590 ts
->trap_states
[last
].running
--;
2591 g_array_remove_index(s
->cpu_state
->trap_stack
, s
->cpu_state
->trap_stack
->len
-1);
2596 static gboolean
irq_entry(void *hook_data
, void *call_data
)
2598 LttvTracefileState
*s
= (LttvTracefileState
*)call_data
;
2599 LttvTraceState
*ts
= (LttvTraceState
*)s
->parent
.t_context
;
2600 LttEvent
*e
= ltt_tracefile_get_event(s
->parent
.tf
);
2601 //guint8 ev_id = ltt_event_eventtype_id(e);
2602 LttvTraceHook
*th
= (LttvTraceHook
*)hook_data
;
2603 struct marker_field
*f
= lttv_trace_get_hook_field(th
, 0);
2604 LttvNameTables
*nt
= ((LttvTraceState
*)(s
->parent
.t_context
))->name_tables
;
2606 LttvExecutionSubmode submode
;
2607 guint64 irq
= ltt_event_get_long_unsigned(e
, f
);
2609 expand_irq_table(ts
, irq
);
2611 submode
= nt
->irq_names
[irq
];
2613 /* Do something with the info about being in user or system mode when int? */
2614 push_state(s
, LTTV_STATE_IRQ
, submode
);
2616 /* update cpu status */
2617 cpu_push_mode(s
->cpu_state
, LTTV_CPU_IRQ
);
2619 /* update irq status */
2620 g_array_append_val(s
->cpu_state
->irq_stack
, irq
);
2621 irq_push_mode(&ts
->irq_states
[irq
], LTTV_IRQ_BUSY
);
2626 static gboolean
soft_irq_exit(void *hook_data
, void *call_data
)
2628 LttvTracefileState
*s
= (LttvTracefileState
*)call_data
;
2629 LttvTraceState
*ts
= (LttvTraceState
*)s
->parent
.t_context
;
2631 pop_state(s
, LTTV_STATE_SOFT_IRQ
);
2633 /* update cpu status */
2634 cpu_pop_mode(s
->cpu_state
);
2636 /* update softirq status */
2637 if (s
->cpu_state
->softirq_stack
->len
> 0) {
2638 gint last
= g_array_index(s
->cpu_state
->softirq_stack
, gint
, s
->cpu_state
->softirq_stack
->len
-1);
2639 if(ts
->soft_irq_states
[last
].running
)
2640 ts
->soft_irq_states
[last
].running
--;
2641 g_array_remove_index(s
->cpu_state
->softirq_stack
, s
->cpu_state
->softirq_stack
->len
-1);
2646 static gboolean
irq_exit(void *hook_data
, void *call_data
)
2648 LttvTracefileState
*s
= (LttvTracefileState
*)call_data
;
2649 LttvTraceState
*ts
= (LttvTraceState
*)s
->parent
.t_context
;
2651 pop_state(s
, LTTV_STATE_IRQ
);
2653 /* update cpu status */
2654 cpu_pop_mode(s
->cpu_state
);
2656 /* update irq status */
2657 if (s
->cpu_state
->irq_stack
->len
> 0) {
2658 gint last
= g_array_index(s
->cpu_state
->irq_stack
, gint
, s
->cpu_state
->irq_stack
->len
-1);
2659 g_array_remove_index(s
->cpu_state
->irq_stack
, s
->cpu_state
->irq_stack
->len
-1);
2660 irq_pop_mode(&ts
->irq_states
[last
]);
2666 static gboolean
soft_irq_raise(void *hook_data
, void *call_data
)
2668 LttvTracefileState
*s
= (LttvTracefileState
*)call_data
;
2669 LttvTraceState
*ts
= (LttvTraceState
*)s
->parent
.t_context
;
2670 LttEvent
*e
= ltt_tracefile_get_event(s
->parent
.tf
);
2671 //guint8 ev_id = ltt_event_eventtype_id(e);
2672 LttvTraceHook
*th
= (LttvTraceHook
*)hook_data
;
2673 struct marker_field
*f
= lttv_trace_get_hook_field(th
, 0);
2674 LttvNameTables
*nt
= ((LttvTraceState
*)(s
->parent
.t_context
))->name_tables
;
2676 LttvExecutionSubmode submode
;
2677 guint64 softirq
= ltt_event_get_long_unsigned(e
, f
);
2678 guint64 nb_softirqs
= nt
->nb_soft_irqs
;
2680 if(softirq
< nb_softirqs
) {
2681 submode
= nt
->soft_irq_names
[softirq
];
2683 /* Fixup an incomplete irq table */
2684 GString
*string
= g_string_new("");
2685 g_string_printf(string
, "softirq %" PRIu64
, softirq
);
2686 submode
= g_quark_from_string(string
->str
);
2687 g_string_free(string
, TRUE
);
2690 /* update softirq status */
2691 /* a soft irq raises are not cumulative */
2692 ts
->soft_irq_states
[softirq
].pending
=1;
2697 static gboolean
soft_irq_entry(void *hook_data
, void *call_data
)
2699 LttvTracefileState
*s
= (LttvTracefileState
*)call_data
;
2700 LttvTraceState
*ts
= (LttvTraceState
*)s
->parent
.t_context
;
2701 LttEvent
*e
= ltt_tracefile_get_event(s
->parent
.tf
);
2702 //guint8 ev_id = ltt_event_eventtype_id(e);
2703 LttvTraceHook
*th
= (LttvTraceHook
*)hook_data
;
2704 struct marker_field
*f
= lttv_trace_get_hook_field(th
, 0);
2705 LttvExecutionSubmode submode
;
2706 guint64 softirq
= ltt_event_get_long_unsigned(e
, f
);
2707 expand_soft_irq_table(ts
, softirq
);
2708 LttvNameTables
*nt
= ((LttvTraceState
*)(s
->parent
.t_context
))->name_tables
;
2709 submode
= nt
->soft_irq_names
[softirq
];
2711 /* Do something with the info about being in user or system mode when int? */
2712 push_state(s
, LTTV_STATE_SOFT_IRQ
, submode
);
2714 /* update cpu status */
2715 cpu_push_mode(s
->cpu_state
, LTTV_CPU_SOFT_IRQ
);
2717 /* update softirq status */
2718 g_array_append_val(s
->cpu_state
->softirq_stack
, softirq
);
2719 if(ts
->soft_irq_states
[softirq
].pending
)
2720 ts
->soft_irq_states
[softirq
].pending
--;
2721 ts
->soft_irq_states
[softirq
].running
++;
2726 static gboolean
enum_interrupt(void *hook_data
, void *call_data
)
2728 LttvTracefileState
*s
= (LttvTracefileState
*)call_data
;
2729 LttvTraceState
*ts
= (LttvTraceState
*)s
->parent
.t_context
;
2730 LttvNameTables
*nt
= ts
->name_tables
;
2731 LttEvent
*e
= ltt_tracefile_get_event(s
->parent
.tf
);
2732 //guint8 ev_id = ltt_event_eventtype_id(e);
2733 LttvTraceHook
*th
= (LttvTraceHook
*)hook_data
;
2735 GQuark action
= g_quark_from_string(ltt_event_get_string(e
,
2736 lttv_trace_get_hook_field(th
, 0)));
2737 guint irq
= ltt_event_get_long_unsigned(e
, lttv_trace_get_hook_field(th
, 1));
2739 expand_irq_table(ts
, irq
);
2740 nt
->irq_names
[irq
] = action
;
2746 static gboolean
bdev_request_issue(void *hook_data
, void *call_data
)
2748 LttvTracefileState
*s
= (LttvTracefileState
*)call_data
;
2749 LttvTraceState
*ts
= (LttvTraceState
*)s
->parent
.t_context
;
2750 LttEvent
*e
= ltt_tracefile_get_event(s
->parent
.tf
);
2751 //guint8 ev_id = ltt_event_eventtype_id(e);
2752 LttvTraceHook
*th
= (LttvTraceHook
*)hook_data
;
2754 guint major
= ltt_event_get_long_unsigned(e
,
2755 lttv_trace_get_hook_field(th
, 0));
2756 guint minor
= ltt_event_get_long_unsigned(e
,
2757 lttv_trace_get_hook_field(th
, 1));
2758 guint oper
= ltt_event_get_long_unsigned(e
,
2759 lttv_trace_get_hook_field(th
, 2));
2760 guint16 devcode
= MKDEV(major
,minor
);
2762 /* have we seen this block device before? */
2763 gpointer bdev
= get_hashed_bdevstate(ts
, devcode
);
2766 bdev_push_mode(bdev
, LTTV_BDEV_BUSY_READING
);
2768 bdev_push_mode(bdev
, LTTV_BDEV_BUSY_WRITING
);
2773 static gboolean
bdev_request_complete(void *hook_data
, void *call_data
)
2775 LttvTracefileState
*s
= (LttvTracefileState
*)call_data
;
2776 LttvTraceState
*ts
= (LttvTraceState
*)s
->parent
.t_context
;
2777 LttEvent
*e
= ltt_tracefile_get_event(s
->parent
.tf
);
2778 LttvTraceHook
*th
= (LttvTraceHook
*)hook_data
;
2780 guint major
= ltt_event_get_long_unsigned(e
,
2781 lttv_trace_get_hook_field(th
, 0));
2782 guint minor
= ltt_event_get_long_unsigned(e
,
2783 lttv_trace_get_hook_field(th
, 1));
2784 //guint oper = ltt_event_get_long_unsigned(e,
2785 // lttv_trace_get_hook_field(th, 2));
2786 guint16 devcode
= MKDEV(major
,minor
);
2788 /* have we seen this block device before? */
2789 gpointer bdev
= get_hashed_bdevstate(ts
, devcode
);
2791 /* update block device */
2792 bdev_pop_mode(bdev
);
2797 static void push_function(LttvTracefileState
*tfs
, guint64 funcptr
)
2801 LttvTraceState
*ts
= (LttvTraceState
*)tfs
->parent
.t_context
;
2802 guint cpu
= tfs
->cpu
;
2803 LttvProcessState
*process
= ts
->running_process
[cpu
];
2805 guint depth
= process
->user_stack
->len
;
2807 process
->user_stack
=
2808 g_array_set_size(process
->user_stack
, depth
+ 1);
2810 new_func
= &g_array_index(process
->user_stack
, guint64
, depth
);
2811 *new_func
= funcptr
;
2812 process
->current_function
= funcptr
;
2815 static void pop_function(LttvTracefileState
*tfs
, guint64 funcptr
)
2817 guint cpu
= tfs
->cpu
;
2818 LttvTraceState
*ts
= (LttvTraceState
*)tfs
->parent
.t_context
;
2819 LttvProcessState
*process
= ts
->running_process
[cpu
];
2821 if(process
->current_function
!= funcptr
){
2822 g_info("Different functions (%lu.%09lu): ignore it\n",
2823 tfs
->parent
.timestamp
.tv_sec
, tfs
->parent
.timestamp
.tv_nsec
);
2824 g_info("process state has %" PRIu64
" when pop_function is %" PRIu64
"\n",
2825 process
->current_function
, funcptr
);
2826 g_info("{ %u, %u, %s, %s, %s }\n",
2829 g_quark_to_string(process
->name
),
2830 g_quark_to_string(process
->brand
),
2831 g_quark_to_string(process
->state
->s
));
2834 guint depth
= process
->user_stack
->len
;
2837 g_info("Trying to pop last function on stack (%lu.%09lu): ignore it\n",
2838 tfs
->parent
.timestamp
.tv_sec
, tfs
->parent
.timestamp
.tv_nsec
);
2842 process
->user_stack
=
2843 g_array_set_size(process
->user_stack
, depth
- 1);
2844 process
->current_function
=
2845 g_array_index(process
->user_stack
, guint64
, depth
- 2);
2849 static gboolean
function_entry(void *hook_data
, void *call_data
)
2851 LttvTracefileState
*s
= (LttvTracefileState
*)call_data
;
2852 LttEvent
*e
= ltt_tracefile_get_event(s
->parent
.tf
);
2853 //guint8 ev_id = ltt_event_eventtype_id(e);
2854 LttvTraceHook
*th
= (LttvTraceHook
*)hook_data
;
2855 struct marker_field
*f
= lttv_trace_get_hook_field(th
, 0);
2856 guint64 funcptr
= ltt_event_get_long_unsigned(e
, f
);
2858 push_function(s
, funcptr
);
2862 static gboolean
function_exit(void *hook_data
, void *call_data
)
2864 LttvTracefileState
*s
= (LttvTracefileState
*)call_data
;
2865 LttEvent
*e
= ltt_tracefile_get_event(s
->parent
.tf
);
2866 //guint8 ev_id = ltt_event_eventtype_id(e);
2867 LttvTraceHook
*th
= (LttvTraceHook
*)hook_data
;
2868 struct marker_field
*f
= lttv_trace_get_hook_field(th
, 0);
2869 guint64 funcptr
= ltt_event_get_long_unsigned(e
, f
);
2871 pop_function(s
, funcptr
);
2875 static gboolean
dump_syscall(void *hook_data
, void *call_data
)
2877 LttvTracefileState
*s
= (LttvTracefileState
*)call_data
;
2878 LttvTraceState
*ts
= (LttvTraceState
*)s
->parent
.t_context
;
2879 LttvNameTables
*nt
= ts
->name_tables
;
2880 LttEvent
*e
= ltt_tracefile_get_event(s
->parent
.tf
);
2881 LttvTraceHook
*th
= (LttvTraceHook
*)hook_data
;
2886 id
= ltt_event_get_unsigned(e
, lttv_trace_get_hook_field(th
, 0));
2887 address
= ltt_event_get_long_unsigned(e
, lttv_trace_get_hook_field(th
, 1));
2888 symbol
= ltt_event_get_string(e
, lttv_trace_get_hook_field(th
, 2));
2890 expand_syscall_table(ts
, id
);
2891 nt
->syscall_names
[id
] = g_quark_from_string(symbol
);
2896 static gboolean
dump_kprobe(void *hook_data
, void *call_data
)
2898 LttvTracefileState
*s
= (LttvTracefileState
*)call_data
;
2899 LttvTraceState
*ts
= (LttvTraceState
*)s
->parent
.t_context
;
2900 LttEvent
*e
= ltt_tracefile_get_event(s
->parent
.tf
);
2901 LttvTraceHook
*th
= (LttvTraceHook
*)hook_data
;
2905 ip
= ltt_event_get_long_unsigned(e
, lttv_trace_get_hook_field(th
, 0));
2906 symbol
= ltt_event_get_string(e
, lttv_trace_get_hook_field(th
, 1));
2908 expand_kprobe_table(ts
, ip
, symbol
);
2913 static gboolean
dump_softirq(void *hook_data
, void *call_data
)
2915 LttvTracefileState
*s
= (LttvTracefileState
*)call_data
;
2916 LttvTraceState
*ts
= (LttvTraceState
*)s
->parent
.t_context
;
2917 LttvNameTables
*nt
= ts
->name_tables
;
2918 LttEvent
*e
= ltt_tracefile_get_event(s
->parent
.tf
);
2919 LttvTraceHook
*th
= (LttvTraceHook
*)hook_data
;
2924 id
= ltt_event_get_unsigned(e
, lttv_trace_get_hook_field(th
, 0));
2925 address
= ltt_event_get_long_unsigned(e
, lttv_trace_get_hook_field(th
, 1));
2926 symbol
= ltt_event_get_string(e
, lttv_trace_get_hook_field(th
, 2));
2928 expand_soft_irq_table(ts
, id
);
2929 nt
->soft_irq_names
[id
] = g_quark_from_string(symbol
);
2934 static gboolean
schedchange(void *hook_data
, void *call_data
)
2936 LttvTracefileState
*s
= (LttvTracefileState
*)call_data
;
2938 LttvTraceState
*ts
= (LttvTraceState
*)s
->parent
.t_context
;
2939 LttvProcessState
*process
= ts
->running_process
[cpu
];
2940 //LttvProcessState *old_process = ts->running_process[cpu];
2942 LttEvent
*e
= ltt_tracefile_get_event(s
->parent
.tf
);
2943 LttvTraceHook
*th
= (LttvTraceHook
*)hook_data
;
2944 guint pid_in
, pid_out
;
2947 pid_out
= ltt_event_get_unsigned(e
, lttv_trace_get_hook_field(th
, 0));
2948 pid_in
= ltt_event_get_unsigned(e
, lttv_trace_get_hook_field(th
, 1));
2949 state_out
= ltt_event_get_long_int(e
, lttv_trace_get_hook_field(th
, 2));
2951 if(likely(process
!= NULL
)) {
2953 /* We could not know but it was not the idle process executing.
2954 This should only happen at the beginning, before the first schedule
2955 event, and when the initial information (current process for each CPU)
2956 is missing. It is not obvious how we could, after the fact, compensate
2957 the wrongly attributed statistics. */
2959 //This test only makes sense once the state is known and if there is no
2960 //missing events. We need to silently ignore schedchange coming after a
2961 //process_free, or it causes glitches. (FIXME)
2962 //if(unlikely(process->pid != pid_out)) {
2963 // g_assert(process->pid == 0);
2965 if(process
->pid
== 0
2966 && process
->state
->t
== LTTV_STATE_MODE_UNKNOWN
) {
2968 /* Scheduling out of pid 0 at beginning of the trace :
2969 * we know for sure it is in syscall mode at this point. */
2970 g_assert(process
->execution_stack
->len
== 1);
2971 process
->state
->t
= LTTV_STATE_SYSCALL
;
2972 process
->state
->s
= LTTV_STATE_WAIT
;
2973 process
->state
->change
= s
->parent
.timestamp
;
2974 process
->state
->entry
= s
->parent
.timestamp
;
2977 if(unlikely(process
->state
->s
== LTTV_STATE_EXIT
)) {
2978 process
->state
->s
= LTTV_STATE_ZOMBIE
;
2979 process
->state
->change
= s
->parent
.timestamp
;
2981 if(unlikely(state_out
== 0)) process
->state
->s
= LTTV_STATE_WAIT_CPU
;
2982 else process
->state
->s
= LTTV_STATE_WAIT
;
2983 process
->state
->change
= s
->parent
.timestamp
;
2986 if(state_out
== 32 || state_out
== 64) { /* EXIT_DEAD || TASK_DEAD */
2987 /* see sched.h for states */
2988 if (!exit_process(s
, process
)) {
2989 process
->state
->s
= LTTV_STATE_DEAD
;
2990 process
->state
->change
= s
->parent
.timestamp
;
2995 process
= ts
->running_process
[cpu
] =
2996 lttv_state_find_process_or_create(
2997 (LttvTraceState
*)s
->parent
.t_context
,
2999 &s
->parent
.timestamp
);
3000 process
->state
->s
= LTTV_STATE_RUN
;
3002 if(process
->usertrace
)
3003 process
->usertrace
->cpu
= cpu
;
3004 // process->last_cpu_index = ltt_tracefile_num(((LttvTracefileContext*)s)->tf);
3005 process
->state
->change
= s
->parent
.timestamp
;
3007 /* update cpu status */
3009 /* going to idle task */
3010 cpu_set_base_mode(s
->cpu_state
, LTTV_CPU_IDLE
);
3012 /* scheduling a real task.
3013 * we must be careful here:
3014 * if we just schedule()'ed to a process that is
3015 * in a trap, we must put the cpu in trap mode
3017 cpu_set_base_mode(s
->cpu_state
, LTTV_CPU_BUSY
);
3018 if(process
->state
->t
== LTTV_STATE_TRAP
)
3019 cpu_push_mode(s
->cpu_state
, LTTV_CPU_TRAP
);
3025 static gboolean
process_fork(void *hook_data
, void *call_data
)
3027 LttvTracefileState
*s
= (LttvTracefileState
*)call_data
;
3028 LttEvent
*e
= ltt_tracefile_get_event(s
->parent
.tf
);
3029 LttvTraceHook
*th
= (LttvTraceHook
*)hook_data
;
3031 guint child_pid
; /* In the Linux Kernel, there is one PID per thread. */
3032 guint child_tgid
; /* tgid in the Linux kernel is the "real" POSIX PID. */
3033 //LttvProcessState *zombie_process;
3035 LttvTraceState
*ts
= (LttvTraceState
*)s
->parent
.t_context
;
3036 LttvProcessState
*process
= ts
->running_process
[cpu
];
3037 LttvProcessState
*child_process
;
3038 struct marker_field
*f
;
3041 parent_pid
= ltt_event_get_unsigned(e
, lttv_trace_get_hook_field(th
, 0));
3044 child_pid
= ltt_event_get_unsigned(e
, lttv_trace_get_hook_field(th
, 1));
3045 s
->parent
.target_pid
= child_pid
;
3048 f
= lttv_trace_get_hook_field(th
, 2);
3050 child_tgid
= ltt_event_get_unsigned(e
, f
);
3054 /* Mathieu : it seems like the process might have been scheduled in before the
3055 * fork, and, in a rare case, might be the current process. This might happen
3056 * in a SMP case where we don't have enough precision on the clocks.
3058 * Test reenabled after precision fixes on time. (Mathieu) */
3060 zombie_process
= lttv_state_find_process(ts
, ANY_CPU
, child_pid
);
3062 if(unlikely(zombie_process
!= NULL
)) {
3063 /* Reutilisation of PID. Only now we are sure that the old PID
3064 * has been released. FIXME : should know when release_task happens instead.
3066 guint num_cpus
= ltt_trace_get_num_cpu(ts
->parent
.t
);
3068 for(i
=0; i
< num_cpus
; i
++) {
3069 g_assert(zombie_process
!= ts
->running_process
[i
]);
3072 exit_process(s
, zombie_process
);
3075 g_assert(process
->pid
!= child_pid
);
3076 // FIXME : Add this test in the "known state" section
3077 // g_assert(process->pid == parent_pid);
3078 child_process
= lttv_state_find_process(ts
, ANY_CPU
, child_pid
);
3079 if(child_process
== NULL
) {
3080 child_process
= lttv_state_create_process(ts
, process
, cpu
,
3081 child_pid
, child_tgid
,
3082 LTTV_STATE_UNNAMED
, &s
->parent
.timestamp
);
3084 /* The process has already been created : due to time imprecision between
3085 * multiple CPUs : it has been scheduled in before creation. Note that we
3086 * shouldn't have this kind of imprecision.
3088 * Simply put a correct parent.
3090 g_error("Process %u has been created at [%lu.%09lu] "
3091 "and inserted at [%lu.%09lu] before \n"
3092 "fork on cpu %u[%lu.%09lu].\n"
3093 "Probably an unsynchronized TSC problem on the traced machine.",
3095 child_process
->creation_time
.tv_sec
,
3096 child_process
->creation_time
.tv_nsec
,
3097 child_process
->insertion_time
.tv_sec
,
3098 child_process
->insertion_time
.tv_nsec
,
3099 cpu
, ltt_event_time(e
).tv_sec
, ltt_event_time(e
).tv_nsec
);
3100 //g_assert(0); /* This is a problematic case : the process has been created
3101 // before the fork event */
3102 child_process
->ppid
= process
->pid
;
3103 child_process
->tgid
= child_tgid
;
3105 g_assert(child_process
->name
== LTTV_STATE_UNNAMED
);
3106 child_process
->name
= process
->name
;
3107 child_process
->brand
= process
->brand
;
3112 /* We stamp a newly created process as kernel_thread.
3113 * The thread should not be running yet. */
3114 static gboolean
process_kernel_thread(void *hook_data
, void *call_data
)
3116 LttvTracefileState
*s
= (LttvTracefileState
*)call_data
;
3117 LttEvent
*e
= ltt_tracefile_get_event(s
->parent
.tf
);
3118 LttvTraceHook
*th
= (LttvTraceHook
*)hook_data
;
3120 LttvTraceState
*ts
= (LttvTraceState
*)s
->parent
.t_context
;
3121 LttvProcessState
*process
;
3122 LttvExecutionState
*es
;
3125 pid
= (guint
)ltt_event_get_long_unsigned(e
, lttv_trace_get_hook_field(th
, 0));
3126 s
->parent
.target_pid
= pid
;
3128 process
= lttv_state_find_process_or_create(ts
, ANY_CPU
, pid
,
3130 if (process
->state
->s
!= LTTV_STATE_DEAD
) {
3131 process
->execution_stack
=
3132 g_array_set_size(process
->execution_stack
, 1);
3133 es
= process
->state
=
3134 &g_array_index(process
->execution_stack
, LttvExecutionState
, 0);
3135 es
->t
= LTTV_STATE_SYSCALL
;
3137 process
->type
= LTTV_STATE_KERNEL_THREAD
;
3142 static gboolean
process_exit(void *hook_data
, void *call_data
)
3144 LttvTracefileState
*s
= (LttvTracefileState
*)call_data
;
3145 LttEvent
*e
= ltt_tracefile_get_event(s
->parent
.tf
);
3146 LttvTraceHook
*th
= (LttvTraceHook
*)hook_data
;
3148 LttvTraceState
*ts
= (LttvTraceState
*)s
->parent
.t_context
;
3149 LttvProcessState
*process
; // = ts->running_process[cpu];
3151 pid
= ltt_event_get_unsigned(e
, lttv_trace_get_hook_field(th
, 0));
3152 s
->parent
.target_pid
= pid
;
3154 // FIXME : Add this test in the "known state" section
3155 // g_assert(process->pid == pid);
3157 process
= lttv_state_find_process(ts
, ANY_CPU
, pid
);
3158 if(likely(process
!= NULL
)) {
3159 process
->state
->s
= LTTV_STATE_EXIT
;
3164 static gboolean
process_free(void *hook_data
, void *call_data
)
3166 LttvTracefileState
*s
= (LttvTracefileState
*)call_data
;
3167 LttvTraceState
*ts
= (LttvTraceState
*)s
->parent
.t_context
;
3168 LttEvent
*e
= ltt_tracefile_get_event(s
->parent
.tf
);
3169 LttvTraceHook
*th
= (LttvTraceHook
*)hook_data
;
3171 LttvProcessState
*process
;
3173 /* PID of the process to release */
3174 release_pid
= ltt_event_get_unsigned(e
, lttv_trace_get_hook_field(th
, 0));
3175 s
->parent
.target_pid
= release_pid
;
3177 g_assert(release_pid
!= 0);
3179 process
= lttv_state_find_process(ts
, ANY_CPU
, release_pid
);
3180 if(likely(process
!= NULL
))
3181 exit_process(s
, process
);
3184 if(likely(process
!= NULL
)) {
3185 /* release_task is happening at kernel level : we can now safely release
3186 * the data structure of the process */
3187 //This test is fun, though, as it may happen that
3188 //at time t : CPU 0 : process_free
3189 //at time t+150ns : CPU 1 : schedule out
3190 //Clearly due to time imprecision, we disable it. (Mathieu)
3191 //If this weird case happen, we have no choice but to put the
3192 //Currently running process on the cpu to 0.
3193 //I re-enable it following time precision fixes. (Mathieu)
3194 //Well, in the case where an process is freed by a process on another CPU
3195 //and still scheduled, it happens that this is the schedchange that will
3196 //drop the last reference count. Do not free it here!
3197 guint num_cpus
= ltt_trace_get_num_cpu(ts
->parent
.t
);
3199 for(i
=0; i
< num_cpus
; i
++) {
3200 //g_assert(process != ts->running_process[i]);
3201 if(process
== ts
->running_process
[i
]) {
3202 //ts->running_process[i] = lttv_state_find_process(ts, i, 0);
3206 if(i
== num_cpus
) /* process is not scheduled */
3207 exit_process(s
, process
);
3214 static gboolean
process_exec(void *hook_data
, void *call_data
)
3216 LttvTracefileState
*s
= (LttvTracefileState
*)call_data
;
3217 LttvTraceState
*ts
= (LttvTraceState
*)s
->parent
.t_context
;
3218 LttEvent
*e
= ltt_tracefile_get_event(s
->parent
.tf
);
3219 LttvTraceHook
*th
= (LttvTraceHook
*)hook_data
;
3222 LttvProcessState
*process
= ts
->running_process
[cpu
];
3224 #if 0//how to use a sequence that must be transformed in a string
3225 /* PID of the process to release */
3226 guint64 name_len
= ltt_event_field_element_number(e
,
3227 lttv_trace_get_hook_field(th
, 0));
3228 //name = ltt_event_get_string(e, lttv_trace_get_hook_field(th, 0));
3229 LttField
*child
= ltt_event_field_element_select(e
,
3230 lttv_trace_get_hook_field(th
, 0), 0);
3232 (gchar
*)(ltt_event_data(e
)+ltt_event_field_offset(e
, child
));
3233 gchar
*null_term_name
= g_new(gchar
, name_len
+1);
3234 memcpy(null_term_name
, name_begin
, name_len
);
3235 null_term_name
[name_len
] = '\0';
3236 process
->name
= g_quark_from_string(null_term_name
);
3239 process
->name
= g_quark_from_string(ltt_event_get_string(e
,
3240 lttv_trace_get_hook_field(th
, 0)));
3241 process
->brand
= LTTV_STATE_UNBRANDED
;
3242 //g_free(null_term_name);
3246 static gboolean
thread_brand(void *hook_data
, void *call_data
)
3248 LttvTracefileState
*s
= (LttvTracefileState
*)call_data
;
3249 LttvTraceState
*ts
= (LttvTraceState
*)s
->parent
.t_context
;
3250 LttEvent
*e
= ltt_tracefile_get_event(s
->parent
.tf
);
3251 LttvTraceHook
*th
= (LttvTraceHook
*)hook_data
;
3254 LttvProcessState
*process
= ts
->running_process
[cpu
];
3256 name
= ltt_event_get_string(e
, lttv_trace_get_hook_field(th
, 0));
3257 process
->brand
= g_quark_from_string(name
);
3262 static gboolean
fs_open(void *hook_data
, void *call_data
)
3264 LttvTracefileState
*s
= (LttvTracefileState
*)call_data
;
3265 LttvTraceState
*ts
= (LttvTraceState
*)s
->parent
.t_context
;
3266 LttEvent
*e
= ltt_tracefile_get_event(s
->parent
.tf
);
3267 LttvTraceHook
*th
= (LttvTraceHook
*)hook_data
;
3268 struct marker_field
*f
;
3272 LttvProcessState
*process
= ts
->running_process
[cpu
];
3274 f
= lttv_trace_get_hook_field(th
, 0);
3275 fd
= ltt_event_get_int(e
, f
);
3277 f
= lttv_trace_get_hook_field(th
, 1);
3278 filename
= ltt_event_get_string(e
, f
);
3280 g_hash_table_insert(process
->fds
, (gpointer
)(long)fd
,
3281 (gpointer
)(unsigned long)g_quark_from_string(filename
));
3286 static void fix_process(gpointer key
, gpointer value
,
3289 LttvProcessState
*process
;
3290 LttvExecutionState
*es
;
3291 process
= (LttvProcessState
*)value
;
3292 LttTime
*timestamp
= (LttTime
*)user_data
;
3294 if(process
->type
== LTTV_STATE_KERNEL_THREAD
) {
3295 es
= &g_array_index(process
->execution_stack
, LttvExecutionState
, 0);
3296 if(es
->t
== LTTV_STATE_MODE_UNKNOWN
) {
3297 es
->t
= LTTV_STATE_SYSCALL
;
3298 es
->n
= LTTV_STATE_SUBMODE_NONE
;
3299 es
->entry
= *timestamp
;
3300 es
->change
= *timestamp
;
3301 es
->cum_cpu_time
= ltt_time_zero
;
3302 if(es
->s
== LTTV_STATE_UNNAMED
)
3303 es
->s
= LTTV_STATE_WAIT
;
3306 es
= &g_array_index(process
->execution_stack
, LttvExecutionState
, 0);
3307 if(es
->t
== LTTV_STATE_MODE_UNKNOWN
) {
3308 es
->t
= LTTV_STATE_USER_MODE
;
3309 es
->n
= LTTV_STATE_SUBMODE_NONE
;
3310 es
->entry
= *timestamp
;
3311 //g_assert(timestamp->tv_sec != 0);
3312 es
->change
= *timestamp
;
3313 es
->cum_cpu_time
= ltt_time_zero
;
3314 if(es
->s
== LTTV_STATE_UNNAMED
)
3315 es
->s
= LTTV_STATE_RUN
;
3317 if(process
->execution_stack
->len
== 1) {
3318 /* Still in bottom unknown mode, means never did a system call
3319 * May be either in user mode, syscall mode, running or waiting.*/
3320 /* FIXME : we may be tagging syscall mode when being user mode */
3321 process
->execution_stack
=
3322 g_array_set_size(process
->execution_stack
, 2);
3323 es
= process
->state
= &g_array_index(process
->execution_stack
,
3324 LttvExecutionState
, 1);
3325 es
->t
= LTTV_STATE_SYSCALL
;
3326 es
->n
= LTTV_STATE_SUBMODE_NONE
;
3327 es
->entry
= *timestamp
;
3328 //g_assert(timestamp->tv_sec != 0);
3329 es
->change
= *timestamp
;
3330 es
->cum_cpu_time
= ltt_time_zero
;
3331 if(es
->s
== LTTV_STATE_WAIT_FORK
)
3332 es
->s
= LTTV_STATE_WAIT
;
3338 static gboolean
statedump_end(void *hook_data
, void *call_data
)
3340 LttvTracefileState
*s
= (LttvTracefileState
*)call_data
;
3341 LttvTraceState
*ts
= (LttvTraceState
*)s
->parent
.t_context
;
3342 LttvTracefileContext
*tfc
= (LttvTracefileContext
*)call_data
;
3343 //LttEvent *e = ltt_tracefile_get_event(s->parent.tf);
3344 //LttvTraceHook *th = (LttvTraceHook *)hook_data;
3346 /* For all processes */
3347 /* if kernel thread, if stack[0] is unknown, set to syscall mode, wait */
3348 /* else, if stack[0] is unknown, set to user mode, running */
3350 g_hash_table_foreach(ts
->processes
, fix_process
, &tfc
->timestamp
);
3355 static gboolean
enum_process_state(void *hook_data
, void *call_data
)
3357 LttvTracefileState
*s
= (LttvTracefileState
*)call_data
;
3358 LttEvent
*e
= ltt_tracefile_get_event(s
->parent
.tf
);
3359 //It's slow : optimise later by doing this before reading trace.
3360 LttvTraceHook
*th
= (LttvTraceHook
*)hook_data
;
3366 LttvTraceState
*ts
= (LttvTraceState
*)s
->parent
.t_context
;
3367 LttvProcessState
*process
= ts
->running_process
[cpu
];
3368 LttvProcessState
*parent_process
;
3369 struct marker_field
*f
;
3370 GQuark type
, mode
, submode
, status
;
3371 LttvExecutionState
*es
;
3375 pid
= ltt_event_get_unsigned(e
, lttv_trace_get_hook_field(th
, 0));
3376 s
->parent
.target_pid
= pid
;
3379 parent_pid
= ltt_event_get_unsigned(e
, lttv_trace_get_hook_field(th
, 1));
3382 command
= ltt_event_get_string(e
, lttv_trace_get_hook_field(th
, 2));
3385 f
= lttv_trace_get_hook_field(th
, 3);
3386 type
= ltt_enum_string_get(f
, ltt_event_get_unsigned(e
, f
));
3388 //FIXME: type is rarely used, enum must match possible types.
3391 f
= lttv_trace_get_hook_field(th
, 4);
3392 mode
= ltt_enum_string_get(f
,ltt_event_get_unsigned(e
, f
));
3395 f
= lttv_trace_get_hook_field(th
, 5);
3396 submode
= ltt_enum_string_get(f
, ltt_event_get_unsigned(e
, f
));
3399 f
= lttv_trace_get_hook_field(th
, 6);
3400 status
= ltt_enum_string_get(f
, ltt_event_get_unsigned(e
, f
));
3403 f
= lttv_trace_get_hook_field(th
, 7);
3405 tgid
= ltt_event_get_unsigned(e
, f
);
3410 nb_cpus
= ltt_trace_get_num_cpu(ts
->parent
.t
);
3411 for(i
=0; i
<nb_cpus
; i
++) {
3412 process
= lttv_state_find_process(ts
, i
, pid
);
3413 g_assert(process
!= NULL
);
3415 process
->ppid
= parent_pid
;
3416 process
->tgid
= tgid
;
3417 process
->name
= g_quark_from_string(command
);
3419 &g_array_index(process
->execution_stack
, LttvExecutionState
, 0);
3420 process
->type
= LTTV_STATE_KERNEL_THREAD
;
3424 /* The process might exist if a process was forked while performing the
3426 process
= lttv_state_find_process(ts
, ANY_CPU
, pid
);
3427 if(process
== NULL
) {
3428 parent_process
= lttv_state_find_process(ts
, ANY_CPU
, parent_pid
);
3429 process
= lttv_state_create_process(ts
, parent_process
, cpu
,
3430 pid
, tgid
, g_quark_from_string(command
),
3431 &s
->parent
.timestamp
);
3433 /* Keep the stack bottom : a running user mode */
3434 /* Disabled because of inconsistencies in the current statedump states. */
3435 if(type
== LTTV_STATE_KERNEL_THREAD
) {
3436 /* Only keep the bottom
3437 * FIXME Kernel thread : can be in syscall or interrupt or trap. */
3438 /* Will cause expected trap when in fact being syscall (even after end of
3440 * Will cause expected interrupt when being syscall. (only before end of
3441 * statedump event) */
3442 // This will cause a "popping last state on stack, ignoring it."
3443 process
->execution_stack
= g_array_set_size(process
->execution_stack
, 1);
3444 es
= process
->state
= &g_array_index(process
->execution_stack
,
3445 LttvExecutionState
, 0);
3446 process
->type
= LTTV_STATE_KERNEL_THREAD
;
3447 es
->t
= LTTV_STATE_MODE_UNKNOWN
;
3448 es
->s
= LTTV_STATE_UNNAMED
;
3449 es
->n
= LTTV_STATE_SUBMODE_UNKNOWN
;
3451 es
->t
= LTTV_STATE_SYSCALL
;
3456 /* User space process :
3457 * bottom : user mode
3458 * either currently running or scheduled out.
3459 * can be scheduled out because interrupted in (user mode or in syscall)
3460 * or because of an explicit call to the scheduler in syscall. Note that
3461 * the scheduler call comes after the irq_exit, so never in interrupt
3463 // temp workaround : set size to 1 : only have user mode bottom of stack.
3464 // will cause g_info message of expected syscall mode when in fact being
3465 // in user mode. Can also cause expected trap when in fact being user
3466 // mode in the event of a page fault reenabling interrupts in the handler.
3467 // Expected syscall and trap can also happen after the end of statedump
3468 // This will cause a "popping last state on stack, ignoring it."
3469 process
->execution_stack
= g_array_set_size(process
->execution_stack
, 1);
3470 es
= process
->state
= &g_array_index(process
->execution_stack
,
3471 LttvExecutionState
, 0);
3472 es
->t
= LTTV_STATE_MODE_UNKNOWN
;
3473 es
->s
= LTTV_STATE_UNNAMED
;
3474 es
->n
= LTTV_STATE_SUBMODE_UNKNOWN
;
3476 es
->t
= LTTV_STATE_USER_MODE
;
3484 es
= process
->state
= &g_array_index(process
->execution_stack
,
3485 LttvExecutionState
, 1);
3486 es
->t
= LTTV_STATE_MODE_UNKNOWN
;
3487 es
->s
= LTTV_STATE_UNNAMED
;
3488 es
->n
= LTTV_STATE_SUBMODE_UNKNOWN
;
3492 /* The process has already been created :
3493 * Probably was forked while dumping the process state or
3494 * was simply scheduled in prior to get the state dump event.
3496 process
->ppid
= parent_pid
;
3497 process
->tgid
= tgid
;
3498 process
->name
= g_quark_from_string(command
);
3499 process
->type
= type
;
3501 &g_array_index(process
->execution_stack
, LttvExecutionState
, 0);
3503 if(es
->t
== LTTV_STATE_MODE_UNKNOWN
) {
3504 if(type
== LTTV_STATE_KERNEL_THREAD
)
3505 es
->t
= LTTV_STATE_SYSCALL
;
3507 es
->t
= LTTV_STATE_USER_MODE
;
3510 /* Don't mess around with the stack, it will eventually become
3511 * ok after the end of state dump. */
3518 gint
lttv_state_hook_add_event_hooks(void *hook_data
, void *call_data
)
3520 LttvTracesetState
*tss
= (LttvTracesetState
*)(call_data
);
3522 lttv_state_add_event_hooks(tss
);
3527 void lttv_state_add_event_hooks(LttvTracesetState
*self
)
3529 LttvTraceset
*traceset
= self
->parent
.ts
;
3531 guint i
, j
, k
, nb_trace
, nb_tracefile
;
3535 LttvTracefileState
*tfs
;
3541 LttvAttributeValue val
;
3543 nb_trace
= lttv_traceset_number(traceset
);
3544 for(i
= 0 ; i
< nb_trace
; i
++) {
3545 ts
= (LttvTraceState
*)self
->parent
.traces
[i
];
3547 /* Find the eventtype id for the following events and register the
3548 associated by id hooks. */
3550 hooks
= g_array_sized_new(FALSE
, FALSE
, sizeof(LttvTraceHook
), 20);
3551 //hooks = g_array_set_size(hooks, 19); // Max possible number of hooks.
3554 lttv_trace_find_hook(ts
->parent
.t
,
3556 LTT_EVENT_SYSCALL_ENTRY
,
3557 FIELD_ARRAY(LTT_FIELD_SYSCALL_ID
),
3558 syscall_entry
, NULL
, &hooks
);
3560 lttv_trace_find_hook(ts
->parent
.t
,
3562 LTT_EVENT_SYSCALL_EXIT
,
3564 syscall_exit
, NULL
, &hooks
);
3566 lttv_trace_find_hook(ts
->parent
.t
,
3568 LTT_EVENT_TRAP_ENTRY
,
3569 FIELD_ARRAY(LTT_FIELD_TRAP_ID
),
3570 trap_entry
, NULL
, &hooks
);
3572 lttv_trace_find_hook(ts
->parent
.t
,
3574 LTT_EVENT_TRAP_EXIT
,
3576 trap_exit
, NULL
, &hooks
);
3578 lttv_trace_find_hook(ts
->parent
.t
,
3580 LTT_EVENT_PAGE_FAULT_ENTRY
,
3581 FIELD_ARRAY(LTT_FIELD_TRAP_ID
),
3582 trap_entry
, NULL
, &hooks
);
3584 lttv_trace_find_hook(ts
->parent
.t
,
3586 LTT_EVENT_PAGE_FAULT_EXIT
,
3588 trap_exit
, NULL
, &hooks
);
3590 lttv_trace_find_hook(ts
->parent
.t
,
3592 LTT_EVENT_PAGE_FAULT_NOSEM_ENTRY
,
3593 FIELD_ARRAY(LTT_FIELD_TRAP_ID
),
3594 trap_entry
, NULL
, &hooks
);
3596 lttv_trace_find_hook(ts
->parent
.t
,
3598 LTT_EVENT_PAGE_FAULT_NOSEM_EXIT
,
3600 trap_exit
, NULL
, &hooks
);
3602 lttv_trace_find_hook(ts
->parent
.t
,
3604 LTT_EVENT_IRQ_ENTRY
,
3605 FIELD_ARRAY(LTT_FIELD_IRQ_ID
),
3606 irq_entry
, NULL
, &hooks
);
3608 lttv_trace_find_hook(ts
->parent
.t
,
3612 irq_exit
, NULL
, &hooks
);
3614 lttv_trace_find_hook(ts
->parent
.t
,
3616 LTT_EVENT_SOFT_IRQ_RAISE
,
3617 FIELD_ARRAY(LTT_FIELD_SOFT_IRQ_ID
),
3618 soft_irq_raise
, NULL
, &hooks
);
3620 lttv_trace_find_hook(ts
->parent
.t
,
3622 LTT_EVENT_SOFT_IRQ_ENTRY
,
3623 FIELD_ARRAY(LTT_FIELD_SOFT_IRQ_ID
),
3624 soft_irq_entry
, NULL
, &hooks
);
3626 lttv_trace_find_hook(ts
->parent
.t
,
3628 LTT_EVENT_SOFT_IRQ_EXIT
,
3630 soft_irq_exit
, NULL
, &hooks
);
3632 lttv_trace_find_hook(ts
->parent
.t
,
3634 LTT_EVENT_SCHED_SCHEDULE
,
3635 FIELD_ARRAY(LTT_FIELD_PREV_PID
, LTT_FIELD_NEXT_PID
,
3636 LTT_FIELD_PREV_STATE
),
3637 schedchange
, NULL
, &hooks
);
3639 lttv_trace_find_hook(ts
->parent
.t
,
3641 LTT_EVENT_PROCESS_FORK
,
3642 FIELD_ARRAY(LTT_FIELD_PARENT_PID
, LTT_FIELD_CHILD_PID
,
3643 LTT_FIELD_CHILD_TGID
),
3644 process_fork
, NULL
, &hooks
);
3646 lttv_trace_find_hook(ts
->parent
.t
,
3648 LTT_EVENT_KTHREAD_CREATE
,
3649 FIELD_ARRAY(LTT_FIELD_PID
),
3650 process_kernel_thread
, NULL
, &hooks
);
3652 lttv_trace_find_hook(ts
->parent
.t
,
3654 LTT_EVENT_PROCESS_EXIT
,
3655 FIELD_ARRAY(LTT_FIELD_PID
),
3656 process_exit
, NULL
, &hooks
);
3658 lttv_trace_find_hook(ts
->parent
.t
,
3660 LTT_EVENT_PROCESS_FREE
,
3661 FIELD_ARRAY(LTT_FIELD_PID
),
3662 process_free
, NULL
, &hooks
);
3664 lttv_trace_find_hook(ts
->parent
.t
,
3667 FIELD_ARRAY(LTT_FIELD_FILENAME
),
3668 process_exec
, NULL
, &hooks
);
3670 lttv_trace_find_hook(ts
->parent
.t
,
3671 LTT_CHANNEL_USERSPACE
,
3672 LTT_EVENT_THREAD_BRAND
,
3673 FIELD_ARRAY(LTT_FIELD_NAME
),
3674 thread_brand
, NULL
, &hooks
);
3676 /* statedump-related hooks */
3677 lttv_trace_find_hook(ts
->parent
.t
,
3678 LTT_CHANNEL_TASK_STATE
,
3679 LTT_EVENT_PROCESS_STATE
,
3680 FIELD_ARRAY(LTT_FIELD_PID
, LTT_FIELD_PARENT_PID
, LTT_FIELD_NAME
,
3681 LTT_FIELD_TYPE
, LTT_FIELD_MODE
, LTT_FIELD_SUBMODE
,
3682 LTT_FIELD_STATUS
, LTT_FIELD_TGID
),
3683 enum_process_state
, NULL
, &hooks
);
3685 lttv_trace_find_hook(ts
->parent
.t
,
3686 LTT_CHANNEL_GLOBAL_STATE
,
3687 LTT_EVENT_STATEDUMP_END
,
3689 statedump_end
, NULL
, &hooks
);
3691 lttv_trace_find_hook(ts
->parent
.t
,
3692 LTT_CHANNEL_IRQ_STATE
,
3693 LTT_EVENT_LIST_INTERRUPT
,
3694 FIELD_ARRAY(LTT_FIELD_ACTION
, LTT_FIELD_IRQ_ID
),
3695 enum_interrupt
, NULL
, &hooks
);
3697 lttv_trace_find_hook(ts
->parent
.t
,
3699 LTT_EVENT_REQUEST_ISSUE
,
3700 FIELD_ARRAY(LTT_FIELD_MAJOR
, LTT_FIELD_MINOR
, LTT_FIELD_OPERATION
),
3701 bdev_request_issue
, NULL
, &hooks
);
3703 lttv_trace_find_hook(ts
->parent
.t
,
3705 LTT_EVENT_REQUEST_COMPLETE
,
3706 FIELD_ARRAY(LTT_FIELD_MAJOR
, LTT_FIELD_MINOR
, LTT_FIELD_OPERATION
),
3707 bdev_request_complete
, NULL
, &hooks
);
3709 lttv_trace_find_hook(ts
->parent
.t
,
3710 LTT_CHANNEL_USERSPACE
,
3711 LTT_EVENT_FUNCTION_ENTRY
,
3712 FIELD_ARRAY(LTT_FIELD_THIS_FN
, LTT_FIELD_CALL_SITE
),
3713 function_entry
, NULL
, &hooks
);
3715 lttv_trace_find_hook(ts
->parent
.t
,
3716 LTT_CHANNEL_USERSPACE
,
3717 LTT_EVENT_FUNCTION_EXIT
,
3718 FIELD_ARRAY(LTT_FIELD_THIS_FN
, LTT_FIELD_CALL_SITE
),
3719 function_exit
, NULL
, &hooks
);
3721 lttv_trace_find_hook(ts
->parent
.t
,
3722 LTT_CHANNEL_SYSCALL_STATE
,
3723 LTT_EVENT_SYS_CALL_TABLE
,
3724 FIELD_ARRAY(LTT_FIELD_ID
, LTT_FIELD_ADDRESS
, LTT_FIELD_SYMBOL
),
3725 dump_syscall
, NULL
, &hooks
);
3727 lttv_trace_find_hook(ts
->parent
.t
,
3728 LTT_CHANNEL_KPROBE_STATE
,
3729 LTT_EVENT_KPROBE_TABLE
,
3730 FIELD_ARRAY(LTT_FIELD_IP
, LTT_FIELD_SYMBOL
),
3731 dump_kprobe
, NULL
, &hooks
);
3733 lttv_trace_find_hook(ts
->parent
.t
,
3734 LTT_CHANNEL_SOFTIRQ_STATE
,
3735 LTT_EVENT_SOFTIRQ_VEC
,
3736 FIELD_ARRAY(LTT_FIELD_ID
, LTT_FIELD_ADDRESS
, LTT_FIELD_SYMBOL
),
3737 dump_softirq
, NULL
, &hooks
);
3739 lttv_trace_find_hook(ts
->parent
.t
,
3742 FIELD_ARRAY(LTT_FIELD_FD
, LTT_FIELD_FILENAME
),
3743 fs_open
, NULL
, &hooks
);
3745 /* Add these hooks to each event_by_id hooks list */
3747 nb_tracefile
= ts
->parent
.tracefiles
->len
;
3749 for(j
= 0 ; j
< nb_tracefile
; j
++) {
3751 LTTV_TRACEFILE_STATE(g_array_index(ts
->parent
.tracefiles
,
3752 LttvTracefileContext
*, j
));
3754 for(k
= 0 ; k
< hooks
->len
; k
++) {
3755 th
= &g_array_index(hooks
, LttvTraceHook
, k
);
3756 if (th
->mdata
== tfs
->parent
.tf
->mdata
)
3758 lttv_hooks_by_id_find(tfs
->parent
.event_by_id
, th
->id
),
3764 lttv_attribute_find(ts
->parent
.a
, LTTV_STATE_HOOKS
, LTTV_POINTER
, &val
);
3765 *(val
.v_pointer
) = hooks
;
3769 gint
lttv_state_hook_remove_event_hooks(void *hook_data
, void *call_data
)
3771 LttvTracesetState
*tss
= (LttvTracesetState
*)(call_data
);
3773 lttv_state_remove_event_hooks(tss
);
3778 void lttv_state_remove_event_hooks(LttvTracesetState
*self
)
3780 LttvTraceset
*traceset
= self
->parent
.ts
;
3782 guint i
, j
, k
, nb_trace
, nb_tracefile
;
3786 LttvTracefileState
*tfs
;
3792 LttvAttributeValue val
;
3794 nb_trace
= lttv_traceset_number(traceset
);
3795 for(i
= 0 ; i
< nb_trace
; i
++) {
3796 ts
= LTTV_TRACE_STATE(self
->parent
.traces
[i
]);
3798 lttv_attribute_find(ts
->parent
.a
, LTTV_STATE_HOOKS
, LTTV_POINTER
, &val
);
3799 hooks
= *(val
.v_pointer
);
3801 /* Remove these hooks from each event_by_id hooks list */
3803 nb_tracefile
= ts
->parent
.tracefiles
->len
;
3805 for(j
= 0 ; j
< nb_tracefile
; j
++) {
3807 LTTV_TRACEFILE_STATE(g_array_index(ts
->parent
.tracefiles
,
3808 LttvTracefileContext
*, j
));
3810 for(k
= 0 ; k
< hooks
->len
; k
++) {
3811 th
= &g_array_index(hooks
, LttvTraceHook
, k
);
3812 if (th
->mdata
== tfs
->parent
.tf
->mdata
)
3813 lttv_hooks_remove_data(
3814 lttv_hooks_by_id_find(tfs
->parent
.event_by_id
, th
->id
),
3819 lttv_trace_hook_remove_all(&hooks
);
3820 g_array_free(hooks
, TRUE
);
3824 static gboolean
state_save_event_hook(void *hook_data
, void *call_data
)
3826 guint
*event_count
= (guint
*)hook_data
;
3828 /* Only save at LTTV_STATE_SAVE_INTERVAL */
3829 if(likely((*event_count
)++ < LTTV_STATE_SAVE_INTERVAL
))
3834 LttvTracefileState
*self
= (LttvTracefileState
*)call_data
;
3836 LttvTraceState
*tcs
= (LttvTraceState
*)(self
->parent
.t_context
);
3838 LttvAttribute
*saved_states_tree
, *saved_state_tree
;
3840 LttvAttributeValue value
;
3842 saved_states_tree
= lttv_attribute_find_subdir(tcs
->parent
.t_a
,
3843 LTTV_STATE_SAVED_STATES
);
3844 saved_state_tree
= g_object_new(LTTV_ATTRIBUTE_TYPE
, NULL
);
3845 value
= lttv_attribute_add(saved_states_tree
,
3846 lttv_attribute_get_number(saved_states_tree
), LTTV_GOBJECT
);
3847 *(value
.v_gobject
) = (GObject
*)saved_state_tree
;
3848 value
= lttv_attribute_add(saved_state_tree
, LTTV_STATE_TIME
, LTTV_TIME
);
3849 *(value
.v_time
) = self
->parent
.timestamp
;
3850 lttv_state_save(tcs
, saved_state_tree
);
3851 g_debug("Saving state at time %lu.%lu", self
->parent
.timestamp
.tv_sec
,
3852 self
->parent
.timestamp
.tv_nsec
);
3854 *(tcs
->max_time_state_recomputed_in_seek
) = self
->parent
.timestamp
;
3859 static gboolean
state_save_after_trace_hook(void *hook_data
, void *call_data
)
3861 LttvTraceState
*tcs
= (LttvTraceState
*)(call_data
);
3863 *(tcs
->max_time_state_recomputed_in_seek
) = tcs
->parent
.time_span
.end_time
;
3868 guint
lttv_state_current_cpu(LttvTracefileState
*tfs
)
3876 static gboolean
block_start(void *hook_data
, void *call_data
)
3878 LttvTracefileState
*self
= (LttvTracefileState
*)call_data
;
3880 LttvTracefileState
*tfcs
;
3882 LttvTraceState
*tcs
= (LttvTraceState
*)(self
->parent
.t_context
);
3884 LttEventPosition
*ep
;
3886 guint i
, nb_block
, nb_event
, nb_tracefile
;
3890 LttvAttribute
*saved_states_tree
, *saved_state_tree
;
3892 LttvAttributeValue value
;
3894 ep
= ltt_event_position_new();
3896 nb_tracefile
= tcs
->parent
.tracefiles
->len
;
3898 /* Count the number of events added since the last block end in any
3901 for(i
= 0 ; i
< nb_tracefile
; i
++) {
3903 LTTV_TRACEFILE_STATE(&g_array_index(tcs
->parent
.tracefiles
,
3904 LttvTracefileContext
, i
));
3905 ltt_event_position(tfcs
->parent
.e
, ep
);
3906 ltt_event_position_get(ep
, &nb_block
, &nb_event
, &tf
);
3907 tcs
->nb_event
+= nb_event
- tfcs
->saved_position
;
3908 tfcs
->saved_position
= nb_event
;
3912 if(tcs
->nb_event
>= tcs
->save_interval
) {
3913 saved_states_tree
= lttv_attribute_find_subdir(tcs
->parent
.t_a
,
3914 LTTV_STATE_SAVED_STATES
);
3915 saved_state_tree
= g_object_new(LTTV_ATTRIBUTE_TYPE
, NULL
);
3916 value
= lttv_attribute_add(saved_states_tree
,
3917 lttv_attribute_get_number(saved_states_tree
), LTTV_GOBJECT
);
3918 *(value
.v_gobject
) = (GObject
*)saved_state_tree
;
3919 value
= lttv_attribute_add(saved_state_tree
, LTTV_STATE_TIME
, LTTV_TIME
);
3920 *(value
.v_time
) = self
->parent
.timestamp
;
3921 lttv_state_save(tcs
, saved_state_tree
);
3923 g_debug("Saving state at time %lu.%lu", self
->parent
.timestamp
.tv_sec
,
3924 self
->parent
.timestamp
.tv_nsec
);
3926 *(tcs
->max_time_state_recomputed_in_seek
) = self
->parent
.timestamp
;
3932 static gboolean
block_end(void *hook_data
, void *call_data
)
3934 LttvTracefileState
*self
= (LttvTracefileState
*)call_data
;
3936 LttvTraceState
*tcs
= (LttvTraceState
*)(self
->parent
.t_context
);
3940 LttEventPosition
*ep
;
3942 guint nb_block
, nb_event
;
3944 ep
= ltt_event_position_new();
3945 ltt_event_position(self
->parent
.e
, ep
);
3946 ltt_event_position_get(ep
, &nb_block
, &nb_event
, &tf
);
3947 tcs
->nb_event
+= nb_event
- self
->saved_position
+ 1;
3948 self
->saved_position
= 0;
3949 *(tcs
->max_time_state_recomputed_in_seek
) = self
->parent
.timestamp
;
3956 void lttv_state_save_add_event_hooks(LttvTracesetState
*self
)
3958 LttvTraceset
*traceset
= self
->parent
.ts
;
3960 guint i
, j
, nb_trace
, nb_tracefile
;
3964 LttvTracefileState
*tfs
;
3966 LttvTraceHook hook_start
, hook_end
;
3968 nb_trace
= lttv_traceset_number(traceset
);
3969 for(i
= 0 ; i
< nb_trace
; i
++) {
3970 ts
= (LttvTraceState
*)self
->parent
.traces
[i
];
3972 lttv_trace_find_hook(ts
->parent
.t
, "core","block_start",NULL
,
3973 NULL
, NULL
, block_start
, &hook_start
);
3974 lttv_trace_find_hook(ts
->parent
.t
, "core","block_end",NULL
,
3975 NULL
, NULL
, block_end
, &hook_end
);
3977 nb_tracefile
= ts
->parent
.tracefiles
->len
;
3979 for(j
= 0 ; j
< nb_tracefile
; j
++) {
3981 LTTV_TRACEFILE_STATE(&g_array_index(ts
->parent
.tracefiles
,
3982 LttvTracefileContext
, j
));
3983 lttv_hooks_add(lttv_hooks_by_id_find(tfs
->parent
.event_by_id
,
3984 hook_start
.id
), hook_start
.h
, NULL
, LTTV_PRIO_STATE
);
3985 lttv_hooks_add(lttv_hooks_by_id_find(tfs
->parent
.event_by_id
,
3986 hook_end
.id
), hook_end
.h
, NULL
, LTTV_PRIO_STATE
);
3992 void lttv_state_save_add_event_hooks(LttvTracesetState
*self
)
3994 LttvTraceset
*traceset
= self
->parent
.ts
;
3996 guint i
, j
, nb_trace
, nb_tracefile
;
4000 LttvTracefileState
*tfs
;
4003 nb_trace
= lttv_traceset_number(traceset
);
4004 for(i
= 0 ; i
< nb_trace
; i
++) {
4006 ts
= (LttvTraceState
*)self
->parent
.traces
[i
];
4007 nb_tracefile
= ts
->parent
.tracefiles
->len
;
4009 if(ts
->has_precomputed_states
) continue;
4011 guint
*event_count
= g_new(guint
, 1);
4014 for(j
= 0 ; j
< nb_tracefile
; j
++) {
4016 LTTV_TRACEFILE_STATE(g_array_index(ts
->parent
.tracefiles
,
4017 LttvTracefileContext
*, j
));
4018 lttv_hooks_add(tfs
->parent
.event
,
4019 state_save_event_hook
,
4026 lttv_process_traceset_begin(&self
->parent
,
4027 NULL
, NULL
, NULL
, NULL
, NULL
);
4031 gint
lttv_state_save_hook_add_event_hooks(void *hook_data
, void *call_data
)
4033 LttvTracesetState
*tss
= (LttvTracesetState
*)(call_data
);
4035 lttv_state_save_add_event_hooks(tss
);
4042 void lttv_state_save_remove_event_hooks(LttvTracesetState
*self
)
4044 LttvTraceset
*traceset
= self
->parent
.ts
;
4046 guint i
, j
, nb_trace
, nb_tracefile
;
4050 LttvTracefileState
*tfs
;
4052 LttvTraceHook hook_start
, hook_end
;
4054 nb_trace
= lttv_traceset_number(traceset
);
4055 for(i
= 0 ; i
< nb_trace
; i
++) {
4056 ts
= LTTV_TRACE_STATE(self
->parent
.traces
[i
]);
4058 lttv_trace_find_hook(ts
->parent
.t
, "core","block_start",NULL
,
4059 NULL
, NULL
, block_start
, &hook_start
);
4061 lttv_trace_find_hook(ts
->parent
.t
, "core","block_end",NULL
,
4062 NULL
, NULL
, block_end
, &hook_end
);
4064 nb_tracefile
= ts
->parent
.tracefiles
->len
;
4066 for(j
= 0 ; j
< nb_tracefile
; j
++) {
4068 LTTV_TRACEFILE_STATE(&g_array_index(ts
->parent
.tracefiles
,
4069 LttvTracefileContext
, j
));
4070 lttv_hooks_remove_data(lttv_hooks_by_id_find(
4071 tfs
->parent
.event_by_id
, hook_start
.id
), hook_start
.h
, NULL
);
4072 lttv_hooks_remove_data(lttv_hooks_by_id_find(
4073 tfs
->parent
.event_by_id
, hook_end
.id
), hook_end
.h
, NULL
);
4079 void lttv_state_save_remove_event_hooks(LttvTracesetState
*self
)
4081 LttvTraceset
*traceset
= self
->parent
.ts
;
4083 guint i
, j
, nb_trace
, nb_tracefile
;
4087 LttvTracefileState
*tfs
;
4089 LttvHooks
*after_trace
= lttv_hooks_new();
4091 lttv_hooks_add(after_trace
,
4092 state_save_after_trace_hook
,
4097 lttv_process_traceset_end(&self
->parent
,
4098 NULL
, after_trace
, NULL
, NULL
, NULL
);
4100 lttv_hooks_destroy(after_trace
);
4102 nb_trace
= lttv_traceset_number(traceset
);
4103 for(i
= 0 ; i
< nb_trace
; i
++) {
4105 ts
= (LttvTraceState
*)self
->parent
.traces
[i
];
4106 nb_tracefile
= ts
->parent
.tracefiles
->len
;
4108 if(ts
->has_precomputed_states
) continue;
4110 guint
*event_count
= NULL
;
4112 for(j
= 0 ; j
< nb_tracefile
; j
++) {
4114 LTTV_TRACEFILE_STATE(g_array_index(ts
->parent
.tracefiles
,
4115 LttvTracefileContext
*, j
));
4116 event_count
= lttv_hooks_remove(tfs
->parent
.event
,
4117 state_save_event_hook
);
4119 if(event_count
) g_free(event_count
);
4123 gint
lttv_state_save_hook_remove_event_hooks(void *hook_data
, void *call_data
)
4125 LttvTracesetState
*tss
= (LttvTracesetState
*)(call_data
);
4127 lttv_state_save_remove_event_hooks(tss
);
4132 void lttv_state_traceset_seek_time_closest(LttvTracesetState
*self
, LttTime t
)
4134 LttvTraceset
*traceset
= self
->parent
.ts
;
4138 int min_pos
, mid_pos
, max_pos
;
4140 guint call_rest
= 0;
4142 LttvTraceState
*tcs
;
4144 LttvAttributeValue value
;
4146 LttvAttributeType type
;
4148 LttvAttributeName name
;
4152 LttvAttribute
*saved_states_tree
, *saved_state_tree
, *closest_tree
= NULL
;
4154 //g_tree_destroy(self->parent.pqueue);
4155 //self->parent.pqueue = g_tree_new(compare_tracefile);
4157 g_info("Entering seek_time_closest for time %lu.%lu", t
.tv_sec
, t
.tv_nsec
);
4159 nb_trace
= lttv_traceset_number(traceset
);
4160 for(i
= 0 ; i
< nb_trace
; i
++) {
4161 tcs
= (LttvTraceState
*)self
->parent
.traces
[i
];
4163 if(ltt_time_compare(t
, *(tcs
->max_time_state_recomputed_in_seek
)) < 0) {
4164 saved_states_tree
= lttv_attribute_find_subdir(tcs
->parent
.t_a
,
4165 LTTV_STATE_SAVED_STATES
);
4168 if(saved_states_tree
) {
4169 max_pos
= lttv_attribute_get_number(saved_states_tree
) - 1;
4170 mid_pos
= max_pos
/ 2;
4171 while(min_pos
< max_pos
) {
4172 type
= lttv_attribute_get(saved_states_tree
, mid_pos
, &name
, &value
,
4174 g_assert(type
== LTTV_GOBJECT
);
4175 saved_state_tree
= *((LttvAttribute
**)(value
.v_gobject
));
4176 type
= lttv_attribute_get_by_name(saved_state_tree
, LTTV_STATE_TIME
,
4178 g_assert(type
== LTTV_TIME
);
4179 if(ltt_time_compare(*(value
.v_time
), t
) < 0) {
4181 closest_tree
= saved_state_tree
;
4183 else max_pos
= mid_pos
- 1;
4185 mid_pos
= (min_pos
+ max_pos
+ 1) / 2;
4189 /* restore the closest earlier saved state */
4191 lttv_state_restore(tcs
, closest_tree
);
4195 /* There is no saved state, yet we want to have it. Restart at T0 */
4197 restore_init_state(tcs
);
4198 lttv_process_trace_seek_time(&(tcs
->parent
), ltt_time_zero
);
4201 /* We want to seek quickly without restoring/updating the state */
4203 restore_init_state(tcs
);
4204 lttv_process_trace_seek_time(&(tcs
->parent
), t
);
4207 if(!call_rest
) g_info("NOT Calling restore");
4212 traceset_state_instance_init (GTypeInstance
*instance
, gpointer g_class
)
4218 traceset_state_finalize (LttvTracesetState
*self
)
4220 G_OBJECT_CLASS(g_type_class_peek(LTTV_TRACESET_CONTEXT_TYPE
))->
4221 finalize(G_OBJECT(self
));
4226 traceset_state_class_init (LttvTracesetContextClass
*klass
)
4228 GObjectClass
*gobject_class
= G_OBJECT_CLASS(klass
);
4230 gobject_class
->finalize
= (void (*)(GObject
*self
)) traceset_state_finalize
;
4231 klass
->init
= (void (*)(LttvTracesetContext
*self
, LttvTraceset
*ts
))init
;
4232 klass
->fini
= (void (*)(LttvTracesetContext
*self
))fini
;
4233 klass
->new_traceset_context
= new_traceset_context
;
4234 klass
->new_trace_context
= new_trace_context
;
4235 klass
->new_tracefile_context
= new_tracefile_context
;
4240 lttv_traceset_state_get_type(void)
4242 static GType type
= 0;
4244 static const GTypeInfo info
= {
4245 sizeof (LttvTracesetStateClass
),
4246 NULL
, /* base_init */
4247 NULL
, /* base_finalize */
4248 (GClassInitFunc
) traceset_state_class_init
, /* class_init */
4249 NULL
, /* class_finalize */
4250 NULL
, /* class_data */
4251 sizeof (LttvTracesetState
),
4252 0, /* n_preallocs */
4253 (GInstanceInitFunc
) traceset_state_instance_init
, /* instance_init */
4254 NULL
/* value handling */
4257 type
= g_type_register_static (LTTV_TRACESET_CONTEXT_TYPE
, "LttvTracesetStateType",
4265 trace_state_instance_init (GTypeInstance
*instance
, gpointer g_class
)
4271 trace_state_finalize (LttvTraceState
*self
)
4273 G_OBJECT_CLASS(g_type_class_peek(LTTV_TRACE_CONTEXT_TYPE
))->
4274 finalize(G_OBJECT(self
));
4279 trace_state_class_init (LttvTraceStateClass
*klass
)
4281 GObjectClass
*gobject_class
= G_OBJECT_CLASS(klass
);
4283 gobject_class
->finalize
= (void (*)(GObject
*self
)) trace_state_finalize
;
4284 klass
->state_save
= state_save
;
4285 klass
->state_restore
= state_restore
;
4286 klass
->state_saved_free
= state_saved_free
;
4291 lttv_trace_state_get_type(void)
4293 static GType type
= 0;
4295 static const GTypeInfo info
= {
4296 sizeof (LttvTraceStateClass
),
4297 NULL
, /* base_init */
4298 NULL
, /* base_finalize */
4299 (GClassInitFunc
) trace_state_class_init
, /* class_init */
4300 NULL
, /* class_finalize */
4301 NULL
, /* class_data */
4302 sizeof (LttvTraceState
),
4303 0, /* n_preallocs */
4304 (GInstanceInitFunc
) trace_state_instance_init
, /* instance_init */
4305 NULL
/* value handling */
4308 type
= g_type_register_static (LTTV_TRACE_CONTEXT_TYPE
,
4309 "LttvTraceStateType", &info
, 0);
4316 tracefile_state_instance_init (GTypeInstance
*instance
, gpointer g_class
)
4322 tracefile_state_finalize (LttvTracefileState
*self
)
4324 G_OBJECT_CLASS(g_type_class_peek(LTTV_TRACEFILE_CONTEXT_TYPE
))->
4325 finalize(G_OBJECT(self
));
4330 tracefile_state_class_init (LttvTracefileStateClass
*klass
)
4332 GObjectClass
*gobject_class
= G_OBJECT_CLASS(klass
);
4334 gobject_class
->finalize
= (void (*)(GObject
*self
)) tracefile_state_finalize
;
4339 lttv_tracefile_state_get_type(void)
4341 static GType type
= 0;
4343 static const GTypeInfo info
= {
4344 sizeof (LttvTracefileStateClass
),
4345 NULL
, /* base_init */
4346 NULL
, /* base_finalize */
4347 (GClassInitFunc
) tracefile_state_class_init
, /* class_init */
4348 NULL
, /* class_finalize */
4349 NULL
, /* class_data */
4350 sizeof (LttvTracefileState
),
4351 0, /* n_preallocs */
4352 (GInstanceInitFunc
) tracefile_state_instance_init
, /* instance_init */
4353 NULL
/* value handling */
4356 type
= g_type_register_static (LTTV_TRACEFILE_CONTEXT_TYPE
,
4357 "LttvTracefileStateType", &info
, 0);
4363 static void module_init()
4365 LTTV_STATE_UNNAMED
= g_quark_from_string("");
4366 LTTV_STATE_UNBRANDED
= g_quark_from_string("");
4367 LTTV_STATE_MODE_UNKNOWN
= g_quark_from_string("MODE_UNKNOWN");
4368 LTTV_STATE_USER_MODE
= g_quark_from_string("USER_MODE");
4369 LTTV_STATE_SYSCALL
= g_quark_from_string("SYSCALL");
4370 LTTV_STATE_TRAP
= g_quark_from_string("TRAP");
4371 LTTV_STATE_IRQ
= g_quark_from_string("IRQ");
4372 LTTV_STATE_SOFT_IRQ
= g_quark_from_string("SOFTIRQ");
4373 LTTV_STATE_SUBMODE_UNKNOWN
= g_quark_from_string("UNKNOWN");
4374 LTTV_STATE_SUBMODE_NONE
= g_quark_from_string("NONE");
4375 LTTV_STATE_WAIT_FORK
= g_quark_from_string("WAIT_FORK");
4376 LTTV_STATE_WAIT_CPU
= g_quark_from_string("WAIT_CPU");
4377 LTTV_STATE_EXIT
= g_quark_from_string("EXIT");
4378 LTTV_STATE_ZOMBIE
= g_quark_from_string("ZOMBIE");
4379 LTTV_STATE_WAIT
= g_quark_from_string("WAIT");
4380 LTTV_STATE_RUN
= g_quark_from_string("RUN");
4381 LTTV_STATE_DEAD
= g_quark_from_string("DEAD");
4382 LTTV_STATE_USER_THREAD
= g_quark_from_string("USER_THREAD");
4383 LTTV_STATE_KERNEL_THREAD
= g_quark_from_string("KERNEL_THREAD");
4384 LTTV_STATE_TRACEFILES
= g_quark_from_string("tracefiles");
4385 LTTV_STATE_PROCESSES
= g_quark_from_string("processes");
4386 LTTV_STATE_PROCESS
= g_quark_from_string("process");
4387 LTTV_STATE_RUNNING_PROCESS
= g_quark_from_string("running_process");
4388 LTTV_STATE_EVENT
= g_quark_from_string("event");
4389 LTTV_STATE_SAVED_STATES
= g_quark_from_string("saved states");
4390 LTTV_STATE_SAVED_STATES_TIME
= g_quark_from_string("saved states time");
4391 LTTV_STATE_TIME
= g_quark_from_string("time");
4392 LTTV_STATE_HOOKS
= g_quark_from_string("saved state hooks");
4393 LTTV_STATE_NAME_TABLES
= g_quark_from_string("name tables");
4394 LTTV_STATE_TRACE_STATE_USE_COUNT
=
4395 g_quark_from_string("trace_state_use_count");
4396 LTTV_STATE_RESOURCE_CPUS
= g_quark_from_string("cpu resource states");
4397 LTTV_STATE_RESOURCE_CPUS
= g_quark_from_string("cpu count");
4398 LTTV_STATE_RESOURCE_IRQS
= g_quark_from_string("irq resource states");
4399 LTTV_STATE_RESOURCE_SOFT_IRQS
= g_quark_from_string("soft irq resource states");
4400 LTTV_STATE_RESOURCE_TRAPS
= g_quark_from_string("trap resource states");
4401 LTTV_STATE_RESOURCE_BLKDEVS
= g_quark_from_string("blkdevs resource states");
4403 LTT_CHANNEL_FD_STATE
= g_quark_from_string("fd_state");
4404 LTT_CHANNEL_GLOBAL_STATE
= g_quark_from_string("global_state");
4405 LTT_CHANNEL_IRQ_STATE
= g_quark_from_string("irq_state");
4406 LTT_CHANNEL_MODULE_STATE
= g_quark_from_string("module_state");
4407 LTT_CHANNEL_NETIF_STATE
= g_quark_from_string("netif_state");
4408 LTT_CHANNEL_SOFTIRQ_STATE
= g_quark_from_string("softirq_state");
4409 LTT_CHANNEL_SWAP_STATE
= g_quark_from_string("swap_state");
4410 LTT_CHANNEL_SYSCALL_STATE
= g_quark_from_string("syscall_state");
4411 LTT_CHANNEL_TASK_STATE
= g_quark_from_string("task_state");
4412 LTT_CHANNEL_VM_STATE
= g_quark_from_string("vm_state");
4413 LTT_CHANNEL_KPROBE_STATE
= g_quark_from_string("kprobe_state");
4414 LTT_CHANNEL_FS
= g_quark_from_string("fs");
4415 LTT_CHANNEL_KERNEL
= g_quark_from_string("kernel");
4416 LTT_CHANNEL_MM
= g_quark_from_string("mm");
4417 LTT_CHANNEL_USERSPACE
= g_quark_from_string("userspace");
4418 LTT_CHANNEL_BLOCK
= g_quark_from_string("block");
4420 LTT_EVENT_SYSCALL_ENTRY
= g_quark_from_string("syscall_entry");
4421 LTT_EVENT_SYSCALL_EXIT
= g_quark_from_string("syscall_exit");
4422 LTT_EVENT_TRAP_ENTRY
= g_quark_from_string("trap_entry");
4423 LTT_EVENT_TRAP_EXIT
= g_quark_from_string("trap_exit");
4424 LTT_EVENT_PAGE_FAULT_ENTRY
= g_quark_from_string("page_fault_entry");
4425 LTT_EVENT_PAGE_FAULT_EXIT
= g_quark_from_string("page_fault_exit");
4426 LTT_EVENT_PAGE_FAULT_NOSEM_ENTRY
= g_quark_from_string("page_fault_nosem_entry");
4427 LTT_EVENT_PAGE_FAULT_NOSEM_EXIT
= g_quark_from_string("page_fault_nosem_exit");
4428 LTT_EVENT_IRQ_ENTRY
= g_quark_from_string("irq_entry");
4429 LTT_EVENT_IRQ_EXIT
= g_quark_from_string("irq_exit");
4430 LTT_EVENT_SOFT_IRQ_RAISE
= g_quark_from_string("softirq_raise");
4431 LTT_EVENT_SOFT_IRQ_ENTRY
= g_quark_from_string("softirq_entry");
4432 LTT_EVENT_SOFT_IRQ_EXIT
= g_quark_from_string("softirq_exit");
4433 LTT_EVENT_SCHED_SCHEDULE
= g_quark_from_string("sched_schedule");
4434 LTT_EVENT_SCHED_TRY_WAKEUP
= g_quark_from_string("sched_try_wakeup");
4435 LTT_EVENT_PROCESS_FORK
= g_quark_from_string("process_fork");
4436 LTT_EVENT_KTHREAD_CREATE
= g_quark_from_string("kthread_create");
4437 LTT_EVENT_PROCESS_EXIT
= g_quark_from_string("process_exit");
4438 LTT_EVENT_PROCESS_FREE
= g_quark_from_string("process_free");
4439 LTT_EVENT_EXEC
= g_quark_from_string("exec");
4440 LTT_EVENT_PROCESS_STATE
= g_quark_from_string("process_state");
4441 LTT_EVENT_STATEDUMP_END
= g_quark_from_string("statedump_end");
4442 LTT_EVENT_FUNCTION_ENTRY
= g_quark_from_string("function_entry");
4443 LTT_EVENT_FUNCTION_EXIT
= g_quark_from_string("function_exit");
4444 LTT_EVENT_THREAD_BRAND
= g_quark_from_string("thread_brand");
4445 LTT_EVENT_REQUEST_ISSUE
= g_quark_from_string("_blk_request_issue");
4446 LTT_EVENT_REQUEST_COMPLETE
= g_quark_from_string("_blk_request_complete");
4447 LTT_EVENT_LIST_INTERRUPT
= g_quark_from_string("interrupt");
4448 LTT_EVENT_SYS_CALL_TABLE
= g_quark_from_string("sys_call_table");
4449 LTT_EVENT_SOFTIRQ_VEC
= g_quark_from_string("softirq_vec");
4450 LTT_EVENT_KPROBE_TABLE
= g_quark_from_string("kprobe_table");
4451 LTT_EVENT_KPROBE
= g_quark_from_string("kprobe");
4452 LTT_EVENT_OPEN
= g_quark_from_string("open");
4453 LTT_EVENT_READ
= g_quark_from_string("read");
4454 LTT_EVENT_POLL_EVENT
= g_quark_from_string("poll_event");
4456 LTT_FIELD_SYSCALL_ID
= g_quark_from_string("syscall_id");
4457 LTT_FIELD_TRAP_ID
= g_quark_from_string("trap_id");
4458 LTT_FIELD_IRQ_ID
= g_quark_from_string("irq_id");
4459 LTT_FIELD_SOFT_IRQ_ID
= g_quark_from_string("softirq_id");
4460 LTT_FIELD_PREV_PID
= g_quark_from_string("prev_pid");
4461 LTT_FIELD_NEXT_PID
= g_quark_from_string("next_pid");
4462 LTT_FIELD_PREV_STATE
= g_quark_from_string("prev_state");
4463 LTT_FIELD_PARENT_PID
= g_quark_from_string("parent_pid");
4464 LTT_FIELD_CHILD_PID
= g_quark_from_string("child_pid");
4465 LTT_FIELD_PID
= g_quark_from_string("pid");
4466 LTT_FIELD_TGID
= g_quark_from_string("tgid");
4467 LTT_FIELD_CHILD_TGID
= g_quark_from_string("child_tgid");
4468 LTT_FIELD_FILENAME
= g_quark_from_string("filename");
4469 LTT_FIELD_NAME
= g_quark_from_string("name");
4470 LTT_FIELD_TYPE
= g_quark_from_string("type");
4471 LTT_FIELD_MODE
= g_quark_from_string("mode");
4472 LTT_FIELD_SUBMODE
= g_quark_from_string("submode");
4473 LTT_FIELD_STATUS
= g_quark_from_string("status");
4474 LTT_FIELD_THIS_FN
= g_quark_from_string("this_fn");
4475 LTT_FIELD_CALL_SITE
= g_quark_from_string("call_site");
4476 LTT_FIELD_MAJOR
= g_quark_from_string("major");
4477 LTT_FIELD_MINOR
= g_quark_from_string("minor");
4478 LTT_FIELD_OPERATION
= g_quark_from_string("direction");
4479 LTT_FIELD_ACTION
= g_quark_from_string("action");
4480 LTT_FIELD_ID
= g_quark_from_string("id");
4481 LTT_FIELD_ADDRESS
= g_quark_from_string("address");
4482 LTT_FIELD_SYMBOL
= g_quark_from_string("symbol");
4483 LTT_FIELD_IP
= g_quark_from_string("ip");
4484 LTT_FIELD_FD
= g_quark_from_string("fd");
4486 LTTV_CPU_UNKNOWN
= g_quark_from_string("unknown");
4487 LTTV_CPU_IDLE
= g_quark_from_string("idle");
4488 LTTV_CPU_BUSY
= g_quark_from_string("busy");
4489 LTTV_CPU_IRQ
= g_quark_from_string("irq");
4490 LTTV_CPU_SOFT_IRQ
= g_quark_from_string("softirq");
4491 LTTV_CPU_TRAP
= g_quark_from_string("trap");
4493 LTTV_IRQ_UNKNOWN
= g_quark_from_string("unknown");
4494 LTTV_IRQ_IDLE
= g_quark_from_string("idle");
4495 LTTV_IRQ_BUSY
= g_quark_from_string("busy");
4497 LTTV_BDEV_UNKNOWN
= g_quark_from_string("unknown");
4498 LTTV_BDEV_IDLE
= g_quark_from_string("idle");
4499 LTTV_BDEV_BUSY_READING
= g_quark_from_string("busy_reading");
4500 LTTV_BDEV_BUSY_WRITING
= g_quark_from_string("busy_writing");
4503 static void module_destroy()
4508 LTTV_MODULE("state", "State computation", \
4509 "Update the system state, possibly saving it at intervals", \
4510 module_init
, module_destroy
)