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
,
144 LTTV_STATE_MODE_UNKNOWN
,
145 LTTV_STATE_USER_MODE
,
146 LTTV_STATE_MAYBE_USER_MODE
,
148 LTTV_STATE_MAYBE_SYSCALL
,
150 LTTV_STATE_MAYBE_TRAP
,
155 LTTV_STATE_SUBMODE_UNKNOWN
,
156 LTTV_STATE_SUBMODE_NONE
;
160 LTTV_STATE_WAIT_FORK
,
169 LTTV_STATE_UNBRANDED
;
172 LTTV_STATE_USER_THREAD
,
173 LTTV_STATE_KERNEL_THREAD
;
191 LTTV_BDEV_BUSY_READING
,
192 LTTV_BDEV_BUSY_WRITING
;
195 LTTV_STATE_TRACEFILES
,
196 LTTV_STATE_PROCESSES
,
198 LTTV_STATE_RUNNING_PROCESS
,
200 LTTV_STATE_SAVED_STATES
,
201 LTTV_STATE_SAVED_STATES_TIME
,
204 LTTV_STATE_NAME_TABLES
,
205 LTTV_STATE_TRACE_STATE_USE_COUNT
,
206 LTTV_STATE_RESOURCE_CPUS
,
207 LTTV_STATE_RESOURCE_CPUS_COUNT
,
208 LTTV_STATE_RESOURCE_IRQS
,
209 LTTV_STATE_RESOURCE_SOFT_IRQS
,
210 LTTV_STATE_RESOURCE_TRAPS
,
211 LTTV_STATE_RESOURCE_BLKDEVS
;
213 static void create_max_time(LttvTraceState
*tcs
);
215 static void get_max_time(LttvTraceState
*tcs
);
217 static void free_max_time(LttvTraceState
*tcs
);
219 static void create_name_tables(LttvTraceState
*tcs
);
221 static void get_name_tables(LttvTraceState
*tcs
);
223 static void free_name_tables(LttvTraceState
*tcs
);
225 static void free_saved_state(LttvTraceState
*tcs
);
227 static void lttv_state_free_process_table(GHashTable
*processes
);
229 static void lttv_trace_states_read_raw(LttvTraceState
*tcs
, FILE *fp
,
230 GPtrArray
*quarktable
);
232 /* Resource function prototypes */
233 static LttvBdevState
*get_hashed_bdevstate(LttvTraceState
*ts
, guint32 devcode
);
234 static LttvBdevState
*bdevstate_new(void);
235 static void bdevstate_free(LttvBdevState
*);
236 static void bdevstate_free_cb(gpointer key
, gpointer value
, gpointer user_data
);
237 static LttvBdevState
*bdevstate_copy(LttvBdevState
*bds
);
240 #if (__WORDSIZE == 32)
241 guint
guint64_hash(gconstpointer key
)
243 guint64 ukey
= *(const guint64
*)key
;
245 return (guint
)ukey
^ (guint
)(ukey
>> 32);
248 gboolean
guint64_equal(gconstpointer a
, gconstpointer b
)
250 guint64 ua
= *(const guint64
*)a
;
251 guint64 ub
= *(const guint64
*)b
;
257 void lttv_state_save(LttvTraceState
*self
, LttvAttribute
*container
)
259 LTTV_TRACE_STATE_GET_CLASS(self
)->state_save(self
, container
);
263 void lttv_state_restore(LttvTraceState
*self
, LttvAttribute
*container
)
265 LTTV_TRACE_STATE_GET_CLASS(self
)->state_restore(self
, container
);
269 void lttv_state_state_saved_free(LttvTraceState
*self
,
270 LttvAttribute
*container
)
272 LTTV_TRACE_STATE_GET_CLASS(self
)->state_saved_free(self
, container
);
276 guint
process_hash(gconstpointer key
)
278 guint pid
= ((const LttvProcessState
*)key
)->pid
;
279 return (pid
>>8 ^ pid
>>4 ^ pid
>>2 ^ pid
) ;
283 /* If the hash table hash function is well distributed,
284 * the process_equal should compare different pid */
285 gboolean
process_equal(gconstpointer a
, gconstpointer b
)
287 const LttvProcessState
*process_a
, *process_b
;
290 process_a
= (const LttvProcessState
*)a
;
291 process_b
= (const LttvProcessState
*)b
;
293 if(likely(process_a
->pid
!= process_b
->pid
)) ret
= FALSE
;
294 else if(likely(process_a
->pid
== 0 &&
295 process_a
->cpu
!= process_b
->cpu
)) ret
= FALSE
;
300 static void delete_usertrace(gpointer key
, gpointer value
, gpointer user_data
)
302 g_tree_destroy((GTree
*)value
);
305 static void lttv_state_free_usertraces(GHashTable
*usertraces
)
307 g_hash_table_foreach(usertraces
, delete_usertrace
, NULL
);
308 g_hash_table_destroy(usertraces
);
311 gboolean
rettrue(gpointer key
, gpointer value
, gpointer user_data
)
316 static guint
check_expand(nb
, id
)
321 return max(id
+ 1, nb
* 2);
324 static void expand_name_table(LttvTraceState
*ts
, GQuark
**table
,
325 guint nb
, guint new_nb
)
327 /* Expand an incomplete table */
328 GQuark
*old_table
= *table
;
329 *table
= g_new(GQuark
, new_nb
);
330 memcpy(*table
, old_table
, nb
* sizeof(GQuark
));
334 static void fill_name_table(LttvTraceState
*ts
, GQuark
*table
, guint nb
,
335 guint new_nb
, const char *def_string
)
338 GString
*fe_name
= g_string_new("");
339 for(i
= nb
; i
< new_nb
; i
++) {
340 g_string_printf(fe_name
, "%s %d", def_string
, i
);
341 table
[i
] = g_quark_from_string(fe_name
->str
);
343 g_string_free(fe_name
, TRUE
);
346 static void expand_syscall_table(LttvTraceState
*ts
, int id
)
348 LttvNameTables
*nt
= ts
->name_tables
;
351 new_nb
= check_expand(nt
->nb_syscalls
, id
);
352 if(likely(new_nb
== nt
->nb_syscalls
))
354 expand_name_table(ts
, &nt
->syscall_names
, nt
->nb_syscalls
, new_nb
);
355 fill_name_table(ts
, nt
->syscall_names
, nt
->nb_syscalls
, new_nb
, "syscall");
356 /* Update the table size */
357 nt
->nb_syscalls
= new_nb
;
360 static void expand_kprobe_table(LttvTraceState
*ts
, guint64 ip
, char *symbol
)
362 LttvNameTables
*nt
= ts
->name_tables
;
363 #if (__WORDSIZE == 32)
364 guint64
*ip_ptr
= g_new(guint64
, 1);
365 g_hash_table_insert(nt
->kprobe_hash
, ip_ptr
,
366 (gpointer
)(glong
)g_quark_from_string(symbol
));
368 g_hash_table_insert(nt
->kprobe_hash
, (gpointer
)ip
,
369 (gpointer
)(glong
)g_quark_from_string(symbol
));
373 static void expand_trap_table(LttvTraceState
*ts
, int id
)
375 LttvNameTables
*nt
= ts
->name_tables
;
376 LttvTrapState
*old_table
;
379 new_nb
= check_expand(nt
->nb_traps
, id
);
380 if(likely(new_nb
== nt
->nb_traps
))
383 expand_name_table(ts
, &nt
->trap_names
, nt
->nb_traps
, new_nb
);
384 fill_name_table(ts
, nt
->trap_names
, nt
->nb_traps
, new_nb
, "trap");
386 old_table
= ts
->trap_states
;
387 ts
->trap_states
= g_new(LttvTrapState
, new_nb
);
388 memcpy(ts
->trap_states
, old_table
, nt
->nb_traps
* sizeof(LttvTrapState
));
390 for(i
= nt
->nb_traps
; i
< new_nb
; i
++)
391 ts
->trap_states
[i
].running
= 0;
393 /* Update the table size */
394 nt
->nb_traps
= new_nb
;
397 static void expand_irq_table(LttvTraceState
*ts
, int id
)
399 LttvNameTables
*nt
= ts
->name_tables
;
400 LttvIRQState
*old_table
;
403 new_nb
= check_expand(nt
->nb_irqs
, id
);
404 if(likely(new_nb
== nt
->nb_irqs
))
407 expand_name_table(ts
, &nt
->irq_names
, nt
->nb_irqs
, new_nb
);
408 fill_name_table(ts
, nt
->irq_names
, nt
->nb_irqs
, new_nb
, "irq");
410 old_table
= ts
->irq_states
;
411 ts
->irq_states
= g_new(LttvIRQState
, new_nb
);
412 memcpy(ts
->irq_states
, old_table
, nt
->nb_irqs
* sizeof(LttvIRQState
));
414 for(i
= nt
->nb_irqs
; i
< new_nb
; i
++)
415 ts
->irq_states
[i
].mode_stack
=
416 g_array_new(FALSE
, FALSE
, sizeof(LttvIRQMode
));
418 /* Update the table size */
419 nt
->nb_irqs
= new_nb
;
422 static void expand_soft_irq_table(LttvTraceState
*ts
, int id
)
424 LttvNameTables
*nt
= ts
->name_tables
;
425 LttvSoftIRQState
*old_table
;
428 new_nb
= check_expand(nt
->nb_soft_irqs
, id
);
429 if(likely(new_nb
== nt
->nb_soft_irqs
))
432 expand_name_table(ts
, &nt
->soft_irq_names
, nt
->nb_soft_irqs
, new_nb
);
433 fill_name_table(ts
, nt
->soft_irq_names
, nt
->nb_soft_irqs
, new_nb
, "softirq");
435 old_table
= ts
->soft_irq_states
;
436 ts
->soft_irq_states
= g_new(LttvSoftIRQState
, new_nb
);
437 memcpy(ts
->soft_irq_states
, old_table
,
438 nt
->nb_soft_irqs
* sizeof(LttvSoftIRQState
));
440 for(i
= nt
->nb_soft_irqs
; i
< new_nb
; i
++)
441 ts
->soft_irq_states
[i
].running
= 0;
443 /* Update the table size */
444 nt
->nb_soft_irqs
= new_nb
;
447 static void restore_init_state(LttvTraceState
*self
)
449 guint i
, nb_cpus
, nb_irqs
, nb_soft_irqs
, nb_traps
;
451 //LttvTracefileState *tfcs;
453 LttTime start_time
, end_time
;
455 /* Free the process tables */
456 if(self
->processes
!= NULL
) lttv_state_free_process_table(self
->processes
);
457 if(self
->usertraces
!= NULL
) lttv_state_free_usertraces(self
->usertraces
);
458 self
->processes
= g_hash_table_new(process_hash
, process_equal
);
459 self
->usertraces
= g_hash_table_new(g_direct_hash
, g_direct_equal
);
462 /* Seek time to beginning */
463 // Mathieu : fix : don't seek traceset here : causes inconsistency in seek
464 // closest. It's the tracecontext job to seek the trace to the beginning
465 // anyway : the init state might be used at the middle of the trace as well...
466 //g_tree_destroy(self->parent.ts_context->pqueue);
467 //self->parent.ts_context->pqueue = g_tree_new(compare_tracefile);
469 ltt_trace_time_span_get(self
->parent
.t
, &start_time
, &end_time
);
471 //lttv_process_trace_seek_time(&self->parent, ltt_time_zero);
473 nb_cpus
= ltt_trace_get_num_cpu(self
->parent
.t
);
474 nb_irqs
= self
->name_tables
->nb_irqs
;
475 nb_soft_irqs
= self
->name_tables
->nb_soft_irqs
;
476 nb_traps
= self
->name_tables
->nb_traps
;
478 /* Put the per cpu running_process to beginning state : process 0. */
479 for(i
=0; i
< nb_cpus
; i
++) {
480 LttvExecutionState
*es
;
481 self
->running_process
[i
] = lttv_state_create_process(self
, NULL
, i
, 0, 0,
482 LTTV_STATE_UNNAMED
, &start_time
);
483 /* We are not sure is it's a kernel thread or normal thread, put the
484 * bottom stack state to unknown */
485 self
->running_process
[i
]->execution_stack
=
486 g_array_set_size(self
->running_process
[i
]->execution_stack
, 1);
487 es
= self
->running_process
[i
]->state
=
488 &g_array_index(self
->running_process
[i
]->execution_stack
,
489 LttvExecutionState
, 0);
490 es
->t
= LTTV_STATE_MODE_UNKNOWN
;
491 es
->s
= LTTV_STATE_UNNAMED
;
493 //self->running_process[i]->state->s = LTTV_STATE_RUN;
494 self
->running_process
[i
]->cpu
= i
;
496 /* reset cpu states */
497 if(self
->cpu_states
[i
].mode_stack
->len
> 0) {
498 g_array_remove_range(self
->cpu_states
[i
].mode_stack
, 0,
499 self
->cpu_states
[i
].mode_stack
->len
);
500 if(self
->cpu_states
[i
].irq_stack
->len
)
501 g_array_remove_range(self
->cpu_states
[i
].irq_stack
, 0,
502 self
->cpu_states
[i
].irq_stack
->len
);
503 if(self
->cpu_states
[i
].softirq_stack
->len
)
504 g_array_remove_range(self
->cpu_states
[i
].softirq_stack
, 0,
505 self
->cpu_states
[i
].softirq_stack
->len
);
506 if(self
->cpu_states
[i
].trap_stack
->len
)
507 g_array_remove_range(self
->cpu_states
[i
].trap_stack
, 0,
508 self
->cpu_states
[i
].trap_stack
->len
);
512 /* reset irq states */
513 for(i
=0; i
<nb_irqs
; i
++) {
514 if(self
->irq_states
[i
].mode_stack
->len
> 0)
515 g_array_remove_range(self
->irq_states
[i
].mode_stack
, 0,
516 self
->irq_states
[i
].mode_stack
->len
);
519 /* reset softirq states */
520 for(i
=0; i
<nb_soft_irqs
; i
++) {
521 self
->soft_irq_states
[i
].pending
= 0;
522 self
->soft_irq_states
[i
].running
= 0;
525 /* reset trap states */
526 for(i
=0; i
<nb_traps
; i
++) {
527 self
->trap_states
[i
].running
= 0;
530 /* reset bdev states */
531 g_hash_table_foreach(self
->bdev_states
, bdevstate_free_cb
, NULL
);
532 //g_hash_table_steal_all(self->bdev_states);
533 g_hash_table_foreach_steal(self
->bdev_states
, rettrue
, NULL
);
536 nb_tracefile
= self
->parent
.tracefiles
->len
;
538 for(i
= 0 ; i
< nb_tracefile
; i
++) {
540 LTTV_TRACEFILE_STATE(g_array_index(self
->parent
.tracefiles
,
541 LttvTracefileContext
*, i
));
542 ltt_trace_time_span_get(self
->parent
.t
, &tfcs
->parent
.timestamp
, NULL
);
543 // tfcs->saved_position = 0;
544 tfcs
->process
= lttv_state_create_process(tfcs
, NULL
,0);
545 tfcs
->process
->state
->s
= LTTV_STATE_RUN
;
546 tfcs
->process
->last_cpu
= tfcs
->cpu_name
;
547 tfcs
->process
->last_cpu_index
= ltt_tracefile_num(((LttvTracefileContext
*)tfcs
)->tf
);
552 //static LttTime time_zero = {0,0};
554 static gint
compare_usertraces(gconstpointer a
, gconstpointer b
,
557 const LttTime
*t1
= (const LttTime
*)a
;
558 const LttTime
*t2
= (const LttTime
*)b
;
560 return ltt_time_compare(*t1
, *t2
);
563 static void free_usertrace_key(gpointer data
)
568 #define MAX_STRING_LEN 4096
570 static void state_load_saved_states(LttvTraceState
*tcs
)
573 GPtrArray
*quarktable
;
574 const char *trace_path
;
578 tcs
->has_precomputed_states
= FALSE
;
582 gchar buf
[MAX_STRING_LEN
];
586 trace_path
= g_quark_to_string(ltt_trace_name(tcs
->parent
.t
));
587 strncpy(path
, trace_path
, PATH_MAX
-1);
588 count
= strnlen(trace_path
, PATH_MAX
-1);
589 // quarktable : open, test
590 strncat(path
, "/precomputed/quarktable", PATH_MAX
-count
-1);
591 fp
= fopen(path
, "r");
593 quarktable
= g_ptr_array_sized_new(4096);
595 /* Index 0 is null */
597 if(hdr
== EOF
) return;
598 g_assert(hdr
== HDR_QUARKS
);
602 if(hdr
== EOF
) break;
603 g_assert(hdr
== HDR_QUARK
);
604 g_ptr_array_set_size(quarktable
, q
+1);
607 res
= fread(&buf
[i
], sizeof(gchar
), 1, fp
);
609 if(buf
[i
] == '\0' || feof(fp
)) break;
612 len
= strnlen(buf
, MAX_STRING_LEN
-1);
613 g_ptr_array_index (quarktable
, q
) = g_new(gchar
, len
+1);
614 strncpy(g_ptr_array_index (quarktable
, q
), buf
, len
+1);
620 // saved_states : open, test
621 strncpy(path
, trace_path
, PATH_MAX
-1);
622 count
= strnlen(trace_path
, PATH_MAX
-1);
623 strncat(path
, "/precomputed/states", PATH_MAX
-count
-1);
624 fp
= fopen(path
, "r");
628 if(hdr
!= HDR_TRACE
) goto end
;
630 lttv_trace_states_read_raw(tcs
, fp
, quarktable
);
632 tcs
->has_precomputed_states
= TRUE
;
637 /* Free the quarktable */
638 for(i
=0; i
<quarktable
->len
; i
++) {
639 string
= g_ptr_array_index (quarktable
, i
);
642 g_ptr_array_free(quarktable
, TRUE
);
646 static void init(LttvTracesetState
*self
, LttvTraceset
*ts
)
648 guint i
, j
, nb_trace
, nb_tracefile
, nb_cpu
;
651 LttvTraceContext
*tc
;
655 LttvTracefileState
*tfcs
;
657 LttvAttributeValue v
;
659 LTTV_TRACESET_CONTEXT_CLASS(g_type_class_peek(LTTV_TRACESET_CONTEXT_TYPE
))->
660 init((LttvTracesetContext
*)self
, ts
);
662 nb_trace
= lttv_traceset_number(ts
);
663 for(i
= 0 ; i
< nb_trace
; i
++) {
664 tc
= self
->parent
.traces
[i
];
665 tcs
= LTTV_TRACE_STATE(tc
);
666 tcs
->save_interval
= LTTV_STATE_SAVE_INTERVAL
;
667 lttv_attribute_find(tcs
->parent
.t_a
, LTTV_STATE_TRACE_STATE_USE_COUNT
,
671 if(*(v
.v_uint
) == 1) {
672 create_name_tables(tcs
);
673 create_max_time(tcs
);
675 get_name_tables(tcs
);
678 nb_tracefile
= tc
->tracefiles
->len
;
679 nb_cpu
= ltt_trace_get_num_cpu(tc
->t
);
680 nb_irq
= tcs
->name_tables
->nb_irqs
;
681 tcs
->processes
= NULL
;
682 tcs
->usertraces
= NULL
;
683 tcs
->running_process
= g_new(LttvProcessState
*, nb_cpu
);
685 /* init cpu resource stuff */
686 tcs
->cpu_states
= g_new(LttvCPUState
, nb_cpu
);
687 for(j
= 0; j
<nb_cpu
; j
++) {
688 tcs
->cpu_states
[j
].mode_stack
= g_array_new(FALSE
, FALSE
, sizeof(LttvCPUMode
));
689 tcs
->cpu_states
[j
].irq_stack
= g_array_new(FALSE
, FALSE
, sizeof(gint
));
690 tcs
->cpu_states
[j
].softirq_stack
= g_array_new(FALSE
, FALSE
, sizeof(gint
));
691 tcs
->cpu_states
[j
].trap_stack
= g_array_new(FALSE
, FALSE
, sizeof(gint
));
692 g_assert(tcs
->cpu_states
[j
].mode_stack
!= NULL
);
695 /* init irq resource stuff */
696 tcs
->irq_states
= g_new(LttvIRQState
, nb_irq
);
697 for(j
= 0; j
<nb_irq
; j
++) {
698 tcs
->irq_states
[j
].mode_stack
= g_array_new(FALSE
, FALSE
, sizeof(LttvIRQMode
));
699 g_assert(tcs
->irq_states
[j
].mode_stack
!= NULL
);
702 /* init soft irq stuff */
703 /* the kernel has a statically fixed max of 32 softirqs */
704 tcs
->soft_irq_states
= g_new(LttvSoftIRQState
, tcs
->name_tables
->nb_soft_irqs
);
706 /* init trap stuff */
707 tcs
->trap_states
= g_new(LttvTrapState
, tcs
->name_tables
->nb_traps
);
709 /* init bdev resource stuff */
710 tcs
->bdev_states
= g_hash_table_new(g_int_hash
, g_int_equal
);
712 restore_init_state(tcs
);
713 for(j
= 0 ; j
< nb_tracefile
; j
++) {
715 LTTV_TRACEFILE_STATE(g_array_index(tc
->tracefiles
,
716 LttvTracefileContext
*, j
));
717 tfcs
->tracefile_name
= ltt_tracefile_name(tfcs
->parent
.tf
);
718 tfcs
->cpu
= ltt_tracefile_cpu(tfcs
->parent
.tf
);
719 tfcs
->cpu_state
= &(tcs
->cpu_states
[tfcs
->cpu
]);
720 if(ltt_tracefile_tid(tfcs
->parent
.tf
) != 0) {
721 /* It's a Usertrace */
722 guint tid
= ltt_tracefile_tid(tfcs
->parent
.tf
);
723 GTree
*usertrace_tree
= (GTree
*)g_hash_table_lookup(tcs
->usertraces
,
724 GUINT_TO_POINTER(tid
));
725 if(!usertrace_tree
) {
726 usertrace_tree
= g_tree_new_full(compare_usertraces
,
727 NULL
, free_usertrace_key
, NULL
);
728 g_hash_table_insert(tcs
->usertraces
,
729 GUINT_TO_POINTER(tid
), usertrace_tree
);
731 LttTime
*timestamp
= g_new(LttTime
, 1);
732 *timestamp
= ltt_interpolate_time_from_tsc(tfcs
->parent
.tf
,
733 ltt_tracefile_creation(tfcs
->parent
.tf
));
734 g_tree_insert(usertrace_tree
, timestamp
, tfcs
);
738 /* See if the trace has saved states */
739 state_load_saved_states(tcs
);
743 static void fini(LttvTracesetState
*self
)
749 //LttvTracefileState *tfcs;
751 LttvAttributeValue v
;
753 nb_trace
= lttv_traceset_number(LTTV_TRACESET_CONTEXT(self
)->ts
);
754 for(i
= 0 ; i
< nb_trace
; i
++) {
755 tcs
= (LttvTraceState
*)(LTTV_TRACESET_CONTEXT(self
)->traces
[i
]);
756 lttv_attribute_find(tcs
->parent
.t_a
, LTTV_STATE_TRACE_STATE_USE_COUNT
,
759 g_assert(*(v
.v_uint
) != 0);
762 if(*(v
.v_uint
) == 0) {
763 free_name_tables(tcs
);
765 free_saved_state(tcs
);
767 g_free(tcs
->running_process
);
768 tcs
->running_process
= NULL
;
769 lttv_state_free_process_table(tcs
->processes
);
770 lttv_state_free_usertraces(tcs
->usertraces
);
771 tcs
->processes
= NULL
;
772 tcs
->usertraces
= NULL
;
774 LTTV_TRACESET_CONTEXT_CLASS(g_type_class_peek(LTTV_TRACESET_CONTEXT_TYPE
))->
775 fini((LttvTracesetContext
*)self
);
779 static LttvTracesetContext
*new_traceset_context(LttvTracesetContext
*self
)
781 return LTTV_TRACESET_CONTEXT(g_object_new(LTTV_TRACESET_STATE_TYPE
, NULL
));
785 static LttvTraceContext
*new_trace_context(LttvTracesetContext
*self
)
787 return LTTV_TRACE_CONTEXT(g_object_new(LTTV_TRACE_STATE_TYPE
, NULL
));
791 static LttvTracefileContext
*new_tracefile_context(LttvTracesetContext
*self
)
793 return LTTV_TRACEFILE_CONTEXT(g_object_new(LTTV_TRACEFILE_STATE_TYPE
, NULL
));
797 /* Write the process state of the trace */
799 static void write_process_state(gpointer key
, gpointer value
,
802 LttvProcessState
*process
;
804 LttvExecutionState
*es
;
806 FILE *fp
= (FILE *)user_data
;
811 process
= (LttvProcessState
*)value
;
812 fprintf(fp
," <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",
813 process
, process
->pid
, process
->tgid
, process
->ppid
,
814 g_quark_to_string(process
->type
),
815 process
->creation_time
.tv_sec
,
816 process
->creation_time
.tv_nsec
,
817 process
->insertion_time
.tv_sec
,
818 process
->insertion_time
.tv_nsec
,
819 g_quark_to_string(process
->name
),
820 g_quark_to_string(process
->brand
),
821 process
->cpu
, process
->free_events
);
823 for(i
= 0 ; i
< process
->execution_stack
->len
; i
++) {
824 es
= &g_array_index(process
->execution_stack
, LttvExecutionState
, i
);
825 fprintf(fp
, " <ES MODE=\"%s\" SUBMODE=\"%s\" ENTRY_S=%lu ENTRY_NS=%lu",
826 g_quark_to_string(es
->t
), g_quark_to_string(es
->n
),
827 es
->entry
.tv_sec
, es
->entry
.tv_nsec
);
828 fprintf(fp
, " CHANGE_S=%lu CHANGE_NS=%lu STATUS=\"%s\"/>\n",
829 es
->change
.tv_sec
, es
->change
.tv_nsec
, g_quark_to_string(es
->s
));
832 for(i
= 0 ; i
< process
->user_stack
->len
; i
++) {
833 address
= g_array_index(process
->user_stack
, guint64
, i
);
834 fprintf(fp
, " <USER_STACK ADDRESS=\"%" PRIu64
"\"/>\n", address
);
837 if(process
->usertrace
) {
838 fprintf(fp
, " <USERTRACE NAME=\"%s\" CPU=%u\n/>",
839 g_quark_to_string(process
->usertrace
->tracefile_name
),
840 process
->usertrace
->cpu
);
844 fprintf(fp
, " </PROCESS>\n");
848 void lttv_state_write(LttvTraceState
*self
, LttTime t
, FILE *fp
)
850 guint i
, nb_tracefile
, nb_block
, offset
;
853 LttvTracefileState
*tfcs
;
857 LttEventPosition
*ep
;
861 ep
= ltt_event_position_new();
863 fprintf(fp
,"<PROCESS_STATE TIME_S=%lu TIME_NS=%lu>\n", t
.tv_sec
, t
.tv_nsec
);
865 g_hash_table_foreach(self
->processes
, write_process_state
, fp
);
867 nb_cpus
= ltt_trace_get_num_cpu(self
->parent
.t
);
868 for(i
=0;i
<nb_cpus
;i
++) {
869 fprintf(fp
," <CPU NUM=%u RUNNING_PROCESS=%u>\n",
870 i
, self
->running_process
[i
]->pid
);
873 nb_tracefile
= self
->parent
.tracefiles
->len
;
875 for(i
= 0 ; i
< nb_tracefile
; i
++) {
877 LTTV_TRACEFILE_STATE(g_array_index(self
->parent
.tracefiles
,
878 LttvTracefileContext
*, i
));
879 fprintf(fp
, " <TRACEFILE TIMESTAMP_S=%lu TIMESTAMP_NS=%lu",
880 tfcs
->parent
.timestamp
.tv_sec
,
881 tfcs
->parent
.timestamp
.tv_nsec
);
882 LttEvent
*e
= ltt_tracefile_get_event(tfcs
->parent
.tf
);
883 if(e
== NULL
) fprintf(fp
,"/>\n");
885 ltt_event_position(e
, ep
);
886 ltt_event_position_get(ep
, &tf
, &nb_block
, &offset
, &tsc
);
887 fprintf(fp
, " BLOCK=%u OFFSET=%u TSC=%" PRIu64
"/>\n", nb_block
, offset
,
892 fprintf(fp
,"</PROCESS_STATE>\n");
896 static void write_process_state_raw(gpointer key
, gpointer value
,
899 LttvProcessState
*process
;
901 LttvExecutionState
*es
;
903 FILE *fp
= (FILE *)user_data
;
908 process
= (LttvProcessState
*)value
;
909 fputc(HDR_PROCESS
, fp
);
910 //fwrite(&header, sizeof(header), 1, fp);
911 //fprintf(fp, "%s", g_quark_to_string(process->type));
913 fwrite(&process
->type
, sizeof(process
->type
), 1, fp
);
914 //fprintf(fp, "%s", g_quark_to_string(process->name));
916 fwrite(&process
->name
, sizeof(process
->name
), 1, fp
);
917 //fprintf(fp, "%s", g_quark_to_string(process->brand));
919 fwrite(&process
->brand
, sizeof(process
->brand
), 1, fp
);
920 fwrite(&process
->pid
, sizeof(process
->pid
), 1, fp
);
921 fwrite(&process
->free_events
, sizeof(process
->free_events
), 1, fp
);
922 fwrite(&process
->tgid
, sizeof(process
->tgid
), 1, fp
);
923 fwrite(&process
->ppid
, sizeof(process
->ppid
), 1, fp
);
924 fwrite(&process
->cpu
, sizeof(process
->cpu
), 1, fp
);
925 fwrite(&process
->creation_time
, sizeof(process
->creation_time
), 1, fp
);
926 fwrite(&process
->insertion_time
, sizeof(process
->insertion_time
), 1, fp
);
929 fprintf(fp
," <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",
930 process
, process
->pid
, process
->tgid
, process
->ppid
,
931 g_quark_to_string(process
->type
),
932 process
->creation_time
.tv_sec
,
933 process
->creation_time
.tv_nsec
,
934 process
->insertion_time
.tv_sec
,
935 process
->insertion_time
.tv_nsec
,
936 g_quark_to_string(process
->name
),
937 g_quark_to_string(process
->brand
),
941 for(i
= 0 ; i
< process
->execution_stack
->len
; i
++) {
942 es
= &g_array_index(process
->execution_stack
, LttvExecutionState
, i
);
945 //fprintf(fp, "%s", g_quark_to_string(es->t));
947 fwrite(&es
->t
, sizeof(es
->t
), 1, fp
);
948 //fprintf(fp, "%s", g_quark_to_string(es->n));
950 fwrite(&es
->n
, sizeof(es
->n
), 1, fp
);
951 //fprintf(fp, "%s", g_quark_to_string(es->s));
953 fwrite(&es
->s
, sizeof(es
->s
), 1, fp
);
954 fwrite(&es
->entry
, sizeof(es
->entry
), 1, fp
);
955 fwrite(&es
->change
, sizeof(es
->change
), 1, fp
);
956 fwrite(&es
->cum_cpu_time
, sizeof(es
->cum_cpu_time
), 1, fp
);
958 fprintf(fp
, " <ES MODE=\"%s\" SUBMODE=\"%s\" ENTRY_S=%lu ENTRY_NS=%lu",
959 g_quark_to_string(es
->t
), g_quark_to_string(es
->n
),
960 es
->entry
.tv_sec
, es
->entry
.tv_nsec
);
961 fprintf(fp
, " CHANGE_S=%lu CHANGE_NS=%lu STATUS=\"%s\"/>\n",
962 es
->change
.tv_sec
, es
->change
.tv_nsec
, g_quark_to_string(es
->s
));
966 for(i
= 0 ; i
< process
->user_stack
->len
; i
++) {
967 address
= g_array_index(process
->user_stack
, guint64
, i
);
968 fputc(HDR_USER_STACK
, fp
);
969 fwrite(&address
, sizeof(address
), 1, fp
);
971 fprintf(fp
, " <USER_STACK ADDRESS=\"%llu\"/>\n", address
);
975 if(process
->usertrace
) {
976 fputc(HDR_USERTRACE
, fp
);
977 //fprintf(fp, "%s", g_quark_to_string(process->usertrace->tracefile_name));
979 fwrite(&process
->usertrace
->tracefile_name
,
980 sizeof(process
->usertrace
->tracefile_name
), 1, fp
);
981 fwrite(&process
->usertrace
->cpu
, sizeof(process
->usertrace
->cpu
), 1, fp
);
983 fprintf(fp
, " <USERTRACE NAME=\"%s\" CPU=%u\n/>",
984 g_quark_to_string(process
->usertrace
->tracefile_name
),
985 process
->usertrace
->cpu
);
992 void lttv_state_write_raw(LttvTraceState
*self
, LttTime t
, FILE *fp
)
994 guint i
, nb_tracefile
, nb_block
, offset
;
997 LttvTracefileState
*tfcs
;
1001 LttEventPosition
*ep
;
1005 ep
= ltt_event_position_new();
1007 //fprintf(fp,"<PROCESS_STATE TIME_S=%lu TIME_NS=%lu>\n", t.tv_sec, t.tv_nsec);
1008 fputc(HDR_PROCESS_STATE
, fp
);
1009 fwrite(&t
, sizeof(t
), 1, fp
);
1011 g_hash_table_foreach(self
->processes
, write_process_state_raw
, fp
);
1013 nb_cpus
= ltt_trace_get_num_cpu(self
->parent
.t
);
1014 for(i
=0;i
<nb_cpus
;i
++) {
1016 fwrite(&i
, sizeof(i
), 1, fp
); /* cpu number */
1017 fwrite(&self
->running_process
[i
]->pid
,
1018 sizeof(self
->running_process
[i
]->pid
), 1, fp
);
1019 //fprintf(fp," <CPU NUM=%u RUNNING_PROCESS=%u>\n",
1020 // i, self->running_process[i]->pid);
1023 nb_tracefile
= self
->parent
.tracefiles
->len
;
1025 for(i
= 0 ; i
< nb_tracefile
; i
++) {
1027 LTTV_TRACEFILE_STATE(g_array_index(self
->parent
.tracefiles
,
1028 LttvTracefileContext
*, i
));
1029 // fprintf(fp, " <TRACEFILE TIMESTAMP_S=%lu TIMESTAMP_NS=%lu",
1030 // tfcs->parent.timestamp.tv_sec,
1031 // tfcs->parent.timestamp.tv_nsec);
1032 fputc(HDR_TRACEFILE
, fp
);
1033 fwrite(&tfcs
->parent
.timestamp
, sizeof(tfcs
->parent
.timestamp
), 1, fp
);
1034 /* Note : if timestamp if LTT_TIME_INFINITE, there will be no
1035 * position following : end of trace */
1036 LttEvent
*e
= ltt_tracefile_get_event(tfcs
->parent
.tf
);
1038 ltt_event_position(e
, ep
);
1039 ltt_event_position_get(ep
, &tf
, &nb_block
, &offset
, &tsc
);
1040 //fprintf(fp, " BLOCK=%u OFFSET=%u TSC=%llu/>\n", nb_block, offset,
1042 fwrite(&nb_block
, sizeof(nb_block
), 1, fp
);
1043 fwrite(&offset
, sizeof(offset
), 1, fp
);
1044 fwrite(&tsc
, sizeof(tsc
), 1, fp
);
1051 /* Read process state from a file */
1053 /* Called because a HDR_PROCESS was found */
1054 static void read_process_state_raw(LttvTraceState
*self
, FILE *fp
,
1055 GPtrArray
*quarktable
)
1057 LttvExecutionState
*es
;
1058 LttvProcessState
*process
, *parent_process
;
1059 LttvProcessState tmp
;
1065 res
= fread(&tmp
.type
, sizeof(tmp
.type
), 1, fp
);
1066 res
+= fread(&tmp
.name
, sizeof(tmp
.name
), 1, fp
);
1067 res
+= fread(&tmp
.brand
, sizeof(tmp
.brand
), 1, fp
);
1068 res
+= fread(&tmp
.pid
, sizeof(tmp
.pid
), 1, fp
);
1069 res
+= fread(&tmp
.free_events
, sizeof(tmp
.free_events
), 1, fp
);
1070 res
+= fread(&tmp
.tgid
, sizeof(tmp
.tgid
), 1, fp
);
1071 res
+= fread(&tmp
.ppid
, sizeof(tmp
.ppid
), 1, fp
);
1072 res
+= fread(&tmp
.cpu
, sizeof(tmp
.cpu
), 1, fp
);
1073 res
+= fread(&tmp
.creation_time
, sizeof(tmp
.creation_time
), 1, fp
);
1074 res
+= fread(&tmp
.insertion_time
, sizeof(tmp
.insertion_time
), 1, fp
);
1075 g_assert(res
== 10);
1078 process
= lttv_state_find_process(self
, tmp
.cpu
, tmp
.pid
);
1080 /* We must link to the parent */
1081 parent_process
= lttv_state_find_process_or_create(self
, ANY_CPU
, tmp
.ppid
,
1083 process
= lttv_state_find_process(self
, ANY_CPU
, tmp
.pid
);
1084 if(process
== NULL
) {
1085 process
= lttv_state_create_process(self
, parent_process
, tmp
.cpu
,
1087 g_quark_from_string((gchar
*)g_ptr_array_index(quarktable
, tmp
.name
)),
1088 &tmp
.creation_time
);
1091 process
->insertion_time
= tmp
.insertion_time
;
1092 process
->creation_time
= tmp
.creation_time
;
1093 process
->type
= g_quark_from_string(
1094 (gchar
*)g_ptr_array_index(quarktable
, tmp
.type
));
1095 process
->tgid
= tmp
.tgid
;
1096 process
->ppid
= tmp
.ppid
;
1097 process
->brand
= g_quark_from_string(
1098 (gchar
*)g_ptr_array_index(quarktable
, tmp
.brand
));
1100 g_quark_from_string((gchar
*)g_ptr_array_index(quarktable
, tmp
.name
));
1101 process
->free_events
= tmp
.free_events
;
1104 if(feof(fp
) || ferror(fp
)) goto end_loop
;
1106 gint hdr
= fgetc(fp
);
1107 if(hdr
== EOF
) goto end_loop
;
1111 process
->execution_stack
=
1112 g_array_set_size(process
->execution_stack
,
1113 process
->execution_stack
->len
+ 1);
1114 es
= &g_array_index(process
->execution_stack
, LttvExecutionState
,
1115 process
->execution_stack
->len
-1);
1116 process
->state
= es
;
1118 res
= fread(&es
->t
, sizeof(es
->t
), 1, fp
);
1120 es
->t
= g_quark_from_string(
1121 (gchar
*)g_ptr_array_index(quarktable
, es
->t
));
1122 res
= fread(&es
->n
, sizeof(es
->n
), 1, fp
);
1124 es
->n
= g_quark_from_string(
1125 (gchar
*)g_ptr_array_index(quarktable
, es
->n
));
1126 res
= fread(&es
->s
, sizeof(es
->s
), 1, fp
);
1128 es
->s
= g_quark_from_string(
1129 (gchar
*)g_ptr_array_index(quarktable
, es
->s
));
1130 res
= fread(&es
->entry
, sizeof(es
->entry
), 1, fp
);
1131 res
+= fread(&es
->change
, sizeof(es
->change
), 1, fp
);
1132 res
+= fread(&es
->cum_cpu_time
, sizeof(es
->cum_cpu_time
), 1, fp
);
1136 case HDR_USER_STACK
:
1137 process
->user_stack
= g_array_set_size(process
->user_stack
,
1138 process
->user_stack
->len
+ 1);
1139 address
= &g_array_index(process
->user_stack
, guint64
,
1140 process
->user_stack
->len
-1);
1141 res
= fread(address
, sizeof(address
), 1, fp
);
1143 process
->current_function
= *address
;
1147 res
= fread(&tmpq
, sizeof(tmpq
), 1, fp
);
1148 res
+= fread(&process
->usertrace
->cpu
,
1149 sizeof(process
->usertrace
->cpu
), 1, fp
);
1163 /* Called because a HDR_PROCESS_STATE was found */
1164 /* Append a saved state to the trace states */
1165 void lttv_state_read_raw(LttvTraceState
*self
, FILE *fp
, GPtrArray
*quarktable
)
1167 guint i
, nb_tracefile
, nb_block
, offset
;
1169 LttvTracefileState
*tfcs
;
1171 LttEventPosition
*ep
;
1180 LttvAttribute
*saved_states_tree
, *saved_state_tree
;
1182 LttvAttributeValue value
;
1183 GTree
*pqueue
= self
->parent
.ts_context
->pqueue
;
1184 ep
= ltt_event_position_new();
1186 restore_init_state(self
);
1188 res
= fread(&t
, sizeof(t
), 1, fp
);
1192 if(feof(fp
) || ferror(fp
)) goto end_loop
;
1194 if(hdr
== EOF
) goto end_loop
;
1198 /* Call read_process_state_raw */
1199 read_process_state_raw(self
, fp
, quarktable
);
1207 case HDR_USER_STACK
:
1209 case HDR_PROCESS_STATE
:
1215 g_error("Error while parsing saved state file : unknown data header %d",
1221 nb_cpus
= ltt_trace_get_num_cpu(self
->parent
.t
);
1222 for(i
=0;i
<nb_cpus
;i
++) {
1225 g_assert(hdr
== HDR_CPU
);
1226 res
= fread(&cpu_num
, sizeof(cpu_num
), 1, fp
); /* cpu number */
1228 g_assert(i
== cpu_num
);
1229 res
= fread(&self
->running_process
[i
]->pid
,
1230 sizeof(self
->running_process
[i
]->pid
), 1, fp
);
1234 nb_tracefile
= self
->parent
.tracefiles
->len
;
1236 for(i
= 0 ; i
< nb_tracefile
; i
++) {
1238 LTTV_TRACEFILE_STATE(g_array_index(self
->parent
.tracefiles
,
1239 LttvTracefileContext
*, i
));
1240 // fprintf(fp, " <TRACEFILE TIMESTAMP_S=%lu TIMESTAMP_NS=%lu",
1241 // tfcs->parent.timestamp.tv_sec,
1242 // tfcs->parent.timestamp.tv_nsec);
1243 g_tree_remove(pqueue
, &tfcs
->parent
);
1245 g_assert(hdr
== HDR_TRACEFILE
);
1246 res
= fread(&tfcs
->parent
.timestamp
, sizeof(tfcs
->parent
.timestamp
), 1, fp
);
1248 /* Note : if timestamp if LTT_TIME_INFINITE, there will be no
1249 * position following : end of trace */
1250 if(ltt_time_compare(tfcs
->parent
.timestamp
, ltt_time_infinite
) != 0) {
1251 res
= fread(&nb_block
, sizeof(nb_block
), 1, fp
);
1252 res
+= fread(&offset
, sizeof(offset
), 1, fp
);
1253 res
+= fread(&tsc
, sizeof(tsc
), 1, fp
);
1255 ltt_event_position_set(ep
, tfcs
->parent
.tf
, nb_block
, offset
, tsc
);
1256 gint ret
= ltt_tracefile_seek_position(tfcs
->parent
.tf
, ep
);
1258 g_tree_insert(pqueue
, &tfcs
->parent
, &tfcs
->parent
);
1263 saved_states_tree
= lttv_attribute_find_subdir(self
->parent
.t_a
,
1264 LTTV_STATE_SAVED_STATES
);
1265 saved_state_tree
= g_object_new(LTTV_ATTRIBUTE_TYPE
, NULL
);
1266 value
= lttv_attribute_add(saved_states_tree
,
1267 lttv_attribute_get_number(saved_states_tree
), LTTV_GOBJECT
);
1268 *(value
.v_gobject
) = (GObject
*)saved_state_tree
;
1269 value
= lttv_attribute_add(saved_state_tree
, LTTV_STATE_TIME
, LTTV_TIME
);
1270 *(value
.v_time
) = t
;
1271 lttv_state_save(self
, saved_state_tree
);
1272 g_debug("Saving state at time %lu.%lu", t
.tv_sec
,
1275 *(self
->max_time_state_recomputed_in_seek
) = t
;
1279 /* Called when a HDR_TRACE is found */
1280 void lttv_trace_states_read_raw(LttvTraceState
*tcs
, FILE *fp
,
1281 GPtrArray
*quarktable
)
1286 if(feof(fp
) || ferror(fp
)) goto end_loop
;
1288 if(hdr
== EOF
) goto end_loop
;
1291 case HDR_PROCESS_STATE
:
1292 /* Call read_process_state_raw */
1293 lttv_state_read_raw(tcs
, fp
, quarktable
);
1301 case HDR_USER_STACK
:
1305 g_error("Error while parsing saved state file :"
1306 " unexpected data header %d",
1310 g_error("Error while parsing saved state file : unknown data header %d",
1315 *(tcs
->max_time_state_recomputed_in_seek
) = tcs
->parent
.time_span
.end_time
;
1316 restore_init_state(tcs
);
1317 lttv_process_trace_seek_time(&tcs
->parent
, ltt_time_zero
);
1323 /* Copy each process from an existing hash table to a new one */
1325 static void copy_process_state(gpointer key
, gpointer value
,gpointer user_data
)
1327 LttvProcessState
*process
, *new_process
;
1329 GHashTable
*new_processes
= (GHashTable
*)user_data
;
1333 process
= (LttvProcessState
*)value
;
1334 new_process
= g_new(LttvProcessState
, 1);
1335 *new_process
= *process
;
1336 new_process
->execution_stack
= g_array_sized_new(FALSE
, FALSE
,
1337 sizeof(LttvExecutionState
), PREALLOCATED_EXECUTION_STACK
);
1338 new_process
->execution_stack
=
1339 g_array_set_size(new_process
->execution_stack
,
1340 process
->execution_stack
->len
);
1341 for(i
= 0 ; i
< process
->execution_stack
->len
; i
++) {
1342 g_array_index(new_process
->execution_stack
, LttvExecutionState
, i
) =
1343 g_array_index(process
->execution_stack
, LttvExecutionState
, i
);
1345 new_process
->state
= &g_array_index(new_process
->execution_stack
,
1346 LttvExecutionState
, new_process
->execution_stack
->len
- 1);
1347 new_process
->user_stack
= g_array_sized_new(FALSE
, FALSE
,
1348 sizeof(guint64
), 0);
1349 new_process
->user_stack
= g_array_set_size(new_process
->user_stack
,
1350 process
->user_stack
->len
);
1351 for(i
= 0 ; i
< process
->user_stack
->len
; i
++) {
1352 g_array_index(new_process
->user_stack
, guint64
, i
) =
1353 g_array_index(process
->user_stack
, guint64
, i
);
1355 new_process
->current_function
= process
->current_function
;
1357 /* fd hash table stuff */
1363 /* copy every item in the hash table */
1364 new_process
->fds
= g_hash_table_new(g_direct_hash
, g_direct_equal
);
1366 g_hash_table_iter_init(&it
, process
->fds
);
1367 while (g_hash_table_iter_next (&it
, (void *)&key
, (void *)&value
)) {
1368 g_hash_table_insert(new_process
->fds
, key
, value
);
1372 /* When done creating the new process state, insert it in the
1374 g_hash_table_insert(new_processes
, new_process
, new_process
);
1378 static GHashTable
*lttv_state_copy_process_table(GHashTable
*processes
)
1380 GHashTable
*new_processes
= g_hash_table_new(process_hash
, process_equal
);
1382 g_hash_table_foreach(processes
, copy_process_state
, new_processes
);
1383 return new_processes
;
1386 static LttvCPUState
*lttv_state_copy_cpu_states(LttvCPUState
*states
, guint n
)
1389 LttvCPUState
*retval
;
1391 retval
= g_new(LttvCPUState
, n
);
1393 for(i
=0; i
<n
; i
++) {
1394 retval
[i
].irq_stack
= g_array_new(FALSE
, FALSE
, sizeof(gint
));
1395 g_array_set_size(retval
[i
].irq_stack
, states
[i
].irq_stack
->len
);
1396 for(j
=0; j
<states
[i
].irq_stack
->len
; j
++) {
1397 g_array_index(retval
[i
].irq_stack
, gint
, j
) =
1398 g_array_index(states
[i
].irq_stack
, gint
, j
);
1401 retval
[i
].softirq_stack
= g_array_new(FALSE
, FALSE
, sizeof(gint
));
1402 g_array_set_size(retval
[i
].softirq_stack
, states
[i
].softirq_stack
->len
);
1403 for(j
=0; j
<states
[i
].softirq_stack
->len
; j
++) {
1404 g_array_index(retval
[i
].softirq_stack
, gint
, j
) =
1405 g_array_index(states
[i
].softirq_stack
, gint
, j
);
1408 retval
[i
].trap_stack
= g_array_new(FALSE
, FALSE
, sizeof(gint
));
1409 g_array_set_size(retval
[i
].trap_stack
, states
[i
].trap_stack
->len
);
1410 for(j
=0; j
<states
[i
].trap_stack
->len
; j
++) {
1411 g_array_index(retval
[i
].trap_stack
, gint
, j
) =
1412 g_array_index(states
[i
].trap_stack
, gint
, j
);
1415 retval
[i
].mode_stack
= g_array_new(FALSE
, FALSE
, sizeof(LttvCPUMode
));
1416 g_array_set_size(retval
[i
].mode_stack
, states
[i
].mode_stack
->len
);
1417 for(j
=0; j
<states
[i
].mode_stack
->len
; j
++) {
1418 g_array_index(retval
[i
].mode_stack
, GQuark
, j
) =
1419 g_array_index(states
[i
].mode_stack
, GQuark
, j
);
1426 static void lttv_state_free_cpu_states(LttvCPUState
*states
, guint n
)
1430 for(i
=0; i
<n
; i
++) {
1431 g_array_free(states
[i
].mode_stack
, TRUE
);
1432 g_array_free(states
[i
].irq_stack
, TRUE
);
1433 g_array_free(states
[i
].softirq_stack
, TRUE
);
1434 g_array_free(states
[i
].trap_stack
, TRUE
);
1440 static LttvIRQState
*lttv_state_copy_irq_states(LttvIRQState
*states
, guint n
)
1443 LttvIRQState
*retval
;
1445 retval
= g_new(LttvIRQState
, n
);
1447 for(i
=0; i
<n
; i
++) {
1448 retval
[i
].mode_stack
= g_array_new(FALSE
, FALSE
, sizeof(LttvIRQMode
));
1449 g_array_set_size(retval
[i
].mode_stack
, states
[i
].mode_stack
->len
);
1450 for(j
=0; j
<states
[i
].mode_stack
->len
; j
++) {
1451 g_array_index(retval
[i
].mode_stack
, GQuark
, j
) =
1452 g_array_index(states
[i
].mode_stack
, GQuark
, j
);
1459 static void lttv_state_free_irq_states(LttvIRQState
*states
, guint n
)
1463 for(i
=0; i
<n
; i
++) {
1464 g_array_free(states
[i
].mode_stack
, TRUE
);
1470 static LttvSoftIRQState
*
1471 lttv_state_copy_soft_irq_states(LttvSoftIRQState
*states
, guint n
)
1474 LttvSoftIRQState
*retval
;
1476 retval
= g_new(LttvSoftIRQState
, n
);
1478 for(i
=0; i
<n
; i
++) {
1479 retval
[i
].pending
= states
[i
].pending
;
1480 retval
[i
].running
= states
[i
].running
;
1486 static void lttv_state_free_soft_irq_states(LttvSoftIRQState
*states
, guint n
)
1491 static LttvTrapState
*
1492 lttv_state_copy_trap_states(LttvTrapState
*states
, guint n
)
1495 LttvTrapState
*retval
;
1497 retval
= g_new(LttvTrapState
, n
);
1499 for(i
=0; i
<n
; i
++) {
1500 retval
[i
].running
= states
[i
].running
;
1506 static void lttv_state_free_trap_states(LttvTrapState
*states
, guint n
)
1511 /* bdevstate stuff */
1513 static LttvBdevState
*get_hashed_bdevstate(LttvTraceState
*ts
, guint32 devcode
)
1515 gint devcode_gint
= devcode
;
1516 gpointer bdev
= g_hash_table_lookup(ts
->bdev_states
, &devcode_gint
);
1518 LttvBdevState
*bdevstate
= g_new(LttvBdevState
, 1);
1519 bdevstate
->mode_stack
= g_array_new(FALSE
, FALSE
, sizeof(GQuark
));
1521 gint
* key
= g_new(gint
, 1);
1523 g_hash_table_insert(ts
->bdev_states
, key
, bdevstate
);
1531 static LttvBdevState
*bdevstate_new(void)
1533 LttvBdevState
*retval
;
1534 retval
= g_new(LttvBdevState
, 1);
1535 retval
->mode_stack
= g_array_new(FALSE
, FALSE
, sizeof(GQuark
));
1540 static void bdevstate_free(LttvBdevState
*bds
)
1542 g_array_free(bds
->mode_stack
, TRUE
);
1546 static void bdevstate_free_cb(gpointer key
, gpointer value
, gpointer user_data
)
1548 LttvBdevState
*bds
= (LttvBdevState
*) value
;
1550 bdevstate_free(bds
);
1553 static LttvBdevState
*bdevstate_copy(LttvBdevState
*bds
)
1555 LttvBdevState
*retval
;
1557 retval
= bdevstate_new();
1558 g_array_insert_vals(retval
->mode_stack
, 0, bds
->mode_stack
->data
,
1559 bds
->mode_stack
->len
);
1564 static void insert_and_copy_bdev_state(gpointer k
, gpointer v
, gpointer u
)
1566 //GHashTable *ht = (GHashTable *)u;
1567 LttvBdevState
*bds
= (LttvBdevState
*)v
;
1568 LttvBdevState
*newbds
;
1570 newbds
= bdevstate_copy(bds
);
1572 g_hash_table_insert(u
, k
, newbds
);
1575 static GHashTable
*lttv_state_copy_blkdev_hashtable(GHashTable
*ht
)
1579 retval
= g_hash_table_new(g_int_hash
, g_int_equal
);
1581 g_hash_table_foreach(ht
, insert_and_copy_bdev_state
, retval
);
1586 /* Free a hashtable and the LttvBdevState structures its values
1589 static void lttv_state_free_blkdev_hashtable(GHashTable
*ht
)
1591 g_hash_table_foreach(ht
, bdevstate_free_cb
, NULL
);
1592 g_hash_table_destroy(ht
);
1595 /* The saved state for each trace contains a member "processes", which
1596 stores a copy of the process table, and a member "tracefiles" with
1597 one entry per tracefile. Each tracefile has a "process" member pointing
1598 to the current process and a "position" member storing the tracefile
1599 position (needed to seek to the current "next" event. */
1601 static void state_save(LttvTraceState
*self
, LttvAttribute
*container
)
1603 guint i
, nb_tracefile
, nb_cpus
, nb_irqs
, nb_soft_irqs
, nb_traps
;
1605 LttvTracefileState
*tfcs
;
1607 LttvAttribute
*tracefiles_tree
, *tracefile_tree
;
1609 guint
*running_process
;
1611 LttvAttributeValue value
;
1613 LttEventPosition
*ep
;
1615 tracefiles_tree
= lttv_attribute_find_subdir(container
,
1616 LTTV_STATE_TRACEFILES
);
1618 value
= lttv_attribute_add(container
, LTTV_STATE_PROCESSES
,
1620 *(value
.v_pointer
) = lttv_state_copy_process_table(self
->processes
);
1622 /* Add the currently running processes array */
1623 nb_cpus
= ltt_trace_get_num_cpu(self
->parent
.t
);
1624 running_process
= g_new(guint
, nb_cpus
);
1625 for(i
=0;i
<nb_cpus
;i
++) {
1626 running_process
[i
] = self
->running_process
[i
]->pid
;
1628 value
= lttv_attribute_add(container
, LTTV_STATE_RUNNING_PROCESS
,
1630 *(value
.v_pointer
) = running_process
;
1632 g_info("State save");
1634 nb_tracefile
= self
->parent
.tracefiles
->len
;
1636 for(i
= 0 ; i
< nb_tracefile
; i
++) {
1638 LTTV_TRACEFILE_STATE(g_array_index(self
->parent
.tracefiles
,
1639 LttvTracefileContext
*, i
));
1640 tracefile_tree
= g_object_new(LTTV_ATTRIBUTE_TYPE
, NULL
);
1641 value
= lttv_attribute_add(tracefiles_tree
, i
,
1643 *(value
.v_gobject
) = (GObject
*)tracefile_tree
;
1645 value
= lttv_attribute_add(tracefile_tree
, LTTV_STATE_PROCESS
,
1647 *(value
.v_uint
) = tfcs
->process
->pid
;
1649 value
= lttv_attribute_add(tracefile_tree
, LTTV_STATE_EVENT
,
1651 /* Only save the position if the tfs has not infinite time. */
1652 //if(!g_tree_lookup(self->parent.ts_context->pqueue, &tfcs->parent)
1653 // && current_tfcs != tfcs) {
1654 if(ltt_time_compare(tfcs
->parent
.timestamp
, ltt_time_infinite
) == 0) {
1655 *(value
.v_pointer
) = NULL
;
1657 LttEvent
*e
= ltt_tracefile_get_event(tfcs
->parent
.tf
);
1658 ep
= ltt_event_position_new();
1659 ltt_event_position(e
, ep
);
1660 *(value
.v_pointer
) = ep
;
1662 guint nb_block
, offset
;
1665 ltt_event_position_get(ep
, &tf
, &nb_block
, &offset
, &tsc
);
1666 g_info("Block %u offset %u tsc %" PRIu64
" time %lu.%lu", nb_block
,
1667 offset
, tsc
, tfcs
->parent
.timestamp
.tv_sec
,
1668 tfcs
->parent
.timestamp
.tv_nsec
);
1672 /* save the cpu state */
1674 value
= lttv_attribute_add(container
, LTTV_STATE_RESOURCE_CPUS_COUNT
,
1676 *(value
.v_uint
) = nb_cpus
;
1678 value
= lttv_attribute_add(container
, LTTV_STATE_RESOURCE_CPUS
,
1680 *(value
.v_pointer
) = lttv_state_copy_cpu_states(self
->cpu_states
, nb_cpus
);
1683 /* save the irq state */
1684 nb_irqs
= self
->name_tables
->nb_irqs
;
1686 value
= lttv_attribute_add(container
, LTTV_STATE_RESOURCE_IRQS
,
1688 *(value
.v_pointer
) = lttv_state_copy_irq_states(self
->irq_states
, nb_irqs
);
1691 /* save the soft irq state */
1692 nb_soft_irqs
= self
->name_tables
->nb_soft_irqs
;
1694 value
= lttv_attribute_add(container
, LTTV_STATE_RESOURCE_SOFT_IRQS
,
1696 *(value
.v_pointer
) = lttv_state_copy_soft_irq_states(self
->soft_irq_states
, nb_soft_irqs
);
1699 /* save the trap state */
1700 nb_traps
= self
->name_tables
->nb_traps
;
1702 value
= lttv_attribute_add(container
, LTTV_STATE_RESOURCE_TRAPS
,
1704 *(value
.v_pointer
) = lttv_state_copy_trap_states(self
->trap_states
, nb_traps
);
1707 /* save the blkdev states */
1708 value
= lttv_attribute_add(container
, LTTV_STATE_RESOURCE_BLKDEVS
,
1710 *(value
.v_pointer
) = lttv_state_copy_blkdev_hashtable(self
->bdev_states
);
1714 static void state_restore(LttvTraceState
*self
, LttvAttribute
*container
)
1716 guint i
, nb_tracefile
, pid
, nb_cpus
, nb_irqs
, nb_soft_irqs
, nb_traps
;
1718 LttvTracefileState
*tfcs
;
1720 LttvAttribute
*tracefiles_tree
, *tracefile_tree
;
1722 guint
*running_process
;
1724 LttvAttributeType type
;
1726 LttvAttributeValue value
;
1728 LttvAttributeName name
;
1732 LttEventPosition
*ep
;
1734 LttvTracesetContext
*tsc
= self
->parent
.ts_context
;
1737 tracefiles_tree
= lttv_attribute_find_subdir(container
,
1738 LTTV_STATE_TRACEFILES
);
1740 type
= lttv_attribute_get_by_name(container
, LTTV_STATE_PROCESSES
,
1742 g_assert(type
== LTTV_POINTER
);
1743 lttv_state_free_process_table(self
->processes
);
1744 self
->processes
= lttv_state_copy_process_table(*(value
.v_pointer
));
1746 /* Add the currently running processes array */
1747 nb_cpus
= ltt_trace_get_num_cpu(self
->parent
.t
);
1748 type
= lttv_attribute_get_by_name(container
, LTTV_STATE_RUNNING_PROCESS
,
1750 g_assert(type
== LTTV_POINTER
);
1751 running_process
= *(value
.v_pointer
);
1752 for(i
=0;i
<nb_cpus
;i
++) {
1753 pid
= running_process
[i
];
1754 self
->running_process
[i
] = lttv_state_find_process(self
, i
, pid
);
1755 g_assert(self
->running_process
[i
] != NULL
);
1758 nb_tracefile
= self
->parent
.tracefiles
->len
;
1760 //g_tree_destroy(tsc->pqueue);
1761 //tsc->pqueue = g_tree_new(compare_tracefile);
1763 /* restore cpu resource states */
1764 type
= lttv_attribute_get_by_name(container
, LTTV_STATE_RESOURCE_CPUS
, &value
);
1765 g_assert(type
== LTTV_POINTER
);
1766 lttv_state_free_cpu_states(self
->cpu_states
, nb_cpus
);
1767 self
->cpu_states
= lttv_state_copy_cpu_states(*(value
.v_pointer
), nb_cpus
);
1769 /* restore irq resource states */
1770 nb_irqs
= self
->name_tables
->nb_irqs
;
1771 type
= lttv_attribute_get_by_name(container
, LTTV_STATE_RESOURCE_IRQS
, &value
);
1772 g_assert(type
== LTTV_POINTER
);
1773 lttv_state_free_irq_states(self
->irq_states
, nb_irqs
);
1774 self
->irq_states
= lttv_state_copy_irq_states(*(value
.v_pointer
), nb_irqs
);
1776 /* restore soft irq resource states */
1777 nb_soft_irqs
= self
->name_tables
->nb_soft_irqs
;
1778 type
= lttv_attribute_get_by_name(container
, LTTV_STATE_RESOURCE_SOFT_IRQS
, &value
);
1779 g_assert(type
== LTTV_POINTER
);
1780 lttv_state_free_soft_irq_states(self
->soft_irq_states
, nb_soft_irqs
);
1781 self
->soft_irq_states
= lttv_state_copy_soft_irq_states(*(value
.v_pointer
), nb_soft_irqs
);
1783 /* restore trap resource states */
1784 nb_traps
= self
->name_tables
->nb_traps
;
1785 type
= lttv_attribute_get_by_name(container
, LTTV_STATE_RESOURCE_TRAPS
, &value
);
1786 g_assert(type
== LTTV_POINTER
);
1787 lttv_state_free_trap_states(self
->trap_states
, nb_traps
);
1788 self
->trap_states
= lttv_state_copy_trap_states(*(value
.v_pointer
), nb_traps
);
1790 /* restore the blkdev states */
1791 type
= lttv_attribute_get_by_name(container
, LTTV_STATE_RESOURCE_BLKDEVS
, &value
);
1792 g_assert(type
== LTTV_POINTER
);
1793 lttv_state_free_blkdev_hashtable(self
->bdev_states
);
1794 self
->bdev_states
= lttv_state_copy_blkdev_hashtable(*(value
.v_pointer
));
1796 for(i
= 0 ; i
< nb_tracefile
; i
++) {
1798 LTTV_TRACEFILE_STATE(g_array_index(self
->parent
.tracefiles
,
1799 LttvTracefileContext
*, i
));
1800 type
= lttv_attribute_get(tracefiles_tree
, i
, &name
, &value
, &is_named
);
1801 g_assert(type
== LTTV_GOBJECT
);
1802 tracefile_tree
= *((LttvAttribute
**)(value
.v_gobject
));
1804 type
= lttv_attribute_get_by_name(tracefile_tree
, LTTV_STATE_PROCESS
,
1806 g_assert(type
== LTTV_UINT
);
1807 pid
= *(value
.v_uint
);
1808 tfcs
->process
= lttv_state_find_process_or_create(tfcs
, pid
);
1810 type
= lttv_attribute_get_by_name(tracefile_tree
, LTTV_STATE_EVENT
,
1812 g_assert(type
== LTTV_POINTER
);
1813 //g_assert(*(value.v_pointer) != NULL);
1814 ep
= *(value
.v_pointer
);
1815 g_assert(tfcs
->parent
.t_context
!= NULL
);
1817 tfcs
->cpu_state
= &self
->cpu_states
[tfcs
->cpu
];
1819 LttvTracefileContext
*tfc
= LTTV_TRACEFILE_CONTEXT(tfcs
);
1820 g_tree_remove(tsc
->pqueue
, tfc
);
1823 retval
= ltt_tracefile_seek_position(tfc
->tf
, ep
);
1824 g_assert_cmpint(retval
, ==, 0);
1825 tfc
->timestamp
= ltt_event_time(ltt_tracefile_get_event(tfc
->tf
));
1826 g_assert_cmpint(ltt_time_compare(tfc
->timestamp
, ltt_time_infinite
),
1828 g_tree_insert(tsc
->pqueue
, tfc
, tfc
);
1829 g_info("Restoring state for a tf at time %lu.%lu",
1830 tfc
->timestamp
.tv_sec
, tfc
->timestamp
.tv_nsec
);
1832 tfc
->timestamp
= ltt_time_infinite
;
1838 static void state_saved_free(LttvTraceState
*self
, LttvAttribute
*container
)
1840 guint i
, nb_tracefile
, nb_cpus
, nb_irqs
, nb_soft_irqs
;
1842 LttvAttribute
*tracefiles_tree
, *tracefile_tree
;
1844 guint
*running_process
;
1846 LttvAttributeType type
;
1848 LttvAttributeValue value
;
1850 LttvAttributeName name
;
1854 tracefiles_tree
= lttv_attribute_find_subdir(container
,
1855 LTTV_STATE_TRACEFILES
);
1856 g_object_ref(G_OBJECT(tracefiles_tree
));
1857 lttv_attribute_remove_by_name(container
, LTTV_STATE_TRACEFILES
);
1859 type
= lttv_attribute_get_by_name(container
, LTTV_STATE_PROCESSES
,
1861 g_assert(type
== LTTV_POINTER
);
1862 lttv_state_free_process_table(*(value
.v_pointer
));
1863 *(value
.v_pointer
) = NULL
;
1864 lttv_attribute_remove_by_name(container
, LTTV_STATE_PROCESSES
);
1866 /* Free running processes array */
1867 type
= lttv_attribute_get_by_name(container
, LTTV_STATE_RUNNING_PROCESS
,
1869 g_assert(type
== LTTV_POINTER
);
1870 running_process
= *(value
.v_pointer
);
1871 g_free(running_process
);
1873 /* free cpu resource states */
1874 type
= lttv_attribute_get_by_name(container
, LTTV_STATE_RESOURCE_CPUS_COUNT
, &value
);
1875 g_assert(type
== LTTV_UINT
);
1876 nb_cpus
= *value
.v_uint
;
1877 type
= lttv_attribute_get_by_name(container
, LTTV_STATE_RESOURCE_CPUS
, &value
);
1878 g_assert(type
== LTTV_POINTER
);
1879 lttv_state_free_cpu_states(*(value
.v_pointer
), nb_cpus
);
1881 /* free irq resource states */
1882 nb_irqs
= self
->name_tables
->nb_irqs
;
1883 type
= lttv_attribute_get_by_name(container
, LTTV_STATE_RESOURCE_IRQS
, &value
);
1884 g_assert(type
== LTTV_POINTER
);
1885 lttv_state_free_irq_states(*(value
.v_pointer
), nb_irqs
);
1887 /* free softirq resource states */
1888 nb_soft_irqs
= self
->name_tables
->nb_soft_irqs
;
1889 type
= lttv_attribute_get_by_name(container
, LTTV_STATE_RESOURCE_SOFT_IRQS
, &value
);
1890 g_assert(type
== LTTV_POINTER
);
1891 lttv_state_free_soft_irq_states(*(value
.v_pointer
), nb_soft_irqs
);
1893 /* free the blkdev states */
1894 type
= lttv_attribute_get_by_name(container
, LTTV_STATE_RESOURCE_BLKDEVS
, &value
);
1895 g_assert(type
== LTTV_POINTER
);
1896 lttv_state_free_blkdev_hashtable(*(value
.v_pointer
));
1898 nb_tracefile
= self
->parent
.tracefiles
->len
;
1900 for(i
= 0 ; i
< nb_tracefile
; i
++) {
1902 type
= lttv_attribute_get(tracefiles_tree
, i
, &name
, &value
, &is_named
);
1903 g_assert(type
== LTTV_GOBJECT
);
1904 tracefile_tree
= *((LttvAttribute
**)(value
.v_gobject
));
1906 type
= lttv_attribute_get_by_name(tracefile_tree
, LTTV_STATE_EVENT
,
1908 g_assert(type
== LTTV_POINTER
);
1909 if(*(value
.v_pointer
) != NULL
) g_free(*(value
.v_pointer
));
1911 g_object_unref(G_OBJECT(tracefiles_tree
));
1915 static void free_saved_state(LttvTraceState
*self
)
1919 LttvAttributeType type
;
1921 LttvAttributeValue value
;
1923 LttvAttributeName name
;
1927 LttvAttribute
*saved_states
;
1929 saved_states
= lttv_attribute_find_subdir(self
->parent
.t_a
,
1930 LTTV_STATE_SAVED_STATES
);
1932 nb
= lttv_attribute_get_number(saved_states
);
1933 for(i
= 0 ; i
< nb
; i
++) {
1934 type
= lttv_attribute_get(saved_states
, i
, &name
, &value
, &is_named
);
1935 g_assert(type
== LTTV_GOBJECT
);
1936 state_saved_free(self
, *((LttvAttribute
**)value
.v_gobject
));
1939 lttv_attribute_remove_by_name(self
->parent
.t_a
, LTTV_STATE_SAVED_STATES
);
1943 static void create_max_time(LttvTraceState
*tcs
)
1945 LttvAttributeValue v
;
1947 lttv_attribute_find(tcs
->parent
.t_a
, LTTV_STATE_SAVED_STATES_TIME
,
1949 g_assert(*(v
.v_pointer
) == NULL
);
1950 *(v
.v_pointer
) = g_new(LttTime
,1);
1951 *((LttTime
*)*(v
.v_pointer
)) = ltt_time_zero
;
1955 static void get_max_time(LttvTraceState
*tcs
)
1957 LttvAttributeValue v
;
1959 lttv_attribute_find(tcs
->parent
.t_a
, LTTV_STATE_SAVED_STATES_TIME
,
1961 g_assert(*(v
.v_pointer
) != NULL
);
1962 tcs
->max_time_state_recomputed_in_seek
= (LttTime
*)*(v
.v_pointer
);
1966 static void free_max_time(LttvTraceState
*tcs
)
1968 LttvAttributeValue v
;
1970 lttv_attribute_find(tcs
->parent
.t_a
, LTTV_STATE_SAVED_STATES_TIME
,
1972 g_free(*(v
.v_pointer
));
1973 *(v
.v_pointer
) = NULL
;
1976 static void create_name_tables(LttvTraceState
*tcs
)
1980 GString
*fe_name
= g_string_new("");
1982 LttvNameTables
*name_tables
= g_new(LttvNameTables
, 1);
1984 LttvAttributeValue v
;
1988 lttv_attribute_find(tcs
->parent
.t_a
, LTTV_STATE_NAME_TABLES
,
1990 g_assert(*(v
.v_pointer
) == NULL
);
1991 *(v
.v_pointer
) = name_tables
;
1993 hooks
= g_array_sized_new(FALSE
, FALSE
, sizeof(LttvTraceHook
), 1);
1995 if(!lttv_trace_find_hook(tcs
->parent
.t
,
1997 LTT_EVENT_SYSCALL_ENTRY
,
1998 FIELD_ARRAY(LTT_FIELD_SYSCALL_ID
),
1999 NULL
, NULL
, &hooks
)) {
2001 // th = lttv_trace_hook_get_first(&th);
2003 // t = ltt_field_type(lttv_trace_get_hook_field(th, 0));
2004 // nb = ltt_type_element_number(t);
2006 // name_tables->syscall_names = g_new(GQuark, nb);
2007 // name_tables->nb_syscalls = nb;
2009 // for(i = 0 ; i < nb ; i++) {
2010 // name_tables->syscall_names[i] = ltt_enum_string_get(t, i);
2011 // if(!name_tables->syscall_names[i]) {
2012 // GString *string = g_string_new("");
2013 // g_string_printf(string, "syscall %u", i);
2014 // name_tables->syscall_names[i] = g_quark_from_string(string->str);
2015 // g_string_free(string, TRUE);
2019 name_tables
->nb_syscalls
= PREALLOC_NB_SYSCALLS
;
2020 name_tables
->syscall_names
= g_new(GQuark
, name_tables
->nb_syscalls
);
2021 for(i
= 0 ; i
< name_tables
->nb_syscalls
; i
++) {
2022 g_string_printf(fe_name
, "syscall %d", i
);
2023 name_tables
->syscall_names
[i
] = g_quark_from_string(fe_name
->str
);
2026 name_tables
->syscall_names
= NULL
;
2027 name_tables
->nb_syscalls
= 0;
2029 lttv_trace_hook_remove_all(&hooks
);
2031 if(!lttv_trace_find_hook(tcs
->parent
.t
,
2033 LTT_EVENT_TRAP_ENTRY
,
2034 FIELD_ARRAY(LTT_FIELD_TRAP_ID
),
2035 NULL
, NULL
, &hooks
) ||
2036 !lttv_trace_find_hook(tcs
->parent
.t
,
2038 LTT_EVENT_PAGE_FAULT_ENTRY
,
2039 FIELD_ARRAY(LTT_FIELD_TRAP_ID
),
2040 NULL
, NULL
, &hooks
)) {
2042 // th = lttv_trace_hook_get_first(&th);
2044 // t = ltt_field_type(lttv_trace_get_hook_field(th, 0));
2045 // //nb = ltt_type_element_number(t);
2047 // name_tables->trap_names = g_new(GQuark, nb);
2048 // for(i = 0 ; i < nb ; i++) {
2049 // name_tables->trap_names[i] = g_quark_from_string(
2050 // ltt_enum_string_get(t, i));
2053 name_tables
->nb_traps
= PREALLOC_NB_TRAPS
;
2054 name_tables
->trap_names
= g_new(GQuark
, name_tables
->nb_traps
);
2055 for(i
= 0 ; i
< name_tables
->nb_traps
; i
++) {
2056 g_string_printf(fe_name
, "trap %d", i
);
2057 name_tables
->trap_names
[i
] = g_quark_from_string(fe_name
->str
);
2060 name_tables
->trap_names
= NULL
;
2061 name_tables
->nb_traps
= 0;
2063 lttv_trace_hook_remove_all(&hooks
);
2065 if(!lttv_trace_find_hook(tcs
->parent
.t
,
2067 LTT_EVENT_IRQ_ENTRY
,
2068 FIELD_ARRAY(LTT_FIELD_IRQ_ID
),
2069 NULL
, NULL
, &hooks
)) {
2072 name_tables->irq_names = g_new(GQuark, nb);
2073 for(i = 0 ; i < nb ; i++) {
2074 name_tables->irq_names[i] = g_quark_from_string(ltt_enum_string_get(t, i));
2077 /* FIXME: LttvIRQState *irq_states should become a g_array */
2079 name_tables
->nb_irqs
= PREALLOC_NB_IRQS
;
2080 name_tables
->irq_names
= g_new(GQuark
, name_tables
->nb_irqs
);
2081 for(i
= 0 ; i
< name_tables
->nb_irqs
; i
++) {
2082 g_string_printf(fe_name
, "irq %d", i
);
2083 name_tables
->irq_names
[i
] = g_quark_from_string(fe_name
->str
);
2086 name_tables
->nb_irqs
= 0;
2087 name_tables
->irq_names
= NULL
;
2089 lttv_trace_hook_remove_all(&hooks
);
2091 name_tables->soft_irq_names = g_new(GQuark, nb);
2092 for(i = 0 ; i < nb ; i++) {
2093 name_tables->soft_irq_names[i] = g_quark_from_string(ltt_enum_string_get(t, i));
2097 name_tables
->nb_soft_irqs
= PREALLOC_NB_SOFT_IRQS
;
2098 name_tables
->soft_irq_names
= g_new(GQuark
, name_tables
->nb_soft_irqs
);
2099 for(i
= 0 ; i
< name_tables
->nb_soft_irqs
; i
++) {
2100 g_string_printf(fe_name
, "softirq %d", i
);
2101 name_tables
->soft_irq_names
[i
] = g_quark_from_string(fe_name
->str
);
2103 g_array_free(hooks
, TRUE
);
2105 g_string_free(fe_name
, TRUE
);
2107 #if (__WORDSIZE == 32)
2108 name_tables
->kprobe_hash
= g_hash_table_new_full(guint64_hash
, guint64_equal
,
2111 name_tables
->kprobe_hash
= g_hash_table_new(g_direct_hash
, g_direct_equal
);
2116 static void get_name_tables(LttvTraceState
*tcs
)
2118 LttvAttributeValue v
;
2120 lttv_attribute_find(tcs
->parent
.t_a
, LTTV_STATE_NAME_TABLES
,
2122 g_assert(*(v
.v_pointer
) != NULL
);
2123 tcs
->name_tables
= (LttvNameTables
*)*(v
.v_pointer
);
2127 static void free_name_tables(LttvTraceState
*tcs
)
2129 LttvNameTables
*name_tables
;
2131 LttvAttributeValue v
;
2133 lttv_attribute_find(tcs
->parent
.t_a
, LTTV_STATE_NAME_TABLES
,
2135 name_tables
= (LttvNameTables
*)*(v
.v_pointer
);
2136 *(v
.v_pointer
) = NULL
;
2138 // g_free(name_tables->eventtype_names);
2139 if(name_tables
->syscall_names
) g_free(name_tables
->syscall_names
);
2140 if(name_tables
->trap_names
) g_free(name_tables
->trap_names
);
2141 if(name_tables
->irq_names
) g_free(name_tables
->irq_names
);
2142 if(name_tables
->soft_irq_names
) g_free(name_tables
->soft_irq_names
);
2143 g_hash_table_destroy(name_tables
->kprobe_hash
);
2144 g_free(name_tables
);
2147 #ifdef HASH_TABLE_DEBUG
2149 static void test_process(gpointer key
, gpointer value
, gpointer user_data
)
2151 LttvProcessState
*process
= (LttvProcessState
*)value
;
2153 /* Test for process corruption */
2154 guint stack_len
= process
->execution_stack
->len
;
2157 static void hash_table_check(GHashTable
*table
)
2159 g_hash_table_foreach(table
, test_process
, NULL
);
2165 /* clears the stack and sets the state passed as argument */
2166 static void cpu_set_base_mode(LttvCPUState
*cpust
, LttvCPUMode state
)
2168 g_array_set_size(cpust
->mode_stack
, 1);
2169 ((GQuark
*)cpust
->mode_stack
->data
)[0] = state
;
2172 static void cpu_push_mode(LttvCPUState
*cpust
, LttvCPUMode state
)
2174 g_array_set_size(cpust
->mode_stack
, cpust
->mode_stack
->len
+ 1);
2175 ((GQuark
*)cpust
->mode_stack
->data
)[cpust
->mode_stack
->len
- 1] = state
;
2178 static void cpu_pop_mode(LttvCPUState
*cpust
)
2180 if(cpust
->mode_stack
->len
<= 1)
2181 cpu_set_base_mode(cpust
, LTTV_CPU_UNKNOWN
);
2183 g_array_set_size(cpust
->mode_stack
, cpust
->mode_stack
->len
- 1);
2186 /* clears the stack and sets the state passed as argument */
2187 static void bdev_set_base_mode(LttvBdevState
*bdevst
, LttvBdevMode state
)
2189 g_array_set_size(bdevst
->mode_stack
, 1);
2190 ((GQuark
*)bdevst
->mode_stack
->data
)[0] = state
;
2193 static void bdev_push_mode(LttvBdevState
*bdevst
, LttvBdevMode state
)
2195 g_array_set_size(bdevst
->mode_stack
, bdevst
->mode_stack
->len
+ 1);
2196 ((GQuark
*)bdevst
->mode_stack
->data
)[bdevst
->mode_stack
->len
- 1] = state
;
2199 static void bdev_pop_mode(LttvBdevState
*bdevst
)
2201 if(bdevst
->mode_stack
->len
<= 1)
2202 bdev_set_base_mode(bdevst
, LTTV_BDEV_UNKNOWN
);
2204 g_array_set_size(bdevst
->mode_stack
, bdevst
->mode_stack
->len
- 1);
2207 static void irq_set_base_mode(LttvIRQState
*irqst
, LttvIRQMode state
)
2209 g_array_set_size(irqst
->mode_stack
, 1);
2210 ((GQuark
*)irqst
->mode_stack
->data
)[0] = state
;
2213 static void irq_push_mode(LttvIRQState
*irqst
, LttvIRQMode state
)
2215 g_array_set_size(irqst
->mode_stack
, irqst
->mode_stack
->len
+ 1);
2216 ((GQuark
*)irqst
->mode_stack
->data
)[irqst
->mode_stack
->len
- 1] = state
;
2219 static void irq_pop_mode(LttvIRQState
*irqst
)
2221 if(irqst
->mode_stack
->len
<= 1)
2222 irq_set_base_mode(irqst
, LTTV_IRQ_UNKNOWN
);
2224 g_array_set_size(irqst
->mode_stack
, irqst
->mode_stack
->len
- 1);
2227 static void push_state(LttvTracefileState
*tfs
, LttvExecutionMode t
,
2230 LttvExecutionState
*es
;
2232 LttvTraceState
*ts
= (LttvTraceState
*)tfs
->parent
.t_context
;
2233 guint cpu
= tfs
->cpu
;
2235 #ifdef HASH_TABLE_DEBUG
2236 hash_table_check(ts
->processes
);
2238 LttvProcessState
*process
= ts
->running_process
[cpu
];
2240 guint depth
= process
->execution_stack
->len
;
2242 process
->execution_stack
=
2243 g_array_set_size(process
->execution_stack
, depth
+ 1);
2246 &g_array_index(process
->execution_stack
, LttvExecutionState
, depth
- 1);
2248 es
= &g_array_index(process
->execution_stack
, LttvExecutionState
, depth
);
2251 es
->entry
= es
->change
= tfs
->parent
.timestamp
;
2252 es
->cum_cpu_time
= ltt_time_zero
;
2253 es
->s
= process
->state
->s
;
2254 process
->state
= es
;
2258 * return 1 when empty, else 0 */
2260 lttv_state_pop_state_cleanup(LttvProcessState
*process
, LttvTracefileState
*tfs
)
2262 guint depth
= process
->execution_stack
->len
;
2268 process
->execution_stack
=
2269 g_array_set_size(process
->execution_stack
, depth
- 1);
2270 process
->state
= &g_array_index(process
->execution_stack
, LttvExecutionState
,
2272 process
->state
->change
= tfs
->parent
.timestamp
;
2277 static void pop_state(LttvTracefileState
*tfs
, LttvExecutionMode t
)
2279 guint cpu
= tfs
->cpu
;
2280 LttvTraceState
*ts
= (LttvTraceState
*)tfs
->parent
.t_context
;
2281 LttvProcessState
*process
= ts
->running_process
[cpu
];
2283 guint depth
= process
->execution_stack
->len
;
2285 if(process
->state
->t
!= t
){
2286 g_info("Different execution mode type (%lu.%09lu): ignore it\n",
2287 tfs
->parent
.timestamp
.tv_sec
, tfs
->parent
.timestamp
.tv_nsec
);
2288 g_info("process state has %s when pop_int is %s\n",
2289 g_quark_to_string(process
->state
->t
),
2290 g_quark_to_string(t
));
2291 g_info("{ %u, %u, %s, %s, %s }\n",
2294 g_quark_to_string(process
->name
),
2295 g_quark_to_string(process
->brand
),
2296 g_quark_to_string(process
->state
->s
));
2301 g_info("Trying to pop last state on stack (%lu.%09lu): ignore it\n",
2302 tfs
->parent
.timestamp
.tv_sec
, tfs
->parent
.timestamp
.tv_nsec
);
2306 process
->execution_stack
=
2307 g_array_set_size(process
->execution_stack
, depth
- 1);
2308 process
->state
= &g_array_index(process
->execution_stack
, LttvExecutionState
,
2310 process
->state
->change
= tfs
->parent
.timestamp
;
2313 struct search_result
{
2314 const LttTime
*time
; /* Requested time */
2315 LttTime
*best
; /* Best result */
2318 static gint
search_usertrace(gconstpointer a
, gconstpointer b
)
2320 const LttTime
*elem_time
= (const LttTime
*)a
;
2321 /* Explicit non const cast */
2322 struct search_result
*res
= (struct search_result
*)b
;
2324 if(ltt_time_compare(*elem_time
, *(res
->time
)) < 0) {
2325 /* The usertrace was created before the schedchange */
2326 /* Get larger keys */
2328 } else if(ltt_time_compare(*elem_time
, *(res
->time
)) >= 0) {
2329 /* The usertrace was created after the schedchange time */
2330 /* Get smaller keys */
2332 if(ltt_time_compare(*elem_time
, *res
->best
) < 0) {
2333 res
->best
= (LttTime
*)elem_time
;
2336 res
->best
= (LttTime
*)elem_time
;
2343 static LttvTracefileState
*ltt_state_usertrace_find(LttvTraceState
*tcs
,
2344 guint pid
, const LttTime
*timestamp
)
2346 LttvTracefileState
*tfs
= NULL
;
2347 struct search_result res
;
2348 /* Find the usertrace associated with a pid and time interval.
2349 * Search in the usertraces by PID (within a hash) and then, for each
2350 * corresponding element of the array, find the first one with creation
2351 * timestamp the lowest, but higher or equal to "timestamp". */
2352 res
.time
= timestamp
;
2354 GTree
*usertrace_tree
= g_hash_table_lookup(tcs
->usertraces
,
2355 GUINT_TO_POINTER(pid
));
2356 if(usertrace_tree
) {
2357 g_tree_search(usertrace_tree
, search_usertrace
, &res
);
2359 tfs
= g_tree_lookup(usertrace_tree
, res
.best
);
2365 /* Return a new and initialized LttvProcessState structure */
2367 LttvProcessState
*lttv_state_create_process(LttvTraceState
*tcs
,
2368 LttvProcessState
*parent
, guint cpu
, guint pid
,
2369 guint tgid
, GQuark name
, const LttTime
*timestamp
)
2371 LttvProcessState
*process
= g_new(LttvProcessState
, 1);
2373 LttvExecutionState
*es
;
2378 process
->tgid
= tgid
;
2380 process
->name
= name
;
2381 process
->brand
= LTTV_STATE_UNBRANDED
;
2382 //process->last_cpu = tfs->cpu_name;
2383 //process->last_cpu_index = ltt_tracefile_num(((LttvTracefileContext*)tfs)->tf);
2384 process
->type
= LTTV_STATE_USER_THREAD
;
2385 process
->usertrace
= ltt_state_usertrace_find(tcs
, pid
, timestamp
);
2386 process
->current_function
= 0; //function 0x0 by default.
2388 g_info("Process %u, core %p", process
->pid
, process
);
2389 g_hash_table_insert(tcs
->processes
, process
, process
);
2392 process
->ppid
= parent
->pid
;
2393 process
->creation_time
= *timestamp
;
2396 /* No parent. This process exists but we are missing all information about
2397 its creation. The birth time is set to zero but we remember the time of
2402 process
->creation_time
= ltt_time_zero
;
2405 process
->insertion_time
= *timestamp
;
2406 sprintf(buffer
,"%d-%lu.%lu",pid
, process
->creation_time
.tv_sec
,
2407 process
->creation_time
.tv_nsec
);
2408 process
->pid_time
= g_quark_from_string(buffer
);
2410 process
->free_events
= 0;
2411 //process->last_cpu = tfs->cpu_name;
2412 //process->last_cpu_index = ltt_tracefile_num(((LttvTracefileContext*)tfs)->tf);
2413 process
->execution_stack
= g_array_sized_new(FALSE
, FALSE
,
2414 sizeof(LttvExecutionState
), PREALLOCATED_EXECUTION_STACK
);
2415 process
->execution_stack
= g_array_set_size(process
->execution_stack
, 2);
2416 es
= process
->state
= &g_array_index(process
->execution_stack
,
2417 LttvExecutionState
, 0);
2418 es
->t
= LTTV_STATE_USER_MODE
;
2419 es
->n
= LTTV_STATE_SUBMODE_NONE
;
2420 es
->entry
= *timestamp
;
2421 //g_assert(timestamp->tv_sec != 0);
2422 es
->change
= *timestamp
;
2423 es
->cum_cpu_time
= ltt_time_zero
;
2424 es
->s
= LTTV_STATE_RUN
;
2426 es
= process
->state
= &g_array_index(process
->execution_stack
,
2427 LttvExecutionState
, 1);
2428 es
->t
= LTTV_STATE_SYSCALL
;
2429 es
->n
= LTTV_STATE_SUBMODE_NONE
;
2430 es
->entry
= *timestamp
;
2431 //g_assert(timestamp->tv_sec != 0);
2432 es
->change
= *timestamp
;
2433 es
->cum_cpu_time
= ltt_time_zero
;
2434 es
->s
= LTTV_STATE_WAIT_FORK
;
2436 /* Allocate an empty function call stack. If it's empty, use 0x0. */
2437 process
->user_stack
= g_array_sized_new(FALSE
, FALSE
,
2438 sizeof(guint64
), 0);
2440 process
->fds
= g_hash_table_new(g_direct_hash
, g_direct_equal
);
2446 lttv_state_find_process(LttvTraceState
*ts
, guint cpu
, guint pid
)
2448 LttvProcessState key
;
2449 LttvProcessState
*process
;
2453 process
= g_hash_table_lookup(ts
->processes
, &key
);
2457 LttvProcessState
*lttv_state_find_process_or_create(LttvTraceState
*ts
,
2458 guint cpu
, guint pid
, const LttTime
*timestamp
)
2460 LttvProcessState
*process
= lttv_state_find_process(ts
, cpu
, pid
);
2461 LttvExecutionState
*es
;
2463 /* Put ltt_time_zero creation time for unexisting processes */
2464 if(unlikely(process
== NULL
)) {
2465 process
= lttv_state_create_process(ts
,
2466 NULL
, cpu
, pid
, 0, LTTV_STATE_UNNAMED
, timestamp
);
2467 /* We are not sure is it's a kernel thread or normal thread, put the
2468 * bottom stack state to unknown */
2469 process
->execution_stack
=
2470 g_array_set_size(process
->execution_stack
, 1);
2471 process
->state
= es
=
2472 &g_array_index(process
->execution_stack
, LttvExecutionState
, 0);
2473 es
->t
= LTTV_STATE_MODE_UNKNOWN
;
2474 es
->s
= LTTV_STATE_UNNAMED
;
2479 /* FIXME : this function should be called when we receive an event telling that
2480 * release_task has been called in the kernel. In happens generally when
2481 * the parent waits for its child termination, but may also happens in special
2482 * cases in the child's exit : when the parent ignores its children SIGCCHLD or
2483 * has the flag SA_NOCLDWAIT. It can also happen when the child is part
2484 * of a killed thread group, but isn't the leader.
2486 static int exit_process(LttvTracefileState
*tfs
, LttvProcessState
*process
)
2488 LttvTraceState
*ts
= LTTV_TRACE_STATE(tfs
->parent
.t_context
);
2489 LttvProcessState key
;
2491 /* Wait for both schedule with exit dead and process free to happen.
2492 * They can happen in any order. */
2493 if (++(process
->free_events
) < 2)
2496 key
.pid
= process
->pid
;
2497 key
.cpu
= process
->cpu
;
2498 g_hash_table_remove(ts
->processes
, &key
);
2499 g_array_free(process
->execution_stack
, TRUE
);
2500 g_array_free(process
->user_stack
, TRUE
);
2502 /* the following also clears the content */
2503 g_hash_table_destroy(process
->fds
);
2510 static void free_process_state(gpointer key
, gpointer value
,gpointer user_data
)
2512 g_array_free(((LttvProcessState
*)value
)->execution_stack
, TRUE
);
2513 g_array_free(((LttvProcessState
*)value
)->user_stack
, TRUE
);
2515 /* the following also clears the content */
2516 g_hash_table_destroy(((LttvProcessState
*)value
)->fds
);
2522 static void lttv_state_free_process_table(GHashTable
*processes
)
2524 g_hash_table_foreach(processes
, free_process_state
, NULL
);
2525 g_hash_table_destroy(processes
);
2529 static gboolean
syscall_entry(void *hook_data
, void *call_data
)
2531 LttvTracefileState
*s
= (LttvTracefileState
*)call_data
;
2533 LttvTraceState
*ts
= (LttvTraceState
*)s
->parent
.t_context
;
2534 LttvProcessState
*process
= ts
->running_process
[cpu
];
2535 LttEvent
*e
= ltt_tracefile_get_event(s
->parent
.tf
);
2536 LttvTraceHook
*th
= (LttvTraceHook
*)hook_data
;
2537 struct marker_field
*f
= lttv_trace_get_hook_field(th
, 0);
2538 LttvExecutionSubmode submode
;
2539 LttvNameTables
*nt
= ((LttvTraceState
*)(s
->parent
.t_context
))->name_tables
;
2541 guint syscall
= ltt_event_get_unsigned(e
, f
);
2542 expand_syscall_table(ts
, syscall
);
2543 submode
= nt
->syscall_names
[syscall
];
2544 /* There can be no system call from PID 0 : unknown state */
2545 if(process
->pid
!= 0)
2546 push_state(s
, LTTV_STATE_SYSCALL
, submode
);
2551 static gboolean
syscall_exit(void *hook_data
, void *call_data
)
2553 LttvTracefileState
*s
= (LttvTracefileState
*)call_data
;
2555 LttvTraceState
*ts
= (LttvTraceState
*)s
->parent
.t_context
;
2556 LttvProcessState
*process
= ts
->running_process
[cpu
];
2558 /* There can be no system call from PID 0 : unknown state */
2559 if(process
->pid
!= 0)
2560 pop_state(s
, LTTV_STATE_SYSCALL
);
2565 static gboolean
trap_entry(void *hook_data
, void *call_data
)
2567 LttvTracefileState
*s
= (LttvTracefileState
*)call_data
;
2568 LttvTraceState
*ts
= (LttvTraceState
*)s
->parent
.t_context
;
2569 LttEvent
*e
= ltt_tracefile_get_event(s
->parent
.tf
);
2570 LttvTraceHook
*th
= (LttvTraceHook
*)hook_data
;
2571 struct marker_field
*f
= lttv_trace_get_hook_field(th
, 0);
2572 LttvNameTables
*nt
= ((LttvTraceState
*)(s
->parent
.t_context
))->name_tables
;
2574 LttvExecutionSubmode submode
;
2576 guint64 trap
= ltt_event_get_long_unsigned(e
, f
);
2578 expand_trap_table(ts
, trap
);
2580 submode
= nt
->trap_names
[trap
];
2582 push_state(s
, LTTV_STATE_TRAP
, submode
);
2584 /* update cpu status */
2585 cpu_push_mode(s
->cpu_state
, LTTV_CPU_TRAP
);
2587 /* update trap status */
2588 g_array_append_val(s
->cpu_state
->trap_stack
, trap
);
2589 ts
->trap_states
[trap
].running
++;
2594 static gboolean
trap_exit(void *hook_data
, void *call_data
)
2596 LttvTracefileState
*s
= (LttvTracefileState
*)call_data
;
2597 LttvTraceState
*ts
= (LttvTraceState
*)s
->parent
.t_context
;
2599 pop_state(s
, LTTV_STATE_TRAP
);
2601 /* update cpu status */
2602 cpu_pop_mode(s
->cpu_state
);
2604 /* update trap status */
2605 if (s
->cpu_state
->trap_stack
->len
> 0) {
2606 gint last
= g_array_index(s
->cpu_state
->trap_stack
, gint
,
2607 s
->cpu_state
->trap_stack
->len
-1);
2608 if(ts
->trap_states
[last
].running
)
2609 ts
->trap_states
[last
].running
--;
2610 g_array_remove_index(s
->cpu_state
->trap_stack
,
2611 s
->cpu_state
->trap_stack
->len
-1);
2616 static gboolean
irq_entry(void *hook_data
, void *call_data
)
2618 LttvTracefileState
*s
= (LttvTracefileState
*)call_data
;
2619 LttvTraceState
*ts
= (LttvTraceState
*)s
->parent
.t_context
;
2620 LttEvent
*e
= ltt_tracefile_get_event(s
->parent
.tf
);
2621 //guint8 ev_id = ltt_event_eventtype_id(e);
2622 LttvTraceHook
*th
= (LttvTraceHook
*)hook_data
;
2623 struct marker_field
*f
= lttv_trace_get_hook_field(th
, 0);
2624 LttvNameTables
*nt
= ((LttvTraceState
*)(s
->parent
.t_context
))->name_tables
;
2626 LttvExecutionSubmode submode
;
2627 guint64 irq
= ltt_event_get_long_unsigned(e
, f
);
2629 expand_irq_table(ts
, irq
);
2631 submode
= nt
->irq_names
[irq
];
2633 /* Do something with the info about being in user or system mode when int? */
2634 push_state(s
, LTTV_STATE_IRQ
, submode
);
2636 /* update cpu status */
2637 cpu_push_mode(s
->cpu_state
, LTTV_CPU_IRQ
);
2639 /* update irq status */
2640 g_array_append_val(s
->cpu_state
->irq_stack
, irq
);
2641 irq_push_mode(&ts
->irq_states
[irq
], LTTV_IRQ_BUSY
);
2646 static gboolean
soft_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_SOFT_IRQ
);
2653 /* update cpu status */
2654 cpu_pop_mode(s
->cpu_state
);
2656 /* update softirq status */
2657 if (s
->cpu_state
->softirq_stack
->len
> 0) {
2658 gint last
= g_array_index(s
->cpu_state
->softirq_stack
, gint
, s
->cpu_state
->softirq_stack
->len
-1);
2659 if(ts
->soft_irq_states
[last
].running
)
2660 ts
->soft_irq_states
[last
].running
--;
2661 g_array_remove_index(s
->cpu_state
->softirq_stack
, s
->cpu_state
->softirq_stack
->len
-1);
2666 static gboolean
irq_exit(void *hook_data
, void *call_data
)
2668 LttvTracefileState
*s
= (LttvTracefileState
*)call_data
;
2669 LttvTraceState
*ts
= (LttvTraceState
*)s
->parent
.t_context
;
2671 pop_state(s
, LTTV_STATE_IRQ
);
2673 /* update cpu status */
2674 cpu_pop_mode(s
->cpu_state
);
2676 /* update irq status */
2677 if (s
->cpu_state
->irq_stack
->len
> 0) {
2678 gint last
= g_array_index(s
->cpu_state
->irq_stack
, gint
, s
->cpu_state
->irq_stack
->len
-1);
2679 g_array_remove_index(s
->cpu_state
->irq_stack
, s
->cpu_state
->irq_stack
->len
-1);
2680 irq_pop_mode(&ts
->irq_states
[last
]);
2686 static gboolean
soft_irq_raise(void *hook_data
, void *call_data
)
2688 LttvTracefileState
*s
= (LttvTracefileState
*)call_data
;
2689 LttvTraceState
*ts
= (LttvTraceState
*)s
->parent
.t_context
;
2690 LttEvent
*e
= ltt_tracefile_get_event(s
->parent
.tf
);
2691 //guint8 ev_id = ltt_event_eventtype_id(e);
2692 LttvTraceHook
*th
= (LttvTraceHook
*)hook_data
;
2693 struct marker_field
*f
= lttv_trace_get_hook_field(th
, 0);
2695 guint64 softirq
= ltt_event_get_long_unsigned(e
, f
);
2697 expand_soft_irq_table(ts
, softirq
);
2699 /* update softirq status */
2700 /* a soft irq raises are not cumulative */
2701 ts
->soft_irq_states
[softirq
].pending
=1;
2706 static gboolean
soft_irq_entry(void *hook_data
, void *call_data
)
2708 LttvTracefileState
*s
= (LttvTracefileState
*)call_data
;
2709 LttvTraceState
*ts
= (LttvTraceState
*)s
->parent
.t_context
;
2710 LttEvent
*e
= ltt_tracefile_get_event(s
->parent
.tf
);
2711 //guint8 ev_id = ltt_event_eventtype_id(e);
2712 LttvTraceHook
*th
= (LttvTraceHook
*)hook_data
;
2713 struct marker_field
*f
= lttv_trace_get_hook_field(th
, 0);
2714 LttvExecutionSubmode submode
;
2715 guint64 softirq
= ltt_event_get_long_unsigned(e
, f
);
2716 expand_soft_irq_table(ts
, softirq
);
2717 LttvNameTables
*nt
= ((LttvTraceState
*)(s
->parent
.t_context
))->name_tables
;
2718 submode
= nt
->soft_irq_names
[softirq
];
2720 /* Do something with the info about being in user or system mode when int? */
2721 push_state(s
, LTTV_STATE_SOFT_IRQ
, submode
);
2723 /* update cpu status */
2724 cpu_push_mode(s
->cpu_state
, LTTV_CPU_SOFT_IRQ
);
2726 /* update softirq status */
2727 g_array_append_val(s
->cpu_state
->softirq_stack
, softirq
);
2728 if(ts
->soft_irq_states
[softirq
].pending
)
2729 ts
->soft_irq_states
[softirq
].pending
--;
2730 ts
->soft_irq_states
[softirq
].running
++;
2735 static gboolean
enum_interrupt(void *hook_data
, void *call_data
)
2737 LttvTracefileState
*s
= (LttvTracefileState
*)call_data
;
2738 LttvTraceState
*ts
= (LttvTraceState
*)s
->parent
.t_context
;
2739 LttvNameTables
*nt
= ts
->name_tables
;
2740 LttEvent
*e
= ltt_tracefile_get_event(s
->parent
.tf
);
2741 //guint8 ev_id = ltt_event_eventtype_id(e);
2742 LttvTraceHook
*th
= (LttvTraceHook
*)hook_data
;
2744 GQuark action
= g_quark_from_string(ltt_event_get_string(e
,
2745 lttv_trace_get_hook_field(th
, 0)));
2746 guint irq
= ltt_event_get_long_unsigned(e
, lttv_trace_get_hook_field(th
, 1));
2748 expand_irq_table(ts
, irq
);
2749 nt
->irq_names
[irq
] = action
;
2755 static gboolean
bdev_request_issue(void *hook_data
, void *call_data
)
2757 LttvTracefileState
*s
= (LttvTracefileState
*)call_data
;
2758 LttvTraceState
*ts
= (LttvTraceState
*)s
->parent
.t_context
;
2759 LttEvent
*e
= ltt_tracefile_get_event(s
->parent
.tf
);
2760 //guint8 ev_id = ltt_event_eventtype_id(e);
2761 LttvTraceHook
*th
= (LttvTraceHook
*)hook_data
;
2763 guint major
= ltt_event_get_long_unsigned(e
,
2764 lttv_trace_get_hook_field(th
, 0));
2765 guint minor
= ltt_event_get_long_unsigned(e
,
2766 lttv_trace_get_hook_field(th
, 1));
2767 guint oper
= ltt_event_get_long_unsigned(e
,
2768 lttv_trace_get_hook_field(th
, 2));
2769 guint32 devcode
= MKDEV(major
,minor
);
2771 /* have we seen this block device before? */
2772 gpointer bdev
= get_hashed_bdevstate(ts
, devcode
);
2775 bdev_push_mode(bdev
, LTTV_BDEV_BUSY_READING
);
2777 bdev_push_mode(bdev
, LTTV_BDEV_BUSY_WRITING
);
2782 static gboolean
bdev_request_complete(void *hook_data
, void *call_data
)
2784 LttvTracefileState
*s
= (LttvTracefileState
*)call_data
;
2785 LttvTraceState
*ts
= (LttvTraceState
*)s
->parent
.t_context
;
2786 LttEvent
*e
= ltt_tracefile_get_event(s
->parent
.tf
);
2787 LttvTraceHook
*th
= (LttvTraceHook
*)hook_data
;
2789 guint major
= ltt_event_get_long_unsigned(e
,
2790 lttv_trace_get_hook_field(th
, 0));
2791 guint minor
= ltt_event_get_long_unsigned(e
,
2792 lttv_trace_get_hook_field(th
, 1));
2793 //guint oper = ltt_event_get_long_unsigned(e,
2794 // lttv_trace_get_hook_field(th, 2));
2795 guint32 devcode
= MKDEV(major
,minor
);
2797 /* have we seen this block device before? */
2798 gpointer bdev
= get_hashed_bdevstate(ts
, devcode
);
2800 /* update block device */
2801 bdev_pop_mode(bdev
);
2806 static void push_function(LttvTracefileState
*tfs
, guint64 funcptr
)
2810 LttvTraceState
*ts
= (LttvTraceState
*)tfs
->parent
.t_context
;
2811 guint cpu
= tfs
->cpu
;
2812 LttvProcessState
*process
= ts
->running_process
[cpu
];
2814 guint depth
= process
->user_stack
->len
;
2816 process
->user_stack
=
2817 g_array_set_size(process
->user_stack
, depth
+ 1);
2819 new_func
= &g_array_index(process
->user_stack
, guint64
, depth
);
2820 *new_func
= funcptr
;
2821 process
->current_function
= funcptr
;
2824 static void pop_function(LttvTracefileState
*tfs
, guint64 funcptr
)
2826 guint cpu
= tfs
->cpu
;
2827 LttvTraceState
*ts
= (LttvTraceState
*)tfs
->parent
.t_context
;
2828 LttvProcessState
*process
= ts
->running_process
[cpu
];
2830 if(process
->current_function
!= funcptr
){
2831 g_info("Different functions (%lu.%09lu): ignore it\n",
2832 tfs
->parent
.timestamp
.tv_sec
, tfs
->parent
.timestamp
.tv_nsec
);
2833 g_info("process state has %" PRIu64
" when pop_function is %" PRIu64
"\n",
2834 process
->current_function
, funcptr
);
2835 g_info("{ %u, %u, %s, %s, %s }\n",
2838 g_quark_to_string(process
->name
),
2839 g_quark_to_string(process
->brand
),
2840 g_quark_to_string(process
->state
->s
));
2843 guint depth
= process
->user_stack
->len
;
2846 g_info("Trying to pop last function on stack (%lu.%09lu): ignore it\n",
2847 tfs
->parent
.timestamp
.tv_sec
, tfs
->parent
.timestamp
.tv_nsec
);
2851 process
->user_stack
=
2852 g_array_set_size(process
->user_stack
, depth
- 1);
2853 process
->current_function
=
2854 g_array_index(process
->user_stack
, guint64
, depth
- 2);
2858 static gboolean
function_entry(void *hook_data
, void *call_data
)
2860 LttvTracefileState
*s
= (LttvTracefileState
*)call_data
;
2861 LttEvent
*e
= ltt_tracefile_get_event(s
->parent
.tf
);
2862 //guint8 ev_id = ltt_event_eventtype_id(e);
2863 LttvTraceHook
*th
= (LttvTraceHook
*)hook_data
;
2864 struct marker_field
*f
= lttv_trace_get_hook_field(th
, 0);
2865 guint64 funcptr
= ltt_event_get_long_unsigned(e
, f
);
2867 push_function(s
, funcptr
);
2871 static gboolean
function_exit(void *hook_data
, void *call_data
)
2873 LttvTracefileState
*s
= (LttvTracefileState
*)call_data
;
2874 LttEvent
*e
= ltt_tracefile_get_event(s
->parent
.tf
);
2875 //guint8 ev_id = ltt_event_eventtype_id(e);
2876 LttvTraceHook
*th
= (LttvTraceHook
*)hook_data
;
2877 struct marker_field
*f
= lttv_trace_get_hook_field(th
, 0);
2878 guint64 funcptr
= ltt_event_get_long_unsigned(e
, f
);
2880 pop_function(s
, funcptr
);
2884 static gboolean
dump_syscall(void *hook_data
, void *call_data
)
2886 LttvTracefileState
*s
= (LttvTracefileState
*)call_data
;
2887 LttvTraceState
*ts
= (LttvTraceState
*)s
->parent
.t_context
;
2888 LttvNameTables
*nt
= ts
->name_tables
;
2889 LttEvent
*e
= ltt_tracefile_get_event(s
->parent
.tf
);
2890 LttvTraceHook
*th
= (LttvTraceHook
*)hook_data
;
2894 id
= ltt_event_get_unsigned(e
, lttv_trace_get_hook_field(th
, 0));
2895 symbol
= ltt_event_get_string(e
, lttv_trace_get_hook_field(th
, 2));
2897 expand_syscall_table(ts
, id
);
2898 nt
->syscall_names
[id
] = g_quark_from_string(symbol
);
2903 static gboolean
dump_kprobe(void *hook_data
, void *call_data
)
2905 LttvTracefileState
*s
= (LttvTracefileState
*)call_data
;
2906 LttvTraceState
*ts
= (LttvTraceState
*)s
->parent
.t_context
;
2907 LttEvent
*e
= ltt_tracefile_get_event(s
->parent
.tf
);
2908 LttvTraceHook
*th
= (LttvTraceHook
*)hook_data
;
2912 ip
= ltt_event_get_long_unsigned(e
, lttv_trace_get_hook_field(th
, 0));
2913 symbol
= ltt_event_get_string(e
, lttv_trace_get_hook_field(th
, 1));
2915 expand_kprobe_table(ts
, ip
, symbol
);
2920 static gboolean
dump_softirq(void *hook_data
, void *call_data
)
2922 LttvTracefileState
*s
= (LttvTracefileState
*)call_data
;
2923 LttvTraceState
*ts
= (LttvTraceState
*)s
->parent
.t_context
;
2924 LttvNameTables
*nt
= ts
->name_tables
;
2925 LttEvent
*e
= ltt_tracefile_get_event(s
->parent
.tf
);
2926 LttvTraceHook
*th
= (LttvTraceHook
*)hook_data
;
2930 id
= ltt_event_get_unsigned(e
, lttv_trace_get_hook_field(th
, 0));
2931 symbol
= ltt_event_get_string(e
, lttv_trace_get_hook_field(th
, 2));
2933 expand_soft_irq_table(ts
, id
);
2934 nt
->soft_irq_names
[id
] = g_quark_from_string(symbol
);
2939 static gboolean
sched_try_wakeup(void *hook_data
, void *call_data
)
2941 LttvTracefileState
*s
= (LttvTracefileState
*)call_data
;
2942 LttEvent
*e
= ltt_tracefile_get_event(s
->parent
.tf
);
2943 LttvTraceHook
*th
= (LttvTraceHook
*)hook_data
;
2944 LttvProcessState
*process
;
2948 woken_pid
= ltt_event_get_int(e
, lttv_trace_get_hook_field(th
, 0));
2949 woken_cpu
= ltt_event_get_unsigned(e
, lttv_trace_get_hook_field(th
, 1));
2951 process
= lttv_state_find_process_or_create(
2952 (LttvTraceState
*)s
->parent
.t_context
,
2953 woken_cpu
, woken_pid
,
2954 &s
->parent
.timestamp
);
2956 if (process
->state
->s
== LTTV_STATE_WAIT
|| process
->state
->s
== LTTV_STATE_WAIT_FORK
)
2958 process
->state
->s
= LTTV_STATE_WAIT_CPU
;
2959 process
->state
->change
= s
->parent
.timestamp
;
2962 g_debug("Wakeup: process %d on CPU %u\n", woken_pid
, woken_cpu
);
2967 static gboolean
schedchange(void *hook_data
, void *call_data
)
2969 LttvTracefileState
*s
= (LttvTracefileState
*)call_data
;
2971 LttvTraceState
*ts
= (LttvTraceState
*)s
->parent
.t_context
;
2972 LttvProcessState
*process
= ts
->running_process
[cpu
];
2973 //LttvProcessState *old_process = ts->running_process[cpu];
2975 LttEvent
*e
= ltt_tracefile_get_event(s
->parent
.tf
);
2976 LttvTraceHook
*th
= (LttvTraceHook
*)hook_data
;
2977 guint pid_in
, pid_out
;
2980 pid_out
= ltt_event_get_unsigned(e
, lttv_trace_get_hook_field(th
, 0));
2981 pid_in
= ltt_event_get_unsigned(e
, lttv_trace_get_hook_field(th
, 1));
2982 state_out
= ltt_event_get_long_int(e
, lttv_trace_get_hook_field(th
, 2));
2984 if(likely(process
!= NULL
)) {
2986 /* We could not know but it was not the idle process executing.
2987 This should only happen at the beginning, before the first schedule
2988 event, and when the initial information (current process for each CPU)
2989 is missing. It is not obvious how we could, after the fact, compensate
2990 the wrongly attributed statistics. */
2992 //This test only makes sense once the state is known and if there is no
2993 //missing events. We need to silently ignore schedchange coming after a
2994 //process_free, or it causes glitches. (FIXME)
2995 //if(unlikely(process->pid != pid_out)) {
2996 // g_assert(process->pid == 0);
2998 if(process
->pid
== 0
2999 && process
->state
->t
== LTTV_STATE_MODE_UNKNOWN
) {
3002 * Scheduling out of pid 0 at beginning of the trace.
3003 * We are typically in system call mode at this point although
3004 * (FIXME) we might be in a trap handler.
3006 g_assert(process
->execution_stack
->len
== 1);
3007 process
->state
->t
= LTTV_STATE_SYSCALL
;
3008 process
->state
->s
= LTTV_STATE_WAIT
;
3009 process
->state
->change
= s
->parent
.timestamp
;
3010 process
->state
->entry
= s
->parent
.timestamp
;
3013 if(unlikely(process
->state
->s
== LTTV_STATE_EXIT
)) {
3014 process
->state
->s
= LTTV_STATE_ZOMBIE
;
3015 process
->state
->change
= s
->parent
.timestamp
;
3017 if(unlikely(state_out
== 0)) process
->state
->s
= LTTV_STATE_WAIT_CPU
;
3018 else process
->state
->s
= LTTV_STATE_WAIT
;
3019 process
->state
->change
= s
->parent
.timestamp
;
3022 if(state_out
== 32 || state_out
== 64) { /* EXIT_DEAD || TASK_DEAD */
3023 /* see sched.h for states */
3024 if (!exit_process(s
, process
)) {
3025 process
->state
->s
= LTTV_STATE_DEAD
;
3026 process
->state
->change
= s
->parent
.timestamp
;
3031 process
= ts
->running_process
[cpu
] = lttv_state_find_process_or_create(
3032 (LttvTraceState
*)s
->parent
.t_context
,
3034 &s
->parent
.timestamp
);
3035 process
->state
->s
= LTTV_STATE_RUN
;
3037 if(process
->usertrace
)
3038 process
->usertrace
->cpu
= cpu
;
3039 // process->last_cpu_index = ltt_tracefile_num(((LttvTracefileContext*)s)->tf);
3040 process
->state
->change
= s
->parent
.timestamp
;
3042 /* update cpu status */
3044 /* going to idle task */
3045 cpu_set_base_mode(s
->cpu_state
, LTTV_CPU_IDLE
);
3047 /* scheduling a real task.
3048 * we must be careful here:
3049 * if we just schedule()'ed to a process that is
3050 * in a trap, we must put the cpu in trap mode
3052 cpu_set_base_mode(s
->cpu_state
, LTTV_CPU_BUSY
);
3053 if(process
->state
->t
== LTTV_STATE_TRAP
)
3054 cpu_push_mode(s
->cpu_state
, LTTV_CPU_TRAP
);
3060 static gboolean
process_fork(void *hook_data
, void *call_data
)
3062 LttvTracefileState
*s
= (LttvTracefileState
*)call_data
;
3063 LttEvent
*e
= ltt_tracefile_get_event(s
->parent
.tf
);
3064 LttvTraceHook
*th
= (LttvTraceHook
*)hook_data
;
3065 guint child_pid
; /* In the Linux Kernel, there is one PID per thread. */
3066 guint child_tgid
; /* tgid in the Linux kernel is the "real" POSIX PID. */
3067 //LttvProcessState *zombie_process;
3069 LttvTraceState
*ts
= (LttvTraceState
*)s
->parent
.t_context
;
3070 LttvProcessState
*process
= ts
->running_process
[cpu
];
3071 LttvProcessState
*child_process
;
3072 struct marker_field
*f
;
3074 /* Skip Parent PID param */
3077 child_pid
= ltt_event_get_unsigned(e
, lttv_trace_get_hook_field(th
, 1));
3078 s
->parent
.target_pid
= child_pid
;
3081 f
= lttv_trace_get_hook_field(th
, 2);
3083 child_tgid
= ltt_event_get_unsigned(e
, f
);
3087 /* Mathieu : it seems like the process might have been scheduled in before the
3088 * fork, and, in a rare case, might be the current process. This might happen
3089 * in a SMP case where we don't have enough precision on the clocks.
3091 * Test reenabled after precision fixes on time. (Mathieu) */
3093 zombie_process
= lttv_state_find_process(ts
, ANY_CPU
, child_pid
);
3095 if(unlikely(zombie_process
!= NULL
)) {
3096 /* Reutilisation of PID. Only now we are sure that the old PID
3097 * has been released. FIXME : should know when release_task happens instead.
3099 guint num_cpus
= ltt_trace_get_num_cpu(ts
->parent
.t
);
3101 for(i
=0; i
< num_cpus
; i
++) {
3102 g_assert(zombie_process
!= ts
->running_process
[i
]);
3105 exit_process(s
, zombie_process
);
3108 g_assert(process
->pid
!= child_pid
);
3109 // FIXME : Add this test in the "known state" section
3110 // g_assert(process->pid == parent_pid);
3111 child_process
= lttv_state_find_process(ts
, ANY_CPU
, child_pid
);
3112 if(child_process
== NULL
) {
3113 child_process
= lttv_state_create_process(ts
, process
, cpu
,
3114 child_pid
, child_tgid
,
3115 LTTV_STATE_UNNAMED
, &s
->parent
.timestamp
);
3117 /* The process has already been created : due to time imprecision between
3118 * multiple CPUs : it has been scheduled in before creation. Note that we
3119 * shouldn't have this kind of imprecision.
3121 * Simply put a correct parent.
3123 g_error("Process %u has been created at [%lu.%09lu] "
3124 "and inserted at [%lu.%09lu] before \n"
3125 "fork on cpu %u[%lu.%09lu].\n"
3126 "Probably an unsynchronized TSC problem on the traced machine.",
3128 child_process
->creation_time
.tv_sec
,
3129 child_process
->creation_time
.tv_nsec
,
3130 child_process
->insertion_time
.tv_sec
,
3131 child_process
->insertion_time
.tv_nsec
,
3132 cpu
, ltt_event_time(e
).tv_sec
, ltt_event_time(e
).tv_nsec
);
3133 //g_assert(0); /* This is a problematic case : the process has been created
3134 // before the fork event */
3135 child_process
->ppid
= process
->pid
;
3136 child_process
->tgid
= child_tgid
;
3138 g_assert(child_process
->name
== LTTV_STATE_UNNAMED
);
3139 child_process
->name
= process
->name
;
3140 child_process
->brand
= process
->brand
;
3145 /* We stamp a newly created process as kernel_thread.
3146 * The thread should not be running yet. */
3147 static gboolean
process_kernel_thread(void *hook_data
, void *call_data
)
3149 LttvTracefileState
*s
= (LttvTracefileState
*)call_data
;
3150 LttEvent
*e
= ltt_tracefile_get_event(s
->parent
.tf
);
3151 LttvTraceHook
*th
= (LttvTraceHook
*)hook_data
;
3153 LttvTraceState
*ts
= (LttvTraceState
*)s
->parent
.t_context
;
3154 LttvProcessState
*process
;
3155 LttvExecutionState
*es
;
3158 pid
= (guint
)ltt_event_get_long_unsigned(e
, lttv_trace_get_hook_field(th
, 0));
3159 s
->parent
.target_pid
= pid
;
3161 process
= lttv_state_find_process_or_create(ts
, ANY_CPU
, pid
,
3163 if (process
->state
->s
!= LTTV_STATE_DEAD
) {
3164 process
->execution_stack
=
3165 g_array_set_size(process
->execution_stack
, 1);
3166 es
= process
->state
=
3167 &g_array_index(process
->execution_stack
, LttvExecutionState
, 0);
3168 es
->t
= LTTV_STATE_SYSCALL
;
3170 process
->type
= LTTV_STATE_KERNEL_THREAD
;
3175 static gboolean
process_exit(void *hook_data
, void *call_data
)
3177 LttvTracefileState
*s
= (LttvTracefileState
*)call_data
;
3178 LttEvent
*e
= ltt_tracefile_get_event(s
->parent
.tf
);
3179 LttvTraceHook
*th
= (LttvTraceHook
*)hook_data
;
3181 LttvTraceState
*ts
= (LttvTraceState
*)s
->parent
.t_context
;
3182 LttvProcessState
*process
; // = ts->running_process[cpu];
3184 pid
= ltt_event_get_unsigned(e
, lttv_trace_get_hook_field(th
, 0));
3185 s
->parent
.target_pid
= pid
;
3187 // FIXME : Add this test in the "known state" section
3188 // g_assert(process->pid == pid);
3190 process
= lttv_state_find_process(ts
, ANY_CPU
, pid
);
3191 if(likely(process
!= NULL
)) {
3192 process
->state
->s
= LTTV_STATE_EXIT
;
3197 static gboolean
process_free(void *hook_data
, void *call_data
)
3199 LttvTracefileState
*s
= (LttvTracefileState
*)call_data
;
3200 LttvTraceState
*ts
= (LttvTraceState
*)s
->parent
.t_context
;
3201 LttEvent
*e
= ltt_tracefile_get_event(s
->parent
.tf
);
3202 LttvTraceHook
*th
= (LttvTraceHook
*)hook_data
;
3204 LttvProcessState
*process
;
3206 /* PID of the process to release */
3207 release_pid
= ltt_event_get_unsigned(e
, lttv_trace_get_hook_field(th
, 0));
3208 s
->parent
.target_pid
= release_pid
;
3210 g_assert(release_pid
!= 0);
3212 process
= lttv_state_find_process(ts
, ANY_CPU
, release_pid
);
3213 if(likely(process
!= NULL
))
3214 exit_process(s
, process
);
3217 if(likely(process
!= NULL
)) {
3218 /* release_task is happening at kernel level : we can now safely release
3219 * the data structure of the process */
3220 //This test is fun, though, as it may happen that
3221 //at time t : CPU 0 : process_free
3222 //at time t+150ns : CPU 1 : schedule out
3223 //Clearly due to time imprecision, we disable it. (Mathieu)
3224 //If this weird case happen, we have no choice but to put the
3225 //Currently running process on the cpu to 0.
3226 //I re-enable it following time precision fixes. (Mathieu)
3227 //Well, in the case where an process is freed by a process on another CPU
3228 //and still scheduled, it happens that this is the schedchange that will
3229 //drop the last reference count. Do not free it here!
3230 guint num_cpus
= ltt_trace_get_num_cpu(ts
->parent
.t
);
3232 for(i
=0; i
< num_cpus
; i
++) {
3233 //g_assert(process != ts->running_process[i]);
3234 if(process
== ts
->running_process
[i
]) {
3235 //ts->running_process[i] = lttv_state_find_process(ts, i, 0);
3239 if(i
== num_cpus
) /* process is not scheduled */
3240 exit_process(s
, process
);
3247 static gboolean
process_exec(void *hook_data
, void *call_data
)
3249 LttvTracefileState
*s
= (LttvTracefileState
*)call_data
;
3250 LttvTraceState
*ts
= (LttvTraceState
*)s
->parent
.t_context
;
3251 LttEvent
*e
= ltt_tracefile_get_event(s
->parent
.tf
);
3252 LttvTraceHook
*th
= (LttvTraceHook
*)hook_data
;
3255 LttvProcessState
*process
= ts
->running_process
[cpu
];
3257 #if 0//how to use a sequence that must be transformed in a string
3258 /* PID of the process to release */
3259 guint64 name_len
= ltt_event_field_element_number(e
,
3260 lttv_trace_get_hook_field(th
, 0));
3261 //name = ltt_event_get_string(e, lttv_trace_get_hook_field(th, 0));
3262 LttField
*child
= ltt_event_field_element_select(e
,
3263 lttv_trace_get_hook_field(th
, 0), 0);
3265 (gchar
*)(ltt_event_data(e
)+ltt_event_field_offset(e
, child
));
3266 gchar
*null_term_name
= g_new(gchar
, name_len
+1);
3267 memcpy(null_term_name
, name_begin
, name_len
);
3268 null_term_name
[name_len
] = '\0';
3269 process
->name
= g_quark_from_string(null_term_name
);
3272 process
->name
= g_quark_from_string(ltt_event_get_string(e
,
3273 lttv_trace_get_hook_field(th
, 0)));
3274 process
->brand
= LTTV_STATE_UNBRANDED
;
3275 //g_free(null_term_name);
3279 static gboolean
thread_brand(void *hook_data
, void *call_data
)
3281 LttvTracefileState
*s
= (LttvTracefileState
*)call_data
;
3282 LttvTraceState
*ts
= (LttvTraceState
*)s
->parent
.t_context
;
3283 LttEvent
*e
= ltt_tracefile_get_event(s
->parent
.tf
);
3284 LttvTraceHook
*th
= (LttvTraceHook
*)hook_data
;
3287 LttvProcessState
*process
= ts
->running_process
[cpu
];
3289 name
= ltt_event_get_string(e
, lttv_trace_get_hook_field(th
, 0));
3290 process
->brand
= g_quark_from_string(name
);
3295 static gboolean
fs_open(void *hook_data
, void *call_data
)
3297 LttvTracefileState
*s
= (LttvTracefileState
*)call_data
;
3298 LttvTraceState
*ts
= (LttvTraceState
*)s
->parent
.t_context
;
3299 LttEvent
*e
= ltt_tracefile_get_event(s
->parent
.tf
);
3300 LttvTraceHook
*th
= (LttvTraceHook
*)hook_data
;
3301 struct marker_field
*f
;
3305 LttvProcessState
*process
= ts
->running_process
[cpu
];
3307 f
= lttv_trace_get_hook_field(th
, 0);
3308 fd
= ltt_event_get_int(e
, f
);
3310 f
= lttv_trace_get_hook_field(th
, 1);
3311 filename
= ltt_event_get_string(e
, f
);
3313 g_hash_table_insert(process
->fds
, (gpointer
)(long)fd
,
3314 (gpointer
)(unsigned long)g_quark_from_string(filename
));
3319 static void print_stack(LttvProcessState
*process
)
3321 LttvExecutionState
*es
;
3324 g_debug("Execution stack for process %u %s:\n",
3325 process
->pid
, g_quark_to_string(process
->name
));
3327 for (i
= 0; i
< process
->execution_stack
->len
; i
++) {
3328 es
= &g_array_index(process
->execution_stack
,
3329 LttvExecutionState
, i
);
3330 g_debug("Depth %d mode %s submode %s status %s\n",
3331 i
, g_quark_to_string(es
->t
),
3332 g_quark_to_string(es
->n
),
3333 g_quark_to_string(es
->s
));
3338 static void fix_process(gpointer key
, gpointer value
, gpointer user_data
)
3340 LttvProcessState
*process
;
3341 LttvExecutionState
*es
;
3342 process
= (LttvProcessState
*)value
;
3343 LttTime
*timestamp
= (LttTime
*)user_data
;
3345 print_stack(process
);
3347 if(process
->type
== LTTV_STATE_KERNEL_THREAD
) {
3348 es
= &g_array_index(process
->execution_stack
, LttvExecutionState
, 0);
3349 if(es
->t
== LTTV_STATE_MAYBE_SYSCALL
) {
3350 es
->t
= LTTV_STATE_SYSCALL
;
3351 es
->n
= LTTV_STATE_SUBMODE_NONE
;
3352 es
->entry
= *timestamp
;
3353 es
->change
= *timestamp
;
3354 es
->cum_cpu_time
= ltt_time_zero
;
3355 if(es
->s
== LTTV_STATE_UNNAMED
)
3356 es
->s
= LTTV_STATE_WAIT
;
3359 es
= &g_array_index(process
->execution_stack
, LttvExecutionState
, 0);
3360 if(es
->t
== LTTV_STATE_MAYBE_USER_MODE
) {
3361 es
->t
= LTTV_STATE_USER_MODE
;
3362 es
->n
= LTTV_STATE_SUBMODE_NONE
;
3363 es
->entry
= *timestamp
;
3364 //g_assert(timestamp->tv_sec != 0);
3365 es
->change
= *timestamp
;
3366 es
->cum_cpu_time
= ltt_time_zero
;
3367 if(es
->s
== LTTV_STATE_UNNAMED
)
3368 es
->s
= LTTV_STATE_RUN
;
3370 if(process
->execution_stack
->len
== 1) {
3371 /* Still in bottom unknown mode, means we either:
3372 * - never did a system call
3373 * - are scheduled out from user mode.
3374 * May be either in user mode, syscall mode, running or waiting.*/
3375 /* CHECK : we may be tagging syscall mode when being user mode
3376 * (should be fixed now) */
3377 if (es
->s
== LTTV_STATE_WAIT_CPU
) {
3378 /* nothing to do: scheduled out from userspace */
3380 process
->execution_stack
=
3381 g_array_set_size(process
->execution_stack
, 2);
3382 es
= process
->state
= &g_array_index(process
->execution_stack
,
3383 LttvExecutionState
, 1);
3384 es
->t
= LTTV_STATE_SYSCALL
;
3385 es
->n
= LTTV_STATE_SUBMODE_NONE
;
3386 es
->entry
= *timestamp
;
3387 //g_assert(timestamp->tv_sec != 0);
3388 es
->change
= *timestamp
;
3389 es
->cum_cpu_time
= ltt_time_zero
;
3390 if(es
->s
== LTTV_STATE_WAIT_FORK
)
3391 es
->s
= LTTV_STATE_WAIT
;
3398 static gboolean
statedump_end(void *hook_data
, void *call_data
)
3400 LttvTracefileState
*s
= (LttvTracefileState
*)call_data
;
3401 LttvTraceState
*ts
= (LttvTraceState
*)s
->parent
.t_context
;
3402 LttvTracefileContext
*tfc
= (LttvTracefileContext
*)call_data
;
3403 //LttEvent *e = ltt_tracefile_get_event(s->parent.tf);
3404 //LttvTraceHook *th = (LttvTraceHook *)hook_data;
3406 /* For all processes */
3407 /* if kernel thread, if stack[0] is unknown, set to syscall mode, wait */
3408 /* else, if stack[0] is unknown, set to user mode, running */
3410 g_hash_table_foreach(ts
->processes
, fix_process
, &tfc
->timestamp
);
3415 static gboolean
enum_process_state(void *hook_data
, void *call_data
)
3417 LttvTracefileState
*s
= (LttvTracefileState
*)call_data
;
3418 LttEvent
*e
= ltt_tracefile_get_event(s
->parent
.tf
);
3419 //It's slow : optimise later by doing this before reading trace.
3420 LttvTraceHook
*th
= (LttvTraceHook
*)hook_data
;
3426 LttvTraceState
*ts
= (LttvTraceState
*)s
->parent
.t_context
;
3427 LttvProcessState
*process
= ts
->running_process
[cpu
];
3428 LttvProcessState
*parent_process
;
3429 struct marker_field
*f
;
3431 LttvExecutionState
*es
;
3435 pid
= ltt_event_get_unsigned(e
, lttv_trace_get_hook_field(th
, 0));
3436 s
->parent
.target_pid
= pid
;
3439 parent_pid
= ltt_event_get_unsigned(e
, lttv_trace_get_hook_field(th
, 1));
3442 command
= ltt_event_get_string(e
, lttv_trace_get_hook_field(th
, 2));
3445 f
= lttv_trace_get_hook_field(th
, 3);
3446 type
= ltt_enum_string_get(f
, ltt_event_get_unsigned(e
, f
));
3448 //FIXME: type is rarely used, enum must match possible types.
3450 /* Skip mode 4th param */
3452 /* Skip submode 5th param */
3454 /* Skip status 6th param */
3457 f
= lttv_trace_get_hook_field(th
, 7);
3459 tgid
= ltt_event_get_unsigned(e
, f
);
3464 nb_cpus
= ltt_trace_get_num_cpu(ts
->parent
.t
);
3465 for(i
=0; i
<nb_cpus
; i
++) {
3466 process
= lttv_state_find_process(ts
, i
, pid
);
3467 g_assert(process
!= NULL
);
3469 process
->ppid
= parent_pid
;
3470 process
->tgid
= tgid
;
3471 process
->name
= g_quark_from_string(command
);
3472 es
= &g_array_index(process
->execution_stack
, LttvExecutionState
, 0);
3473 process
->type
= LTTV_STATE_KERNEL_THREAD
;
3477 /* The process might exist if a process was forked while performing the
3479 process
= lttv_state_find_process(ts
, ANY_CPU
, pid
);
3480 if(process
== NULL
) {
3481 parent_process
= lttv_state_find_process(ts
, ANY_CPU
, parent_pid
);
3482 process
= lttv_state_create_process(ts
, parent_process
, cpu
,
3483 pid
, tgid
, g_quark_from_string(command
),
3484 &s
->parent
.timestamp
);
3486 /* Keep the stack bottom : a running user mode */
3487 /* Disabled because of inconsistencies in the current statedump states. */
3488 if(type
== LTTV_STATE_KERNEL_THREAD
) {
3489 /* Only keep the bottom
3490 * FIXME Kernel thread : can be in syscall or interrupt or trap. */
3491 /* Will cause expected trap when in fact being syscall (even after end of
3493 * Will cause expected interrupt when being syscall. (only before end of
3494 * statedump event) */
3495 // This will cause a "popping last state on stack, ignoring it."
3496 process
->execution_stack
= g_array_set_size(process
->execution_stack
, 1);
3497 es
= process
->state
= &g_array_index(process
->execution_stack
,
3498 LttvExecutionState
, 0);
3499 process
->type
= LTTV_STATE_KERNEL_THREAD
;
3500 es
->t
= LTTV_STATE_MAYBE_SYSCALL
;
3501 es
->s
= LTTV_STATE_UNNAMED
;
3502 es
->n
= LTTV_STATE_SUBMODE_UNKNOWN
;
3506 /* User space process :
3507 * bottom : user mode
3508 * either currently running or scheduled out.
3509 * can be scheduled out because interrupted in (user mode or in syscall)
3510 * or because of an explicit call to the scheduler in syscall. Note that
3511 * the scheduler call comes after the irq_exit, so never in interrupt
3513 // temp workaround : set size to 1 : only have user mode bottom of stack.
3514 // will cause g_info message of expected syscall mode when in fact being
3515 // in user mode. Can also cause expected trap when in fact being user
3516 // mode in the event of a page fault reenabling interrupts in the handler.
3517 // Expected syscall and trap can also happen after the end of statedump
3518 // This will cause a "popping last state on stack, ignoring it."
3519 process
->execution_stack
= g_array_set_size(process
->execution_stack
, 1);
3520 es
= process
->state
= &g_array_index(process
->execution_stack
,
3521 LttvExecutionState
, 0);
3522 es
->t
= LTTV_STATE_MAYBE_USER_MODE
;
3523 es
->s
= LTTV_STATE_UNNAMED
;
3524 es
->n
= LTTV_STATE_SUBMODE_UNKNOWN
;
3531 es
= process
->state
= &g_array_index(process
->execution_stack
,
3532 LttvExecutionState
, 1);
3533 es
->t
= LTTV_STATE_MODE_UNKNOWN
;
3534 es
->s
= LTTV_STATE_UNNAMED
;
3535 es
->n
= LTTV_STATE_SUBMODE_UNKNOWN
;
3539 /* The process has already been created :
3540 * Probably was forked while dumping the process state or
3541 * was simply scheduled in prior to get the state dump event.
3543 process
->ppid
= parent_pid
;
3544 process
->tgid
= tgid
;
3545 process
->name
= g_quark_from_string(command
);
3546 process
->type
= type
;
3547 es
= &g_array_index(process
->execution_stack
, LttvExecutionState
, 0);
3549 if(es
->t
== LTTV_STATE_MODE_UNKNOWN
) {
3550 if(type
== LTTV_STATE_KERNEL_THREAD
)
3551 es
->t
= LTTV_STATE_SYSCALL
;
3553 es
->t
= LTTV_STATE_USER_MODE
;
3556 /* Don't mess around with the stack, it will eventually become
3557 * ok after the end of state dump. */
3564 gint
lttv_state_hook_add_event_hooks(void *hook_data
, void *call_data
)
3566 LttvTracesetState
*tss
= (LttvTracesetState
*)(call_data
);
3568 lttv_state_add_event_hooks(tss
);
3573 void lttv_state_add_event_hooks(LttvTracesetState
*self
)
3575 LttvTraceset
*traceset
= self
->parent
.ts
;
3577 guint i
, j
, k
, nb_trace
, nb_tracefile
;
3581 LttvTracefileState
*tfs
;
3587 LttvAttributeValue val
;
3589 nb_trace
= lttv_traceset_number(traceset
);
3590 for(i
= 0 ; i
< nb_trace
; i
++) {
3591 ts
= (LttvTraceState
*)self
->parent
.traces
[i
];
3593 /* Find the eventtype id for the following events and register the
3594 associated by id hooks. */
3596 hooks
= g_array_sized_new(FALSE
, FALSE
, sizeof(LttvTraceHook
), 20);
3597 //hooks = g_array_set_size(hooks, 19); // Max possible number of hooks.
3600 lttv_trace_find_hook(ts
->parent
.t
,
3602 LTT_EVENT_SYSCALL_ENTRY
,
3603 FIELD_ARRAY(LTT_FIELD_SYSCALL_ID
),
3604 syscall_entry
, NULL
, &hooks
);
3606 lttv_trace_find_hook(ts
->parent
.t
,
3608 LTT_EVENT_SYSCALL_EXIT
,
3610 syscall_exit
, NULL
, &hooks
);
3612 lttv_trace_find_hook(ts
->parent
.t
,
3614 LTT_EVENT_TRAP_ENTRY
,
3615 FIELD_ARRAY(LTT_FIELD_TRAP_ID
),
3616 trap_entry
, NULL
, &hooks
);
3618 lttv_trace_find_hook(ts
->parent
.t
,
3620 LTT_EVENT_TRAP_EXIT
,
3622 trap_exit
, NULL
, &hooks
);
3624 lttv_trace_find_hook(ts
->parent
.t
,
3626 LTT_EVENT_PAGE_FAULT_ENTRY
,
3627 FIELD_ARRAY(LTT_FIELD_TRAP_ID
),
3628 trap_entry
, NULL
, &hooks
);
3630 lttv_trace_find_hook(ts
->parent
.t
,
3632 LTT_EVENT_PAGE_FAULT_EXIT
,
3634 trap_exit
, NULL
, &hooks
);
3636 lttv_trace_find_hook(ts
->parent
.t
,
3638 LTT_EVENT_PAGE_FAULT_NOSEM_ENTRY
,
3639 FIELD_ARRAY(LTT_FIELD_TRAP_ID
),
3640 trap_entry
, NULL
, &hooks
);
3642 lttv_trace_find_hook(ts
->parent
.t
,
3644 LTT_EVENT_PAGE_FAULT_NOSEM_EXIT
,
3646 trap_exit
, NULL
, &hooks
);
3648 lttv_trace_find_hook(ts
->parent
.t
,
3650 LTT_EVENT_IRQ_ENTRY
,
3651 FIELD_ARRAY(LTT_FIELD_IRQ_ID
),
3652 irq_entry
, NULL
, &hooks
);
3654 lttv_trace_find_hook(ts
->parent
.t
,
3658 irq_exit
, NULL
, &hooks
);
3660 lttv_trace_find_hook(ts
->parent
.t
,
3662 LTT_EVENT_SOFT_IRQ_RAISE
,
3663 FIELD_ARRAY(LTT_FIELD_SOFT_IRQ_ID
),
3664 soft_irq_raise
, NULL
, &hooks
);
3666 lttv_trace_find_hook(ts
->parent
.t
,
3668 LTT_EVENT_SOFT_IRQ_ENTRY
,
3669 FIELD_ARRAY(LTT_FIELD_SOFT_IRQ_ID
),
3670 soft_irq_entry
, NULL
, &hooks
);
3672 lttv_trace_find_hook(ts
->parent
.t
,
3674 LTT_EVENT_SOFT_IRQ_EXIT
,
3676 soft_irq_exit
, NULL
, &hooks
);
3678 lttv_trace_find_hook(ts
->parent
.t
,
3680 LTT_EVENT_SCHED_SCHEDULE
,
3681 FIELD_ARRAY(LTT_FIELD_PREV_PID
, LTT_FIELD_NEXT_PID
,
3682 LTT_FIELD_PREV_STATE
),
3683 schedchange
, NULL
, &hooks
);
3685 lttv_trace_find_hook(ts
->parent
.t
,
3687 LTT_EVENT_SCHED_TRY_WAKEUP
,
3688 FIELD_ARRAY(LTT_FIELD_PID
, LTT_FIELD_CPU_ID
, LTT_FIELD_STATE
),
3689 sched_try_wakeup
, NULL
, &hooks
);
3691 lttv_trace_find_hook(ts
->parent
.t
,
3693 LTT_EVENT_PROCESS_FORK
,
3694 FIELD_ARRAY(LTT_FIELD_PARENT_PID
, LTT_FIELD_CHILD_PID
,
3695 LTT_FIELD_CHILD_TGID
),
3696 process_fork
, NULL
, &hooks
);
3698 lttv_trace_find_hook(ts
->parent
.t
,
3700 LTT_EVENT_KTHREAD_CREATE
,
3701 FIELD_ARRAY(LTT_FIELD_PID
),
3702 process_kernel_thread
, NULL
, &hooks
);
3704 lttv_trace_find_hook(ts
->parent
.t
,
3706 LTT_EVENT_PROCESS_EXIT
,
3707 FIELD_ARRAY(LTT_FIELD_PID
),
3708 process_exit
, NULL
, &hooks
);
3710 lttv_trace_find_hook(ts
->parent
.t
,
3712 LTT_EVENT_PROCESS_FREE
,
3713 FIELD_ARRAY(LTT_FIELD_PID
),
3714 process_free
, NULL
, &hooks
);
3716 lttv_trace_find_hook(ts
->parent
.t
,
3719 FIELD_ARRAY(LTT_FIELD_FILENAME
),
3720 process_exec
, NULL
, &hooks
);
3722 lttv_trace_find_hook(ts
->parent
.t
,
3723 LTT_CHANNEL_USERSPACE
,
3724 LTT_EVENT_THREAD_BRAND
,
3725 FIELD_ARRAY(LTT_FIELD_NAME
),
3726 thread_brand
, NULL
, &hooks
);
3728 /* statedump-related hooks */
3729 lttv_trace_find_hook(ts
->parent
.t
,
3730 LTT_CHANNEL_TASK_STATE
,
3731 LTT_EVENT_PROCESS_STATE
,
3732 FIELD_ARRAY(LTT_FIELD_PID
, LTT_FIELD_PARENT_PID
, LTT_FIELD_NAME
,
3733 LTT_FIELD_TYPE
, LTT_FIELD_MODE
, LTT_FIELD_SUBMODE
,
3734 LTT_FIELD_STATUS
, LTT_FIELD_TGID
),
3735 enum_process_state
, NULL
, &hooks
);
3737 lttv_trace_find_hook(ts
->parent
.t
,
3738 LTT_CHANNEL_GLOBAL_STATE
,
3739 LTT_EVENT_STATEDUMP_END
,
3741 statedump_end
, NULL
, &hooks
);
3743 lttv_trace_find_hook(ts
->parent
.t
,
3744 LTT_CHANNEL_IRQ_STATE
,
3745 LTT_EVENT_LIST_INTERRUPT
,
3746 FIELD_ARRAY(LTT_FIELD_ACTION
, LTT_FIELD_IRQ_ID
),
3747 enum_interrupt
, NULL
, &hooks
);
3749 lttv_trace_find_hook(ts
->parent
.t
,
3751 LTT_EVENT_REQUEST_ISSUE
,
3752 FIELD_ARRAY(LTT_FIELD_MAJOR
, LTT_FIELD_MINOR
, LTT_FIELD_OPERATION
),
3753 bdev_request_issue
, NULL
, &hooks
);
3755 lttv_trace_find_hook(ts
->parent
.t
,
3757 LTT_EVENT_REQUEST_COMPLETE
,
3758 FIELD_ARRAY(LTT_FIELD_MAJOR
, LTT_FIELD_MINOR
, LTT_FIELD_OPERATION
),
3759 bdev_request_complete
, NULL
, &hooks
);
3761 lttv_trace_find_hook(ts
->parent
.t
,
3762 LTT_CHANNEL_USERSPACE
,
3763 LTT_EVENT_FUNCTION_ENTRY
,
3764 FIELD_ARRAY(LTT_FIELD_THIS_FN
, LTT_FIELD_CALL_SITE
),
3765 function_entry
, NULL
, &hooks
);
3767 lttv_trace_find_hook(ts
->parent
.t
,
3768 LTT_CHANNEL_USERSPACE
,
3769 LTT_EVENT_FUNCTION_EXIT
,
3770 FIELD_ARRAY(LTT_FIELD_THIS_FN
, LTT_FIELD_CALL_SITE
),
3771 function_exit
, NULL
, &hooks
);
3773 lttv_trace_find_hook(ts
->parent
.t
,
3774 LTT_CHANNEL_SYSCALL_STATE
,
3775 LTT_EVENT_SYS_CALL_TABLE
,
3776 FIELD_ARRAY(LTT_FIELD_ID
, LTT_FIELD_ADDRESS
, LTT_FIELD_SYMBOL
),
3777 dump_syscall
, NULL
, &hooks
);
3779 lttv_trace_find_hook(ts
->parent
.t
,
3780 LTT_CHANNEL_KPROBE_STATE
,
3781 LTT_EVENT_KPROBE_TABLE
,
3782 FIELD_ARRAY(LTT_FIELD_IP
, LTT_FIELD_SYMBOL
),
3783 dump_kprobe
, NULL
, &hooks
);
3785 lttv_trace_find_hook(ts
->parent
.t
,
3786 LTT_CHANNEL_SOFTIRQ_STATE
,
3787 LTT_EVENT_SOFTIRQ_VEC
,
3788 FIELD_ARRAY(LTT_FIELD_ID
, LTT_FIELD_ADDRESS
, LTT_FIELD_SYMBOL
),
3789 dump_softirq
, NULL
, &hooks
);
3791 lttv_trace_find_hook(ts
->parent
.t
,
3794 FIELD_ARRAY(LTT_FIELD_FD
, LTT_FIELD_FILENAME
),
3795 fs_open
, NULL
, &hooks
);
3797 /* Add these hooks to each event_by_id hooks list */
3799 nb_tracefile
= ts
->parent
.tracefiles
->len
;
3801 for(j
= 0 ; j
< nb_tracefile
; j
++) {
3803 LTTV_TRACEFILE_STATE(g_array_index(ts
->parent
.tracefiles
,
3804 LttvTracefileContext
*, j
));
3806 for(k
= 0 ; k
< hooks
->len
; k
++) {
3807 th
= &g_array_index(hooks
, LttvTraceHook
, k
);
3808 if (th
->mdata
== tfs
->parent
.tf
->mdata
)
3810 lttv_hooks_by_id_find(tfs
->parent
.event_by_id
, th
->id
),
3816 lttv_attribute_find(ts
->parent
.a
, LTTV_STATE_HOOKS
, LTTV_POINTER
, &val
);
3817 *(val
.v_pointer
) = hooks
;
3821 gint
lttv_state_hook_remove_event_hooks(void *hook_data
, void *call_data
)
3823 LttvTracesetState
*tss
= (LttvTracesetState
*)(call_data
);
3825 lttv_state_remove_event_hooks(tss
);
3830 void lttv_state_remove_event_hooks(LttvTracesetState
*self
)
3832 LttvTraceset
*traceset
= self
->parent
.ts
;
3834 guint i
, j
, k
, nb_trace
, nb_tracefile
;
3838 LttvTracefileState
*tfs
;
3844 LttvAttributeValue val
;
3846 nb_trace
= lttv_traceset_number(traceset
);
3847 for(i
= 0 ; i
< nb_trace
; i
++) {
3848 ts
= LTTV_TRACE_STATE(self
->parent
.traces
[i
]);
3850 lttv_attribute_find(ts
->parent
.a
, LTTV_STATE_HOOKS
, LTTV_POINTER
, &val
);
3851 hooks
= *(val
.v_pointer
);
3853 /* Remove these hooks from each event_by_id hooks list */
3855 nb_tracefile
= ts
->parent
.tracefiles
->len
;
3857 for(j
= 0 ; j
< nb_tracefile
; j
++) {
3859 LTTV_TRACEFILE_STATE(g_array_index(ts
->parent
.tracefiles
,
3860 LttvTracefileContext
*, j
));
3862 for(k
= 0 ; k
< hooks
->len
; k
++) {
3863 th
= &g_array_index(hooks
, LttvTraceHook
, k
);
3864 if (th
->mdata
== tfs
->parent
.tf
->mdata
)
3865 lttv_hooks_remove_data(
3866 lttv_hooks_by_id_find(tfs
->parent
.event_by_id
, th
->id
),
3871 lttv_trace_hook_remove_all(&hooks
);
3872 g_array_free(hooks
, TRUE
);
3876 static gboolean
state_save_event_hook(void *hook_data
, void *call_data
)
3878 guint
*event_count
= (guint
*)hook_data
;
3880 /* Only save at LTTV_STATE_SAVE_INTERVAL */
3881 if(likely((*event_count
)++ < LTTV_STATE_SAVE_INTERVAL
))
3886 LttvTracefileState
*self
= (LttvTracefileState
*)call_data
;
3888 LttvTraceState
*tcs
= (LttvTraceState
*)(self
->parent
.t_context
);
3890 LttvAttribute
*saved_states_tree
, *saved_state_tree
;
3892 LttvAttributeValue value
;
3894 saved_states_tree
= lttv_attribute_find_subdir(tcs
->parent
.t_a
,
3895 LTTV_STATE_SAVED_STATES
);
3896 saved_state_tree
= g_object_new(LTTV_ATTRIBUTE_TYPE
, NULL
);
3897 value
= lttv_attribute_add(saved_states_tree
,
3898 lttv_attribute_get_number(saved_states_tree
), LTTV_GOBJECT
);
3899 *(value
.v_gobject
) = (GObject
*)saved_state_tree
;
3900 value
= lttv_attribute_add(saved_state_tree
, LTTV_STATE_TIME
, LTTV_TIME
);
3901 *(value
.v_time
) = self
->parent
.timestamp
;
3902 lttv_state_save(tcs
, saved_state_tree
);
3903 g_debug("Saving state at time %lu.%lu", self
->parent
.timestamp
.tv_sec
,
3904 self
->parent
.timestamp
.tv_nsec
);
3906 *(tcs
->max_time_state_recomputed_in_seek
) = self
->parent
.timestamp
;
3911 static gboolean
state_save_after_trace_hook(void *hook_data
, void *call_data
)
3913 LttvTraceState
*tcs
= (LttvTraceState
*)(call_data
);
3915 *(tcs
->max_time_state_recomputed_in_seek
) = tcs
->parent
.time_span
.end_time
;
3920 guint
lttv_state_current_cpu(LttvTracefileState
*tfs
)
3928 static gboolean
block_start(void *hook_data
, void *call_data
)
3930 LttvTracefileState
*self
= (LttvTracefileState
*)call_data
;
3932 LttvTracefileState
*tfcs
;
3934 LttvTraceState
*tcs
= (LttvTraceState
*)(self
->parent
.t_context
);
3936 LttEventPosition
*ep
;
3938 guint i
, nb_block
, nb_event
, nb_tracefile
;
3942 LttvAttribute
*saved_states_tree
, *saved_state_tree
;
3944 LttvAttributeValue value
;
3946 ep
= ltt_event_position_new();
3948 nb_tracefile
= tcs
->parent
.tracefiles
->len
;
3950 /* Count the number of events added since the last block end in any
3953 for(i
= 0 ; i
< nb_tracefile
; i
++) {
3955 LTTV_TRACEFILE_STATE(&g_array_index(tcs
->parent
.tracefiles
,
3956 LttvTracefileContext
, i
));
3957 ltt_event_position(tfcs
->parent
.e
, ep
);
3958 ltt_event_position_get(ep
, &nb_block
, &nb_event
, &tf
);
3959 tcs
->nb_event
+= nb_event
- tfcs
->saved_position
;
3960 tfcs
->saved_position
= nb_event
;
3964 if(tcs
->nb_event
>= tcs
->save_interval
) {
3965 saved_states_tree
= lttv_attribute_find_subdir(tcs
->parent
.t_a
,
3966 LTTV_STATE_SAVED_STATES
);
3967 saved_state_tree
= g_object_new(LTTV_ATTRIBUTE_TYPE
, NULL
);
3968 value
= lttv_attribute_add(saved_states_tree
,
3969 lttv_attribute_get_number(saved_states_tree
), LTTV_GOBJECT
);
3970 *(value
.v_gobject
) = (GObject
*)saved_state_tree
;
3971 value
= lttv_attribute_add(saved_state_tree
, LTTV_STATE_TIME
, LTTV_TIME
);
3972 *(value
.v_time
) = self
->parent
.timestamp
;
3973 lttv_state_save(tcs
, saved_state_tree
);
3975 g_debug("Saving state at time %lu.%lu", self
->parent
.timestamp
.tv_sec
,
3976 self
->parent
.timestamp
.tv_nsec
);
3978 *(tcs
->max_time_state_recomputed_in_seek
) = self
->parent
.timestamp
;
3984 static gboolean
block_end(void *hook_data
, void *call_data
)
3986 LttvTracefileState
*self
= (LttvTracefileState
*)call_data
;
3988 LttvTraceState
*tcs
= (LttvTraceState
*)(self
->parent
.t_context
);
3992 LttEventPosition
*ep
;
3994 guint nb_block
, nb_event
;
3996 ep
= ltt_event_position_new();
3997 ltt_event_position(self
->parent
.e
, ep
);
3998 ltt_event_position_get(ep
, &nb_block
, &nb_event
, &tf
);
3999 tcs
->nb_event
+= nb_event
- self
->saved_position
+ 1;
4000 self
->saved_position
= 0;
4001 *(tcs
->max_time_state_recomputed_in_seek
) = self
->parent
.timestamp
;
4008 void lttv_state_save_add_event_hooks(LttvTracesetState
*self
)
4010 LttvTraceset
*traceset
= self
->parent
.ts
;
4012 guint i
, j
, nb_trace
, nb_tracefile
;
4016 LttvTracefileState
*tfs
;
4018 LttvTraceHook hook_start
, hook_end
;
4020 nb_trace
= lttv_traceset_number(traceset
);
4021 for(i
= 0 ; i
< nb_trace
; i
++) {
4022 ts
= (LttvTraceState
*)self
->parent
.traces
[i
];
4024 lttv_trace_find_hook(ts
->parent
.t
, "core","block_start",NULL
,
4025 NULL
, NULL
, block_start
, &hook_start
);
4026 lttv_trace_find_hook(ts
->parent
.t
, "core","block_end",NULL
,
4027 NULL
, NULL
, block_end
, &hook_end
);
4029 nb_tracefile
= ts
->parent
.tracefiles
->len
;
4031 for(j
= 0 ; j
< nb_tracefile
; j
++) {
4033 LTTV_TRACEFILE_STATE(&g_array_index(ts
->parent
.tracefiles
,
4034 LttvTracefileContext
, j
));
4035 lttv_hooks_add(lttv_hooks_by_id_find(tfs
->parent
.event_by_id
,
4036 hook_start
.id
), hook_start
.h
, NULL
, LTTV_PRIO_STATE
);
4037 lttv_hooks_add(lttv_hooks_by_id_find(tfs
->parent
.event_by_id
,
4038 hook_end
.id
), hook_end
.h
, NULL
, LTTV_PRIO_STATE
);
4044 void lttv_state_save_add_event_hooks(LttvTracesetState
*self
)
4046 LttvTraceset
*traceset
= self
->parent
.ts
;
4048 guint i
, j
, nb_trace
, nb_tracefile
;
4052 LttvTracefileState
*tfs
;
4055 nb_trace
= lttv_traceset_number(traceset
);
4056 for(i
= 0 ; i
< nb_trace
; i
++) {
4058 ts
= (LttvTraceState
*)self
->parent
.traces
[i
];
4059 nb_tracefile
= ts
->parent
.tracefiles
->len
;
4061 if(ts
->has_precomputed_states
) continue;
4063 guint
*event_count
= g_new(guint
, 1);
4066 for(j
= 0 ; j
< nb_tracefile
; j
++) {
4068 LTTV_TRACEFILE_STATE(g_array_index(ts
->parent
.tracefiles
,
4069 LttvTracefileContext
*, j
));
4070 lttv_hooks_add(tfs
->parent
.event
,
4071 state_save_event_hook
,
4078 lttv_process_traceset_begin(&self
->parent
,
4079 NULL
, NULL
, NULL
, NULL
, NULL
);
4083 gint
lttv_state_save_hook_add_event_hooks(void *hook_data
, void *call_data
)
4085 LttvTracesetState
*tss
= (LttvTracesetState
*)(call_data
);
4087 lttv_state_save_add_event_hooks(tss
);
4094 void lttv_state_save_remove_event_hooks(LttvTracesetState
*self
)
4096 LttvTraceset
*traceset
= self
->parent
.ts
;
4098 guint i
, j
, nb_trace
, nb_tracefile
;
4102 LttvTracefileState
*tfs
;
4104 LttvTraceHook hook_start
, hook_end
;
4106 nb_trace
= lttv_traceset_number(traceset
);
4107 for(i
= 0 ; i
< nb_trace
; i
++) {
4108 ts
= LTTV_TRACE_STATE(self
->parent
.traces
[i
]);
4110 lttv_trace_find_hook(ts
->parent
.t
, "core","block_start",NULL
,
4111 NULL
, NULL
, block_start
, &hook_start
);
4113 lttv_trace_find_hook(ts
->parent
.t
, "core","block_end",NULL
,
4114 NULL
, NULL
, block_end
, &hook_end
);
4116 nb_tracefile
= ts
->parent
.tracefiles
->len
;
4118 for(j
= 0 ; j
< nb_tracefile
; j
++) {
4120 LTTV_TRACEFILE_STATE(&g_array_index(ts
->parent
.tracefiles
,
4121 LttvTracefileContext
, j
));
4122 lttv_hooks_remove_data(lttv_hooks_by_id_find(
4123 tfs
->parent
.event_by_id
, hook_start
.id
), hook_start
.h
, NULL
);
4124 lttv_hooks_remove_data(lttv_hooks_by_id_find(
4125 tfs
->parent
.event_by_id
, hook_end
.id
), hook_end
.h
, NULL
);
4131 void lttv_state_save_remove_event_hooks(LttvTracesetState
*self
)
4133 LttvTraceset
*traceset
= self
->parent
.ts
;
4135 guint i
, j
, nb_trace
, nb_tracefile
;
4139 LttvTracefileState
*tfs
;
4141 LttvHooks
*after_trace
= lttv_hooks_new();
4143 lttv_hooks_add(after_trace
,
4144 state_save_after_trace_hook
,
4149 lttv_process_traceset_end(&self
->parent
,
4150 NULL
, after_trace
, NULL
, NULL
, NULL
);
4152 lttv_hooks_destroy(after_trace
);
4154 nb_trace
= lttv_traceset_number(traceset
);
4155 for(i
= 0 ; i
< nb_trace
; i
++) {
4157 ts
= (LttvTraceState
*)self
->parent
.traces
[i
];
4158 nb_tracefile
= ts
->parent
.tracefiles
->len
;
4160 if(ts
->has_precomputed_states
) continue;
4162 guint
*event_count
= NULL
;
4164 for(j
= 0 ; j
< nb_tracefile
; j
++) {
4166 LTTV_TRACEFILE_STATE(g_array_index(ts
->parent
.tracefiles
,
4167 LttvTracefileContext
*, j
));
4168 event_count
= lttv_hooks_remove(tfs
->parent
.event
,
4169 state_save_event_hook
);
4171 if(event_count
) g_free(event_count
);
4175 gint
lttv_state_save_hook_remove_event_hooks(void *hook_data
, void *call_data
)
4177 LttvTracesetState
*tss
= (LttvTracesetState
*)(call_data
);
4179 lttv_state_save_remove_event_hooks(tss
);
4184 void lttv_state_traceset_seek_time_closest(LttvTracesetState
*self
, LttTime t
)
4186 LttvTraceset
*traceset
= self
->parent
.ts
;
4190 int min_pos
, mid_pos
, max_pos
;
4192 guint call_rest
= 0;
4194 LttvTraceState
*tcs
;
4196 LttvAttributeValue value
;
4198 LttvAttributeType type
;
4200 LttvAttributeName name
;
4204 LttvAttribute
*saved_states_tree
, *saved_state_tree
, *closest_tree
= NULL
;
4206 //g_tree_destroy(self->parent.pqueue);
4207 //self->parent.pqueue = g_tree_new(compare_tracefile);
4209 g_info("Entering seek_time_closest for time %lu.%lu", t
.tv_sec
, t
.tv_nsec
);
4211 nb_trace
= lttv_traceset_number(traceset
);
4212 for(i
= 0 ; i
< nb_trace
; i
++) {
4213 tcs
= (LttvTraceState
*)self
->parent
.traces
[i
];
4215 if(ltt_time_compare(t
, *(tcs
->max_time_state_recomputed_in_seek
)) < 0) {
4216 saved_states_tree
= lttv_attribute_find_subdir(tcs
->parent
.t_a
,
4217 LTTV_STATE_SAVED_STATES
);
4220 if(saved_states_tree
) {
4221 max_pos
= lttv_attribute_get_number(saved_states_tree
) - 1;
4222 mid_pos
= max_pos
/ 2;
4223 while(min_pos
< max_pos
) {
4224 type
= lttv_attribute_get(saved_states_tree
, mid_pos
,
4225 &name
, &value
, &is_named
);
4226 g_assert(type
== LTTV_GOBJECT
);
4227 saved_state_tree
= *((LttvAttribute
**)(value
.v_gobject
));
4228 type
= lttv_attribute_get_by_name(saved_state_tree
,
4229 LTTV_STATE_TIME
, &value
);
4230 g_assert(type
== LTTV_TIME
);
4231 if(ltt_time_compare(*(value
.v_time
), t
) < 0) {
4233 closest_tree
= saved_state_tree
;
4235 else max_pos
= mid_pos
- 1;
4237 mid_pos
= (min_pos
+ max_pos
+ 1) / 2;
4241 /* restore the closest earlier saved state */
4243 lttv_state_restore(tcs
, closest_tree
);
4247 /* There is no saved state, yet we want to have it. Restart at T0 */
4249 restore_init_state(tcs
);
4250 lttv_process_trace_seek_time(&(tcs
->parent
), ltt_time_zero
);
4253 /* We want to seek quickly without restoring/updating the state */
4255 restore_init_state(tcs
);
4256 lttv_process_trace_seek_time(&(tcs
->parent
), t
);
4259 if(!call_rest
) g_info("NOT Calling restore");
4263 static void traceset_state_instance_init (GTypeInstance
*instance
, gpointer g_class
)
4268 static void traceset_state_finalize (LttvTracesetState
*self
)
4270 G_OBJECT_CLASS(g_type_class_peek(LTTV_TRACESET_CONTEXT_TYPE
))->
4271 finalize(G_OBJECT(self
));
4275 static void traceset_state_class_init (LttvTracesetContextClass
*klass
)
4277 GObjectClass
*gobject_class
= G_OBJECT_CLASS(klass
);
4279 gobject_class
->finalize
= (void (*)(GObject
*self
)) traceset_state_finalize
;
4280 klass
->init
= (void (*)(LttvTracesetContext
*self
, LttvTraceset
*ts
))init
;
4281 klass
->fini
= (void (*)(LttvTracesetContext
*self
))fini
;
4282 klass
->new_traceset_context
= new_traceset_context
;
4283 klass
->new_trace_context
= new_trace_context
;
4284 klass
->new_tracefile_context
= new_tracefile_context
;
4288 GType
lttv_traceset_state_get_type(void)
4290 static GType type
= 0;
4292 static const GTypeInfo info
= {
4293 sizeof (LttvTracesetStateClass
),
4294 NULL
, /* base_init */
4295 NULL
, /* base_finalize */
4296 (GClassInitFunc
) traceset_state_class_init
, /* class_init */
4297 NULL
, /* class_finalize */
4298 NULL
, /* class_data */
4299 sizeof (LttvTracesetState
),
4300 0, /* n_preallocs */
4301 (GInstanceInitFunc
) traceset_state_instance_init
, /* instance_init */
4302 NULL
/* value handling */
4305 type
= g_type_register_static (LTTV_TRACESET_CONTEXT_TYPE
, "LttvTracesetStateType",
4312 static void trace_state_instance_init (GTypeInstance
*instance
, gpointer g_class
)
4317 static void trace_state_finalize (LttvTraceState
*self
)
4319 G_OBJECT_CLASS(g_type_class_peek(LTTV_TRACE_CONTEXT_TYPE
))->
4320 finalize(G_OBJECT(self
));
4324 static void trace_state_class_init (LttvTraceStateClass
*klass
)
4326 GObjectClass
*gobject_class
= G_OBJECT_CLASS(klass
);
4328 gobject_class
->finalize
= (void (*)(GObject
*self
)) trace_state_finalize
;
4329 klass
->state_save
= state_save
;
4330 klass
->state_restore
= state_restore
;
4331 klass
->state_saved_free
= state_saved_free
;
4335 GType
lttv_trace_state_get_type(void)
4337 static GType type
= 0;
4339 static const GTypeInfo info
= {
4340 sizeof (LttvTraceStateClass
),
4341 NULL
, /* base_init */
4342 NULL
, /* base_finalize */
4343 (GClassInitFunc
) trace_state_class_init
, /* class_init */
4344 NULL
, /* class_finalize */
4345 NULL
, /* class_data */
4346 sizeof (LttvTraceState
),
4347 0, /* n_preallocs */
4348 (GInstanceInitFunc
) trace_state_instance_init
, /* instance_init */
4349 NULL
/* value handling */
4352 type
= g_type_register_static (LTTV_TRACE_CONTEXT_TYPE
,
4353 "LttvTraceStateType", &info
, 0);
4359 static void tracefile_state_instance_init (GTypeInstance
*instance
,
4365 static void tracefile_state_finalize (LttvTracefileState
*self
)
4367 G_OBJECT_CLASS(g_type_class_peek(LTTV_TRACEFILE_CONTEXT_TYPE
))->
4368 finalize(G_OBJECT(self
));
4372 static void tracefile_state_class_init (LttvTracefileStateClass
*klass
)
4374 GObjectClass
*gobject_class
= G_OBJECT_CLASS(klass
);
4376 gobject_class
->finalize
= (void (*)(GObject
*self
)) tracefile_state_finalize
;
4380 GType
lttv_tracefile_state_get_type(void)
4382 static GType type
= 0;
4384 static const GTypeInfo info
= {
4385 sizeof (LttvTracefileStateClass
),
4386 NULL
, /* base_init */
4387 NULL
, /* base_finalize */
4388 (GClassInitFunc
) tracefile_state_class_init
, /* class_init */
4389 NULL
, /* class_finalize */
4390 NULL
, /* class_data */
4391 sizeof (LttvTracefileState
),
4392 0, /* n_preallocs */
4393 (GInstanceInitFunc
) tracefile_state_instance_init
, /* instance_init */
4394 NULL
/* value handling */
4397 type
= g_type_register_static (LTTV_TRACEFILE_CONTEXT_TYPE
,
4398 "LttvTracefileStateType", &info
, 0);
4404 static void module_init()
4406 LTTV_STATE_UNNAMED
= g_quark_from_string("");
4407 LTTV_STATE_UNBRANDED
= g_quark_from_string("");
4408 LTTV_STATE_MODE_UNKNOWN
= g_quark_from_string("MODE_UNKNOWN");
4409 LTTV_STATE_USER_MODE
= g_quark_from_string("USER_MODE");
4410 LTTV_STATE_MAYBE_USER_MODE
= g_quark_from_string("MAYBE_USER_MODE");
4411 LTTV_STATE_SYSCALL
= g_quark_from_string("SYSCALL");
4412 LTTV_STATE_MAYBE_SYSCALL
= g_quark_from_string("MAYBE_SYSCALL");
4413 LTTV_STATE_TRAP
= g_quark_from_string("TRAP");
4414 LTTV_STATE_MAYBE_TRAP
= g_quark_from_string("MAYBE_TRAP");
4415 LTTV_STATE_IRQ
= g_quark_from_string("IRQ");
4416 LTTV_STATE_SOFT_IRQ
= g_quark_from_string("SOFTIRQ");
4417 LTTV_STATE_SUBMODE_UNKNOWN
= g_quark_from_string("UNKNOWN");
4418 LTTV_STATE_SUBMODE_NONE
= g_quark_from_string("NONE");
4419 LTTV_STATE_WAIT_FORK
= g_quark_from_string("WAIT_FORK");
4420 LTTV_STATE_WAIT_CPU
= g_quark_from_string("WAIT_CPU");
4421 LTTV_STATE_EXIT
= g_quark_from_string("EXIT");
4422 LTTV_STATE_ZOMBIE
= g_quark_from_string("ZOMBIE");
4423 LTTV_STATE_WAIT
= g_quark_from_string("WAIT");
4424 LTTV_STATE_RUN
= g_quark_from_string("RUN");
4425 LTTV_STATE_DEAD
= g_quark_from_string("DEAD");
4426 LTTV_STATE_USER_THREAD
= g_quark_from_string("USER_THREAD");
4427 LTTV_STATE_KERNEL_THREAD
= g_quark_from_string("KERNEL_THREAD");
4428 LTTV_STATE_TRACEFILES
= g_quark_from_string("tracefiles");
4429 LTTV_STATE_PROCESSES
= g_quark_from_string("processes");
4430 LTTV_STATE_PROCESS
= g_quark_from_string("process");
4431 LTTV_STATE_RUNNING_PROCESS
= g_quark_from_string("running_process");
4432 LTTV_STATE_EVENT
= g_quark_from_string("event");
4433 LTTV_STATE_SAVED_STATES
= g_quark_from_string("saved states");
4434 LTTV_STATE_SAVED_STATES_TIME
= g_quark_from_string("saved states time");
4435 LTTV_STATE_TIME
= g_quark_from_string("time");
4436 LTTV_STATE_HOOKS
= g_quark_from_string("saved state hooks");
4437 LTTV_STATE_NAME_TABLES
= g_quark_from_string("name tables");
4438 LTTV_STATE_TRACE_STATE_USE_COUNT
=
4439 g_quark_from_string("trace_state_use_count");
4440 LTTV_STATE_RESOURCE_CPUS
= g_quark_from_string("cpu resource states");
4441 LTTV_STATE_RESOURCE_CPUS
= g_quark_from_string("cpu count");
4442 LTTV_STATE_RESOURCE_IRQS
= g_quark_from_string("irq resource states");
4443 LTTV_STATE_RESOURCE_SOFT_IRQS
= g_quark_from_string("soft irq resource states");
4444 LTTV_STATE_RESOURCE_TRAPS
= g_quark_from_string("trap resource states");
4445 LTTV_STATE_RESOURCE_BLKDEVS
= g_quark_from_string("blkdevs resource states");
4447 LTT_CHANNEL_FD_STATE
= g_quark_from_string("fd_state");
4448 LTT_CHANNEL_GLOBAL_STATE
= g_quark_from_string("global_state");
4449 LTT_CHANNEL_IRQ_STATE
= g_quark_from_string("irq_state");
4450 LTT_CHANNEL_MODULE_STATE
= g_quark_from_string("module_state");
4451 LTT_CHANNEL_NETIF_STATE
= g_quark_from_string("netif_state");
4452 LTT_CHANNEL_SOFTIRQ_STATE
= g_quark_from_string("softirq_state");
4453 LTT_CHANNEL_SWAP_STATE
= g_quark_from_string("swap_state");
4454 LTT_CHANNEL_SYSCALL_STATE
= g_quark_from_string("syscall_state");
4455 LTT_CHANNEL_TASK_STATE
= g_quark_from_string("task_state");
4456 LTT_CHANNEL_VM_STATE
= g_quark_from_string("vm_state");
4457 LTT_CHANNEL_KPROBE_STATE
= g_quark_from_string("kprobe_state");
4458 LTT_CHANNEL_FS
= g_quark_from_string("fs");
4459 LTT_CHANNEL_KERNEL
= g_quark_from_string("kernel");
4460 LTT_CHANNEL_MM
= g_quark_from_string("mm");
4461 LTT_CHANNEL_USERSPACE
= g_quark_from_string("userspace");
4462 LTT_CHANNEL_BLOCK
= g_quark_from_string("block");
4464 LTT_EVENT_SYSCALL_ENTRY
= g_quark_from_string("syscall_entry");
4465 LTT_EVENT_SYSCALL_EXIT
= g_quark_from_string("syscall_exit");
4466 LTT_EVENT_TRAP_ENTRY
= g_quark_from_string("trap_entry");
4467 LTT_EVENT_TRAP_EXIT
= g_quark_from_string("trap_exit");
4468 LTT_EVENT_PAGE_FAULT_ENTRY
= g_quark_from_string("page_fault_entry");
4469 LTT_EVENT_PAGE_FAULT_EXIT
= g_quark_from_string("page_fault_exit");
4470 LTT_EVENT_PAGE_FAULT_NOSEM_ENTRY
= g_quark_from_string("page_fault_nosem_entry");
4471 LTT_EVENT_PAGE_FAULT_NOSEM_EXIT
= g_quark_from_string("page_fault_nosem_exit");
4472 LTT_EVENT_IRQ_ENTRY
= g_quark_from_string("irq_entry");
4473 LTT_EVENT_IRQ_EXIT
= g_quark_from_string("irq_exit");
4474 LTT_EVENT_SOFT_IRQ_RAISE
= g_quark_from_string("softirq_raise");
4475 LTT_EVENT_SOFT_IRQ_ENTRY
= g_quark_from_string("softirq_entry");
4476 LTT_EVENT_SOFT_IRQ_EXIT
= g_quark_from_string("softirq_exit");
4477 LTT_EVENT_SCHED_SCHEDULE
= g_quark_from_string("sched_schedule");
4478 LTT_EVENT_SCHED_TRY_WAKEUP
= g_quark_from_string("sched_try_wakeup");
4479 LTT_EVENT_PROCESS_FORK
= g_quark_from_string("process_fork");
4480 LTT_EVENT_KTHREAD_CREATE
= g_quark_from_string("kthread_create");
4481 LTT_EVENT_PROCESS_EXIT
= g_quark_from_string("process_exit");
4482 LTT_EVENT_PROCESS_FREE
= g_quark_from_string("process_free");
4483 LTT_EVENT_EXEC
= g_quark_from_string("exec");
4484 LTT_EVENT_PROCESS_STATE
= g_quark_from_string("process_state");
4485 LTT_EVENT_STATEDUMP_END
= g_quark_from_string("statedump_end");
4486 LTT_EVENT_FUNCTION_ENTRY
= g_quark_from_string("function_entry");
4487 LTT_EVENT_FUNCTION_EXIT
= g_quark_from_string("function_exit");
4488 LTT_EVENT_THREAD_BRAND
= g_quark_from_string("thread_brand");
4489 LTT_EVENT_REQUEST_ISSUE
= g_quark_from_string("_blk_request_issue");
4490 LTT_EVENT_REQUEST_COMPLETE
= g_quark_from_string("_blk_request_complete");
4491 LTT_EVENT_LIST_INTERRUPT
= g_quark_from_string("interrupt");
4492 LTT_EVENT_SYS_CALL_TABLE
= g_quark_from_string("sys_call_table");
4493 LTT_EVENT_SOFTIRQ_VEC
= g_quark_from_string("softirq_vec");
4494 LTT_EVENT_KPROBE_TABLE
= g_quark_from_string("kprobe_table");
4495 LTT_EVENT_KPROBE
= g_quark_from_string("kprobe");
4496 LTT_EVENT_OPEN
= g_quark_from_string("open");
4497 LTT_EVENT_READ
= g_quark_from_string("read");
4498 LTT_EVENT_POLL_EVENT
= g_quark_from_string("poll_event");
4500 LTT_FIELD_SYSCALL_ID
= g_quark_from_string("syscall_id");
4501 LTT_FIELD_TRAP_ID
= g_quark_from_string("trap_id");
4502 LTT_FIELD_IRQ_ID
= g_quark_from_string("irq_id");
4503 LTT_FIELD_SOFT_IRQ_ID
= g_quark_from_string("softirq_id");
4504 LTT_FIELD_PREV_PID
= g_quark_from_string("prev_pid");
4505 LTT_FIELD_NEXT_PID
= g_quark_from_string("next_pid");
4506 LTT_FIELD_PREV_STATE
= g_quark_from_string("prev_state");
4507 LTT_FIELD_PARENT_PID
= g_quark_from_string("parent_pid");
4508 LTT_FIELD_CHILD_PID
= g_quark_from_string("child_pid");
4509 LTT_FIELD_PID
= g_quark_from_string("pid");
4510 LTT_FIELD_TGID
= g_quark_from_string("tgid");
4511 LTT_FIELD_CHILD_TGID
= g_quark_from_string("child_tgid");
4512 LTT_FIELD_FILENAME
= g_quark_from_string("filename");
4513 LTT_FIELD_NAME
= g_quark_from_string("name");
4514 LTT_FIELD_TYPE
= g_quark_from_string("type");
4515 LTT_FIELD_MODE
= g_quark_from_string("mode");
4516 LTT_FIELD_SUBMODE
= g_quark_from_string("submode");
4517 LTT_FIELD_STATUS
= g_quark_from_string("status");
4518 LTT_FIELD_THIS_FN
= g_quark_from_string("this_fn");
4519 LTT_FIELD_CALL_SITE
= g_quark_from_string("call_site");
4520 LTT_FIELD_MAJOR
= g_quark_from_string("major");
4521 LTT_FIELD_MINOR
= g_quark_from_string("minor");
4522 LTT_FIELD_OPERATION
= g_quark_from_string("direction");
4523 LTT_FIELD_ACTION
= g_quark_from_string("action");
4524 LTT_FIELD_ID
= g_quark_from_string("id");
4525 LTT_FIELD_ADDRESS
= g_quark_from_string("address");
4526 LTT_FIELD_SYMBOL
= g_quark_from_string("symbol");
4527 LTT_FIELD_IP
= g_quark_from_string("ip");
4528 LTT_FIELD_FD
= g_quark_from_string("fd");
4529 LTT_FIELD_STATE
= g_quark_from_string("state");
4530 LTT_FIELD_CPU_ID
= g_quark_from_string("cpu_id");
4532 LTTV_CPU_UNKNOWN
= g_quark_from_string("unknown");
4533 LTTV_CPU_IDLE
= g_quark_from_string("idle");
4534 LTTV_CPU_BUSY
= g_quark_from_string("busy");
4535 LTTV_CPU_IRQ
= g_quark_from_string("irq");
4536 LTTV_CPU_SOFT_IRQ
= g_quark_from_string("softirq");
4537 LTTV_CPU_TRAP
= g_quark_from_string("trap");
4539 LTTV_IRQ_UNKNOWN
= g_quark_from_string("unknown");
4540 LTTV_IRQ_IDLE
= g_quark_from_string("idle");
4541 LTTV_IRQ_BUSY
= g_quark_from_string("busy");
4543 LTTV_BDEV_UNKNOWN
= g_quark_from_string("unknown");
4544 LTTV_BDEV_IDLE
= g_quark_from_string("idle");
4545 LTTV_BDEV_BUSY_READING
= g_quark_from_string("busy_reading");
4546 LTTV_BDEV_BUSY_WRITING
= g_quark_from_string("busy_writing");
4549 static void module_destroy()
4554 LTTV_MODULE("state", "State computation", \
4555 "Update the system state, possibly saving it at intervals", \
4556 module_init
, module_destroy
)