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
,
152 LTTV_STATE_SUBMODE_UNKNOWN
,
153 LTTV_STATE_SUBMODE_NONE
;
157 LTTV_STATE_WAIT_FORK
,
166 LTTV_STATE_UNBRANDED
;
169 LTTV_STATE_USER_THREAD
,
170 LTTV_STATE_KERNEL_THREAD
;
188 LTTV_BDEV_BUSY_READING
,
189 LTTV_BDEV_BUSY_WRITING
;
192 LTTV_STATE_TRACEFILES
,
193 LTTV_STATE_PROCESSES
,
195 LTTV_STATE_RUNNING_PROCESS
,
197 LTTV_STATE_SAVED_STATES
,
198 LTTV_STATE_SAVED_STATES_TIME
,
201 LTTV_STATE_NAME_TABLES
,
202 LTTV_STATE_TRACE_STATE_USE_COUNT
,
203 LTTV_STATE_RESOURCE_CPUS
,
204 LTTV_STATE_RESOURCE_CPUS_COUNT
,
205 LTTV_STATE_RESOURCE_IRQS
,
206 LTTV_STATE_RESOURCE_SOFT_IRQS
,
207 LTTV_STATE_RESOURCE_TRAPS
,
208 LTTV_STATE_RESOURCE_BLKDEVS
;
210 static void create_max_time(LttvTraceState
*tcs
);
212 static void get_max_time(LttvTraceState
*tcs
);
214 static void free_max_time(LttvTraceState
*tcs
);
216 static void create_name_tables(LttvTraceState
*tcs
);
218 static void get_name_tables(LttvTraceState
*tcs
);
220 static void free_name_tables(LttvTraceState
*tcs
);
222 static void free_saved_state(LttvTraceState
*tcs
);
224 static void lttv_state_free_process_table(GHashTable
*processes
);
226 static void lttv_trace_states_read_raw(LttvTraceState
*tcs
, FILE *fp
,
227 GPtrArray
*quarktable
);
229 /* Resource function prototypes */
230 static LttvBdevState
*get_hashed_bdevstate(LttvTraceState
*ts
, guint16 devcode
);
231 static LttvBdevState
*bdevstate_new(void);
232 static void bdevstate_free(LttvBdevState
*);
233 static void bdevstate_free_cb(gpointer key
, gpointer value
, gpointer user_data
);
234 static LttvBdevState
*bdevstate_copy(LttvBdevState
*bds
);
237 #if (__WORDSIZE == 32)
238 guint
guint64_hash(gconstpointer key
)
240 guint64 ukey
= *(const guint64
*)key
;
242 return (guint
)ukey
^ (guint
)(ukey
>> 32);
245 gboolean
guint64_equal(gconstpointer a
, gconstpointer b
)
247 guint64 ua
= *(const guint64
*)a
;
248 guint64 ub
= *(const guint64
*)b
;
254 void lttv_state_save(LttvTraceState
*self
, LttvAttribute
*container
)
256 LTTV_TRACE_STATE_GET_CLASS(self
)->state_save(self
, container
);
260 void lttv_state_restore(LttvTraceState
*self
, LttvAttribute
*container
)
262 LTTV_TRACE_STATE_GET_CLASS(self
)->state_restore(self
, container
);
266 void lttv_state_state_saved_free(LttvTraceState
*self
,
267 LttvAttribute
*container
)
269 LTTV_TRACE_STATE_GET_CLASS(self
)->state_saved_free(self
, container
);
273 guint
process_hash(gconstpointer key
)
275 guint pid
= ((const LttvProcessState
*)key
)->pid
;
276 return (pid
>>8 ^ pid
>>4 ^ pid
>>2 ^ pid
) ;
280 /* If the hash table hash function is well distributed,
281 * the process_equal should compare different pid */
282 gboolean
process_equal(gconstpointer a
, gconstpointer b
)
284 const LttvProcessState
*process_a
, *process_b
;
287 process_a
= (const LttvProcessState
*)a
;
288 process_b
= (const LttvProcessState
*)b
;
290 if(likely(process_a
->pid
!= process_b
->pid
)) ret
= FALSE
;
291 else if(likely(process_a
->pid
== 0 &&
292 process_a
->cpu
!= process_b
->cpu
)) ret
= FALSE
;
297 static void delete_usertrace(gpointer key
, gpointer value
, gpointer user_data
)
299 g_tree_destroy((GTree
*)value
);
302 static void lttv_state_free_usertraces(GHashTable
*usertraces
)
304 g_hash_table_foreach(usertraces
, delete_usertrace
, NULL
);
305 g_hash_table_destroy(usertraces
);
308 gboolean
rettrue(gpointer key
, gpointer value
, gpointer user_data
)
313 static guint
check_expand(nb
, id
)
318 return max(id
+ 1, nb
* 2);
321 static void expand_name_table(LttvTraceState
*ts
, GQuark
**table
,
322 guint nb
, guint new_nb
)
324 /* Expand an incomplete table */
325 GQuark
*old_table
= *table
;
326 *table
= g_new(GQuark
, new_nb
);
327 memcpy(*table
, old_table
, nb
* sizeof(GQuark
));
331 static void fill_name_table(LttvTraceState
*ts
, GQuark
*table
, guint nb
,
332 guint new_nb
, const char *def_string
)
335 GString
*fe_name
= g_string_new("");
336 for(i
= nb
; i
< new_nb
; i
++) {
337 g_string_printf(fe_name
, "%s %d", def_string
, i
);
338 table
[i
] = g_quark_from_string(fe_name
->str
);
340 g_string_free(fe_name
, TRUE
);
343 static void expand_syscall_table(LttvTraceState
*ts
, int id
)
345 LttvNameTables
*nt
= ts
->name_tables
;
348 new_nb
= check_expand(nt
->nb_syscalls
, id
);
349 if(likely(new_nb
== nt
->nb_syscalls
))
351 expand_name_table(ts
, &nt
->syscall_names
, nt
->nb_syscalls
, new_nb
);
352 fill_name_table(ts
, nt
->syscall_names
, nt
->nb_syscalls
, new_nb
, "syscall");
353 /* Update the table size */
354 nt
->nb_syscalls
= new_nb
;
357 static void expand_kprobe_table(LttvTraceState
*ts
, guint64 ip
, char *symbol
)
359 LttvNameTables
*nt
= ts
->name_tables
;
360 #if (__WORDSIZE == 32)
361 guint64
*ip_ptr
= g_new(guint64
, 1);
362 g_hash_table_insert(nt
->kprobe_hash
, ip_ptr
,
363 (gpointer
)(glong
)g_quark_from_string(symbol
));
365 g_hash_table_insert(nt
->kprobe_hash
, (gpointer
)ip
,
366 (gpointer
)(glong
)g_quark_from_string(symbol
));
370 static void expand_trap_table(LttvTraceState
*ts
, int id
)
372 LttvNameTables
*nt
= ts
->name_tables
;
373 LttvTrapState
*old_table
;
376 new_nb
= check_expand(nt
->nb_traps
, id
);
377 if(likely(new_nb
== nt
->nb_traps
))
380 expand_name_table(ts
, &nt
->trap_names
, nt
->nb_traps
, new_nb
);
381 fill_name_table(ts
, nt
->trap_names
, nt
->nb_traps
, new_nb
, "trap");
383 old_table
= ts
->trap_states
;
384 ts
->trap_states
= g_new(LttvTrapState
, new_nb
);
385 memcpy(ts
->trap_states
, old_table
, nt
->nb_traps
* sizeof(LttvTrapState
));
387 for(i
= nt
->nb_traps
; i
< new_nb
; i
++)
388 ts
->trap_states
[i
].running
= 0;
390 /* Update the table size */
391 nt
->nb_traps
= new_nb
;
394 static void expand_irq_table(LttvTraceState
*ts
, int id
)
396 LttvNameTables
*nt
= ts
->name_tables
;
397 LttvIRQState
*old_table
;
400 new_nb
= check_expand(nt
->nb_irqs
, id
);
401 if(likely(new_nb
== nt
->nb_irqs
))
404 expand_name_table(ts
, &nt
->irq_names
, nt
->nb_irqs
, new_nb
);
405 fill_name_table(ts
, nt
->irq_names
, nt
->nb_irqs
, new_nb
, "irq");
407 old_table
= ts
->irq_states
;
408 ts
->irq_states
= g_new(LttvIRQState
, new_nb
);
409 memcpy(ts
->irq_states
, old_table
, nt
->nb_irqs
* sizeof(LttvIRQState
));
411 for(i
= nt
->nb_irqs
; i
< new_nb
; i
++)
412 ts
->irq_states
[i
].mode_stack
=
413 g_array_new(FALSE
, FALSE
, sizeof(LttvIRQMode
));
415 /* Update the table size */
416 nt
->nb_irqs
= new_nb
;
419 static void expand_soft_irq_table(LttvTraceState
*ts
, int id
)
421 LttvNameTables
*nt
= ts
->name_tables
;
422 LttvSoftIRQState
*old_table
;
425 new_nb
= check_expand(nt
->nb_soft_irqs
, id
);
426 if(likely(new_nb
== nt
->nb_soft_irqs
))
429 expand_name_table(ts
, &nt
->soft_irq_names
, nt
->nb_soft_irqs
, new_nb
);
430 fill_name_table(ts
, nt
->soft_irq_names
, nt
->nb_soft_irqs
, new_nb
, "softirq");
432 old_table
= ts
->soft_irq_states
;
433 ts
->soft_irq_states
= g_new(LttvSoftIRQState
, new_nb
);
434 memcpy(ts
->soft_irq_states
, old_table
,
435 nt
->nb_soft_irqs
* sizeof(LttvSoftIRQState
));
437 for(i
= nt
->nb_soft_irqs
; i
< new_nb
; i
++)
438 ts
->soft_irq_states
[i
].running
= 0;
440 /* Update the table size */
441 nt
->nb_soft_irqs
= new_nb
;
445 restore_init_state(LttvTraceState
*self
)
447 guint i
, nb_cpus
, nb_irqs
, nb_soft_irqs
, nb_traps
;
449 //LttvTracefileState *tfcs;
451 LttTime start_time
, end_time
;
453 /* Free the process tables */
454 if(self
->processes
!= NULL
) lttv_state_free_process_table(self
->processes
);
455 if(self
->usertraces
!= NULL
) lttv_state_free_usertraces(self
->usertraces
);
456 self
->processes
= g_hash_table_new(process_hash
, process_equal
);
457 self
->usertraces
= g_hash_table_new(g_direct_hash
, g_direct_equal
);
460 /* Seek time to beginning */
461 // Mathieu : fix : don't seek traceset here : causes inconsistency in seek
462 // closest. It's the tracecontext job to seek the trace to the beginning
463 // anyway : the init state might be used at the middle of the trace as well...
464 //g_tree_destroy(self->parent.ts_context->pqueue);
465 //self->parent.ts_context->pqueue = g_tree_new(compare_tracefile);
467 ltt_trace_time_span_get(self
->parent
.t
, &start_time
, &end_time
);
469 //lttv_process_trace_seek_time(&self->parent, ltt_time_zero);
471 nb_cpus
= ltt_trace_get_num_cpu(self
->parent
.t
);
472 nb_irqs
= self
->name_tables
->nb_irqs
;
473 nb_soft_irqs
= self
->name_tables
->nb_soft_irqs
;
474 nb_traps
= self
->name_tables
->nb_traps
;
476 /* Put the per cpu running_process to beginning state : process 0. */
477 for(i
=0; i
< nb_cpus
; i
++) {
478 LttvExecutionState
*es
;
479 self
->running_process
[i
] = lttv_state_create_process(self
, NULL
, i
, 0, 0,
480 LTTV_STATE_UNNAMED
, &start_time
);
481 /* We are not sure is it's a kernel thread or normal thread, put the
482 * bottom stack state to unknown */
483 self
->running_process
[i
]->execution_stack
=
484 g_array_set_size(self
->running_process
[i
]->execution_stack
, 1);
485 es
= self
->running_process
[i
]->state
=
486 &g_array_index(self
->running_process
[i
]->execution_stack
,
487 LttvExecutionState
, 0);
488 es
->t
= LTTV_STATE_MODE_UNKNOWN
;
489 es
->s
= LTTV_STATE_UNNAMED
;
491 //self->running_process[i]->state->s = LTTV_STATE_RUN;
492 self
->running_process
[i
]->cpu
= i
;
494 /* reset cpu states */
495 if(self
->cpu_states
[i
].mode_stack
->len
> 0) {
496 g_array_remove_range(self
->cpu_states
[i
].mode_stack
, 0, self
->cpu_states
[i
].mode_stack
->len
);
497 if(self
->cpu_states
[i
].irq_stack
->len
)
498 g_array_remove_range(self
->cpu_states
[i
].irq_stack
, 0, self
->cpu_states
[i
].irq_stack
->len
);
499 if(self
->cpu_states
[i
].softirq_stack
->len
)
500 g_array_remove_range(self
->cpu_states
[i
].softirq_stack
, 0, self
->cpu_states
[i
].softirq_stack
->len
);
501 if(self
->cpu_states
[i
].trap_stack
->len
)
502 g_array_remove_range(self
->cpu_states
[i
].trap_stack
, 0, self
->cpu_states
[i
].trap_stack
->len
);
506 /* reset irq states */
507 for(i
=0; i
<nb_irqs
; i
++) {
508 if(self
->irq_states
[i
].mode_stack
->len
> 0)
509 g_array_remove_range(self
->irq_states
[i
].mode_stack
, 0, self
->irq_states
[i
].mode_stack
->len
);
512 /* reset softirq states */
513 for(i
=0; i
<nb_soft_irqs
; i
++) {
514 self
->soft_irq_states
[i
].pending
= 0;
515 self
->soft_irq_states
[i
].running
= 0;
518 /* reset trap states */
519 for(i
=0; i
<nb_traps
; i
++) {
520 self
->trap_states
[i
].running
= 0;
523 /* reset bdev states */
524 g_hash_table_foreach(self
->bdev_states
, bdevstate_free_cb
, NULL
);
525 //g_hash_table_steal_all(self->bdev_states);
526 g_hash_table_foreach_steal(self
->bdev_states
, rettrue
, NULL
);
529 nb_tracefile
= self
->parent
.tracefiles
->len
;
531 for(i
= 0 ; i
< nb_tracefile
; i
++) {
533 LTTV_TRACEFILE_STATE(g_array_index(self
->parent
.tracefiles
,
534 LttvTracefileContext
*, i
));
535 ltt_trace_time_span_get(self
->parent
.t
, &tfcs
->parent
.timestamp
, NULL
);
536 // tfcs->saved_position = 0;
537 tfcs
->process
= lttv_state_create_process(tfcs
, NULL
,0);
538 tfcs
->process
->state
->s
= LTTV_STATE_RUN
;
539 tfcs
->process
->last_cpu
= tfcs
->cpu_name
;
540 tfcs
->process
->last_cpu_index
= ltt_tracefile_num(((LttvTracefileContext
*)tfcs
)->tf
);
545 //static LttTime time_zero = {0,0};
547 static gint
compare_usertraces(gconstpointer a
, gconstpointer b
,
550 const LttTime
*t1
= (const LttTime
*)a
;
551 const LttTime
*t2
= (const LttTime
*)b
;
553 return ltt_time_compare(*t1
, *t2
);
556 static void free_usertrace_key(gpointer data
)
561 #define MAX_STRING_LEN 4096
564 state_load_saved_states(LttvTraceState
*tcs
)
567 GPtrArray
*quarktable
;
568 const char *trace_path
;
572 tcs
->has_precomputed_states
= FALSE
;
576 gchar buf
[MAX_STRING_LEN
];
579 trace_path
= g_quark_to_string(ltt_trace_name(tcs
->parent
.t
));
580 strncpy(path
, trace_path
, PATH_MAX
-1);
581 count
= strnlen(trace_path
, PATH_MAX
-1);
582 // quarktable : open, test
583 strncat(path
, "/precomputed/quarktable", PATH_MAX
-count
-1);
584 fp
= fopen(path
, "r");
586 quarktable
= g_ptr_array_sized_new(4096);
588 /* Index 0 is null */
590 if(hdr
== EOF
) return;
591 g_assert(hdr
== HDR_QUARKS
);
595 if(hdr
== EOF
) break;
596 g_assert(hdr
== HDR_QUARK
);
597 g_ptr_array_set_size(quarktable
, q
+1);
600 fread(&buf
[i
], sizeof(gchar
), 1, fp
);
601 if(buf
[i
] == '\0' || feof(fp
)) break;
604 len
= strnlen(buf
, MAX_STRING_LEN
-1);
605 g_ptr_array_index (quarktable
, q
) = g_new(gchar
, len
+1);
606 strncpy(g_ptr_array_index (quarktable
, q
), buf
, len
+1);
612 // saved_states : open, test
613 strncpy(path
, trace_path
, PATH_MAX
-1);
614 count
= strnlen(trace_path
, PATH_MAX
-1);
615 strncat(path
, "/precomputed/states", PATH_MAX
-count
-1);
616 fp
= fopen(path
, "r");
620 if(hdr
!= HDR_TRACE
) goto end
;
622 lttv_trace_states_read_raw(tcs
, fp
, quarktable
);
624 tcs
->has_precomputed_states
= TRUE
;
629 /* Free the quarktable */
630 for(i
=0; i
<quarktable
->len
; i
++) {
631 string
= g_ptr_array_index (quarktable
, i
);
634 g_ptr_array_free(quarktable
, TRUE
);
639 init(LttvTracesetState
*self
, LttvTraceset
*ts
)
641 guint i
, j
, nb_trace
, nb_tracefile
, nb_cpu
;
644 LttvTraceContext
*tc
;
648 LttvTracefileState
*tfcs
;
650 LttvAttributeValue v
;
652 LTTV_TRACESET_CONTEXT_CLASS(g_type_class_peek(LTTV_TRACESET_CONTEXT_TYPE
))->
653 init((LttvTracesetContext
*)self
, ts
);
655 nb_trace
= lttv_traceset_number(ts
);
656 for(i
= 0 ; i
< nb_trace
; i
++) {
657 tc
= self
->parent
.traces
[i
];
658 tcs
= LTTV_TRACE_STATE(tc
);
659 tcs
->save_interval
= LTTV_STATE_SAVE_INTERVAL
;
660 lttv_attribute_find(tcs
->parent
.t_a
, LTTV_STATE_TRACE_STATE_USE_COUNT
,
664 if(*(v
.v_uint
) == 1) {
665 create_name_tables(tcs
);
666 create_max_time(tcs
);
668 get_name_tables(tcs
);
671 nb_tracefile
= tc
->tracefiles
->len
;
672 nb_cpu
= ltt_trace_get_num_cpu(tc
->t
);
673 nb_irq
= tcs
->name_tables
->nb_irqs
;
674 tcs
->processes
= NULL
;
675 tcs
->usertraces
= NULL
;
676 tcs
->running_process
= g_new(LttvProcessState
*, nb_cpu
);
678 /* init cpu resource stuff */
679 tcs
->cpu_states
= g_new(LttvCPUState
, nb_cpu
);
680 for(j
= 0; j
<nb_cpu
; j
++) {
681 tcs
->cpu_states
[j
].mode_stack
= g_array_new(FALSE
, FALSE
, sizeof(LttvCPUMode
));
682 tcs
->cpu_states
[j
].irq_stack
= g_array_new(FALSE
, FALSE
, sizeof(gint
));
683 tcs
->cpu_states
[j
].softirq_stack
= g_array_new(FALSE
, FALSE
, sizeof(gint
));
684 tcs
->cpu_states
[j
].trap_stack
= g_array_new(FALSE
, FALSE
, sizeof(gint
));
685 g_assert(tcs
->cpu_states
[j
].mode_stack
!= NULL
);
688 /* init irq resource stuff */
689 tcs
->irq_states
= g_new(LttvIRQState
, nb_irq
);
690 for(j
= 0; j
<nb_irq
; j
++) {
691 tcs
->irq_states
[j
].mode_stack
= g_array_new(FALSE
, FALSE
, sizeof(LttvIRQMode
));
692 g_assert(tcs
->irq_states
[j
].mode_stack
!= NULL
);
695 /* init soft irq stuff */
696 /* the kernel has a statically fixed max of 32 softirqs */
697 tcs
->soft_irq_states
= g_new(LttvSoftIRQState
, tcs
->name_tables
->nb_soft_irqs
);
699 /* init trap stuff */
700 tcs
->trap_states
= g_new(LttvTrapState
, tcs
->name_tables
->nb_traps
);
702 /* init bdev resource stuff */
703 tcs
->bdev_states
= g_hash_table_new(g_int_hash
, g_int_equal
);
705 restore_init_state(tcs
);
706 for(j
= 0 ; j
< nb_tracefile
; j
++) {
708 LTTV_TRACEFILE_STATE(g_array_index(tc
->tracefiles
,
709 LttvTracefileContext
*, j
));
710 tfcs
->tracefile_name
= ltt_tracefile_name(tfcs
->parent
.tf
);
711 tfcs
->cpu
= ltt_tracefile_cpu(tfcs
->parent
.tf
);
712 tfcs
->cpu_state
= &(tcs
->cpu_states
[tfcs
->cpu
]);
713 if(ltt_tracefile_tid(tfcs
->parent
.tf
) != 0) {
714 /* It's a Usertrace */
715 guint tid
= ltt_tracefile_tid(tfcs
->parent
.tf
);
716 GTree
*usertrace_tree
= (GTree
*)g_hash_table_lookup(tcs
->usertraces
,
717 GUINT_TO_POINTER(tid
));
718 if(!usertrace_tree
) {
719 usertrace_tree
= g_tree_new_full(compare_usertraces
,
720 NULL
, free_usertrace_key
, NULL
);
721 g_hash_table_insert(tcs
->usertraces
,
722 GUINT_TO_POINTER(tid
), usertrace_tree
);
724 LttTime
*timestamp
= g_new(LttTime
, 1);
725 *timestamp
= ltt_interpolate_time_from_tsc(tfcs
->parent
.tf
,
726 ltt_tracefile_creation(tfcs
->parent
.tf
));
727 g_tree_insert(usertrace_tree
, timestamp
, tfcs
);
731 /* See if the trace has saved states */
732 state_load_saved_states(tcs
);
737 fini(LttvTracesetState
*self
)
743 //LttvTracefileState *tfcs;
745 LttvAttributeValue v
;
747 nb_trace
= lttv_traceset_number(LTTV_TRACESET_CONTEXT(self
)->ts
);
748 for(i
= 0 ; i
< nb_trace
; i
++) {
749 tcs
= (LttvTraceState
*)(LTTV_TRACESET_CONTEXT(self
)->traces
[i
]);
750 lttv_attribute_find(tcs
->parent
.t_a
, LTTV_STATE_TRACE_STATE_USE_COUNT
,
753 g_assert(*(v
.v_uint
) != 0);
756 if(*(v
.v_uint
) == 0) {
757 free_name_tables(tcs
);
759 free_saved_state(tcs
);
761 g_free(tcs
->running_process
);
762 tcs
->running_process
= NULL
;
763 lttv_state_free_process_table(tcs
->processes
);
764 lttv_state_free_usertraces(tcs
->usertraces
);
765 tcs
->processes
= NULL
;
766 tcs
->usertraces
= NULL
;
768 LTTV_TRACESET_CONTEXT_CLASS(g_type_class_peek(LTTV_TRACESET_CONTEXT_TYPE
))->
769 fini((LttvTracesetContext
*)self
);
773 static LttvTracesetContext
*
774 new_traceset_context(LttvTracesetContext
*self
)
776 return LTTV_TRACESET_CONTEXT(g_object_new(LTTV_TRACESET_STATE_TYPE
, NULL
));
780 static LttvTraceContext
*
781 new_trace_context(LttvTracesetContext
*self
)
783 return LTTV_TRACE_CONTEXT(g_object_new(LTTV_TRACE_STATE_TYPE
, NULL
));
787 static LttvTracefileContext
*
788 new_tracefile_context(LttvTracesetContext
*self
)
790 return LTTV_TRACEFILE_CONTEXT(g_object_new(LTTV_TRACEFILE_STATE_TYPE
, NULL
));
794 /* Write the process state of the trace */
796 static void write_process_state(gpointer key
, gpointer value
,
799 LttvProcessState
*process
;
801 LttvExecutionState
*es
;
803 FILE *fp
= (FILE *)user_data
;
808 process
= (LttvProcessState
*)value
;
810 " <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",
811 process
, process
->pid
, process
->tgid
, process
->ppid
,
812 g_quark_to_string(process
->type
),
813 process
->creation_time
.tv_sec
,
814 process
->creation_time
.tv_nsec
,
815 process
->insertion_time
.tv_sec
,
816 process
->insertion_time
.tv_nsec
,
817 g_quark_to_string(process
->name
),
818 g_quark_to_string(process
->brand
),
819 process
->cpu
, process
->free_events
);
821 for(i
= 0 ; i
< process
->execution_stack
->len
; i
++) {
822 es
= &g_array_index(process
->execution_stack
, LttvExecutionState
, i
);
823 fprintf(fp
, " <ES MODE=\"%s\" SUBMODE=\"%s\" ENTRY_S=%lu ENTRY_NS=%lu",
824 g_quark_to_string(es
->t
), g_quark_to_string(es
->n
),
825 es
->entry
.tv_sec
, es
->entry
.tv_nsec
);
826 fprintf(fp
, " CHANGE_S=%lu CHANGE_NS=%lu STATUS=\"%s\"/>\n",
827 es
->change
.tv_sec
, es
->change
.tv_nsec
, g_quark_to_string(es
->s
));
830 for(i
= 0 ; i
< process
->user_stack
->len
; i
++) {
831 address
= g_array_index(process
->user_stack
, guint64
, i
);
832 fprintf(fp
, " <USER_STACK ADDRESS=\"%" PRIu64
"\"/>\n",
836 if(process
->usertrace
) {
837 fprintf(fp
, " <USERTRACE NAME=\"%s\" CPU=%u\n/>",
838 g_quark_to_string(process
->usertrace
->tracefile_name
),
839 process
->usertrace
->cpu
);
843 fprintf(fp
, " </PROCESS>\n");
847 void lttv_state_write(LttvTraceState
*self
, LttTime t
, FILE *fp
)
849 guint i
, nb_tracefile
, nb_block
, offset
;
852 LttvTracefileState
*tfcs
;
856 LttEventPosition
*ep
;
860 ep
= ltt_event_position_new();
862 fprintf(fp
,"<PROCESS_STATE TIME_S=%lu TIME_NS=%lu>\n", t
.tv_sec
, t
.tv_nsec
);
864 g_hash_table_foreach(self
->processes
, write_process_state
, fp
);
866 nb_cpus
= ltt_trace_get_num_cpu(self
->parent
.t
);
867 for(i
=0;i
<nb_cpus
;i
++) {
868 fprintf(fp
," <CPU NUM=%u RUNNING_PROCESS=%u>\n",
869 i
, self
->running_process
[i
]->pid
);
872 nb_tracefile
= self
->parent
.tracefiles
->len
;
874 for(i
= 0 ; i
< nb_tracefile
; i
++) {
876 LTTV_TRACEFILE_STATE(g_array_index(self
->parent
.tracefiles
,
877 LttvTracefileContext
*, i
));
878 fprintf(fp
, " <TRACEFILE TIMESTAMP_S=%lu TIMESTAMP_NS=%lu",
879 tfcs
->parent
.timestamp
.tv_sec
,
880 tfcs
->parent
.timestamp
.tv_nsec
);
881 LttEvent
*e
= ltt_tracefile_get_event(tfcs
->parent
.tf
);
882 if(e
== NULL
) fprintf(fp
,"/>\n");
884 ltt_event_position(e
, ep
);
885 ltt_event_position_get(ep
, &tf
, &nb_block
, &offset
, &tsc
);
886 fprintf(fp
, " BLOCK=%u OFFSET=%u TSC=%" PRIu64
"/>\n", nb_block
, offset
,
891 fprintf(fp
,"</PROCESS_STATE>\n");
895 static void write_process_state_raw(gpointer key
, gpointer value
,
898 LttvProcessState
*process
;
900 LttvExecutionState
*es
;
902 FILE *fp
= (FILE *)user_data
;
907 process
= (LttvProcessState
*)value
;
908 fputc(HDR_PROCESS
, fp
);
909 //fwrite(&header, sizeof(header), 1, fp);
910 //fprintf(fp, "%s", g_quark_to_string(process->type));
912 fwrite(&process
->type
, sizeof(process
->type
), 1, fp
);
913 //fprintf(fp, "%s", g_quark_to_string(process->name));
915 fwrite(&process
->name
, sizeof(process
->name
), 1, fp
);
916 //fprintf(fp, "%s", g_quark_to_string(process->brand));
918 fwrite(&process
->brand
, sizeof(process
->brand
), 1, fp
);
919 fwrite(&process
->pid
, sizeof(process
->pid
), 1, fp
);
920 fwrite(&process
->free_events
, sizeof(process
->free_events
), 1, fp
);
921 fwrite(&process
->tgid
, sizeof(process
->tgid
), 1, fp
);
922 fwrite(&process
->ppid
, sizeof(process
->ppid
), 1, fp
);
923 fwrite(&process
->cpu
, sizeof(process
->cpu
), 1, fp
);
924 fwrite(&process
->creation_time
, sizeof(process
->creation_time
), 1, fp
);
925 fwrite(&process
->insertion_time
, sizeof(process
->insertion_time
), 1, fp
);
929 " <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",
976 if(process
->usertrace
) {
977 fputc(HDR_USERTRACE
, fp
);
978 //fprintf(fp, "%s", g_quark_to_string(process->usertrace->tracefile_name));
980 fwrite(&process
->usertrace
->tracefile_name
,
981 sizeof(process
->usertrace
->tracefile_name
), 1, fp
);
982 fwrite(&process
->usertrace
->cpu
, sizeof(process
->usertrace
->cpu
), 1, fp
);
984 fprintf(fp
, " <USERTRACE NAME=\"%s\" CPU=%u\n/>",
985 g_quark_to_string(process
->usertrace
->tracefile_name
),
986 process
->usertrace
->cpu
);
993 void lttv_state_write_raw(LttvTraceState
*self
, LttTime t
, FILE *fp
)
995 guint i
, nb_tracefile
, nb_block
, offset
;
998 LttvTracefileState
*tfcs
;
1002 LttEventPosition
*ep
;
1006 ep
= ltt_event_position_new();
1008 //fprintf(fp,"<PROCESS_STATE TIME_S=%lu TIME_NS=%lu>\n", t.tv_sec, t.tv_nsec);
1009 fputc(HDR_PROCESS_STATE
, fp
);
1010 fwrite(&t
, sizeof(t
), 1, fp
);
1012 g_hash_table_foreach(self
->processes
, write_process_state_raw
, fp
);
1014 nb_cpus
= ltt_trace_get_num_cpu(self
->parent
.t
);
1015 for(i
=0;i
<nb_cpus
;i
++) {
1017 fwrite(&i
, sizeof(i
), 1, fp
); /* cpu number */
1018 fwrite(&self
->running_process
[i
]->pid
,
1019 sizeof(self
->running_process
[i
]->pid
), 1, fp
);
1020 //fprintf(fp," <CPU NUM=%u RUNNING_PROCESS=%u>\n",
1021 // i, self->running_process[i]->pid);
1024 nb_tracefile
= self
->parent
.tracefiles
->len
;
1026 for(i
= 0 ; i
< nb_tracefile
; i
++) {
1028 LTTV_TRACEFILE_STATE(g_array_index(self
->parent
.tracefiles
,
1029 LttvTracefileContext
*, i
));
1030 // fprintf(fp, " <TRACEFILE TIMESTAMP_S=%lu TIMESTAMP_NS=%lu",
1031 // tfcs->parent.timestamp.tv_sec,
1032 // tfcs->parent.timestamp.tv_nsec);
1033 fputc(HDR_TRACEFILE
, fp
);
1034 fwrite(&tfcs
->parent
.timestamp
, sizeof(tfcs
->parent
.timestamp
), 1, fp
);
1035 /* Note : if timestamp if LTT_TIME_INFINITE, there will be no
1036 * position following : end of trace */
1037 LttEvent
*e
= ltt_tracefile_get_event(tfcs
->parent
.tf
);
1039 ltt_event_position(e
, ep
);
1040 ltt_event_position_get(ep
, &tf
, &nb_block
, &offset
, &tsc
);
1041 //fprintf(fp, " BLOCK=%u OFFSET=%u TSC=%llu/>\n", nb_block, offset,
1043 fwrite(&nb_block
, sizeof(nb_block
), 1, fp
);
1044 fwrite(&offset
, sizeof(offset
), 1, fp
);
1045 fwrite(&tsc
, sizeof(tsc
), 1, fp
);
1052 /* Read process state from a file */
1054 /* Called because a HDR_PROCESS was found */
1055 static void read_process_state_raw(LttvTraceState
*self
, FILE *fp
,
1056 GPtrArray
*quarktable
)
1058 LttvExecutionState
*es
;
1059 LttvProcessState
*process
, *parent_process
;
1060 LttvProcessState tmp
;
1065 /* TODO : check return value */
1066 fread(&tmp
.type
, sizeof(tmp
.type
), 1, fp
);
1067 fread(&tmp
.name
, sizeof(tmp
.name
), 1, fp
);
1068 fread(&tmp
.brand
, sizeof(tmp
.brand
), 1, fp
);
1069 fread(&tmp
.pid
, sizeof(tmp
.pid
), 1, fp
);
1070 fread(&tmp
.free_events
, sizeof(tmp
.free_events
), 1, fp
);
1071 fread(&tmp
.tgid
, sizeof(tmp
.tgid
), 1, fp
);
1072 fread(&tmp
.ppid
, sizeof(tmp
.ppid
), 1, fp
);
1073 fread(&tmp
.cpu
, sizeof(tmp
.cpu
), 1, fp
);
1074 fread(&tmp
.creation_time
, sizeof(tmp
.creation_time
), 1, fp
);
1075 fread(&tmp
.insertion_time
, sizeof(tmp
.insertion_time
), 1, fp
);
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 fread(&es
->t
, sizeof(es
->t
), 1, fp
);
1119 es
->t
= g_quark_from_string(
1120 (gchar
*)g_ptr_array_index(quarktable
, es
->t
));
1121 fread(&es
->n
, sizeof(es
->n
), 1, fp
);
1122 es
->n
= g_quark_from_string(
1123 (gchar
*)g_ptr_array_index(quarktable
, es
->n
));
1124 fread(&es
->s
, sizeof(es
->s
), 1, fp
);
1125 es
->s
= g_quark_from_string(
1126 (gchar
*)g_ptr_array_index(quarktable
, es
->s
));
1127 fread(&es
->entry
, sizeof(es
->entry
), 1, fp
);
1128 fread(&es
->change
, sizeof(es
->change
), 1, fp
);
1129 fread(&es
->cum_cpu_time
, sizeof(es
->cum_cpu_time
), 1, fp
);
1131 case HDR_USER_STACK
:
1132 process
->user_stack
= g_array_set_size(process
->user_stack
,
1133 process
->user_stack
->len
+ 1);
1134 address
= &g_array_index(process
->user_stack
, guint64
,
1135 process
->user_stack
->len
-1);
1136 fread(address
, sizeof(address
), 1, fp
);
1137 process
->current_function
= *address
;
1140 fread(&tmpq
, sizeof(tmpq
), 1, fp
);
1141 fread(&process
->usertrace
->cpu
, sizeof(process
->usertrace
->cpu
), 1, fp
);
1153 /* Called because a HDR_PROCESS_STATE was found */
1154 /* Append a saved state to the trace states */
1155 void lttv_state_read_raw(LttvTraceState
*self
, FILE *fp
, GPtrArray
*quarktable
)
1157 guint i
, nb_tracefile
, nb_block
, offset
;
1159 LttvTracefileState
*tfcs
;
1161 LttEventPosition
*ep
;
1169 LttvAttribute
*saved_states_tree
, *saved_state_tree
;
1171 LttvAttributeValue value
;
1172 GTree
*pqueue
= self
->parent
.ts_context
->pqueue
;
1173 ep
= ltt_event_position_new();
1175 restore_init_state(self
);
1177 fread(&t
, sizeof(t
), 1, fp
);
1180 if(feof(fp
) || ferror(fp
)) goto end_loop
;
1182 if(hdr
== EOF
) goto end_loop
;
1186 /* Call read_process_state_raw */
1187 read_process_state_raw(self
, fp
, quarktable
);
1195 case HDR_USER_STACK
:
1197 case HDR_PROCESS_STATE
:
1203 g_error("Error while parsing saved state file : unknown data header %d",
1209 nb_cpus
= ltt_trace_get_num_cpu(self
->parent
.t
);
1210 for(i
=0;i
<nb_cpus
;i
++) {
1213 g_assert(hdr
== HDR_CPU
);
1214 fread(&cpu_num
, sizeof(cpu_num
), 1, fp
); /* cpu number */
1215 g_assert(i
== cpu_num
);
1216 fread(&self
->running_process
[i
]->pid
,
1217 sizeof(self
->running_process
[i
]->pid
), 1, fp
);
1220 nb_tracefile
= self
->parent
.tracefiles
->len
;
1222 for(i
= 0 ; i
< nb_tracefile
; i
++) {
1224 LTTV_TRACEFILE_STATE(g_array_index(self
->parent
.tracefiles
,
1225 LttvTracefileContext
*, i
));
1226 // fprintf(fp, " <TRACEFILE TIMESTAMP_S=%lu TIMESTAMP_NS=%lu",
1227 // tfcs->parent.timestamp.tv_sec,
1228 // tfcs->parent.timestamp.tv_nsec);
1229 g_tree_remove(pqueue
, &tfcs
->parent
);
1231 g_assert(hdr
== HDR_TRACEFILE
);
1232 fread(&tfcs
->parent
.timestamp
, sizeof(tfcs
->parent
.timestamp
), 1, fp
);
1233 /* Note : if timestamp if LTT_TIME_INFINITE, there will be no
1234 * position following : end of trace */
1235 if(ltt_time_compare(tfcs
->parent
.timestamp
, ltt_time_infinite
) != 0) {
1236 fread(&nb_block
, sizeof(nb_block
), 1, fp
);
1237 fread(&offset
, sizeof(offset
), 1, fp
);
1238 fread(&tsc
, sizeof(tsc
), 1, fp
);
1239 ltt_event_position_set(ep
, tfcs
->parent
.tf
, nb_block
, offset
, tsc
);
1240 gint ret
= ltt_tracefile_seek_position(tfcs
->parent
.tf
, ep
);
1242 g_tree_insert(pqueue
, &tfcs
->parent
, &tfcs
->parent
);
1247 saved_states_tree
= lttv_attribute_find_subdir(self
->parent
.t_a
,
1248 LTTV_STATE_SAVED_STATES
);
1249 saved_state_tree
= g_object_new(LTTV_ATTRIBUTE_TYPE
, NULL
);
1250 value
= lttv_attribute_add(saved_states_tree
,
1251 lttv_attribute_get_number(saved_states_tree
), LTTV_GOBJECT
);
1252 *(value
.v_gobject
) = (GObject
*)saved_state_tree
;
1253 value
= lttv_attribute_add(saved_state_tree
, LTTV_STATE_TIME
, LTTV_TIME
);
1254 *(value
.v_time
) = t
;
1255 lttv_state_save(self
, saved_state_tree
);
1256 g_debug("Saving state at time %lu.%lu", t
.tv_sec
,
1259 *(self
->max_time_state_recomputed_in_seek
) = t
;
1263 /* Called when a HDR_TRACE is found */
1264 void lttv_trace_states_read_raw(LttvTraceState
*tcs
, FILE *fp
,
1265 GPtrArray
*quarktable
)
1270 if(feof(fp
) || ferror(fp
)) goto end_loop
;
1272 if(hdr
== EOF
) goto end_loop
;
1275 case HDR_PROCESS_STATE
:
1276 /* Call read_process_state_raw */
1277 lttv_state_read_raw(tcs
, fp
, quarktable
);
1285 case HDR_USER_STACK
:
1289 g_error("Error while parsing saved state file :"
1290 " unexpected data header %d",
1294 g_error("Error while parsing saved state file : unknown data header %d",
1299 *(tcs
->max_time_state_recomputed_in_seek
) = tcs
->parent
.time_span
.end_time
;
1300 restore_init_state(tcs
);
1301 lttv_process_trace_seek_time(&tcs
->parent
, ltt_time_zero
);
1307 /* Copy each process from an existing hash table to a new one */
1309 static void copy_process_state(gpointer key
, gpointer value
,gpointer user_data
)
1311 LttvProcessState
*process
, *new_process
;
1313 GHashTable
*new_processes
= (GHashTable
*)user_data
;
1317 process
= (LttvProcessState
*)value
;
1318 new_process
= g_new(LttvProcessState
, 1);
1319 *new_process
= *process
;
1320 new_process
->execution_stack
= g_array_sized_new(FALSE
, FALSE
,
1321 sizeof(LttvExecutionState
), PREALLOCATED_EXECUTION_STACK
);
1322 new_process
->execution_stack
=
1323 g_array_set_size(new_process
->execution_stack
,
1324 process
->execution_stack
->len
);
1325 for(i
= 0 ; i
< process
->execution_stack
->len
; i
++) {
1326 g_array_index(new_process
->execution_stack
, LttvExecutionState
, i
) =
1327 g_array_index(process
->execution_stack
, LttvExecutionState
, i
);
1329 new_process
->state
= &g_array_index(new_process
->execution_stack
,
1330 LttvExecutionState
, new_process
->execution_stack
->len
- 1);
1331 new_process
->user_stack
= g_array_sized_new(FALSE
, FALSE
,
1332 sizeof(guint64
), 0);
1333 new_process
->user_stack
=
1334 g_array_set_size(new_process
->user_stack
,
1335 process
->user_stack
->len
);
1336 for(i
= 0 ; i
< process
->user_stack
->len
; i
++) {
1337 g_array_index(new_process
->user_stack
, guint64
, i
) =
1338 g_array_index(process
->user_stack
, guint64
, i
);
1340 new_process
->current_function
= process
->current_function
;
1342 /* fd hash table stuff */
1348 /* copy every item in the hash table */
1349 new_process
->fds
= g_hash_table_new(g_direct_hash
, g_direct_equal
);
1351 g_hash_table_iter_init(&it
, process
->fds
);
1352 while (g_hash_table_iter_next (&it
, (void *)&key
, (void *)&value
)) {
1353 g_hash_table_insert(new_process
->fds
, key
, value
);
1357 /* When done creating the new process state, insert it in the
1359 g_hash_table_insert(new_processes
, new_process
, new_process
);
1363 static GHashTable
*lttv_state_copy_process_table(GHashTable
*processes
)
1365 GHashTable
*new_processes
= g_hash_table_new(process_hash
, process_equal
);
1367 g_hash_table_foreach(processes
, copy_process_state
, new_processes
);
1368 return new_processes
;
1371 static LttvCPUState
*lttv_state_copy_cpu_states(LttvCPUState
*states
, guint n
)
1374 LttvCPUState
*retval
;
1376 retval
= g_new(LttvCPUState
, n
);
1378 for(i
=0; i
<n
; i
++) {
1379 retval
[i
].irq_stack
= g_array_new(FALSE
, FALSE
, sizeof(gint
));
1380 g_array_set_size(retval
[i
].irq_stack
, states
[i
].irq_stack
->len
);
1381 for(j
=0; j
<states
[i
].irq_stack
->len
; j
++) {
1382 g_array_index(retval
[i
].irq_stack
, gint
, j
) = g_array_index(states
[i
].irq_stack
, gint
, j
);
1385 retval
[i
].softirq_stack
= g_array_new(FALSE
, FALSE
, sizeof(gint
));
1386 g_array_set_size(retval
[i
].softirq_stack
, states
[i
].softirq_stack
->len
);
1387 for(j
=0; j
<states
[i
].softirq_stack
->len
; j
++) {
1388 g_array_index(retval
[i
].softirq_stack
, gint
, j
) = g_array_index(states
[i
].softirq_stack
, gint
, j
);
1391 retval
[i
].trap_stack
= g_array_new(FALSE
, FALSE
, sizeof(gint
));
1392 g_array_set_size(retval
[i
].trap_stack
, states
[i
].trap_stack
->len
);
1393 for(j
=0; j
<states
[i
].trap_stack
->len
; j
++) {
1394 g_array_index(retval
[i
].trap_stack
, gint
, j
) = g_array_index(states
[i
].trap_stack
, gint
, j
);
1397 retval
[i
].mode_stack
= g_array_new(FALSE
, FALSE
, sizeof(LttvCPUMode
));
1398 g_array_set_size(retval
[i
].mode_stack
, states
[i
].mode_stack
->len
);
1399 for(j
=0; j
<states
[i
].mode_stack
->len
; j
++) {
1400 g_array_index(retval
[i
].mode_stack
, GQuark
, j
) = g_array_index(states
[i
].mode_stack
, GQuark
, j
);
1407 static void lttv_state_free_cpu_states(LttvCPUState
*states
, guint n
)
1411 for(i
=0; i
<n
; i
++) {
1412 g_array_free(states
[i
].mode_stack
, TRUE
);
1413 g_array_free(states
[i
].irq_stack
, TRUE
);
1414 g_array_free(states
[i
].softirq_stack
, TRUE
);
1415 g_array_free(states
[i
].trap_stack
, TRUE
);
1421 static LttvIRQState
*lttv_state_copy_irq_states(LttvIRQState
*states
, guint n
)
1424 LttvIRQState
*retval
;
1426 retval
= g_new(LttvIRQState
, n
);
1428 for(i
=0; i
<n
; i
++) {
1429 retval
[i
].mode_stack
= g_array_new(FALSE
, FALSE
, sizeof(LttvIRQMode
));
1430 g_array_set_size(retval
[i
].mode_stack
, states
[i
].mode_stack
->len
);
1431 for(j
=0; j
<states
[i
].mode_stack
->len
; j
++) {
1432 g_array_index(retval
[i
].mode_stack
, GQuark
, j
) = g_array_index(states
[i
].mode_stack
, GQuark
, j
);
1439 static void lttv_state_free_irq_states(LttvIRQState
*states
, guint n
)
1443 for(i
=0; i
<n
; i
++) {
1444 g_array_free(states
[i
].mode_stack
, TRUE
);
1450 static LttvSoftIRQState
*lttv_state_copy_soft_irq_states(LttvSoftIRQState
*states
, guint n
)
1453 LttvSoftIRQState
*retval
;
1455 retval
= g_new(LttvSoftIRQState
, n
);
1457 for(i
=0; i
<n
; i
++) {
1458 retval
[i
].pending
= states
[i
].pending
;
1459 retval
[i
].running
= states
[i
].running
;
1465 static void lttv_state_free_soft_irq_states(LttvSoftIRQState
*states
, guint n
)
1470 static LttvTrapState
*lttv_state_copy_trap_states(LttvTrapState
*states
, guint n
)
1473 LttvTrapState
*retval
;
1475 retval
= g_new(LttvTrapState
, n
);
1477 for(i
=0; i
<n
; i
++) {
1478 retval
[i
].running
= states
[i
].running
;
1484 static void lttv_state_free_trap_states(LttvTrapState
*states
, guint n
)
1489 /* bdevstate stuff */
1491 static LttvBdevState
*get_hashed_bdevstate(LttvTraceState
*ts
, guint16 devcode
)
1493 gint devcode_gint
= devcode
;
1494 gpointer bdev
= g_hash_table_lookup(ts
->bdev_states
, &devcode_gint
);
1496 LttvBdevState
*bdevstate
= g_new(LttvBdevState
, 1);
1497 bdevstate
->mode_stack
= g_array_new(FALSE
, FALSE
, sizeof(GQuark
));
1499 gint
* key
= g_new(gint
, 1);
1501 g_hash_table_insert(ts
->bdev_states
, key
, bdevstate
);
1509 static LttvBdevState
*bdevstate_new(void)
1511 LttvBdevState
*retval
;
1512 retval
= g_new(LttvBdevState
, 1);
1513 retval
->mode_stack
= g_array_new(FALSE
, FALSE
, sizeof(GQuark
));
1518 static void bdevstate_free(LttvBdevState
*bds
)
1520 g_array_free(bds
->mode_stack
, TRUE
);
1524 static void bdevstate_free_cb(gpointer key
, gpointer value
, gpointer user_data
)
1526 LttvBdevState
*bds
= (LttvBdevState
*) value
;
1528 bdevstate_free(bds
);
1531 static LttvBdevState
*bdevstate_copy(LttvBdevState
*bds
)
1533 LttvBdevState
*retval
;
1535 retval
= bdevstate_new();
1536 g_array_insert_vals(retval
->mode_stack
, 0, bds
->mode_stack
->data
, bds
->mode_stack
->len
);
1541 static void insert_and_copy_bdev_state(gpointer k
, gpointer v
, gpointer u
)
1543 //GHashTable *ht = (GHashTable *)u;
1544 LttvBdevState
*bds
= (LttvBdevState
*)v
;
1545 LttvBdevState
*newbds
;
1547 newbds
= bdevstate_copy(bds
);
1549 g_hash_table_insert(u
, k
, newbds
);
1552 static GHashTable
*lttv_state_copy_blkdev_hashtable(GHashTable
*ht
)
1556 retval
= g_hash_table_new(g_int_hash
, g_int_equal
);
1558 g_hash_table_foreach(ht
, insert_and_copy_bdev_state
, retval
);
1563 /* Free a hashtable and the LttvBdevState structures its values
1566 static void lttv_state_free_blkdev_hashtable(GHashTable
*ht
)
1568 g_hash_table_foreach(ht
, bdevstate_free_cb
, NULL
);
1569 g_hash_table_destroy(ht
);
1572 /* The saved state for each trace contains a member "processes", which
1573 stores a copy of the process table, and a member "tracefiles" with
1574 one entry per tracefile. Each tracefile has a "process" member pointing
1575 to the current process and a "position" member storing the tracefile
1576 position (needed to seek to the current "next" event. */
1578 static void state_save(LttvTraceState
*self
, LttvAttribute
*container
)
1580 guint i
, nb_tracefile
, nb_cpus
, nb_irqs
, nb_soft_irqs
, nb_traps
;
1582 LttvTracefileState
*tfcs
;
1584 LttvAttribute
*tracefiles_tree
, *tracefile_tree
;
1586 guint
*running_process
;
1588 LttvAttributeValue value
;
1590 LttEventPosition
*ep
;
1592 tracefiles_tree
= lttv_attribute_find_subdir(container
,
1593 LTTV_STATE_TRACEFILES
);
1595 value
= lttv_attribute_add(container
, LTTV_STATE_PROCESSES
,
1597 *(value
.v_pointer
) = lttv_state_copy_process_table(self
->processes
);
1599 /* Add the currently running processes array */
1600 nb_cpus
= ltt_trace_get_num_cpu(self
->parent
.t
);
1601 running_process
= g_new(guint
, nb_cpus
);
1602 for(i
=0;i
<nb_cpus
;i
++) {
1603 running_process
[i
] = self
->running_process
[i
]->pid
;
1605 value
= lttv_attribute_add(container
, LTTV_STATE_RUNNING_PROCESS
,
1607 *(value
.v_pointer
) = running_process
;
1609 g_info("State save");
1611 nb_tracefile
= self
->parent
.tracefiles
->len
;
1613 for(i
= 0 ; i
< nb_tracefile
; i
++) {
1615 LTTV_TRACEFILE_STATE(g_array_index(self
->parent
.tracefiles
,
1616 LttvTracefileContext
*, i
));
1617 tracefile_tree
= g_object_new(LTTV_ATTRIBUTE_TYPE
, NULL
);
1618 value
= lttv_attribute_add(tracefiles_tree
, i
,
1620 *(value
.v_gobject
) = (GObject
*)tracefile_tree
;
1622 value
= lttv_attribute_add(tracefile_tree
, LTTV_STATE_PROCESS
,
1624 *(value
.v_uint
) = tfcs
->process
->pid
;
1626 value
= lttv_attribute_add(tracefile_tree
, LTTV_STATE_EVENT
,
1628 /* Only save the position if the tfs has not infinite time. */
1629 //if(!g_tree_lookup(self->parent.ts_context->pqueue, &tfcs->parent)
1630 // && current_tfcs != tfcs) {
1631 if(ltt_time_compare(tfcs
->parent
.timestamp
, ltt_time_infinite
) == 0) {
1632 *(value
.v_pointer
) = NULL
;
1634 LttEvent
*e
= ltt_tracefile_get_event(tfcs
->parent
.tf
);
1635 ep
= ltt_event_position_new();
1636 ltt_event_position(e
, ep
);
1637 *(value
.v_pointer
) = ep
;
1639 guint nb_block
, offset
;
1642 ltt_event_position_get(ep
, &tf
, &nb_block
, &offset
, &tsc
);
1643 g_info("Block %u offset %u tsc %" PRIu64
" time %lu.%lu", nb_block
, offset
,
1645 tfcs
->parent
.timestamp
.tv_sec
, tfcs
->parent
.timestamp
.tv_nsec
);
1649 /* save the cpu state */
1651 value
= lttv_attribute_add(container
, LTTV_STATE_RESOURCE_CPUS_COUNT
,
1653 *(value
.v_uint
) = nb_cpus
;
1655 value
= lttv_attribute_add(container
, LTTV_STATE_RESOURCE_CPUS
,
1657 *(value
.v_pointer
) = lttv_state_copy_cpu_states(self
->cpu_states
, nb_cpus
);
1660 /* save the irq state */
1661 nb_irqs
= self
->name_tables
->nb_irqs
;
1663 value
= lttv_attribute_add(container
, LTTV_STATE_RESOURCE_IRQS
,
1665 *(value
.v_pointer
) = lttv_state_copy_irq_states(self
->irq_states
, nb_irqs
);
1668 /* save the soft irq state */
1669 nb_soft_irqs
= self
->name_tables
->nb_soft_irqs
;
1671 value
= lttv_attribute_add(container
, LTTV_STATE_RESOURCE_SOFT_IRQS
,
1673 *(value
.v_pointer
) = lttv_state_copy_soft_irq_states(self
->soft_irq_states
, nb_soft_irqs
);
1676 /* save the trap state */
1677 nb_traps
= self
->name_tables
->nb_traps
;
1679 value
= lttv_attribute_add(container
, LTTV_STATE_RESOURCE_TRAPS
,
1681 *(value
.v_pointer
) = lttv_state_copy_trap_states(self
->trap_states
, nb_traps
);
1684 /* save the blkdev states */
1685 value
= lttv_attribute_add(container
, LTTV_STATE_RESOURCE_BLKDEVS
,
1687 *(value
.v_pointer
) = lttv_state_copy_blkdev_hashtable(self
->bdev_states
);
1691 static void state_restore(LttvTraceState
*self
, LttvAttribute
*container
)
1693 guint i
, nb_tracefile
, pid
, nb_cpus
, nb_irqs
, nb_soft_irqs
, nb_traps
;
1695 LttvTracefileState
*tfcs
;
1697 LttvAttribute
*tracefiles_tree
, *tracefile_tree
;
1699 guint
*running_process
;
1701 LttvAttributeType type
;
1703 LttvAttributeValue value
;
1705 LttvAttributeName name
;
1709 LttEventPosition
*ep
;
1711 LttvTracesetContext
*tsc
= self
->parent
.ts_context
;
1714 tracefiles_tree
= lttv_attribute_find_subdir(container
,
1715 LTTV_STATE_TRACEFILES
);
1717 type
= lttv_attribute_get_by_name(container
, LTTV_STATE_PROCESSES
,
1719 g_assert(type
== LTTV_POINTER
);
1720 lttv_state_free_process_table(self
->processes
);
1721 self
->processes
= lttv_state_copy_process_table(*(value
.v_pointer
));
1723 /* Add the currently running processes array */
1724 nb_cpus
= ltt_trace_get_num_cpu(self
->parent
.t
);
1725 type
= lttv_attribute_get_by_name(container
, LTTV_STATE_RUNNING_PROCESS
,
1727 g_assert(type
== LTTV_POINTER
);
1728 running_process
= *(value
.v_pointer
);
1729 for(i
=0;i
<nb_cpus
;i
++) {
1730 pid
= running_process
[i
];
1731 self
->running_process
[i
] = lttv_state_find_process(self
, i
, pid
);
1732 g_assert(self
->running_process
[i
] != NULL
);
1735 nb_tracefile
= self
->parent
.tracefiles
->len
;
1737 //g_tree_destroy(tsc->pqueue);
1738 //tsc->pqueue = g_tree_new(compare_tracefile);
1740 /* restore cpu resource states */
1741 type
= lttv_attribute_get_by_name(container
, LTTV_STATE_RESOURCE_CPUS
, &value
);
1742 g_assert(type
== LTTV_POINTER
);
1743 lttv_state_free_cpu_states(self
->cpu_states
, nb_cpus
);
1744 self
->cpu_states
= lttv_state_copy_cpu_states(*(value
.v_pointer
), nb_cpus
);
1746 /* restore irq resource states */
1747 nb_irqs
= self
->name_tables
->nb_irqs
;
1748 type
= lttv_attribute_get_by_name(container
, LTTV_STATE_RESOURCE_IRQS
, &value
);
1749 g_assert(type
== LTTV_POINTER
);
1750 lttv_state_free_irq_states(self
->irq_states
, nb_irqs
);
1751 self
->irq_states
= lttv_state_copy_irq_states(*(value
.v_pointer
), nb_irqs
);
1753 /* restore soft irq resource states */
1754 nb_soft_irqs
= self
->name_tables
->nb_soft_irqs
;
1755 type
= lttv_attribute_get_by_name(container
, LTTV_STATE_RESOURCE_SOFT_IRQS
, &value
);
1756 g_assert(type
== LTTV_POINTER
);
1757 lttv_state_free_soft_irq_states(self
->soft_irq_states
, nb_soft_irqs
);
1758 self
->soft_irq_states
= lttv_state_copy_soft_irq_states(*(value
.v_pointer
), nb_soft_irqs
);
1760 /* restore trap resource states */
1761 nb_traps
= self
->name_tables
->nb_traps
;
1762 type
= lttv_attribute_get_by_name(container
, LTTV_STATE_RESOURCE_TRAPS
, &value
);
1763 g_assert(type
== LTTV_POINTER
);
1764 lttv_state_free_trap_states(self
->trap_states
, nb_traps
);
1765 self
->trap_states
= lttv_state_copy_trap_states(*(value
.v_pointer
), nb_traps
);
1767 /* restore the blkdev states */
1768 type
= lttv_attribute_get_by_name(container
, LTTV_STATE_RESOURCE_BLKDEVS
, &value
);
1769 g_assert(type
== LTTV_POINTER
);
1770 lttv_state_free_blkdev_hashtable(self
->bdev_states
);
1771 self
->bdev_states
= lttv_state_copy_blkdev_hashtable(*(value
.v_pointer
));
1773 for(i
= 0 ; i
< nb_tracefile
; i
++) {
1775 LTTV_TRACEFILE_STATE(g_array_index(self
->parent
.tracefiles
,
1776 LttvTracefileContext
*, i
));
1777 type
= lttv_attribute_get(tracefiles_tree
, i
, &name
, &value
, &is_named
);
1778 g_assert(type
== LTTV_GOBJECT
);
1779 tracefile_tree
= *((LttvAttribute
**)(value
.v_gobject
));
1781 type
= lttv_attribute_get_by_name(tracefile_tree
, LTTV_STATE_PROCESS
,
1783 g_assert(type
== LTTV_UINT
);
1784 pid
= *(value
.v_uint
);
1785 tfcs
->process
= lttv_state_find_process_or_create(tfcs
, pid
);
1787 type
= lttv_attribute_get_by_name(tracefile_tree
, LTTV_STATE_EVENT
,
1789 g_assert(type
== LTTV_POINTER
);
1790 //g_assert(*(value.v_pointer) != NULL);
1791 ep
= *(value
.v_pointer
);
1792 g_assert(tfcs
->parent
.t_context
!= NULL
);
1794 tfcs
->cpu_state
= &self
->cpu_states
[tfcs
->cpu
];
1796 LttvTracefileContext
*tfc
= LTTV_TRACEFILE_CONTEXT(tfcs
);
1797 g_tree_remove(tsc
->pqueue
, tfc
);
1800 retval
= ltt_tracefile_seek_position(tfc
->tf
, ep
);
1801 g_assert_cmpint(retval
, ==, 0);
1802 tfc
->timestamp
= ltt_event_time(ltt_tracefile_get_event(tfc
->tf
));
1803 g_assert_cmpint(ltt_time_compare(tfc
->timestamp
, ltt_time_infinite
), !=, 0);
1804 g_tree_insert(tsc
->pqueue
, tfc
, tfc
);
1805 g_info("Restoring state for a tf at time %lu.%lu", tfc
->timestamp
.tv_sec
, tfc
->timestamp
.tv_nsec
);
1807 tfc
->timestamp
= ltt_time_infinite
;
1813 static void state_saved_free(LttvTraceState
*self
, LttvAttribute
*container
)
1815 guint i
, nb_tracefile
, nb_cpus
, nb_irqs
, nb_soft_irqs
;
1817 LttvTracefileState
*tfcs
;
1819 LttvAttribute
*tracefiles_tree
, *tracefile_tree
;
1821 guint
*running_process
;
1823 LttvAttributeType type
;
1825 LttvAttributeValue value
;
1827 LttvAttributeName name
;
1831 tracefiles_tree
= lttv_attribute_find_subdir(container
,
1832 LTTV_STATE_TRACEFILES
);
1833 g_object_ref(G_OBJECT(tracefiles_tree
));
1834 lttv_attribute_remove_by_name(container
, LTTV_STATE_TRACEFILES
);
1836 type
= lttv_attribute_get_by_name(container
, LTTV_STATE_PROCESSES
,
1838 g_assert(type
== LTTV_POINTER
);
1839 lttv_state_free_process_table(*(value
.v_pointer
));
1840 *(value
.v_pointer
) = NULL
;
1841 lttv_attribute_remove_by_name(container
, LTTV_STATE_PROCESSES
);
1843 /* Free running processes array */
1844 type
= lttv_attribute_get_by_name(container
, LTTV_STATE_RUNNING_PROCESS
,
1846 g_assert(type
== LTTV_POINTER
);
1847 running_process
= *(value
.v_pointer
);
1848 g_free(running_process
);
1850 /* free cpu resource states */
1851 type
= lttv_attribute_get_by_name(container
, LTTV_STATE_RESOURCE_CPUS_COUNT
, &value
);
1852 g_assert(type
== LTTV_UINT
);
1853 nb_cpus
= *value
.v_uint
;
1854 type
= lttv_attribute_get_by_name(container
, LTTV_STATE_RESOURCE_CPUS
, &value
);
1855 g_assert(type
== LTTV_POINTER
);
1856 lttv_state_free_cpu_states(*(value
.v_pointer
), nb_cpus
);
1858 /* free irq resource states */
1859 nb_irqs
= self
->name_tables
->nb_irqs
;
1860 type
= lttv_attribute_get_by_name(container
, LTTV_STATE_RESOURCE_IRQS
, &value
);
1861 g_assert(type
== LTTV_POINTER
);
1862 lttv_state_free_irq_states(*(value
.v_pointer
), nb_irqs
);
1864 /* free softirq resource states */
1865 nb_soft_irqs
= self
->name_tables
->nb_soft_irqs
;
1866 type
= lttv_attribute_get_by_name(container
, LTTV_STATE_RESOURCE_SOFT_IRQS
, &value
);
1867 g_assert(type
== LTTV_POINTER
);
1868 lttv_state_free_soft_irq_states(*(value
.v_pointer
), nb_soft_irqs
);
1870 /* free the blkdev states */
1871 type
= lttv_attribute_get_by_name(container
, LTTV_STATE_RESOURCE_BLKDEVS
, &value
);
1872 g_assert(type
== LTTV_POINTER
);
1873 lttv_state_free_blkdev_hashtable(*(value
.v_pointer
));
1875 nb_tracefile
= self
->parent
.tracefiles
->len
;
1877 for(i
= 0 ; i
< nb_tracefile
; i
++) {
1879 LTTV_TRACEFILE_STATE(g_array_index(self
->parent
.tracefiles
,
1880 LttvTracefileContext
*, i
));
1881 type
= lttv_attribute_get(tracefiles_tree
, i
, &name
, &value
, &is_named
);
1882 g_assert(type
== LTTV_GOBJECT
);
1883 tracefile_tree
= *((LttvAttribute
**)(value
.v_gobject
));
1885 type
= lttv_attribute_get_by_name(tracefile_tree
, LTTV_STATE_EVENT
,
1887 g_assert(type
== LTTV_POINTER
);
1888 if(*(value
.v_pointer
) != NULL
) g_free(*(value
.v_pointer
));
1890 g_object_unref(G_OBJECT(tracefiles_tree
));
1894 static void free_saved_state(LttvTraceState
*self
)
1898 LttvAttributeType type
;
1900 LttvAttributeValue value
;
1902 LttvAttributeName name
;
1906 LttvAttribute
*saved_states
;
1908 saved_states
= lttv_attribute_find_subdir(self
->parent
.t_a
,
1909 LTTV_STATE_SAVED_STATES
);
1911 nb
= lttv_attribute_get_number(saved_states
);
1912 for(i
= 0 ; i
< nb
; i
++) {
1913 type
= lttv_attribute_get(saved_states
, i
, &name
, &value
, &is_named
);
1914 g_assert(type
== LTTV_GOBJECT
);
1915 state_saved_free(self
, *((LttvAttribute
**)value
.v_gobject
));
1918 lttv_attribute_remove_by_name(self
->parent
.t_a
, LTTV_STATE_SAVED_STATES
);
1923 create_max_time(LttvTraceState
*tcs
)
1925 LttvAttributeValue v
;
1927 lttv_attribute_find(tcs
->parent
.t_a
, LTTV_STATE_SAVED_STATES_TIME
,
1929 g_assert(*(v
.v_pointer
) == NULL
);
1930 *(v
.v_pointer
) = g_new(LttTime
,1);
1931 *((LttTime
*)*(v
.v_pointer
)) = ltt_time_zero
;
1936 get_max_time(LttvTraceState
*tcs
)
1938 LttvAttributeValue v
;
1940 lttv_attribute_find(tcs
->parent
.t_a
, LTTV_STATE_SAVED_STATES_TIME
,
1942 g_assert(*(v
.v_pointer
) != NULL
);
1943 tcs
->max_time_state_recomputed_in_seek
= (LttTime
*)*(v
.v_pointer
);
1948 free_max_time(LttvTraceState
*tcs
)
1950 LttvAttributeValue v
;
1952 lttv_attribute_find(tcs
->parent
.t_a
, LTTV_STATE_SAVED_STATES_TIME
,
1954 g_free(*(v
.v_pointer
));
1955 *(v
.v_pointer
) = NULL
;
1959 create_name_tables(LttvTraceState
*tcs
)
1963 GString
*fe_name
= g_string_new("");
1965 LttvNameTables
*name_tables
= g_new(LttvNameTables
, 1);
1967 LttvAttributeValue v
;
1971 lttv_attribute_find(tcs
->parent
.t_a
, LTTV_STATE_NAME_TABLES
,
1973 g_assert(*(v
.v_pointer
) == NULL
);
1974 *(v
.v_pointer
) = name_tables
;
1976 hooks
= g_array_sized_new(FALSE
, FALSE
, sizeof(LttvTraceHook
), 1);
1978 if(!lttv_trace_find_hook(tcs
->parent
.t
,
1980 LTT_EVENT_SYSCALL_ENTRY
,
1981 FIELD_ARRAY(LTT_FIELD_SYSCALL_ID
),
1982 NULL
, NULL
, &hooks
)) {
1984 // th = lttv_trace_hook_get_first(&th);
1986 // t = ltt_field_type(lttv_trace_get_hook_field(th, 0));
1987 // nb = ltt_type_element_number(t);
1989 // name_tables->syscall_names = g_new(GQuark, nb);
1990 // name_tables->nb_syscalls = nb;
1992 // for(i = 0 ; i < nb ; i++) {
1993 // name_tables->syscall_names[i] = ltt_enum_string_get(t, i);
1994 // if(!name_tables->syscall_names[i]) {
1995 // GString *string = g_string_new("");
1996 // g_string_printf(string, "syscall %u", i);
1997 // name_tables->syscall_names[i] = g_quark_from_string(string->str);
1998 // g_string_free(string, TRUE);
2002 name_tables
->nb_syscalls
= 256;
2003 name_tables
->syscall_names
= g_new(GQuark
, 256);
2004 for(i
= 0 ; i
< 256 ; i
++) {
2005 g_string_printf(fe_name
, "syscall %d", i
);
2006 name_tables
->syscall_names
[i
] = g_quark_from_string(fe_name
->str
);
2009 name_tables
->syscall_names
= NULL
;
2010 name_tables
->nb_syscalls
= 0;
2012 lttv_trace_hook_remove_all(&hooks
);
2014 if(!lttv_trace_find_hook(tcs
->parent
.t
,
2016 LTT_EVENT_TRAP_ENTRY
,
2017 FIELD_ARRAY(LTT_FIELD_TRAP_ID
),
2018 NULL
, NULL
, &hooks
) ||
2019 !lttv_trace_find_hook(tcs
->parent
.t
,
2021 LTT_EVENT_PAGE_FAULT_ENTRY
,
2022 FIELD_ARRAY(LTT_FIELD_TRAP_ID
),
2023 NULL
, NULL
, &hooks
)) {
2025 // th = lttv_trace_hook_get_first(&th);
2027 // t = ltt_field_type(lttv_trace_get_hook_field(th, 0));
2028 // //nb = ltt_type_element_number(t);
2030 // name_tables->trap_names = g_new(GQuark, nb);
2031 // for(i = 0 ; i < nb ; i++) {
2032 // name_tables->trap_names[i] = g_quark_from_string(
2033 // ltt_enum_string_get(t, i));
2036 name_tables
->nb_traps
= 256;
2037 name_tables
->trap_names
= g_new(GQuark
, 256);
2038 for(i
= 0 ; i
< 256 ; i
++) {
2039 g_string_printf(fe_name
, "trap %d", i
);
2040 name_tables
->trap_names
[i
] = g_quark_from_string(fe_name
->str
);
2043 name_tables
->trap_names
= NULL
;
2044 name_tables
->nb_traps
= 0;
2046 lttv_trace_hook_remove_all(&hooks
);
2048 if(!lttv_trace_find_hook(tcs
->parent
.t
,
2050 LTT_EVENT_IRQ_ENTRY
,
2051 FIELD_ARRAY(LTT_FIELD_IRQ_ID
),
2052 NULL
, NULL
, &hooks
)) {
2055 name_tables->irq_names = g_new(GQuark, nb);
2056 for(i = 0 ; i < nb ; i++) {
2057 name_tables->irq_names[i] = g_quark_from_string(ltt_enum_string_get(t, i));
2061 name_tables
->nb_irqs
= 256;
2062 name_tables
->irq_names
= g_new(GQuark
, 256);
2063 for(i
= 0 ; i
< 256 ; i
++) {
2064 g_string_printf(fe_name
, "irq %d", i
);
2065 name_tables
->irq_names
[i
] = g_quark_from_string(fe_name
->str
);
2068 name_tables
->nb_irqs
= 0;
2069 name_tables
->irq_names
= NULL
;
2071 lttv_trace_hook_remove_all(&hooks
);
2073 name_tables->soft_irq_names = g_new(GQuark, nb);
2074 for(i = 0 ; i < nb ; i++) {
2075 name_tables->soft_irq_names[i] = g_quark_from_string(ltt_enum_string_get(t, i));
2079 /* the kernel is limited to 32 statically defined softirqs */
2080 name_tables
->nb_soft_irqs
= 32;
2081 name_tables
->soft_irq_names
= g_new(GQuark
, name_tables
->nb_soft_irqs
);
2082 for(i
= 0 ; i
< name_tables
->nb_soft_irqs
; i
++) {
2083 g_string_printf(fe_name
, "softirq %d", i
);
2084 name_tables
->soft_irq_names
[i
] = g_quark_from_string(fe_name
->str
);
2086 g_array_free(hooks
, TRUE
);
2088 g_string_free(fe_name
, TRUE
);
2090 #if (__WORDSIZE == 32)
2091 name_tables
->kprobe_hash
= g_hash_table_new_full(guint64_hash
, guint64_equal
,
2094 name_tables
->kprobe_hash
= g_hash_table_new(g_direct_hash
, g_direct_equal
);
2100 get_name_tables(LttvTraceState
*tcs
)
2102 LttvAttributeValue v
;
2104 lttv_attribute_find(tcs
->parent
.t_a
, LTTV_STATE_NAME_TABLES
,
2106 g_assert(*(v
.v_pointer
) != NULL
);
2107 tcs
->name_tables
= (LttvNameTables
*)*(v
.v_pointer
);
2112 free_name_tables(LttvTraceState
*tcs
)
2114 LttvNameTables
*name_tables
;
2116 LttvAttributeValue v
;
2118 lttv_attribute_find(tcs
->parent
.t_a
, LTTV_STATE_NAME_TABLES
,
2120 name_tables
= (LttvNameTables
*)*(v
.v_pointer
);
2121 *(v
.v_pointer
) = NULL
;
2123 // g_free(name_tables->eventtype_names);
2124 if(name_tables
->syscall_names
) g_free(name_tables
->syscall_names
);
2125 if(name_tables
->trap_names
) g_free(name_tables
->trap_names
);
2126 if(name_tables
->irq_names
) g_free(name_tables
->irq_names
);
2127 if(name_tables
->soft_irq_names
) g_free(name_tables
->soft_irq_names
);
2128 g_hash_table_destroy(name_tables
->kprobe_hash
);
2129 g_free(name_tables
);
2132 #ifdef HASH_TABLE_DEBUG
2134 static void test_process(gpointer key
, gpointer value
, gpointer user_data
)
2136 LttvProcessState
*process
= (LttvProcessState
*)value
;
2138 /* Test for process corruption */
2139 guint stack_len
= process
->execution_stack
->len
;
2142 static void hash_table_check(GHashTable
*table
)
2144 g_hash_table_foreach(table
, test_process
, NULL
);
2150 /* clears the stack and sets the state passed as argument */
2151 static void cpu_set_base_mode(LttvCPUState
*cpust
, LttvCPUMode state
)
2153 g_array_set_size(cpust
->mode_stack
, 1);
2154 ((GQuark
*)cpust
->mode_stack
->data
)[0] = state
;
2157 static void cpu_push_mode(LttvCPUState
*cpust
, LttvCPUMode state
)
2159 g_array_set_size(cpust
->mode_stack
, cpust
->mode_stack
->len
+ 1);
2160 ((GQuark
*)cpust
->mode_stack
->data
)[cpust
->mode_stack
->len
- 1] = state
;
2163 static void cpu_pop_mode(LttvCPUState
*cpust
)
2165 if(cpust
->mode_stack
->len
<= 1)
2166 cpu_set_base_mode(cpust
, LTTV_CPU_UNKNOWN
);
2168 g_array_set_size(cpust
->mode_stack
, cpust
->mode_stack
->len
- 1);
2171 /* clears the stack and sets the state passed as argument */
2172 static void bdev_set_base_mode(LttvBdevState
*bdevst
, LttvBdevMode state
)
2174 g_array_set_size(bdevst
->mode_stack
, 1);
2175 ((GQuark
*)bdevst
->mode_stack
->data
)[0] = state
;
2178 static void bdev_push_mode(LttvBdevState
*bdevst
, LttvBdevMode state
)
2180 g_array_set_size(bdevst
->mode_stack
, bdevst
->mode_stack
->len
+ 1);
2181 ((GQuark
*)bdevst
->mode_stack
->data
)[bdevst
->mode_stack
->len
- 1] = state
;
2184 static void bdev_pop_mode(LttvBdevState
*bdevst
)
2186 if(bdevst
->mode_stack
->len
<= 1)
2187 bdev_set_base_mode(bdevst
, LTTV_BDEV_UNKNOWN
);
2189 g_array_set_size(bdevst
->mode_stack
, bdevst
->mode_stack
->len
- 1);
2192 static void irq_set_base_mode(LttvIRQState
*irqst
, LttvIRQMode state
)
2194 g_array_set_size(irqst
->mode_stack
, 1);
2195 ((GQuark
*)irqst
->mode_stack
->data
)[0] = state
;
2198 static void irq_push_mode(LttvIRQState
*irqst
, LttvIRQMode state
)
2200 g_array_set_size(irqst
->mode_stack
, irqst
->mode_stack
->len
+ 1);
2201 ((GQuark
*)irqst
->mode_stack
->data
)[irqst
->mode_stack
->len
- 1] = state
;
2204 static void irq_pop_mode(LttvIRQState
*irqst
)
2206 if(irqst
->mode_stack
->len
<= 1)
2207 irq_set_base_mode(irqst
, LTTV_IRQ_UNKNOWN
);
2209 g_array_set_size(irqst
->mode_stack
, irqst
->mode_stack
->len
- 1);
2212 static void push_state(LttvTracefileState
*tfs
, LttvExecutionMode t
,
2215 LttvExecutionState
*es
;
2217 LttvTraceState
*ts
= (LttvTraceState
*)tfs
->parent
.t_context
;
2218 guint cpu
= tfs
->cpu
;
2220 #ifdef HASH_TABLE_DEBUG
2221 hash_table_check(ts
->processes
);
2223 LttvProcessState
*process
= ts
->running_process
[cpu
];
2225 guint depth
= process
->execution_stack
->len
;
2227 process
->execution_stack
=
2228 g_array_set_size(process
->execution_stack
, depth
+ 1);
2231 &g_array_index(process
->execution_stack
, LttvExecutionState
, depth
- 1);
2233 es
= &g_array_index(process
->execution_stack
, LttvExecutionState
, depth
);
2236 es
->entry
= es
->change
= tfs
->parent
.timestamp
;
2237 es
->cum_cpu_time
= ltt_time_zero
;
2238 es
->s
= process
->state
->s
;
2239 process
->state
= es
;
2243 * return 1 when empty, else 0 */
2244 int lttv_state_pop_state_cleanup(LttvProcessState
*process
,
2245 LttvTracefileState
*tfs
)
2247 guint depth
= process
->execution_stack
->len
;
2253 process
->execution_stack
=
2254 g_array_set_size(process
->execution_stack
, depth
- 1);
2255 process
->state
= &g_array_index(process
->execution_stack
, LttvExecutionState
,
2257 process
->state
->change
= tfs
->parent
.timestamp
;
2262 static void pop_state(LttvTracefileState
*tfs
, LttvExecutionMode t
)
2264 guint cpu
= tfs
->cpu
;
2265 LttvTraceState
*ts
= (LttvTraceState
*)tfs
->parent
.t_context
;
2266 LttvProcessState
*process
= ts
->running_process
[cpu
];
2268 guint depth
= process
->execution_stack
->len
;
2270 if(process
->state
->t
!= t
){
2271 g_info("Different execution mode type (%lu.%09lu): ignore it\n",
2272 tfs
->parent
.timestamp
.tv_sec
, tfs
->parent
.timestamp
.tv_nsec
);
2273 g_info("process state has %s when pop_int is %s\n",
2274 g_quark_to_string(process
->state
->t
),
2275 g_quark_to_string(t
));
2276 g_info("{ %u, %u, %s, %s, %s }\n",
2279 g_quark_to_string(process
->name
),
2280 g_quark_to_string(process
->brand
),
2281 g_quark_to_string(process
->state
->s
));
2286 g_info("Trying to pop last state on stack (%lu.%09lu): ignore it\n",
2287 tfs
->parent
.timestamp
.tv_sec
, tfs
->parent
.timestamp
.tv_nsec
);
2291 process
->execution_stack
=
2292 g_array_set_size(process
->execution_stack
, depth
- 1);
2293 process
->state
= &g_array_index(process
->execution_stack
, LttvExecutionState
,
2295 process
->state
->change
= tfs
->parent
.timestamp
;
2298 struct search_result
{
2299 const LttTime
*time
; /* Requested time */
2300 LttTime
*best
; /* Best result */
2303 static gint
search_usertrace(gconstpointer a
, gconstpointer b
)
2305 const LttTime
*elem_time
= (const LttTime
*)a
;
2306 /* Explicit non const cast */
2307 struct search_result
*res
= (struct search_result
*)b
;
2309 if(ltt_time_compare(*elem_time
, *(res
->time
)) < 0) {
2310 /* The usertrace was created before the schedchange */
2311 /* Get larger keys */
2313 } else if(ltt_time_compare(*elem_time
, *(res
->time
)) >= 0) {
2314 /* The usertrace was created after the schedchange time */
2315 /* Get smaller keys */
2317 if(ltt_time_compare(*elem_time
, *res
->best
) < 0) {
2318 res
->best
= (LttTime
*)elem_time
;
2321 res
->best
= (LttTime
*)elem_time
;
2328 static LttvTracefileState
*ltt_state_usertrace_find(LttvTraceState
*tcs
,
2329 guint pid
, const LttTime
*timestamp
)
2331 LttvTracefileState
*tfs
= NULL
;
2332 struct search_result res
;
2333 /* Find the usertrace associated with a pid and time interval.
2334 * Search in the usertraces by PID (within a hash) and then, for each
2335 * corresponding element of the array, find the first one with creation
2336 * timestamp the lowest, but higher or equal to "timestamp". */
2337 res
.time
= timestamp
;
2339 GTree
*usertrace_tree
= g_hash_table_lookup(tcs
->usertraces
,
2340 GUINT_TO_POINTER(pid
));
2341 if(usertrace_tree
) {
2342 g_tree_search(usertrace_tree
, search_usertrace
, &res
);
2344 tfs
= g_tree_lookup(usertrace_tree
, res
.best
);
2350 /* Return a new and initialized LttvProcessState structure */
2353 lttv_state_create_process(LttvTraceState
*tcs
, LttvProcessState
*parent
,
2354 guint cpu
, guint pid
, guint tgid
, GQuark name
, const LttTime
*timestamp
)
2356 LttvProcessState
*process
= g_new(LttvProcessState
, 1);
2358 LttvExecutionState
*es
;
2363 process
->tgid
= tgid
;
2365 process
->name
= name
;
2366 process
->brand
= LTTV_STATE_UNBRANDED
;
2367 //process->last_cpu = tfs->cpu_name;
2368 //process->last_cpu_index = ltt_tracefile_num(((LttvTracefileContext*)tfs)->tf);
2369 process
->type
= LTTV_STATE_USER_THREAD
;
2370 process
->usertrace
= ltt_state_usertrace_find(tcs
, pid
, timestamp
);
2371 process
->current_function
= 0; //function 0x0 by default.
2373 g_info("Process %u, core %p", process
->pid
, process
);
2374 g_hash_table_insert(tcs
->processes
, process
, process
);
2377 process
->ppid
= parent
->pid
;
2378 process
->creation_time
= *timestamp
;
2381 /* No parent. This process exists but we are missing all information about
2382 its creation. The birth time is set to zero but we remember the time of
2387 process
->creation_time
= ltt_time_zero
;
2390 process
->insertion_time
= *timestamp
;
2391 sprintf(buffer
,"%d-%lu.%lu",pid
, process
->creation_time
.tv_sec
,
2392 process
->creation_time
.tv_nsec
);
2393 process
->pid_time
= g_quark_from_string(buffer
);
2395 process
->free_events
= 0;
2396 //process->last_cpu = tfs->cpu_name;
2397 //process->last_cpu_index = ltt_tracefile_num(((LttvTracefileContext*)tfs)->tf);
2398 process
->execution_stack
= g_array_sized_new(FALSE
, FALSE
,
2399 sizeof(LttvExecutionState
), PREALLOCATED_EXECUTION_STACK
);
2400 process
->execution_stack
= g_array_set_size(process
->execution_stack
, 2);
2401 es
= process
->state
= &g_array_index(process
->execution_stack
,
2402 LttvExecutionState
, 0);
2403 es
->t
= LTTV_STATE_USER_MODE
;
2404 es
->n
= LTTV_STATE_SUBMODE_NONE
;
2405 es
->entry
= *timestamp
;
2406 //g_assert(timestamp->tv_sec != 0);
2407 es
->change
= *timestamp
;
2408 es
->cum_cpu_time
= ltt_time_zero
;
2409 es
->s
= LTTV_STATE_RUN
;
2411 es
= process
->state
= &g_array_index(process
->execution_stack
,
2412 LttvExecutionState
, 1);
2413 es
->t
= LTTV_STATE_SYSCALL
;
2414 es
->n
= LTTV_STATE_SUBMODE_NONE
;
2415 es
->entry
= *timestamp
;
2416 //g_assert(timestamp->tv_sec != 0);
2417 es
->change
= *timestamp
;
2418 es
->cum_cpu_time
= ltt_time_zero
;
2419 es
->s
= LTTV_STATE_WAIT_FORK
;
2421 /* Allocate an empty function call stack. If it's empty, use 0x0. */
2422 process
->user_stack
= g_array_sized_new(FALSE
, FALSE
,
2423 sizeof(guint64
), 0);
2425 process
->fds
= g_hash_table_new(g_direct_hash
, g_direct_equal
);
2430 LttvProcessState
*lttv_state_find_process(LttvTraceState
*ts
, guint cpu
,
2433 LttvProcessState key
;
2434 LttvProcessState
*process
;
2438 process
= g_hash_table_lookup(ts
->processes
, &key
);
2443 lttv_state_find_process_or_create(LttvTraceState
*ts
, guint cpu
, guint pid
,
2444 const LttTime
*timestamp
)
2446 LttvProcessState
*process
= lttv_state_find_process(ts
, cpu
, pid
);
2447 LttvExecutionState
*es
;
2449 /* Put ltt_time_zero creation time for unexisting processes */
2450 if(unlikely(process
== NULL
)) {
2451 process
= lttv_state_create_process(ts
,
2452 NULL
, cpu
, pid
, 0, LTTV_STATE_UNNAMED
, timestamp
);
2453 /* We are not sure is it's a kernel thread or normal thread, put the
2454 * bottom stack state to unknown */
2455 process
->execution_stack
=
2456 g_array_set_size(process
->execution_stack
, 1);
2457 process
->state
= es
=
2458 &g_array_index(process
->execution_stack
, LttvExecutionState
, 0);
2459 es
->t
= LTTV_STATE_MODE_UNKNOWN
;
2460 es
->s
= LTTV_STATE_UNNAMED
;
2465 /* FIXME : this function should be called when we receive an event telling that
2466 * release_task has been called in the kernel. In happens generally when
2467 * the parent waits for its child termination, but may also happens in special
2468 * cases in the child's exit : when the parent ignores its children SIGCCHLD or
2469 * has the flag SA_NOCLDWAIT. It can also happen when the child is part
2470 * of a killed thread group, but isn't the leader.
2472 static int exit_process(LttvTracefileState
*tfs
, LttvProcessState
*process
)
2474 LttvTraceState
*ts
= LTTV_TRACE_STATE(tfs
->parent
.t_context
);
2475 LttvProcessState key
;
2477 /* Wait for both schedule with exit dead and process free to happen.
2478 * They can happen in any order. */
2479 if (++(process
->free_events
) < 2)
2482 key
.pid
= process
->pid
;
2483 key
.cpu
= process
->cpu
;
2484 g_hash_table_remove(ts
->processes
, &key
);
2485 g_array_free(process
->execution_stack
, TRUE
);
2486 g_array_free(process
->user_stack
, TRUE
);
2488 /* the following also clears the content */
2489 g_hash_table_destroy(process
->fds
);
2496 static void free_process_state(gpointer key
, gpointer value
,gpointer user_data
)
2498 g_array_free(((LttvProcessState
*)value
)->execution_stack
, TRUE
);
2499 g_array_free(((LttvProcessState
*)value
)->user_stack
, TRUE
);
2501 /* the following also clears the content */
2502 g_hash_table_destroy(((LttvProcessState
*)value
)->fds
);
2508 static void lttv_state_free_process_table(GHashTable
*processes
)
2510 g_hash_table_foreach(processes
, free_process_state
, NULL
);
2511 g_hash_table_destroy(processes
);
2515 static gboolean
syscall_entry(void *hook_data
, void *call_data
)
2517 LttvTracefileState
*s
= (LttvTracefileState
*)call_data
;
2519 LttvTraceState
*ts
= (LttvTraceState
*)s
->parent
.t_context
;
2520 LttvProcessState
*process
= ts
->running_process
[cpu
];
2521 LttEvent
*e
= ltt_tracefile_get_event(s
->parent
.tf
);
2522 LttvTraceHook
*th
= (LttvTraceHook
*)hook_data
;
2523 struct marker_field
*f
= lttv_trace_get_hook_field(th
, 0);
2524 LttvExecutionSubmode submode
;
2525 LttvNameTables
*nt
= ((LttvTraceState
*)(s
->parent
.t_context
))->name_tables
;
2527 guint syscall
= ltt_event_get_unsigned(e
, f
);
2528 expand_syscall_table(ts
, syscall
);
2529 submode
= nt
->syscall_names
[syscall
];
2530 /* There can be no system call from PID 0 : unknown state */
2531 if(process
->pid
!= 0)
2532 push_state(s
, LTTV_STATE_SYSCALL
, submode
);
2537 static gboolean
syscall_exit(void *hook_data
, void *call_data
)
2539 LttvTracefileState
*s
= (LttvTracefileState
*)call_data
;
2541 LttvTraceState
*ts
= (LttvTraceState
*)s
->parent
.t_context
;
2542 LttvProcessState
*process
= ts
->running_process
[cpu
];
2544 /* There can be no system call from PID 0 : unknown state */
2545 if(process
->pid
!= 0)
2546 pop_state(s
, LTTV_STATE_SYSCALL
);
2551 static gboolean
trap_entry(void *hook_data
, void *call_data
)
2553 LttvTracefileState
*s
= (LttvTracefileState
*)call_data
;
2554 LttvTraceState
*ts
= (LttvTraceState
*)s
->parent
.t_context
;
2555 LttEvent
*e
= ltt_tracefile_get_event(s
->parent
.tf
);
2556 LttvTraceHook
*th
= (LttvTraceHook
*)hook_data
;
2557 struct marker_field
*f
= lttv_trace_get_hook_field(th
, 0);
2558 LttvNameTables
*nt
= ((LttvTraceState
*)(s
->parent
.t_context
))->name_tables
;
2560 LttvExecutionSubmode submode
;
2562 guint64 trap
= ltt_event_get_long_unsigned(e
, f
);
2564 expand_trap_table(ts
, trap
);
2566 submode
= nt
->trap_names
[trap
];
2568 push_state(s
, LTTV_STATE_TRAP
, submode
);
2570 /* update cpu status */
2571 cpu_push_mode(s
->cpu_state
, LTTV_CPU_TRAP
);
2573 /* update trap status */
2574 g_array_append_val(s
->cpu_state
->trap_stack
, trap
);
2575 ts
->trap_states
[trap
].running
++;
2580 static gboolean
trap_exit(void *hook_data
, void *call_data
)
2582 LttvTracefileState
*s
= (LttvTracefileState
*)call_data
;
2583 LttvTraceState
*ts
= (LttvTraceState
*)s
->parent
.t_context
;
2585 pop_state(s
, LTTV_STATE_TRAP
);
2587 /* update cpu status */
2588 cpu_pop_mode(s
->cpu_state
);
2590 /* update trap status */
2591 if (s
->cpu_state
->trap_stack
->len
> 0) {
2592 gint last
= g_array_index(s
->cpu_state
->trap_stack
, gint
, s
->cpu_state
->trap_stack
->len
-1);
2593 if(ts
->trap_states
[last
].running
)
2594 ts
->trap_states
[last
].running
--;
2595 g_array_remove_index(s
->cpu_state
->trap_stack
, s
->cpu_state
->trap_stack
->len
-1);
2600 static gboolean
irq_entry(void *hook_data
, void *call_data
)
2602 LttvTracefileState
*s
= (LttvTracefileState
*)call_data
;
2603 LttvTraceState
*ts
= (LttvTraceState
*)s
->parent
.t_context
;
2604 LttEvent
*e
= ltt_tracefile_get_event(s
->parent
.tf
);
2605 //guint8 ev_id = ltt_event_eventtype_id(e);
2606 LttvTraceHook
*th
= (LttvTraceHook
*)hook_data
;
2607 struct marker_field
*f
= lttv_trace_get_hook_field(th
, 0);
2608 LttvNameTables
*nt
= ((LttvTraceState
*)(s
->parent
.t_context
))->name_tables
;
2610 LttvExecutionSubmode submode
;
2611 guint64 irq
= ltt_event_get_long_unsigned(e
, f
);
2613 expand_irq_table(ts
, irq
);
2615 submode
= nt
->irq_names
[irq
];
2617 /* Do something with the info about being in user or system mode when int? */
2618 push_state(s
, LTTV_STATE_IRQ
, submode
);
2620 /* update cpu status */
2621 cpu_push_mode(s
->cpu_state
, LTTV_CPU_IRQ
);
2623 /* update irq status */
2624 g_array_append_val(s
->cpu_state
->irq_stack
, irq
);
2625 irq_push_mode(&ts
->irq_states
[irq
], LTTV_IRQ_BUSY
);
2630 static gboolean
soft_irq_exit(void *hook_data
, void *call_data
)
2632 LttvTracefileState
*s
= (LttvTracefileState
*)call_data
;
2633 LttvTraceState
*ts
= (LttvTraceState
*)s
->parent
.t_context
;
2635 pop_state(s
, LTTV_STATE_SOFT_IRQ
);
2637 /* update cpu status */
2638 cpu_pop_mode(s
->cpu_state
);
2640 /* update softirq status */
2641 if (s
->cpu_state
->softirq_stack
->len
> 0) {
2642 gint last
= g_array_index(s
->cpu_state
->softirq_stack
, gint
, s
->cpu_state
->softirq_stack
->len
-1);
2643 if(ts
->soft_irq_states
[last
].running
)
2644 ts
->soft_irq_states
[last
].running
--;
2645 g_array_remove_index(s
->cpu_state
->softirq_stack
, s
->cpu_state
->softirq_stack
->len
-1);
2650 static gboolean
irq_exit(void *hook_data
, void *call_data
)
2652 LttvTracefileState
*s
= (LttvTracefileState
*)call_data
;
2653 LttvTraceState
*ts
= (LttvTraceState
*)s
->parent
.t_context
;
2655 pop_state(s
, LTTV_STATE_IRQ
);
2657 /* update cpu status */
2658 cpu_pop_mode(s
->cpu_state
);
2660 /* update irq status */
2661 if (s
->cpu_state
->irq_stack
->len
> 0) {
2662 gint last
= g_array_index(s
->cpu_state
->irq_stack
, gint
, s
->cpu_state
->irq_stack
->len
-1);
2663 g_array_remove_index(s
->cpu_state
->irq_stack
, s
->cpu_state
->irq_stack
->len
-1);
2664 irq_pop_mode(&ts
->irq_states
[last
]);
2670 static gboolean
soft_irq_raise(void *hook_data
, void *call_data
)
2672 LttvTracefileState
*s
= (LttvTracefileState
*)call_data
;
2673 LttvTraceState
*ts
= (LttvTraceState
*)s
->parent
.t_context
;
2674 LttEvent
*e
= ltt_tracefile_get_event(s
->parent
.tf
);
2675 //guint8 ev_id = ltt_event_eventtype_id(e);
2676 LttvTraceHook
*th
= (LttvTraceHook
*)hook_data
;
2677 struct marker_field
*f
= lttv_trace_get_hook_field(th
, 0);
2678 LttvNameTables
*nt
= ((LttvTraceState
*)(s
->parent
.t_context
))->name_tables
;
2680 LttvExecutionSubmode submode
;
2681 guint64 softirq
= ltt_event_get_long_unsigned(e
, f
);
2682 guint64 nb_softirqs
= nt
->nb_soft_irqs
;
2684 if(softirq
< nb_softirqs
) {
2685 submode
= nt
->soft_irq_names
[softirq
];
2687 /* Fixup an incomplete irq table */
2688 GString
*string
= g_string_new("");
2689 g_string_printf(string
, "softirq %" PRIu64
, softirq
);
2690 submode
= g_quark_from_string(string
->str
);
2691 g_string_free(string
, TRUE
);
2694 /* update softirq status */
2695 /* a soft irq raises are not cumulative */
2696 ts
->soft_irq_states
[softirq
].pending
=1;
2701 static gboolean
soft_irq_entry(void *hook_data
, void *call_data
)
2703 LttvTracefileState
*s
= (LttvTracefileState
*)call_data
;
2704 LttvTraceState
*ts
= (LttvTraceState
*)s
->parent
.t_context
;
2705 LttEvent
*e
= ltt_tracefile_get_event(s
->parent
.tf
);
2706 //guint8 ev_id = ltt_event_eventtype_id(e);
2707 LttvTraceHook
*th
= (LttvTraceHook
*)hook_data
;
2708 struct marker_field
*f
= lttv_trace_get_hook_field(th
, 0);
2709 LttvExecutionSubmode submode
;
2710 guint64 softirq
= ltt_event_get_long_unsigned(e
, f
);
2711 expand_soft_irq_table(ts
, softirq
);
2712 LttvNameTables
*nt
= ((LttvTraceState
*)(s
->parent
.t_context
))->name_tables
;
2713 submode
= nt
->soft_irq_names
[softirq
];
2715 /* Do something with the info about being in user or system mode when int? */
2716 push_state(s
, LTTV_STATE_SOFT_IRQ
, submode
);
2718 /* update cpu status */
2719 cpu_push_mode(s
->cpu_state
, LTTV_CPU_SOFT_IRQ
);
2721 /* update softirq status */
2722 g_array_append_val(s
->cpu_state
->softirq_stack
, softirq
);
2723 if(ts
->soft_irq_states
[softirq
].pending
)
2724 ts
->soft_irq_states
[softirq
].pending
--;
2725 ts
->soft_irq_states
[softirq
].running
++;
2730 static gboolean
enum_interrupt(void *hook_data
, void *call_data
)
2732 LttvTracefileState
*s
= (LttvTracefileState
*)call_data
;
2733 LttvTraceState
*ts
= (LttvTraceState
*)s
->parent
.t_context
;
2734 LttvNameTables
*nt
= ts
->name_tables
;
2735 LttEvent
*e
= ltt_tracefile_get_event(s
->parent
.tf
);
2736 //guint8 ev_id = ltt_event_eventtype_id(e);
2737 LttvTraceHook
*th
= (LttvTraceHook
*)hook_data
;
2739 GQuark action
= g_quark_from_string(ltt_event_get_string(e
,
2740 lttv_trace_get_hook_field(th
, 0)));
2741 guint irq
= ltt_event_get_long_unsigned(e
, lttv_trace_get_hook_field(th
, 1));
2743 expand_irq_table(ts
, irq
);
2744 nt
->irq_names
[irq
] = action
;
2750 static gboolean
bdev_request_issue(void *hook_data
, void *call_data
)
2752 LttvTracefileState
*s
= (LttvTracefileState
*)call_data
;
2753 LttvTraceState
*ts
= (LttvTraceState
*)s
->parent
.t_context
;
2754 LttEvent
*e
= ltt_tracefile_get_event(s
->parent
.tf
);
2755 //guint8 ev_id = ltt_event_eventtype_id(e);
2756 LttvTraceHook
*th
= (LttvTraceHook
*)hook_data
;
2758 guint major
= ltt_event_get_long_unsigned(e
,
2759 lttv_trace_get_hook_field(th
, 0));
2760 guint minor
= ltt_event_get_long_unsigned(e
,
2761 lttv_trace_get_hook_field(th
, 1));
2762 guint oper
= ltt_event_get_long_unsigned(e
,
2763 lttv_trace_get_hook_field(th
, 2));
2764 guint16 devcode
= MKDEV(major
,minor
);
2766 /* have we seen this block device before? */
2767 gpointer bdev
= get_hashed_bdevstate(ts
, devcode
);
2770 bdev_push_mode(bdev
, LTTV_BDEV_BUSY_READING
);
2772 bdev_push_mode(bdev
, LTTV_BDEV_BUSY_WRITING
);
2777 static gboolean
bdev_request_complete(void *hook_data
, void *call_data
)
2779 LttvTracefileState
*s
= (LttvTracefileState
*)call_data
;
2780 LttvTraceState
*ts
= (LttvTraceState
*)s
->parent
.t_context
;
2781 LttEvent
*e
= ltt_tracefile_get_event(s
->parent
.tf
);
2782 LttvTraceHook
*th
= (LttvTraceHook
*)hook_data
;
2784 guint major
= ltt_event_get_long_unsigned(e
,
2785 lttv_trace_get_hook_field(th
, 0));
2786 guint minor
= ltt_event_get_long_unsigned(e
,
2787 lttv_trace_get_hook_field(th
, 1));
2788 //guint oper = ltt_event_get_long_unsigned(e,
2789 // lttv_trace_get_hook_field(th, 2));
2790 guint16 devcode
= MKDEV(major
,minor
);
2792 /* have we seen this block device before? */
2793 gpointer bdev
= get_hashed_bdevstate(ts
, devcode
);
2795 /* update block device */
2796 bdev_pop_mode(bdev
);
2801 static void push_function(LttvTracefileState
*tfs
, guint64 funcptr
)
2805 LttvTraceState
*ts
= (LttvTraceState
*)tfs
->parent
.t_context
;
2806 guint cpu
= tfs
->cpu
;
2807 LttvProcessState
*process
= ts
->running_process
[cpu
];
2809 guint depth
= process
->user_stack
->len
;
2811 process
->user_stack
=
2812 g_array_set_size(process
->user_stack
, depth
+ 1);
2814 new_func
= &g_array_index(process
->user_stack
, guint64
, depth
);
2815 *new_func
= funcptr
;
2816 process
->current_function
= funcptr
;
2819 static void pop_function(LttvTracefileState
*tfs
, guint64 funcptr
)
2821 guint cpu
= tfs
->cpu
;
2822 LttvTraceState
*ts
= (LttvTraceState
*)tfs
->parent
.t_context
;
2823 LttvProcessState
*process
= ts
->running_process
[cpu
];
2825 if(process
->current_function
!= funcptr
){
2826 g_info("Different functions (%lu.%09lu): ignore it\n",
2827 tfs
->parent
.timestamp
.tv_sec
, tfs
->parent
.timestamp
.tv_nsec
);
2828 g_info("process state has %" PRIu64
" when pop_function is %" PRIu64
"\n",
2829 process
->current_function
, funcptr
);
2830 g_info("{ %u, %u, %s, %s, %s }\n",
2833 g_quark_to_string(process
->name
),
2834 g_quark_to_string(process
->brand
),
2835 g_quark_to_string(process
->state
->s
));
2838 guint depth
= process
->user_stack
->len
;
2841 g_info("Trying to pop last function on stack (%lu.%09lu): ignore it\n",
2842 tfs
->parent
.timestamp
.tv_sec
, tfs
->parent
.timestamp
.tv_nsec
);
2846 process
->user_stack
=
2847 g_array_set_size(process
->user_stack
, depth
- 1);
2848 process
->current_function
=
2849 g_array_index(process
->user_stack
, guint64
, depth
- 2);
2853 static gboolean
function_entry(void *hook_data
, void *call_data
)
2855 LttvTracefileState
*s
= (LttvTracefileState
*)call_data
;
2856 LttEvent
*e
= ltt_tracefile_get_event(s
->parent
.tf
);
2857 //guint8 ev_id = ltt_event_eventtype_id(e);
2858 LttvTraceHook
*th
= (LttvTraceHook
*)hook_data
;
2859 struct marker_field
*f
= lttv_trace_get_hook_field(th
, 0);
2860 guint64 funcptr
= ltt_event_get_long_unsigned(e
, f
);
2862 push_function(s
, funcptr
);
2866 static gboolean
function_exit(void *hook_data
, void *call_data
)
2868 LttvTracefileState
*s
= (LttvTracefileState
*)call_data
;
2869 LttEvent
*e
= ltt_tracefile_get_event(s
->parent
.tf
);
2870 //guint8 ev_id = ltt_event_eventtype_id(e);
2871 LttvTraceHook
*th
= (LttvTraceHook
*)hook_data
;
2872 struct marker_field
*f
= lttv_trace_get_hook_field(th
, 0);
2873 guint64 funcptr
= ltt_event_get_long_unsigned(e
, f
);
2875 pop_function(s
, funcptr
);
2879 static gboolean
dump_syscall(void *hook_data
, void *call_data
)
2881 LttvTracefileState
*s
= (LttvTracefileState
*)call_data
;
2882 LttvTraceState
*ts
= (LttvTraceState
*)s
->parent
.t_context
;
2883 LttvNameTables
*nt
= ts
->name_tables
;
2884 LttEvent
*e
= ltt_tracefile_get_event(s
->parent
.tf
);
2885 LttvTraceHook
*th
= (LttvTraceHook
*)hook_data
;
2890 id
= ltt_event_get_unsigned(e
, lttv_trace_get_hook_field(th
, 0));
2891 address
= ltt_event_get_long_unsigned(e
, lttv_trace_get_hook_field(th
, 1));
2892 symbol
= ltt_event_get_string(e
, lttv_trace_get_hook_field(th
, 2));
2894 expand_syscall_table(ts
, id
);
2895 nt
->syscall_names
[id
] = g_quark_from_string(symbol
);
2900 static gboolean
dump_kprobe(void *hook_data
, void *call_data
)
2902 LttvTracefileState
*s
= (LttvTracefileState
*)call_data
;
2903 LttvTraceState
*ts
= (LttvTraceState
*)s
->parent
.t_context
;
2904 LttEvent
*e
= ltt_tracefile_get_event(s
->parent
.tf
);
2905 LttvTraceHook
*th
= (LttvTraceHook
*)hook_data
;
2909 ip
= ltt_event_get_long_unsigned(e
, lttv_trace_get_hook_field(th
, 0));
2910 symbol
= ltt_event_get_string(e
, lttv_trace_get_hook_field(th
, 1));
2912 expand_kprobe_table(ts
, ip
, symbol
);
2917 static gboolean
dump_softirq(void *hook_data
, void *call_data
)
2919 LttvTracefileState
*s
= (LttvTracefileState
*)call_data
;
2920 LttvTraceState
*ts
= (LttvTraceState
*)s
->parent
.t_context
;
2921 LttvNameTables
*nt
= ts
->name_tables
;
2922 LttEvent
*e
= ltt_tracefile_get_event(s
->parent
.tf
);
2923 LttvTraceHook
*th
= (LttvTraceHook
*)hook_data
;
2928 id
= ltt_event_get_unsigned(e
, lttv_trace_get_hook_field(th
, 0));
2929 address
= ltt_event_get_long_unsigned(e
, lttv_trace_get_hook_field(th
, 1));
2930 symbol
= ltt_event_get_string(e
, lttv_trace_get_hook_field(th
, 2));
2932 expand_soft_irq_table(ts
, id
);
2933 nt
->soft_irq_names
[id
] = g_quark_from_string(symbol
);
2938 static gboolean
sched_try_wakeup(void *hook_data
, void *call_data
)
2940 LttvTracefileState
*s
= (LttvTracefileState
*)call_data
;
2941 LttEvent
*e
= ltt_tracefile_get_event(s
->parent
.tf
);
2942 LttvTraceHook
*th
= (LttvTraceHook
*)hook_data
;
2943 LttvProcessState
*process
;
2947 woken_pid
= ltt_event_get_int(e
, lttv_trace_get_hook_field(th
, 0));
2948 woken_cpu
= ltt_event_get_unsigned(e
, lttv_trace_get_hook_field(th
, 1));
2950 process
= lttv_state_find_process_or_create(
2951 (LttvTraceState
*)s
->parent
.t_context
,
2952 woken_cpu
, woken_pid
,
2953 &s
->parent
.timestamp
);
2954 process
->state
->s
= LTTV_STATE_WAIT_CPU
;
2955 process
->state
->change
= s
->parent
.timestamp
;
2957 g_debug("Wakeup: process %d on CPU %u\n", woken_pid
, woken_cpu
);
2962 static gboolean
schedchange(void *hook_data
, void *call_data
)
2964 LttvTracefileState
*s
= (LttvTracefileState
*)call_data
;
2966 LttvTraceState
*ts
= (LttvTraceState
*)s
->parent
.t_context
;
2967 LttvProcessState
*process
= ts
->running_process
[cpu
];
2968 //LttvProcessState *old_process = ts->running_process[cpu];
2970 LttEvent
*e
= ltt_tracefile_get_event(s
->parent
.tf
);
2971 LttvTraceHook
*th
= (LttvTraceHook
*)hook_data
;
2972 guint pid_in
, pid_out
;
2975 pid_out
= ltt_event_get_unsigned(e
, lttv_trace_get_hook_field(th
, 0));
2976 pid_in
= ltt_event_get_unsigned(e
, lttv_trace_get_hook_field(th
, 1));
2977 state_out
= ltt_event_get_long_int(e
, lttv_trace_get_hook_field(th
, 2));
2979 if(likely(process
!= NULL
)) {
2981 /* We could not know but it was not the idle process executing.
2982 This should only happen at the beginning, before the first schedule
2983 event, and when the initial information (current process for each CPU)
2984 is missing. It is not obvious how we could, after the fact, compensate
2985 the wrongly attributed statistics. */
2987 //This test only makes sense once the state is known and if there is no
2988 //missing events. We need to silently ignore schedchange coming after a
2989 //process_free, or it causes glitches. (FIXME)
2990 //if(unlikely(process->pid != pid_out)) {
2991 // g_assert(process->pid == 0);
2993 if(process
->pid
== 0
2994 && process
->state
->t
== LTTV_STATE_MODE_UNKNOWN
) {
2996 /* Scheduling out of pid 0 at beginning of the trace :
2997 * we know for sure it is in syscall mode at this point. */
2998 g_assert(process
->execution_stack
->len
== 1);
2999 process
->state
->t
= LTTV_STATE_SYSCALL
;
3000 process
->state
->s
= LTTV_STATE_WAIT
;
3001 process
->state
->change
= s
->parent
.timestamp
;
3002 process
->state
->entry
= s
->parent
.timestamp
;
3005 if(unlikely(process
->state
->s
== LTTV_STATE_EXIT
)) {
3006 process
->state
->s
= LTTV_STATE_ZOMBIE
;
3007 process
->state
->change
= s
->parent
.timestamp
;
3009 if(unlikely(state_out
== 0)) process
->state
->s
= LTTV_STATE_WAIT_CPU
;
3010 else process
->state
->s
= LTTV_STATE_WAIT
;
3011 process
->state
->change
= s
->parent
.timestamp
;
3014 if(state_out
== 32 || state_out
== 64) { /* EXIT_DEAD || TASK_DEAD */
3015 /* see sched.h for states */
3016 if (!exit_process(s
, process
)) {
3017 process
->state
->s
= LTTV_STATE_DEAD
;
3018 process
->state
->change
= s
->parent
.timestamp
;
3023 process
= ts
->running_process
[cpu
] =
3024 lttv_state_find_process_or_create(
3025 (LttvTraceState
*)s
->parent
.t_context
,
3027 &s
->parent
.timestamp
);
3028 process
->state
->s
= LTTV_STATE_RUN
;
3030 if(process
->usertrace
)
3031 process
->usertrace
->cpu
= cpu
;
3032 // process->last_cpu_index = ltt_tracefile_num(((LttvTracefileContext*)s)->tf);
3033 process
->state
->change
= s
->parent
.timestamp
;
3035 /* update cpu status */
3037 /* going to idle task */
3038 cpu_set_base_mode(s
->cpu_state
, LTTV_CPU_IDLE
);
3040 /* scheduling a real task.
3041 * we must be careful here:
3042 * if we just schedule()'ed to a process that is
3043 * in a trap, we must put the cpu in trap mode
3045 cpu_set_base_mode(s
->cpu_state
, LTTV_CPU_BUSY
);
3046 if(process
->state
->t
== LTTV_STATE_TRAP
)
3047 cpu_push_mode(s
->cpu_state
, LTTV_CPU_TRAP
);
3053 static gboolean
process_fork(void *hook_data
, void *call_data
)
3055 LttvTracefileState
*s
= (LttvTracefileState
*)call_data
;
3056 LttEvent
*e
= ltt_tracefile_get_event(s
->parent
.tf
);
3057 LttvTraceHook
*th
= (LttvTraceHook
*)hook_data
;
3059 guint child_pid
; /* In the Linux Kernel, there is one PID per thread. */
3060 guint child_tgid
; /* tgid in the Linux kernel is the "real" POSIX PID. */
3061 //LttvProcessState *zombie_process;
3063 LttvTraceState
*ts
= (LttvTraceState
*)s
->parent
.t_context
;
3064 LttvProcessState
*process
= ts
->running_process
[cpu
];
3065 LttvProcessState
*child_process
;
3066 struct marker_field
*f
;
3069 parent_pid
= ltt_event_get_unsigned(e
, lttv_trace_get_hook_field(th
, 0));
3072 child_pid
= ltt_event_get_unsigned(e
, lttv_trace_get_hook_field(th
, 1));
3073 s
->parent
.target_pid
= child_pid
;
3076 f
= lttv_trace_get_hook_field(th
, 2);
3078 child_tgid
= ltt_event_get_unsigned(e
, f
);
3082 /* Mathieu : it seems like the process might have been scheduled in before the
3083 * fork, and, in a rare case, might be the current process. This might happen
3084 * in a SMP case where we don't have enough precision on the clocks.
3086 * Test reenabled after precision fixes on time. (Mathieu) */
3088 zombie_process
= lttv_state_find_process(ts
, ANY_CPU
, child_pid
);
3090 if(unlikely(zombie_process
!= NULL
)) {
3091 /* Reutilisation of PID. Only now we are sure that the old PID
3092 * has been released. FIXME : should know when release_task happens instead.
3094 guint num_cpus
= ltt_trace_get_num_cpu(ts
->parent
.t
);
3096 for(i
=0; i
< num_cpus
; i
++) {
3097 g_assert(zombie_process
!= ts
->running_process
[i
]);
3100 exit_process(s
, zombie_process
);
3103 g_assert(process
->pid
!= child_pid
);
3104 // FIXME : Add this test in the "known state" section
3105 // g_assert(process->pid == parent_pid);
3106 child_process
= lttv_state_find_process(ts
, ANY_CPU
, child_pid
);
3107 if(child_process
== NULL
) {
3108 child_process
= lttv_state_create_process(ts
, process
, cpu
,
3109 child_pid
, child_tgid
,
3110 LTTV_STATE_UNNAMED
, &s
->parent
.timestamp
);
3112 /* The process has already been created : due to time imprecision between
3113 * multiple CPUs : it has been scheduled in before creation. Note that we
3114 * shouldn't have this kind of imprecision.
3116 * Simply put a correct parent.
3118 g_error("Process %u has been created at [%lu.%09lu] "
3119 "and inserted at [%lu.%09lu] before \n"
3120 "fork on cpu %u[%lu.%09lu].\n"
3121 "Probably an unsynchronized TSC problem on the traced machine.",
3123 child_process
->creation_time
.tv_sec
,
3124 child_process
->creation_time
.tv_nsec
,
3125 child_process
->insertion_time
.tv_sec
,
3126 child_process
->insertion_time
.tv_nsec
,
3127 cpu
, ltt_event_time(e
).tv_sec
, ltt_event_time(e
).tv_nsec
);
3128 //g_assert(0); /* This is a problematic case : the process has been created
3129 // before the fork event */
3130 child_process
->ppid
= process
->pid
;
3131 child_process
->tgid
= child_tgid
;
3133 g_assert(child_process
->name
== LTTV_STATE_UNNAMED
);
3134 child_process
->name
= process
->name
;
3135 child_process
->brand
= process
->brand
;
3140 /* We stamp a newly created process as kernel_thread.
3141 * The thread should not be running yet. */
3142 static gboolean
process_kernel_thread(void *hook_data
, void *call_data
)
3144 LttvTracefileState
*s
= (LttvTracefileState
*)call_data
;
3145 LttEvent
*e
= ltt_tracefile_get_event(s
->parent
.tf
);
3146 LttvTraceHook
*th
= (LttvTraceHook
*)hook_data
;
3148 LttvTraceState
*ts
= (LttvTraceState
*)s
->parent
.t_context
;
3149 LttvProcessState
*process
;
3150 LttvExecutionState
*es
;
3153 pid
= (guint
)ltt_event_get_long_unsigned(e
, lttv_trace_get_hook_field(th
, 0));
3154 s
->parent
.target_pid
= pid
;
3156 process
= lttv_state_find_process_or_create(ts
, ANY_CPU
, pid
,
3158 if (process
->state
->s
!= LTTV_STATE_DEAD
) {
3159 process
->execution_stack
=
3160 g_array_set_size(process
->execution_stack
, 1);
3161 es
= process
->state
=
3162 &g_array_index(process
->execution_stack
, LttvExecutionState
, 0);
3163 es
->t
= LTTV_STATE_SYSCALL
;
3165 process
->type
= LTTV_STATE_KERNEL_THREAD
;
3170 static gboolean
process_exit(void *hook_data
, void *call_data
)
3172 LttvTracefileState
*s
= (LttvTracefileState
*)call_data
;
3173 LttEvent
*e
= ltt_tracefile_get_event(s
->parent
.tf
);
3174 LttvTraceHook
*th
= (LttvTraceHook
*)hook_data
;
3176 LttvTraceState
*ts
= (LttvTraceState
*)s
->parent
.t_context
;
3177 LttvProcessState
*process
; // = ts->running_process[cpu];
3179 pid
= ltt_event_get_unsigned(e
, lttv_trace_get_hook_field(th
, 0));
3180 s
->parent
.target_pid
= pid
;
3182 // FIXME : Add this test in the "known state" section
3183 // g_assert(process->pid == pid);
3185 process
= lttv_state_find_process(ts
, ANY_CPU
, pid
);
3186 if(likely(process
!= NULL
)) {
3187 process
->state
->s
= LTTV_STATE_EXIT
;
3192 static gboolean
process_free(void *hook_data
, void *call_data
)
3194 LttvTracefileState
*s
= (LttvTracefileState
*)call_data
;
3195 LttvTraceState
*ts
= (LttvTraceState
*)s
->parent
.t_context
;
3196 LttEvent
*e
= ltt_tracefile_get_event(s
->parent
.tf
);
3197 LttvTraceHook
*th
= (LttvTraceHook
*)hook_data
;
3199 LttvProcessState
*process
;
3201 /* PID of the process to release */
3202 release_pid
= ltt_event_get_unsigned(e
, lttv_trace_get_hook_field(th
, 0));
3203 s
->parent
.target_pid
= release_pid
;
3205 g_assert(release_pid
!= 0);
3207 process
= lttv_state_find_process(ts
, ANY_CPU
, release_pid
);
3208 if(likely(process
!= NULL
))
3209 exit_process(s
, process
);
3212 if(likely(process
!= NULL
)) {
3213 /* release_task is happening at kernel level : we can now safely release
3214 * the data structure of the process */
3215 //This test is fun, though, as it may happen that
3216 //at time t : CPU 0 : process_free
3217 //at time t+150ns : CPU 1 : schedule out
3218 //Clearly due to time imprecision, we disable it. (Mathieu)
3219 //If this weird case happen, we have no choice but to put the
3220 //Currently running process on the cpu to 0.
3221 //I re-enable it following time precision fixes. (Mathieu)
3222 //Well, in the case where an process is freed by a process on another CPU
3223 //and still scheduled, it happens that this is the schedchange that will
3224 //drop the last reference count. Do not free it here!
3225 guint num_cpus
= ltt_trace_get_num_cpu(ts
->parent
.t
);
3227 for(i
=0; i
< num_cpus
; i
++) {
3228 //g_assert(process != ts->running_process[i]);
3229 if(process
== ts
->running_process
[i
]) {
3230 //ts->running_process[i] = lttv_state_find_process(ts, i, 0);
3234 if(i
== num_cpus
) /* process is not scheduled */
3235 exit_process(s
, process
);
3242 static gboolean
process_exec(void *hook_data
, void *call_data
)
3244 LttvTracefileState
*s
= (LttvTracefileState
*)call_data
;
3245 LttvTraceState
*ts
= (LttvTraceState
*)s
->parent
.t_context
;
3246 LttEvent
*e
= ltt_tracefile_get_event(s
->parent
.tf
);
3247 LttvTraceHook
*th
= (LttvTraceHook
*)hook_data
;
3250 LttvProcessState
*process
= ts
->running_process
[cpu
];
3252 #if 0//how to use a sequence that must be transformed in a string
3253 /* PID of the process to release */
3254 guint64 name_len
= ltt_event_field_element_number(e
,
3255 lttv_trace_get_hook_field(th
, 0));
3256 //name = ltt_event_get_string(e, lttv_trace_get_hook_field(th, 0));
3257 LttField
*child
= ltt_event_field_element_select(e
,
3258 lttv_trace_get_hook_field(th
, 0), 0);
3260 (gchar
*)(ltt_event_data(e
)+ltt_event_field_offset(e
, child
));
3261 gchar
*null_term_name
= g_new(gchar
, name_len
+1);
3262 memcpy(null_term_name
, name_begin
, name_len
);
3263 null_term_name
[name_len
] = '\0';
3264 process
->name
= g_quark_from_string(null_term_name
);
3267 process
->name
= g_quark_from_string(ltt_event_get_string(e
,
3268 lttv_trace_get_hook_field(th
, 0)));
3269 process
->brand
= LTTV_STATE_UNBRANDED
;
3270 //g_free(null_term_name);
3274 static gboolean
thread_brand(void *hook_data
, void *call_data
)
3276 LttvTracefileState
*s
= (LttvTracefileState
*)call_data
;
3277 LttvTraceState
*ts
= (LttvTraceState
*)s
->parent
.t_context
;
3278 LttEvent
*e
= ltt_tracefile_get_event(s
->parent
.tf
);
3279 LttvTraceHook
*th
= (LttvTraceHook
*)hook_data
;
3282 LttvProcessState
*process
= ts
->running_process
[cpu
];
3284 name
= ltt_event_get_string(e
, lttv_trace_get_hook_field(th
, 0));
3285 process
->brand
= g_quark_from_string(name
);
3290 static gboolean
fs_open(void *hook_data
, void *call_data
)
3292 LttvTracefileState
*s
= (LttvTracefileState
*)call_data
;
3293 LttvTraceState
*ts
= (LttvTraceState
*)s
->parent
.t_context
;
3294 LttEvent
*e
= ltt_tracefile_get_event(s
->parent
.tf
);
3295 LttvTraceHook
*th
= (LttvTraceHook
*)hook_data
;
3296 struct marker_field
*f
;
3300 LttvProcessState
*process
= ts
->running_process
[cpu
];
3302 f
= lttv_trace_get_hook_field(th
, 0);
3303 fd
= ltt_event_get_int(e
, f
);
3305 f
= lttv_trace_get_hook_field(th
, 1);
3306 filename
= ltt_event_get_string(e
, f
);
3308 g_hash_table_insert(process
->fds
, (gpointer
)(long)fd
,
3309 (gpointer
)(unsigned long)g_quark_from_string(filename
));
3314 static void fix_process(gpointer key
, gpointer value
,
3317 LttvProcessState
*process
;
3318 LttvExecutionState
*es
;
3319 process
= (LttvProcessState
*)value
;
3320 LttTime
*timestamp
= (LttTime
*)user_data
;
3322 if(process
->type
== LTTV_STATE_KERNEL_THREAD
) {
3323 es
= &g_array_index(process
->execution_stack
, LttvExecutionState
, 0);
3324 if(es
->t
== LTTV_STATE_MODE_UNKNOWN
) {
3325 es
->t
= LTTV_STATE_SYSCALL
;
3326 es
->n
= LTTV_STATE_SUBMODE_NONE
;
3327 es
->entry
= *timestamp
;
3328 es
->change
= *timestamp
;
3329 es
->cum_cpu_time
= ltt_time_zero
;
3330 if(es
->s
== LTTV_STATE_UNNAMED
)
3331 es
->s
= LTTV_STATE_WAIT
;
3334 es
= &g_array_index(process
->execution_stack
, LttvExecutionState
, 0);
3335 if(es
->t
== LTTV_STATE_MODE_UNKNOWN
) {
3336 es
->t
= LTTV_STATE_USER_MODE
;
3337 es
->n
= LTTV_STATE_SUBMODE_NONE
;
3338 es
->entry
= *timestamp
;
3339 //g_assert(timestamp->tv_sec != 0);
3340 es
->change
= *timestamp
;
3341 es
->cum_cpu_time
= ltt_time_zero
;
3342 if(es
->s
== LTTV_STATE_UNNAMED
)
3343 es
->s
= LTTV_STATE_RUN
;
3345 if(process
->execution_stack
->len
== 1) {
3346 /* Still in bottom unknown mode, means never did a system call
3347 * May be either in user mode, syscall mode, running or waiting.*/
3348 /* FIXME : we may be tagging syscall mode when being user mode */
3349 process
->execution_stack
=
3350 g_array_set_size(process
->execution_stack
, 2);
3351 es
= process
->state
= &g_array_index(process
->execution_stack
,
3352 LttvExecutionState
, 1);
3353 es
->t
= LTTV_STATE_SYSCALL
;
3354 es
->n
= LTTV_STATE_SUBMODE_NONE
;
3355 es
->entry
= *timestamp
;
3356 //g_assert(timestamp->tv_sec != 0);
3357 es
->change
= *timestamp
;
3358 es
->cum_cpu_time
= ltt_time_zero
;
3359 if(es
->s
== LTTV_STATE_WAIT_FORK
)
3360 es
->s
= LTTV_STATE_WAIT
;
3366 static gboolean
statedump_end(void *hook_data
, void *call_data
)
3368 LttvTracefileState
*s
= (LttvTracefileState
*)call_data
;
3369 LttvTraceState
*ts
= (LttvTraceState
*)s
->parent
.t_context
;
3370 LttvTracefileContext
*tfc
= (LttvTracefileContext
*)call_data
;
3371 //LttEvent *e = ltt_tracefile_get_event(s->parent.tf);
3372 //LttvTraceHook *th = (LttvTraceHook *)hook_data;
3374 /* For all processes */
3375 /* if kernel thread, if stack[0] is unknown, set to syscall mode, wait */
3376 /* else, if stack[0] is unknown, set to user mode, running */
3378 g_hash_table_foreach(ts
->processes
, fix_process
, &tfc
->timestamp
);
3383 static gboolean
enum_process_state(void *hook_data
, void *call_data
)
3385 LttvTracefileState
*s
= (LttvTracefileState
*)call_data
;
3386 LttEvent
*e
= ltt_tracefile_get_event(s
->parent
.tf
);
3387 //It's slow : optimise later by doing this before reading trace.
3388 LttvTraceHook
*th
= (LttvTraceHook
*)hook_data
;
3394 LttvTraceState
*ts
= (LttvTraceState
*)s
->parent
.t_context
;
3395 LttvProcessState
*process
= ts
->running_process
[cpu
];
3396 LttvProcessState
*parent_process
;
3397 struct marker_field
*f
;
3398 GQuark type
, mode
, submode
, status
;
3399 LttvExecutionState
*es
;
3403 pid
= ltt_event_get_unsigned(e
, lttv_trace_get_hook_field(th
, 0));
3404 s
->parent
.target_pid
= pid
;
3407 parent_pid
= ltt_event_get_unsigned(e
, lttv_trace_get_hook_field(th
, 1));
3410 command
= ltt_event_get_string(e
, lttv_trace_get_hook_field(th
, 2));
3413 f
= lttv_trace_get_hook_field(th
, 3);
3414 type
= ltt_enum_string_get(f
, ltt_event_get_unsigned(e
, f
));
3416 //FIXME: type is rarely used, enum must match possible types.
3419 f
= lttv_trace_get_hook_field(th
, 4);
3420 mode
= ltt_enum_string_get(f
,ltt_event_get_unsigned(e
, f
));
3423 f
= lttv_trace_get_hook_field(th
, 5);
3424 submode
= ltt_enum_string_get(f
, ltt_event_get_unsigned(e
, f
));
3427 f
= lttv_trace_get_hook_field(th
, 6);
3428 status
= ltt_enum_string_get(f
, ltt_event_get_unsigned(e
, f
));
3431 f
= lttv_trace_get_hook_field(th
, 7);
3433 tgid
= ltt_event_get_unsigned(e
, f
);
3438 nb_cpus
= ltt_trace_get_num_cpu(ts
->parent
.t
);
3439 for(i
=0; i
<nb_cpus
; i
++) {
3440 process
= lttv_state_find_process(ts
, i
, pid
);
3441 g_assert(process
!= NULL
);
3443 process
->ppid
= parent_pid
;
3444 process
->tgid
= tgid
;
3445 process
->name
= g_quark_from_string(command
);
3447 &g_array_index(process
->execution_stack
, LttvExecutionState
, 0);
3448 process
->type
= LTTV_STATE_KERNEL_THREAD
;
3452 /* The process might exist if a process was forked while performing the
3454 process
= lttv_state_find_process(ts
, ANY_CPU
, pid
);
3455 if(process
== NULL
) {
3456 parent_process
= lttv_state_find_process(ts
, ANY_CPU
, parent_pid
);
3457 process
= lttv_state_create_process(ts
, parent_process
, cpu
,
3458 pid
, tgid
, g_quark_from_string(command
),
3459 &s
->parent
.timestamp
);
3461 /* Keep the stack bottom : a running user mode */
3462 /* Disabled because of inconsistencies in the current statedump states. */
3463 if(type
== LTTV_STATE_KERNEL_THREAD
) {
3464 /* Only keep the bottom
3465 * FIXME Kernel thread : can be in syscall or interrupt or trap. */
3466 /* Will cause expected trap when in fact being syscall (even after end of
3468 * Will cause expected interrupt when being syscall. (only before end of
3469 * statedump event) */
3470 // This will cause a "popping last state on stack, ignoring it."
3471 process
->execution_stack
= g_array_set_size(process
->execution_stack
, 1);
3472 es
= process
->state
= &g_array_index(process
->execution_stack
,
3473 LttvExecutionState
, 0);
3474 process
->type
= LTTV_STATE_KERNEL_THREAD
;
3475 es
->t
= LTTV_STATE_MODE_UNKNOWN
;
3476 es
->s
= LTTV_STATE_UNNAMED
;
3477 es
->n
= LTTV_STATE_SUBMODE_UNKNOWN
;
3479 es
->t
= LTTV_STATE_SYSCALL
;
3484 /* User space process :
3485 * bottom : user mode
3486 * either currently running or scheduled out.
3487 * can be scheduled out because interrupted in (user mode or in syscall)
3488 * or because of an explicit call to the scheduler in syscall. Note that
3489 * the scheduler call comes after the irq_exit, so never in interrupt
3491 // temp workaround : set size to 1 : only have user mode bottom of stack.
3492 // will cause g_info message of expected syscall mode when in fact being
3493 // in user mode. Can also cause expected trap when in fact being user
3494 // mode in the event of a page fault reenabling interrupts in the handler.
3495 // Expected syscall and trap can also happen after the end of statedump
3496 // This will cause a "popping last state on stack, ignoring it."
3497 process
->execution_stack
= g_array_set_size(process
->execution_stack
, 1);
3498 es
= process
->state
= &g_array_index(process
->execution_stack
,
3499 LttvExecutionState
, 0);
3500 es
->t
= LTTV_STATE_MODE_UNKNOWN
;
3501 es
->s
= LTTV_STATE_UNNAMED
;
3502 es
->n
= LTTV_STATE_SUBMODE_UNKNOWN
;
3504 es
->t
= LTTV_STATE_USER_MODE
;
3512 es
= process
->state
= &g_array_index(process
->execution_stack
,
3513 LttvExecutionState
, 1);
3514 es
->t
= LTTV_STATE_MODE_UNKNOWN
;
3515 es
->s
= LTTV_STATE_UNNAMED
;
3516 es
->n
= LTTV_STATE_SUBMODE_UNKNOWN
;
3520 /* The process has already been created :
3521 * Probably was forked while dumping the process state or
3522 * was simply scheduled in prior to get the state dump event.
3524 process
->ppid
= parent_pid
;
3525 process
->tgid
= tgid
;
3526 process
->name
= g_quark_from_string(command
);
3527 process
->type
= type
;
3529 &g_array_index(process
->execution_stack
, LttvExecutionState
, 0);
3531 if(es
->t
== LTTV_STATE_MODE_UNKNOWN
) {
3532 if(type
== LTTV_STATE_KERNEL_THREAD
)
3533 es
->t
= LTTV_STATE_SYSCALL
;
3535 es
->t
= LTTV_STATE_USER_MODE
;
3538 /* Don't mess around with the stack, it will eventually become
3539 * ok after the end of state dump. */
3546 gint
lttv_state_hook_add_event_hooks(void *hook_data
, void *call_data
)
3548 LttvTracesetState
*tss
= (LttvTracesetState
*)(call_data
);
3550 lttv_state_add_event_hooks(tss
);
3555 void lttv_state_add_event_hooks(LttvTracesetState
*self
)
3557 LttvTraceset
*traceset
= self
->parent
.ts
;
3559 guint i
, j
, k
, nb_trace
, nb_tracefile
;
3563 LttvTracefileState
*tfs
;
3569 LttvAttributeValue val
;
3571 nb_trace
= lttv_traceset_number(traceset
);
3572 for(i
= 0 ; i
< nb_trace
; i
++) {
3573 ts
= (LttvTraceState
*)self
->parent
.traces
[i
];
3575 /* Find the eventtype id for the following events and register the
3576 associated by id hooks. */
3578 hooks
= g_array_sized_new(FALSE
, FALSE
, sizeof(LttvTraceHook
), 20);
3579 //hooks = g_array_set_size(hooks, 19); // Max possible number of hooks.
3582 lttv_trace_find_hook(ts
->parent
.t
,
3584 LTT_EVENT_SYSCALL_ENTRY
,
3585 FIELD_ARRAY(LTT_FIELD_SYSCALL_ID
),
3586 syscall_entry
, NULL
, &hooks
);
3588 lttv_trace_find_hook(ts
->parent
.t
,
3590 LTT_EVENT_SYSCALL_EXIT
,
3592 syscall_exit
, NULL
, &hooks
);
3594 lttv_trace_find_hook(ts
->parent
.t
,
3596 LTT_EVENT_TRAP_ENTRY
,
3597 FIELD_ARRAY(LTT_FIELD_TRAP_ID
),
3598 trap_entry
, NULL
, &hooks
);
3600 lttv_trace_find_hook(ts
->parent
.t
,
3602 LTT_EVENT_TRAP_EXIT
,
3604 trap_exit
, NULL
, &hooks
);
3606 lttv_trace_find_hook(ts
->parent
.t
,
3608 LTT_EVENT_PAGE_FAULT_ENTRY
,
3609 FIELD_ARRAY(LTT_FIELD_TRAP_ID
),
3610 trap_entry
, NULL
, &hooks
);
3612 lttv_trace_find_hook(ts
->parent
.t
,
3614 LTT_EVENT_PAGE_FAULT_EXIT
,
3616 trap_exit
, NULL
, &hooks
);
3618 lttv_trace_find_hook(ts
->parent
.t
,
3620 LTT_EVENT_PAGE_FAULT_NOSEM_ENTRY
,
3621 FIELD_ARRAY(LTT_FIELD_TRAP_ID
),
3622 trap_entry
, NULL
, &hooks
);
3624 lttv_trace_find_hook(ts
->parent
.t
,
3626 LTT_EVENT_PAGE_FAULT_NOSEM_EXIT
,
3628 trap_exit
, NULL
, &hooks
);
3630 lttv_trace_find_hook(ts
->parent
.t
,
3632 LTT_EVENT_IRQ_ENTRY
,
3633 FIELD_ARRAY(LTT_FIELD_IRQ_ID
),
3634 irq_entry
, NULL
, &hooks
);
3636 lttv_trace_find_hook(ts
->parent
.t
,
3640 irq_exit
, NULL
, &hooks
);
3642 lttv_trace_find_hook(ts
->parent
.t
,
3644 LTT_EVENT_SOFT_IRQ_RAISE
,
3645 FIELD_ARRAY(LTT_FIELD_SOFT_IRQ_ID
),
3646 soft_irq_raise
, NULL
, &hooks
);
3648 lttv_trace_find_hook(ts
->parent
.t
,
3650 LTT_EVENT_SOFT_IRQ_ENTRY
,
3651 FIELD_ARRAY(LTT_FIELD_SOFT_IRQ_ID
),
3652 soft_irq_entry
, NULL
, &hooks
);
3654 lttv_trace_find_hook(ts
->parent
.t
,
3656 LTT_EVENT_SOFT_IRQ_EXIT
,
3658 soft_irq_exit
, NULL
, &hooks
);
3660 lttv_trace_find_hook(ts
->parent
.t
,
3662 LTT_EVENT_SCHED_SCHEDULE
,
3663 FIELD_ARRAY(LTT_FIELD_PREV_PID
, LTT_FIELD_NEXT_PID
,
3664 LTT_FIELD_PREV_STATE
),
3665 schedchange
, NULL
, &hooks
);
3667 lttv_trace_find_hook(ts
->parent
.t
,
3669 LTT_EVENT_SCHED_TRY_WAKEUP
,
3670 FIELD_ARRAY(LTT_FIELD_PID
, LTT_FIELD_CPU_ID
, LTT_FIELD_STATE
),
3671 sched_try_wakeup
, NULL
, &hooks
);
3673 lttv_trace_find_hook(ts
->parent
.t
,
3675 LTT_EVENT_PROCESS_FORK
,
3676 FIELD_ARRAY(LTT_FIELD_PARENT_PID
, LTT_FIELD_CHILD_PID
,
3677 LTT_FIELD_CHILD_TGID
),
3678 process_fork
, NULL
, &hooks
);
3680 lttv_trace_find_hook(ts
->parent
.t
,
3682 LTT_EVENT_KTHREAD_CREATE
,
3683 FIELD_ARRAY(LTT_FIELD_PID
),
3684 process_kernel_thread
, NULL
, &hooks
);
3686 lttv_trace_find_hook(ts
->parent
.t
,
3688 LTT_EVENT_PROCESS_EXIT
,
3689 FIELD_ARRAY(LTT_FIELD_PID
),
3690 process_exit
, NULL
, &hooks
);
3692 lttv_trace_find_hook(ts
->parent
.t
,
3694 LTT_EVENT_PROCESS_FREE
,
3695 FIELD_ARRAY(LTT_FIELD_PID
),
3696 process_free
, NULL
, &hooks
);
3698 lttv_trace_find_hook(ts
->parent
.t
,
3701 FIELD_ARRAY(LTT_FIELD_FILENAME
),
3702 process_exec
, NULL
, &hooks
);
3704 lttv_trace_find_hook(ts
->parent
.t
,
3705 LTT_CHANNEL_USERSPACE
,
3706 LTT_EVENT_THREAD_BRAND
,
3707 FIELD_ARRAY(LTT_FIELD_NAME
),
3708 thread_brand
, NULL
, &hooks
);
3710 /* statedump-related hooks */
3711 lttv_trace_find_hook(ts
->parent
.t
,
3712 LTT_CHANNEL_TASK_STATE
,
3713 LTT_EVENT_PROCESS_STATE
,
3714 FIELD_ARRAY(LTT_FIELD_PID
, LTT_FIELD_PARENT_PID
, LTT_FIELD_NAME
,
3715 LTT_FIELD_TYPE
, LTT_FIELD_MODE
, LTT_FIELD_SUBMODE
,
3716 LTT_FIELD_STATUS
, LTT_FIELD_TGID
),
3717 enum_process_state
, NULL
, &hooks
);
3719 lttv_trace_find_hook(ts
->parent
.t
,
3720 LTT_CHANNEL_GLOBAL_STATE
,
3721 LTT_EVENT_STATEDUMP_END
,
3723 statedump_end
, NULL
, &hooks
);
3725 lttv_trace_find_hook(ts
->parent
.t
,
3726 LTT_CHANNEL_IRQ_STATE
,
3727 LTT_EVENT_LIST_INTERRUPT
,
3728 FIELD_ARRAY(LTT_FIELD_ACTION
, LTT_FIELD_IRQ_ID
),
3729 enum_interrupt
, NULL
, &hooks
);
3731 lttv_trace_find_hook(ts
->parent
.t
,
3733 LTT_EVENT_REQUEST_ISSUE
,
3734 FIELD_ARRAY(LTT_FIELD_MAJOR
, LTT_FIELD_MINOR
, LTT_FIELD_OPERATION
),
3735 bdev_request_issue
, NULL
, &hooks
);
3737 lttv_trace_find_hook(ts
->parent
.t
,
3739 LTT_EVENT_REQUEST_COMPLETE
,
3740 FIELD_ARRAY(LTT_FIELD_MAJOR
, LTT_FIELD_MINOR
, LTT_FIELD_OPERATION
),
3741 bdev_request_complete
, NULL
, &hooks
);
3743 lttv_trace_find_hook(ts
->parent
.t
,
3744 LTT_CHANNEL_USERSPACE
,
3745 LTT_EVENT_FUNCTION_ENTRY
,
3746 FIELD_ARRAY(LTT_FIELD_THIS_FN
, LTT_FIELD_CALL_SITE
),
3747 function_entry
, NULL
, &hooks
);
3749 lttv_trace_find_hook(ts
->parent
.t
,
3750 LTT_CHANNEL_USERSPACE
,
3751 LTT_EVENT_FUNCTION_EXIT
,
3752 FIELD_ARRAY(LTT_FIELD_THIS_FN
, LTT_FIELD_CALL_SITE
),
3753 function_exit
, NULL
, &hooks
);
3755 lttv_trace_find_hook(ts
->parent
.t
,
3756 LTT_CHANNEL_SYSCALL_STATE
,
3757 LTT_EVENT_SYS_CALL_TABLE
,
3758 FIELD_ARRAY(LTT_FIELD_ID
, LTT_FIELD_ADDRESS
, LTT_FIELD_SYMBOL
),
3759 dump_syscall
, NULL
, &hooks
);
3761 lttv_trace_find_hook(ts
->parent
.t
,
3762 LTT_CHANNEL_KPROBE_STATE
,
3763 LTT_EVENT_KPROBE_TABLE
,
3764 FIELD_ARRAY(LTT_FIELD_IP
, LTT_FIELD_SYMBOL
),
3765 dump_kprobe
, NULL
, &hooks
);
3767 lttv_trace_find_hook(ts
->parent
.t
,
3768 LTT_CHANNEL_SOFTIRQ_STATE
,
3769 LTT_EVENT_SOFTIRQ_VEC
,
3770 FIELD_ARRAY(LTT_FIELD_ID
, LTT_FIELD_ADDRESS
, LTT_FIELD_SYMBOL
),
3771 dump_softirq
, NULL
, &hooks
);
3773 lttv_trace_find_hook(ts
->parent
.t
,
3776 FIELD_ARRAY(LTT_FIELD_FD
, LTT_FIELD_FILENAME
),
3777 fs_open
, NULL
, &hooks
);
3779 /* Add these hooks to each event_by_id hooks list */
3781 nb_tracefile
= ts
->parent
.tracefiles
->len
;
3783 for(j
= 0 ; j
< nb_tracefile
; j
++) {
3785 LTTV_TRACEFILE_STATE(g_array_index(ts
->parent
.tracefiles
,
3786 LttvTracefileContext
*, j
));
3788 for(k
= 0 ; k
< hooks
->len
; k
++) {
3789 th
= &g_array_index(hooks
, LttvTraceHook
, k
);
3790 if (th
->mdata
== tfs
->parent
.tf
->mdata
)
3792 lttv_hooks_by_id_find(tfs
->parent
.event_by_id
, th
->id
),
3798 lttv_attribute_find(ts
->parent
.a
, LTTV_STATE_HOOKS
, LTTV_POINTER
, &val
);
3799 *(val
.v_pointer
) = hooks
;
3803 gint
lttv_state_hook_remove_event_hooks(void *hook_data
, void *call_data
)
3805 LttvTracesetState
*tss
= (LttvTracesetState
*)(call_data
);
3807 lttv_state_remove_event_hooks(tss
);
3812 void lttv_state_remove_event_hooks(LttvTracesetState
*self
)
3814 LttvTraceset
*traceset
= self
->parent
.ts
;
3816 guint i
, j
, k
, nb_trace
, nb_tracefile
;
3820 LttvTracefileState
*tfs
;
3826 LttvAttributeValue val
;
3828 nb_trace
= lttv_traceset_number(traceset
);
3829 for(i
= 0 ; i
< nb_trace
; i
++) {
3830 ts
= LTTV_TRACE_STATE(self
->parent
.traces
[i
]);
3832 lttv_attribute_find(ts
->parent
.a
, LTTV_STATE_HOOKS
, LTTV_POINTER
, &val
);
3833 hooks
= *(val
.v_pointer
);
3835 /* Remove these hooks from each event_by_id hooks list */
3837 nb_tracefile
= ts
->parent
.tracefiles
->len
;
3839 for(j
= 0 ; j
< nb_tracefile
; j
++) {
3841 LTTV_TRACEFILE_STATE(g_array_index(ts
->parent
.tracefiles
,
3842 LttvTracefileContext
*, j
));
3844 for(k
= 0 ; k
< hooks
->len
; k
++) {
3845 th
= &g_array_index(hooks
, LttvTraceHook
, k
);
3846 if (th
->mdata
== tfs
->parent
.tf
->mdata
)
3847 lttv_hooks_remove_data(
3848 lttv_hooks_by_id_find(tfs
->parent
.event_by_id
, th
->id
),
3853 lttv_trace_hook_remove_all(&hooks
);
3854 g_array_free(hooks
, TRUE
);
3858 static gboolean
state_save_event_hook(void *hook_data
, void *call_data
)
3860 guint
*event_count
= (guint
*)hook_data
;
3862 /* Only save at LTTV_STATE_SAVE_INTERVAL */
3863 if(likely((*event_count
)++ < LTTV_STATE_SAVE_INTERVAL
))
3868 LttvTracefileState
*self
= (LttvTracefileState
*)call_data
;
3870 LttvTraceState
*tcs
= (LttvTraceState
*)(self
->parent
.t_context
);
3872 LttvAttribute
*saved_states_tree
, *saved_state_tree
;
3874 LttvAttributeValue value
;
3876 saved_states_tree
= lttv_attribute_find_subdir(tcs
->parent
.t_a
,
3877 LTTV_STATE_SAVED_STATES
);
3878 saved_state_tree
= g_object_new(LTTV_ATTRIBUTE_TYPE
, NULL
);
3879 value
= lttv_attribute_add(saved_states_tree
,
3880 lttv_attribute_get_number(saved_states_tree
), LTTV_GOBJECT
);
3881 *(value
.v_gobject
) = (GObject
*)saved_state_tree
;
3882 value
= lttv_attribute_add(saved_state_tree
, LTTV_STATE_TIME
, LTTV_TIME
);
3883 *(value
.v_time
) = self
->parent
.timestamp
;
3884 lttv_state_save(tcs
, saved_state_tree
);
3885 g_debug("Saving state at time %lu.%lu", self
->parent
.timestamp
.tv_sec
,
3886 self
->parent
.timestamp
.tv_nsec
);
3888 *(tcs
->max_time_state_recomputed_in_seek
) = self
->parent
.timestamp
;
3893 static gboolean
state_save_after_trace_hook(void *hook_data
, void *call_data
)
3895 LttvTraceState
*tcs
= (LttvTraceState
*)(call_data
);
3897 *(tcs
->max_time_state_recomputed_in_seek
) = tcs
->parent
.time_span
.end_time
;
3902 guint
lttv_state_current_cpu(LttvTracefileState
*tfs
)
3910 static gboolean
block_start(void *hook_data
, void *call_data
)
3912 LttvTracefileState
*self
= (LttvTracefileState
*)call_data
;
3914 LttvTracefileState
*tfcs
;
3916 LttvTraceState
*tcs
= (LttvTraceState
*)(self
->parent
.t_context
);
3918 LttEventPosition
*ep
;
3920 guint i
, nb_block
, nb_event
, nb_tracefile
;
3924 LttvAttribute
*saved_states_tree
, *saved_state_tree
;
3926 LttvAttributeValue value
;
3928 ep
= ltt_event_position_new();
3930 nb_tracefile
= tcs
->parent
.tracefiles
->len
;
3932 /* Count the number of events added since the last block end in any
3935 for(i
= 0 ; i
< nb_tracefile
; i
++) {
3937 LTTV_TRACEFILE_STATE(&g_array_index(tcs
->parent
.tracefiles
,
3938 LttvTracefileContext
, i
));
3939 ltt_event_position(tfcs
->parent
.e
, ep
);
3940 ltt_event_position_get(ep
, &nb_block
, &nb_event
, &tf
);
3941 tcs
->nb_event
+= nb_event
- tfcs
->saved_position
;
3942 tfcs
->saved_position
= nb_event
;
3946 if(tcs
->nb_event
>= tcs
->save_interval
) {
3947 saved_states_tree
= lttv_attribute_find_subdir(tcs
->parent
.t_a
,
3948 LTTV_STATE_SAVED_STATES
);
3949 saved_state_tree
= g_object_new(LTTV_ATTRIBUTE_TYPE
, NULL
);
3950 value
= lttv_attribute_add(saved_states_tree
,
3951 lttv_attribute_get_number(saved_states_tree
), LTTV_GOBJECT
);
3952 *(value
.v_gobject
) = (GObject
*)saved_state_tree
;
3953 value
= lttv_attribute_add(saved_state_tree
, LTTV_STATE_TIME
, LTTV_TIME
);
3954 *(value
.v_time
) = self
->parent
.timestamp
;
3955 lttv_state_save(tcs
, saved_state_tree
);
3957 g_debug("Saving state at time %lu.%lu", self
->parent
.timestamp
.tv_sec
,
3958 self
->parent
.timestamp
.tv_nsec
);
3960 *(tcs
->max_time_state_recomputed_in_seek
) = self
->parent
.timestamp
;
3966 static gboolean
block_end(void *hook_data
, void *call_data
)
3968 LttvTracefileState
*self
= (LttvTracefileState
*)call_data
;
3970 LttvTraceState
*tcs
= (LttvTraceState
*)(self
->parent
.t_context
);
3974 LttEventPosition
*ep
;
3976 guint nb_block
, nb_event
;
3978 ep
= ltt_event_position_new();
3979 ltt_event_position(self
->parent
.e
, ep
);
3980 ltt_event_position_get(ep
, &nb_block
, &nb_event
, &tf
);
3981 tcs
->nb_event
+= nb_event
- self
->saved_position
+ 1;
3982 self
->saved_position
= 0;
3983 *(tcs
->max_time_state_recomputed_in_seek
) = self
->parent
.timestamp
;
3990 void lttv_state_save_add_event_hooks(LttvTracesetState
*self
)
3992 LttvTraceset
*traceset
= self
->parent
.ts
;
3994 guint i
, j
, nb_trace
, nb_tracefile
;
3998 LttvTracefileState
*tfs
;
4000 LttvTraceHook hook_start
, hook_end
;
4002 nb_trace
= lttv_traceset_number(traceset
);
4003 for(i
= 0 ; i
< nb_trace
; i
++) {
4004 ts
= (LttvTraceState
*)self
->parent
.traces
[i
];
4006 lttv_trace_find_hook(ts
->parent
.t
, "core","block_start",NULL
,
4007 NULL
, NULL
, block_start
, &hook_start
);
4008 lttv_trace_find_hook(ts
->parent
.t
, "core","block_end",NULL
,
4009 NULL
, NULL
, block_end
, &hook_end
);
4011 nb_tracefile
= ts
->parent
.tracefiles
->len
;
4013 for(j
= 0 ; j
< nb_tracefile
; j
++) {
4015 LTTV_TRACEFILE_STATE(&g_array_index(ts
->parent
.tracefiles
,
4016 LttvTracefileContext
, j
));
4017 lttv_hooks_add(lttv_hooks_by_id_find(tfs
->parent
.event_by_id
,
4018 hook_start
.id
), hook_start
.h
, NULL
, LTTV_PRIO_STATE
);
4019 lttv_hooks_add(lttv_hooks_by_id_find(tfs
->parent
.event_by_id
,
4020 hook_end
.id
), hook_end
.h
, NULL
, LTTV_PRIO_STATE
);
4026 void lttv_state_save_add_event_hooks(LttvTracesetState
*self
)
4028 LttvTraceset
*traceset
= self
->parent
.ts
;
4030 guint i
, j
, nb_trace
, nb_tracefile
;
4034 LttvTracefileState
*tfs
;
4037 nb_trace
= lttv_traceset_number(traceset
);
4038 for(i
= 0 ; i
< nb_trace
; i
++) {
4040 ts
= (LttvTraceState
*)self
->parent
.traces
[i
];
4041 nb_tracefile
= ts
->parent
.tracefiles
->len
;
4043 if(ts
->has_precomputed_states
) continue;
4045 guint
*event_count
= g_new(guint
, 1);
4048 for(j
= 0 ; j
< nb_tracefile
; j
++) {
4050 LTTV_TRACEFILE_STATE(g_array_index(ts
->parent
.tracefiles
,
4051 LttvTracefileContext
*, j
));
4052 lttv_hooks_add(tfs
->parent
.event
,
4053 state_save_event_hook
,
4060 lttv_process_traceset_begin(&self
->parent
,
4061 NULL
, NULL
, NULL
, NULL
, NULL
);
4065 gint
lttv_state_save_hook_add_event_hooks(void *hook_data
, void *call_data
)
4067 LttvTracesetState
*tss
= (LttvTracesetState
*)(call_data
);
4069 lttv_state_save_add_event_hooks(tss
);
4076 void lttv_state_save_remove_event_hooks(LttvTracesetState
*self
)
4078 LttvTraceset
*traceset
= self
->parent
.ts
;
4080 guint i
, j
, nb_trace
, nb_tracefile
;
4084 LttvTracefileState
*tfs
;
4086 LttvTraceHook hook_start
, hook_end
;
4088 nb_trace
= lttv_traceset_number(traceset
);
4089 for(i
= 0 ; i
< nb_trace
; i
++) {
4090 ts
= LTTV_TRACE_STATE(self
->parent
.traces
[i
]);
4092 lttv_trace_find_hook(ts
->parent
.t
, "core","block_start",NULL
,
4093 NULL
, NULL
, block_start
, &hook_start
);
4095 lttv_trace_find_hook(ts
->parent
.t
, "core","block_end",NULL
,
4096 NULL
, NULL
, block_end
, &hook_end
);
4098 nb_tracefile
= ts
->parent
.tracefiles
->len
;
4100 for(j
= 0 ; j
< nb_tracefile
; j
++) {
4102 LTTV_TRACEFILE_STATE(&g_array_index(ts
->parent
.tracefiles
,
4103 LttvTracefileContext
, j
));
4104 lttv_hooks_remove_data(lttv_hooks_by_id_find(
4105 tfs
->parent
.event_by_id
, hook_start
.id
), hook_start
.h
, NULL
);
4106 lttv_hooks_remove_data(lttv_hooks_by_id_find(
4107 tfs
->parent
.event_by_id
, hook_end
.id
), hook_end
.h
, NULL
);
4113 void lttv_state_save_remove_event_hooks(LttvTracesetState
*self
)
4115 LttvTraceset
*traceset
= self
->parent
.ts
;
4117 guint i
, j
, nb_trace
, nb_tracefile
;
4121 LttvTracefileState
*tfs
;
4123 LttvHooks
*after_trace
= lttv_hooks_new();
4125 lttv_hooks_add(after_trace
,
4126 state_save_after_trace_hook
,
4131 lttv_process_traceset_end(&self
->parent
,
4132 NULL
, after_trace
, NULL
, NULL
, NULL
);
4134 lttv_hooks_destroy(after_trace
);
4136 nb_trace
= lttv_traceset_number(traceset
);
4137 for(i
= 0 ; i
< nb_trace
; i
++) {
4139 ts
= (LttvTraceState
*)self
->parent
.traces
[i
];
4140 nb_tracefile
= ts
->parent
.tracefiles
->len
;
4142 if(ts
->has_precomputed_states
) continue;
4144 guint
*event_count
= NULL
;
4146 for(j
= 0 ; j
< nb_tracefile
; j
++) {
4148 LTTV_TRACEFILE_STATE(g_array_index(ts
->parent
.tracefiles
,
4149 LttvTracefileContext
*, j
));
4150 event_count
= lttv_hooks_remove(tfs
->parent
.event
,
4151 state_save_event_hook
);
4153 if(event_count
) g_free(event_count
);
4157 gint
lttv_state_save_hook_remove_event_hooks(void *hook_data
, void *call_data
)
4159 LttvTracesetState
*tss
= (LttvTracesetState
*)(call_data
);
4161 lttv_state_save_remove_event_hooks(tss
);
4166 void lttv_state_traceset_seek_time_closest(LttvTracesetState
*self
, LttTime t
)
4168 LttvTraceset
*traceset
= self
->parent
.ts
;
4172 int min_pos
, mid_pos
, max_pos
;
4174 guint call_rest
= 0;
4176 LttvTraceState
*tcs
;
4178 LttvAttributeValue value
;
4180 LttvAttributeType type
;
4182 LttvAttributeName name
;
4186 LttvAttribute
*saved_states_tree
, *saved_state_tree
, *closest_tree
= NULL
;
4188 //g_tree_destroy(self->parent.pqueue);
4189 //self->parent.pqueue = g_tree_new(compare_tracefile);
4191 g_info("Entering seek_time_closest for time %lu.%lu", t
.tv_sec
, t
.tv_nsec
);
4193 nb_trace
= lttv_traceset_number(traceset
);
4194 for(i
= 0 ; i
< nb_trace
; i
++) {
4195 tcs
= (LttvTraceState
*)self
->parent
.traces
[i
];
4197 if(ltt_time_compare(t
, *(tcs
->max_time_state_recomputed_in_seek
)) < 0) {
4198 saved_states_tree
= lttv_attribute_find_subdir(tcs
->parent
.t_a
,
4199 LTTV_STATE_SAVED_STATES
);
4202 if(saved_states_tree
) {
4203 max_pos
= lttv_attribute_get_number(saved_states_tree
) - 1;
4204 mid_pos
= max_pos
/ 2;
4205 while(min_pos
< max_pos
) {
4206 type
= lttv_attribute_get(saved_states_tree
, mid_pos
, &name
, &value
,
4208 g_assert(type
== LTTV_GOBJECT
);
4209 saved_state_tree
= *((LttvAttribute
**)(value
.v_gobject
));
4210 type
= lttv_attribute_get_by_name(saved_state_tree
, LTTV_STATE_TIME
,
4212 g_assert(type
== LTTV_TIME
);
4213 if(ltt_time_compare(*(value
.v_time
), t
) < 0) {
4215 closest_tree
= saved_state_tree
;
4217 else max_pos
= mid_pos
- 1;
4219 mid_pos
= (min_pos
+ max_pos
+ 1) / 2;
4223 /* restore the closest earlier saved state */
4225 lttv_state_restore(tcs
, closest_tree
);
4229 /* There is no saved state, yet we want to have it. Restart at T0 */
4231 restore_init_state(tcs
);
4232 lttv_process_trace_seek_time(&(tcs
->parent
), ltt_time_zero
);
4235 /* We want to seek quickly without restoring/updating the state */
4237 restore_init_state(tcs
);
4238 lttv_process_trace_seek_time(&(tcs
->parent
), t
);
4241 if(!call_rest
) g_info("NOT Calling restore");
4246 traceset_state_instance_init (GTypeInstance
*instance
, gpointer g_class
)
4252 traceset_state_finalize (LttvTracesetState
*self
)
4254 G_OBJECT_CLASS(g_type_class_peek(LTTV_TRACESET_CONTEXT_TYPE
))->
4255 finalize(G_OBJECT(self
));
4260 traceset_state_class_init (LttvTracesetContextClass
*klass
)
4262 GObjectClass
*gobject_class
= G_OBJECT_CLASS(klass
);
4264 gobject_class
->finalize
= (void (*)(GObject
*self
)) traceset_state_finalize
;
4265 klass
->init
= (void (*)(LttvTracesetContext
*self
, LttvTraceset
*ts
))init
;
4266 klass
->fini
= (void (*)(LttvTracesetContext
*self
))fini
;
4267 klass
->new_traceset_context
= new_traceset_context
;
4268 klass
->new_trace_context
= new_trace_context
;
4269 klass
->new_tracefile_context
= new_tracefile_context
;
4274 lttv_traceset_state_get_type(void)
4276 static GType type
= 0;
4278 static const GTypeInfo info
= {
4279 sizeof (LttvTracesetStateClass
),
4280 NULL
, /* base_init */
4281 NULL
, /* base_finalize */
4282 (GClassInitFunc
) traceset_state_class_init
, /* class_init */
4283 NULL
, /* class_finalize */
4284 NULL
, /* class_data */
4285 sizeof (LttvTracesetState
),
4286 0, /* n_preallocs */
4287 (GInstanceInitFunc
) traceset_state_instance_init
, /* instance_init */
4288 NULL
/* value handling */
4291 type
= g_type_register_static (LTTV_TRACESET_CONTEXT_TYPE
, "LttvTracesetStateType",
4299 trace_state_instance_init (GTypeInstance
*instance
, gpointer g_class
)
4305 trace_state_finalize (LttvTraceState
*self
)
4307 G_OBJECT_CLASS(g_type_class_peek(LTTV_TRACE_CONTEXT_TYPE
))->
4308 finalize(G_OBJECT(self
));
4313 trace_state_class_init (LttvTraceStateClass
*klass
)
4315 GObjectClass
*gobject_class
= G_OBJECT_CLASS(klass
);
4317 gobject_class
->finalize
= (void (*)(GObject
*self
)) trace_state_finalize
;
4318 klass
->state_save
= state_save
;
4319 klass
->state_restore
= state_restore
;
4320 klass
->state_saved_free
= state_saved_free
;
4325 lttv_trace_state_get_type(void)
4327 static GType type
= 0;
4329 static const GTypeInfo info
= {
4330 sizeof (LttvTraceStateClass
),
4331 NULL
, /* base_init */
4332 NULL
, /* base_finalize */
4333 (GClassInitFunc
) trace_state_class_init
, /* class_init */
4334 NULL
, /* class_finalize */
4335 NULL
, /* class_data */
4336 sizeof (LttvTraceState
),
4337 0, /* n_preallocs */
4338 (GInstanceInitFunc
) trace_state_instance_init
, /* instance_init */
4339 NULL
/* value handling */
4342 type
= g_type_register_static (LTTV_TRACE_CONTEXT_TYPE
,
4343 "LttvTraceStateType", &info
, 0);
4350 tracefile_state_instance_init (GTypeInstance
*instance
, gpointer g_class
)
4356 tracefile_state_finalize (LttvTracefileState
*self
)
4358 G_OBJECT_CLASS(g_type_class_peek(LTTV_TRACEFILE_CONTEXT_TYPE
))->
4359 finalize(G_OBJECT(self
));
4364 tracefile_state_class_init (LttvTracefileStateClass
*klass
)
4366 GObjectClass
*gobject_class
= G_OBJECT_CLASS(klass
);
4368 gobject_class
->finalize
= (void (*)(GObject
*self
)) tracefile_state_finalize
;
4373 lttv_tracefile_state_get_type(void)
4375 static GType type
= 0;
4377 static const GTypeInfo info
= {
4378 sizeof (LttvTracefileStateClass
),
4379 NULL
, /* base_init */
4380 NULL
, /* base_finalize */
4381 (GClassInitFunc
) tracefile_state_class_init
, /* class_init */
4382 NULL
, /* class_finalize */
4383 NULL
, /* class_data */
4384 sizeof (LttvTracefileState
),
4385 0, /* n_preallocs */
4386 (GInstanceInitFunc
) tracefile_state_instance_init
, /* instance_init */
4387 NULL
/* value handling */
4390 type
= g_type_register_static (LTTV_TRACEFILE_CONTEXT_TYPE
,
4391 "LttvTracefileStateType", &info
, 0);
4397 static void module_init()
4399 LTTV_STATE_UNNAMED
= g_quark_from_string("");
4400 LTTV_STATE_UNBRANDED
= g_quark_from_string("");
4401 LTTV_STATE_MODE_UNKNOWN
= g_quark_from_string("MODE_UNKNOWN");
4402 LTTV_STATE_USER_MODE
= g_quark_from_string("USER_MODE");
4403 LTTV_STATE_SYSCALL
= g_quark_from_string("SYSCALL");
4404 LTTV_STATE_TRAP
= g_quark_from_string("TRAP");
4405 LTTV_STATE_IRQ
= g_quark_from_string("IRQ");
4406 LTTV_STATE_SOFT_IRQ
= g_quark_from_string("SOFTIRQ");
4407 LTTV_STATE_SUBMODE_UNKNOWN
= g_quark_from_string("UNKNOWN");
4408 LTTV_STATE_SUBMODE_NONE
= g_quark_from_string("NONE");
4409 LTTV_STATE_WAIT_FORK
= g_quark_from_string("WAIT_FORK");
4410 LTTV_STATE_WAIT_CPU
= g_quark_from_string("WAIT_CPU");
4411 LTTV_STATE_EXIT
= g_quark_from_string("EXIT");
4412 LTTV_STATE_ZOMBIE
= g_quark_from_string("ZOMBIE");
4413 LTTV_STATE_WAIT
= g_quark_from_string("WAIT");
4414 LTTV_STATE_RUN
= g_quark_from_string("RUN");
4415 LTTV_STATE_DEAD
= g_quark_from_string("DEAD");
4416 LTTV_STATE_USER_THREAD
= g_quark_from_string("USER_THREAD");
4417 LTTV_STATE_KERNEL_THREAD
= g_quark_from_string("KERNEL_THREAD");
4418 LTTV_STATE_TRACEFILES
= g_quark_from_string("tracefiles");
4419 LTTV_STATE_PROCESSES
= g_quark_from_string("processes");
4420 LTTV_STATE_PROCESS
= g_quark_from_string("process");
4421 LTTV_STATE_RUNNING_PROCESS
= g_quark_from_string("running_process");
4422 LTTV_STATE_EVENT
= g_quark_from_string("event");
4423 LTTV_STATE_SAVED_STATES
= g_quark_from_string("saved states");
4424 LTTV_STATE_SAVED_STATES_TIME
= g_quark_from_string("saved states time");
4425 LTTV_STATE_TIME
= g_quark_from_string("time");
4426 LTTV_STATE_HOOKS
= g_quark_from_string("saved state hooks");
4427 LTTV_STATE_NAME_TABLES
= g_quark_from_string("name tables");
4428 LTTV_STATE_TRACE_STATE_USE_COUNT
=
4429 g_quark_from_string("trace_state_use_count");
4430 LTTV_STATE_RESOURCE_CPUS
= g_quark_from_string("cpu resource states");
4431 LTTV_STATE_RESOURCE_CPUS
= g_quark_from_string("cpu count");
4432 LTTV_STATE_RESOURCE_IRQS
= g_quark_from_string("irq resource states");
4433 LTTV_STATE_RESOURCE_SOFT_IRQS
= g_quark_from_string("soft irq resource states");
4434 LTTV_STATE_RESOURCE_TRAPS
= g_quark_from_string("trap resource states");
4435 LTTV_STATE_RESOURCE_BLKDEVS
= g_quark_from_string("blkdevs resource states");
4437 LTT_CHANNEL_FD_STATE
= g_quark_from_string("fd_state");
4438 LTT_CHANNEL_GLOBAL_STATE
= g_quark_from_string("global_state");
4439 LTT_CHANNEL_IRQ_STATE
= g_quark_from_string("irq_state");
4440 LTT_CHANNEL_MODULE_STATE
= g_quark_from_string("module_state");
4441 LTT_CHANNEL_NETIF_STATE
= g_quark_from_string("netif_state");
4442 LTT_CHANNEL_SOFTIRQ_STATE
= g_quark_from_string("softirq_state");
4443 LTT_CHANNEL_SWAP_STATE
= g_quark_from_string("swap_state");
4444 LTT_CHANNEL_SYSCALL_STATE
= g_quark_from_string("syscall_state");
4445 LTT_CHANNEL_TASK_STATE
= g_quark_from_string("task_state");
4446 LTT_CHANNEL_VM_STATE
= g_quark_from_string("vm_state");
4447 LTT_CHANNEL_KPROBE_STATE
= g_quark_from_string("kprobe_state");
4448 LTT_CHANNEL_FS
= g_quark_from_string("fs");
4449 LTT_CHANNEL_KERNEL
= g_quark_from_string("kernel");
4450 LTT_CHANNEL_MM
= g_quark_from_string("mm");
4451 LTT_CHANNEL_USERSPACE
= g_quark_from_string("userspace");
4452 LTT_CHANNEL_BLOCK
= g_quark_from_string("block");
4454 LTT_EVENT_SYSCALL_ENTRY
= g_quark_from_string("syscall_entry");
4455 LTT_EVENT_SYSCALL_EXIT
= g_quark_from_string("syscall_exit");
4456 LTT_EVENT_TRAP_ENTRY
= g_quark_from_string("trap_entry");
4457 LTT_EVENT_TRAP_EXIT
= g_quark_from_string("trap_exit");
4458 LTT_EVENT_PAGE_FAULT_ENTRY
= g_quark_from_string("page_fault_entry");
4459 LTT_EVENT_PAGE_FAULT_EXIT
= g_quark_from_string("page_fault_exit");
4460 LTT_EVENT_PAGE_FAULT_NOSEM_ENTRY
= g_quark_from_string("page_fault_nosem_entry");
4461 LTT_EVENT_PAGE_FAULT_NOSEM_EXIT
= g_quark_from_string("page_fault_nosem_exit");
4462 LTT_EVENT_IRQ_ENTRY
= g_quark_from_string("irq_entry");
4463 LTT_EVENT_IRQ_EXIT
= g_quark_from_string("irq_exit");
4464 LTT_EVENT_SOFT_IRQ_RAISE
= g_quark_from_string("softirq_raise");
4465 LTT_EVENT_SOFT_IRQ_ENTRY
= g_quark_from_string("softirq_entry");
4466 LTT_EVENT_SOFT_IRQ_EXIT
= g_quark_from_string("softirq_exit");
4467 LTT_EVENT_SCHED_SCHEDULE
= g_quark_from_string("sched_schedule");
4468 LTT_EVENT_SCHED_TRY_WAKEUP
= g_quark_from_string("sched_try_wakeup");
4469 LTT_EVENT_PROCESS_FORK
= g_quark_from_string("process_fork");
4470 LTT_EVENT_KTHREAD_CREATE
= g_quark_from_string("kthread_create");
4471 LTT_EVENT_PROCESS_EXIT
= g_quark_from_string("process_exit");
4472 LTT_EVENT_PROCESS_FREE
= g_quark_from_string("process_free");
4473 LTT_EVENT_EXEC
= g_quark_from_string("exec");
4474 LTT_EVENT_PROCESS_STATE
= g_quark_from_string("process_state");
4475 LTT_EVENT_STATEDUMP_END
= g_quark_from_string("statedump_end");
4476 LTT_EVENT_FUNCTION_ENTRY
= g_quark_from_string("function_entry");
4477 LTT_EVENT_FUNCTION_EXIT
= g_quark_from_string("function_exit");
4478 LTT_EVENT_THREAD_BRAND
= g_quark_from_string("thread_brand");
4479 LTT_EVENT_REQUEST_ISSUE
= g_quark_from_string("_blk_request_issue");
4480 LTT_EVENT_REQUEST_COMPLETE
= g_quark_from_string("_blk_request_complete");
4481 LTT_EVENT_LIST_INTERRUPT
= g_quark_from_string("interrupt");
4482 LTT_EVENT_SYS_CALL_TABLE
= g_quark_from_string("sys_call_table");
4483 LTT_EVENT_SOFTIRQ_VEC
= g_quark_from_string("softirq_vec");
4484 LTT_EVENT_KPROBE_TABLE
= g_quark_from_string("kprobe_table");
4485 LTT_EVENT_KPROBE
= g_quark_from_string("kprobe");
4486 LTT_EVENT_OPEN
= g_quark_from_string("open");
4487 LTT_EVENT_READ
= g_quark_from_string("read");
4488 LTT_EVENT_POLL_EVENT
= g_quark_from_string("poll_event");
4490 LTT_FIELD_SYSCALL_ID
= g_quark_from_string("syscall_id");
4491 LTT_FIELD_TRAP_ID
= g_quark_from_string("trap_id");
4492 LTT_FIELD_IRQ_ID
= g_quark_from_string("irq_id");
4493 LTT_FIELD_SOFT_IRQ_ID
= g_quark_from_string("softirq_id");
4494 LTT_FIELD_PREV_PID
= g_quark_from_string("prev_pid");
4495 LTT_FIELD_NEXT_PID
= g_quark_from_string("next_pid");
4496 LTT_FIELD_PREV_STATE
= g_quark_from_string("prev_state");
4497 LTT_FIELD_PARENT_PID
= g_quark_from_string("parent_pid");
4498 LTT_FIELD_CHILD_PID
= g_quark_from_string("child_pid");
4499 LTT_FIELD_PID
= g_quark_from_string("pid");
4500 LTT_FIELD_TGID
= g_quark_from_string("tgid");
4501 LTT_FIELD_CHILD_TGID
= g_quark_from_string("child_tgid");
4502 LTT_FIELD_FILENAME
= g_quark_from_string("filename");
4503 LTT_FIELD_NAME
= g_quark_from_string("name");
4504 LTT_FIELD_TYPE
= g_quark_from_string("type");
4505 LTT_FIELD_MODE
= g_quark_from_string("mode");
4506 LTT_FIELD_SUBMODE
= g_quark_from_string("submode");
4507 LTT_FIELD_STATUS
= g_quark_from_string("status");
4508 LTT_FIELD_THIS_FN
= g_quark_from_string("this_fn");
4509 LTT_FIELD_CALL_SITE
= g_quark_from_string("call_site");
4510 LTT_FIELD_MAJOR
= g_quark_from_string("major");
4511 LTT_FIELD_MINOR
= g_quark_from_string("minor");
4512 LTT_FIELD_OPERATION
= g_quark_from_string("direction");
4513 LTT_FIELD_ACTION
= g_quark_from_string("action");
4514 LTT_FIELD_ID
= g_quark_from_string("id");
4515 LTT_FIELD_ADDRESS
= g_quark_from_string("address");
4516 LTT_FIELD_SYMBOL
= g_quark_from_string("symbol");
4517 LTT_FIELD_IP
= g_quark_from_string("ip");
4518 LTT_FIELD_FD
= g_quark_from_string("fd");
4519 LTT_FIELD_STATE
= g_quark_from_string("state");
4520 LTT_FIELD_CPU_ID
= g_quark_from_string("cpu_id");
4522 LTTV_CPU_UNKNOWN
= g_quark_from_string("unknown");
4523 LTTV_CPU_IDLE
= g_quark_from_string("idle");
4524 LTTV_CPU_BUSY
= g_quark_from_string("busy");
4525 LTTV_CPU_IRQ
= g_quark_from_string("irq");
4526 LTTV_CPU_SOFT_IRQ
= g_quark_from_string("softirq");
4527 LTTV_CPU_TRAP
= g_quark_from_string("trap");
4529 LTTV_IRQ_UNKNOWN
= g_quark_from_string("unknown");
4530 LTTV_IRQ_IDLE
= g_quark_from_string("idle");
4531 LTTV_IRQ_BUSY
= g_quark_from_string("busy");
4533 LTTV_BDEV_UNKNOWN
= g_quark_from_string("unknown");
4534 LTTV_BDEV_IDLE
= g_quark_from_string("idle");
4535 LTTV_BDEV_BUSY_READING
= g_quark_from_string("busy_reading");
4536 LTTV_BDEV_BUSY_WRITING
= g_quark_from_string("busy_writing");
4539 static void module_destroy()
4544 LTTV_MODULE("state", "State computation", \
4545 "Update the system state, possibly saving it at intervals", \
4546 module_init
, module_destroy
)