1 /* This file is part of the Linux Trace Toolkit viewer
2 * Copyright (C) 2003-2004 Michel Dagenais
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License Version 2 as
6 * published by the Free Software Foundation;
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
13 * You should have received a copy of the GNU General Public License
14 * along with this program; if not, write to the Free Software
15 * Foundation, Inc., 59 Temple Place - Suite 330, Boston,
25 #include <lttv/lttv.h>
26 #include <lttv/module.h>
27 #include <lttv/state.h>
28 #include <ltt/trace.h>
29 #include <ltt/event.h>
31 #include <ltt/marker-desc.h>
34 #include <ltt/ltt-private.h>
39 * usertrace is there only to be able to update the current CPU of the
40 * usertraces when there is a schedchange. it is a way to link the ProcessState
41 * to the associated usertrace. Link only created upon thread creation.
43 * The cpu id is necessary : it gives us back the current ProcessState when we
44 * are considering data from the usertrace.
47 #define PREALLOCATED_EXECUTION_STACK 10
53 LTT_CHANNEL_GLOBAL_STATE
,
54 LTT_CHANNEL_IRQ_STATE
,
55 LTT_CHANNEL_MODULE_STATE
,
56 LTT_CHANNEL_NETIF_STATE
,
57 LTT_CHANNEL_SOFTIRQ_STATE
,
58 LTT_CHANNEL_SWAP_STATE
,
59 LTT_CHANNEL_SYSCALL_STATE
,
60 LTT_CHANNEL_TASK_STATE
,
62 LTT_CHANNEL_KPROBE_STATE
,
66 LTT_CHANNEL_USERSPACE
,
72 LTT_EVENT_SYSCALL_ENTRY
,
73 LTT_EVENT_SYSCALL_EXIT
,
74 LTT_EVENT_PAGE_FAULT_NOSEM_ENTRY
,
75 LTT_EVENT_PAGE_FAULT_NOSEM_EXIT
,
76 LTT_EVENT_PAGE_FAULT_ENTRY
,
77 LTT_EVENT_PAGE_FAULT_EXIT
,
82 LTT_EVENT_SOFT_IRQ_RAISE
,
83 LTT_EVENT_SOFT_IRQ_ENTRY
,
84 LTT_EVENT_SOFT_IRQ_EXIT
,
85 LTT_EVENT_SCHED_SCHEDULE
,
86 LTT_EVENT_PROCESS_FORK
,
87 LTT_EVENT_KTHREAD_CREATE
,
88 LTT_EVENT_PROCESS_EXIT
,
89 LTT_EVENT_PROCESS_FREE
,
91 LTT_EVENT_PROCESS_STATE
,
92 LTT_EVENT_STATEDUMP_END
,
93 LTT_EVENT_FUNCTION_ENTRY
,
94 LTT_EVENT_FUNCTION_EXIT
,
95 LTT_EVENT_THREAD_BRAND
,
96 LTT_EVENT_REQUEST_ISSUE
,
97 LTT_EVENT_REQUEST_COMPLETE
,
98 LTT_EVENT_LIST_INTERRUPT
,
99 LTT_EVENT_SYS_CALL_TABLE
,
100 LTT_EVENT_SOFTIRQ_VEC
,
101 LTT_EVENT_KPROBE_TABLE
,
107 LTT_FIELD_SYSCALL_ID
,
110 LTT_FIELD_SOFT_IRQ_ID
,
113 LTT_FIELD_PREV_STATE
,
114 LTT_FIELD_PARENT_PID
,
118 LTT_FIELD_CHILD_TGID
,
137 LTTV_STATE_MODE_UNKNOWN
,
138 LTTV_STATE_USER_MODE
,
145 LTTV_STATE_SUBMODE_UNKNOWN
,
146 LTTV_STATE_SUBMODE_NONE
;
150 LTTV_STATE_WAIT_FORK
,
159 LTTV_STATE_UNBRANDED
;
162 LTTV_STATE_USER_THREAD
,
163 LTTV_STATE_KERNEL_THREAD
;
181 LTTV_BDEV_BUSY_READING
,
182 LTTV_BDEV_BUSY_WRITING
;
185 LTTV_STATE_TRACEFILES
,
186 LTTV_STATE_PROCESSES
,
188 LTTV_STATE_RUNNING_PROCESS
,
190 LTTV_STATE_SAVED_STATES
,
191 LTTV_STATE_SAVED_STATES_TIME
,
194 LTTV_STATE_NAME_TABLES
,
195 LTTV_STATE_TRACE_STATE_USE_COUNT
,
196 LTTV_STATE_RESOURCE_CPUS
,
197 LTTV_STATE_RESOURCE_CPUS_COUNT
,
198 LTTV_STATE_RESOURCE_IRQS
,
199 LTTV_STATE_RESOURCE_SOFT_IRQS
,
200 LTTV_STATE_RESOURCE_TRAPS
,
201 LTTV_STATE_RESOURCE_BLKDEVS
;
203 static void create_max_time(LttvTraceState
*tcs
);
205 static void get_max_time(LttvTraceState
*tcs
);
207 static void free_max_time(LttvTraceState
*tcs
);
209 static void create_name_tables(LttvTraceState
*tcs
);
211 static void get_name_tables(LttvTraceState
*tcs
);
213 static void free_name_tables(LttvTraceState
*tcs
);
215 static void free_saved_state(LttvTraceState
*tcs
);
217 static void lttv_state_free_process_table(GHashTable
*processes
);
219 static void lttv_trace_states_read_raw(LttvTraceState
*tcs
, FILE *fp
,
220 GPtrArray
*quarktable
);
222 /* Resource function prototypes */
223 static LttvBdevState
*get_hashed_bdevstate(LttvTraceState
*ts
, guint16 devcode
);
224 static LttvBdevState
*bdevstate_new(void);
225 static void bdevstate_free(LttvBdevState
*);
226 static void bdevstate_free_cb(gpointer key
, gpointer value
, gpointer user_data
);
227 static LttvBdevState
*bdevstate_copy(LttvBdevState
*bds
);
230 void lttv_state_save(LttvTraceState
*self
, LttvAttribute
*container
)
232 LTTV_TRACE_STATE_GET_CLASS(self
)->state_save(self
, container
);
236 void lttv_state_restore(LttvTraceState
*self
, LttvAttribute
*container
)
238 LTTV_TRACE_STATE_GET_CLASS(self
)->state_restore(self
, container
);
242 void lttv_state_state_saved_free(LttvTraceState
*self
,
243 LttvAttribute
*container
)
245 LTTV_TRACE_STATE_GET_CLASS(self
)->state_saved_free(self
, container
);
249 guint
process_hash(gconstpointer key
)
251 guint pid
= ((const LttvProcessState
*)key
)->pid
;
252 return (pid
>>8 ^ pid
>>4 ^ pid
>>2 ^ pid
) ;
256 /* If the hash table hash function is well distributed,
257 * the process_equal should compare different pid */
258 gboolean
process_equal(gconstpointer a
, gconstpointer b
)
260 const LttvProcessState
*process_a
, *process_b
;
263 process_a
= (const LttvProcessState
*)a
;
264 process_b
= (const LttvProcessState
*)b
;
266 if(likely(process_a
->pid
!= process_b
->pid
)) ret
= FALSE
;
267 else if(likely(process_a
->pid
== 0 &&
268 process_a
->cpu
!= process_b
->cpu
)) ret
= FALSE
;
273 static void delete_usertrace(gpointer key
, gpointer value
, gpointer user_data
)
275 g_tree_destroy((GTree
*)value
);
278 static void lttv_state_free_usertraces(GHashTable
*usertraces
)
280 g_hash_table_foreach(usertraces
, delete_usertrace
, NULL
);
281 g_hash_table_destroy(usertraces
);
284 gboolean
rettrue(gpointer key
, gpointer value
, gpointer user_data
)
289 static guint
check_expand(nb
, id
)
294 return max(id
+ 1, nb
* 2);
297 static void expand_name_table(LttvTraceState
*ts
, GQuark
**table
,
298 guint nb
, guint new_nb
)
300 /* Expand an incomplete table */
301 GQuark
*old_table
= *table
;
302 *table
= g_new(GQuark
, new_nb
);
303 memcpy(*table
, old_table
, nb
* sizeof(GQuark
));
306 static void fill_name_table(LttvTraceState
*ts
, GQuark
*table
, guint nb
,
307 guint new_nb
, const char *def_string
)
310 GString
*fe_name
= g_string_new("");
311 for(i
= nb
; i
< new_nb
; i
++) {
312 g_string_printf(fe_name
, "%s %d", def_string
, i
);
313 table
[i
] = g_quark_from_string(fe_name
->str
);
315 g_string_free(fe_name
, TRUE
);
318 static void expand_syscall_table(LttvTraceState
*ts
, int id
)
320 guint new_nb
= check_expand(ts
->nb_syscalls
, id
);
321 if(likely(new_nb
== ts
->nb_syscalls
))
323 expand_name_table(ts
, &ts
->syscall_names
, ts
->nb_syscalls
, new_nb
);
324 fill_name_table(ts
, ts
->syscall_names
, ts
->nb_syscalls
, new_nb
, "syscall");
325 /* Update the table size */
326 ts
->nb_syscalls
= new_nb
;
329 static void expand_kprobe_table(LttvTraceState
*ts
, guint64 ip
, char *symbol
)
331 g_hash_table_insert(ts
->kprobe_hash
, (gpointer
)ip
,
332 (gpointer
)(glong
)g_quark_from_string(symbol
));
335 static void expand_trap_table(LttvTraceState
*ts
, int id
)
337 guint new_nb
= check_expand(ts
->nb_traps
, id
);
339 if(likely(new_nb
== ts
->nb_traps
))
341 expand_name_table(ts
, &ts
->trap_names
, ts
->nb_traps
, new_nb
);
342 fill_name_table(ts
, ts
->trap_names
, ts
->nb_traps
, new_nb
, "trap");
343 /* Update the table size */
344 ts
->nb_traps
= new_nb
;
346 LttvTrapState
*old_table
= ts
->trap_states
;
347 ts
->trap_states
= g_new(LttvTrapState
, new_nb
);
348 memcpy(ts
->trap_states
, old_table
,
349 ts
->nb_traps
* sizeof(LttvTrapState
));
350 for(i
= ts
->nb_traps
; i
< new_nb
; i
++)
351 ts
->trap_states
[i
].running
= 0;
354 static void expand_irq_table(LttvTraceState
*ts
, int id
)
356 guint new_nb
= check_expand(ts
->nb_irqs
, id
);
358 if(likely(new_nb
== ts
->nb_irqs
))
360 expand_name_table(ts
, &ts
->irq_names
, ts
->nb_irqs
, new_nb
);
361 fill_name_table(ts
, ts
->irq_names
, ts
->nb_irqs
, new_nb
, "irq");
363 LttvIRQState
*old_table
= ts
->irq_states
;
364 ts
->irq_states
= g_new(LttvIRQState
, new_nb
);
365 memcpy(ts
->irq_states
, old_table
, ts
->nb_irqs
* sizeof(LttvIRQState
));
366 for(i
= ts
->nb_irqs
; i
< new_nb
; i
++) {
367 ts
->irq_states
[i
].mode_stack
= g_array_new(FALSE
, FALSE
, sizeof(LttvIRQMode
));
370 /* Update the table size */
371 ts
->nb_irqs
= new_nb
;
374 static void expand_soft_irq_table(LttvTraceState
*ts
, int id
)
376 guint new_nb
= check_expand(ts
->nb_soft_irqs
, id
);
378 if(likely(new_nb
== ts
->nb_soft_irqs
))
380 expand_name_table(ts
, &ts
->soft_irq_names
, ts
->nb_soft_irqs
, new_nb
);
381 fill_name_table(ts
, ts
->soft_irq_names
, ts
->nb_soft_irqs
, new_nb
, "softirq");
383 LttvSoftIRQState
*old_table
= ts
->soft_irq_states
;
384 ts
->soft_irq_states
= g_new(LttvSoftIRQState
, new_nb
);
385 memcpy(ts
->soft_irq_states
, old_table
,
386 ts
->nb_soft_irqs
* sizeof(LttvSoftIRQState
));
387 for(i
= ts
->nb_soft_irqs
; i
< new_nb
; i
++)
388 ts
->soft_irq_states
[i
].running
= 0;
390 /* Update the table size */
391 ts
->nb_soft_irqs
= new_nb
;
395 restore_init_state(LttvTraceState
*self
)
397 guint i
, nb_cpus
, nb_irqs
, nb_soft_irqs
, nb_traps
;
399 //LttvTracefileState *tfcs;
401 LttTime start_time
, end_time
;
403 /* Free the process tables */
404 if(self
->processes
!= NULL
) lttv_state_free_process_table(self
->processes
);
405 if(self
->usertraces
!= NULL
) lttv_state_free_usertraces(self
->usertraces
);
406 self
->processes
= g_hash_table_new(process_hash
, process_equal
);
407 self
->usertraces
= g_hash_table_new(g_direct_hash
, g_direct_equal
);
410 /* Seek time to beginning */
411 // Mathieu : fix : don't seek traceset here : causes inconsistency in seek
412 // closest. It's the tracecontext job to seek the trace to the beginning
413 // anyway : the init state might be used at the middle of the trace as well...
414 //g_tree_destroy(self->parent.ts_context->pqueue);
415 //self->parent.ts_context->pqueue = g_tree_new(compare_tracefile);
417 ltt_trace_time_span_get(self
->parent
.t
, &start_time
, &end_time
);
419 //lttv_process_trace_seek_time(&self->parent, ltt_time_zero);
421 nb_cpus
= ltt_trace_get_num_cpu(self
->parent
.t
);
422 nb_irqs
= self
->nb_irqs
;
423 nb_soft_irqs
= self
->nb_soft_irqs
;
424 nb_traps
= self
->nb_traps
;
426 /* Put the per cpu running_process to beginning state : process 0. */
427 for(i
=0; i
< nb_cpus
; i
++) {
428 LttvExecutionState
*es
;
429 self
->running_process
[i
] = lttv_state_create_process(self
, NULL
, i
, 0, 0,
430 LTTV_STATE_UNNAMED
, &start_time
);
431 /* We are not sure is it's a kernel thread or normal thread, put the
432 * bottom stack state to unknown */
433 self
->running_process
[i
]->execution_stack
=
434 g_array_set_size(self
->running_process
[i
]->execution_stack
, 1);
435 es
= self
->running_process
[i
]->state
=
436 &g_array_index(self
->running_process
[i
]->execution_stack
,
437 LttvExecutionState
, 0);
438 es
->t
= LTTV_STATE_MODE_UNKNOWN
;
439 es
->s
= LTTV_STATE_UNNAMED
;
441 //self->running_process[i]->state->s = LTTV_STATE_RUN;
442 self
->running_process
[i
]->cpu
= i
;
444 /* reset cpu states */
445 if(self
->cpu_states
[i
].mode_stack
->len
> 0) {
446 g_array_remove_range(self
->cpu_states
[i
].mode_stack
, 0, self
->cpu_states
[i
].mode_stack
->len
);
447 self
->cpu_states
[i
].last_irq
= -1;
448 self
->cpu_states
[i
].last_soft_irq
= -1;
449 self
->cpu_states
[i
].last_trap
= -1;
453 /* reset irq states */
454 for(i
=0; i
<nb_irqs
; i
++) {
455 if(self
->irq_states
[i
].mode_stack
->len
> 0)
456 g_array_remove_range(self
->irq_states
[i
].mode_stack
, 0, self
->irq_states
[i
].mode_stack
->len
);
459 /* reset softirq states */
460 for(i
=0; i
<nb_soft_irqs
; i
++) {
461 self
->soft_irq_states
[i
].pending
= 0;
462 self
->soft_irq_states
[i
].running
= 0;
465 /* reset trap states */
466 for(i
=0; i
<nb_traps
; i
++) {
467 self
->trap_states
[i
].running
= 0;
470 /* reset bdev states */
471 g_hash_table_foreach(self
->bdev_states
, bdevstate_free_cb
, NULL
);
472 //g_hash_table_steal_all(self->bdev_states);
473 g_hash_table_foreach_steal(self
->bdev_states
, rettrue
, NULL
);
476 nb_tracefile
= self
->parent
.tracefiles
->len
;
478 for(i
= 0 ; i
< nb_tracefile
; i
++) {
480 LTTV_TRACEFILE_STATE(g_array_index(self
->parent
.tracefiles
,
481 LttvTracefileContext
*, i
));
482 ltt_trace_time_span_get(self
->parent
.t
, &tfcs
->parent
.timestamp
, NULL
);
483 // tfcs->saved_position = 0;
484 tfcs
->process
= lttv_state_create_process(tfcs
, NULL
,0);
485 tfcs
->process
->state
->s
= LTTV_STATE_RUN
;
486 tfcs
->process
->last_cpu
= tfcs
->cpu_name
;
487 tfcs
->process
->last_cpu_index
= ltt_tracefile_num(((LttvTracefileContext
*)tfcs
)->tf
);
492 //static LttTime time_zero = {0,0};
494 static gint
compare_usertraces(gconstpointer a
, gconstpointer b
,
497 const LttTime
*t1
= (const LttTime
*)a
;
498 const LttTime
*t2
= (const LttTime
*)b
;
500 return ltt_time_compare(*t1
, *t2
);
503 static void free_usertrace_key(gpointer data
)
508 #define MAX_STRING_LEN 4096
511 state_load_saved_states(LttvTraceState
*tcs
)
514 GPtrArray
*quarktable
;
515 const char *trace_path
;
519 tcs
->has_precomputed_states
= FALSE
;
523 gchar buf
[MAX_STRING_LEN
];
526 trace_path
= g_quark_to_string(ltt_trace_name(tcs
->parent
.t
));
527 strncpy(path
, trace_path
, PATH_MAX
-1);
528 count
= strnlen(trace_path
, PATH_MAX
-1);
529 // quarktable : open, test
530 strncat(path
, "/precomputed/quarktable", PATH_MAX
-count
-1);
531 fp
= fopen(path
, "r");
533 quarktable
= g_ptr_array_sized_new(4096);
535 /* Index 0 is null */
537 if(hdr
== EOF
) return;
538 g_assert(hdr
== HDR_QUARKS
);
542 if(hdr
== EOF
) break;
543 g_assert(hdr
== HDR_QUARK
);
544 g_ptr_array_set_size(quarktable
, q
+1);
547 fread(&buf
[i
], sizeof(gchar
), 1, fp
);
548 if(buf
[i
] == '\0' || feof(fp
)) break;
551 len
= strnlen(buf
, MAX_STRING_LEN
-1);
552 g_ptr_array_index (quarktable
, q
) = g_new(gchar
, len
+1);
553 strncpy(g_ptr_array_index (quarktable
, q
), buf
, len
+1);
559 // saved_states : open, test
560 strncpy(path
, trace_path
, PATH_MAX
-1);
561 count
= strnlen(trace_path
, PATH_MAX
-1);
562 strncat(path
, "/precomputed/states", PATH_MAX
-count
-1);
563 fp
= fopen(path
, "r");
567 if(hdr
!= HDR_TRACE
) goto end
;
569 lttv_trace_states_read_raw(tcs
, fp
, quarktable
);
571 tcs
->has_precomputed_states
= TRUE
;
576 /* Free the quarktable */
577 for(i
=0; i
<quarktable
->len
; i
++) {
578 string
= g_ptr_array_index (quarktable
, i
);
581 g_ptr_array_free(quarktable
, TRUE
);
586 init(LttvTracesetState
*self
, LttvTraceset
*ts
)
588 guint i
, j
, nb_trace
, nb_tracefile
, nb_cpu
;
591 LttvTraceContext
*tc
;
595 LttvTracefileState
*tfcs
;
597 LttvAttributeValue v
;
599 LTTV_TRACESET_CONTEXT_CLASS(g_type_class_peek(LTTV_TRACESET_CONTEXT_TYPE
))->
600 init((LttvTracesetContext
*)self
, ts
);
602 nb_trace
= lttv_traceset_number(ts
);
603 for(i
= 0 ; i
< nb_trace
; i
++) {
604 tc
= self
->parent
.traces
[i
];
605 tcs
= LTTV_TRACE_STATE(tc
);
606 tcs
->save_interval
= LTTV_STATE_SAVE_INTERVAL
;
607 lttv_attribute_find(tcs
->parent
.t_a
, LTTV_STATE_TRACE_STATE_USE_COUNT
,
611 if(*(v
.v_uint
) == 1) {
612 create_name_tables(tcs
);
613 create_max_time(tcs
);
615 get_name_tables(tcs
);
618 nb_tracefile
= tc
->tracefiles
->len
;
619 nb_cpu
= ltt_trace_get_num_cpu(tc
->t
);
620 nb_irq
= tcs
->nb_irqs
;
621 tcs
->processes
= NULL
;
622 tcs
->usertraces
= NULL
;
623 tcs
->running_process
= g_new(LttvProcessState
*, nb_cpu
);
625 /* init cpu resource stuff */
626 tcs
->cpu_states
= g_new(LttvCPUState
, nb_cpu
);
627 for(j
= 0; j
<nb_cpu
; j
++) {
628 tcs
->cpu_states
[j
].mode_stack
= g_array_new(FALSE
, FALSE
, sizeof(LttvCPUMode
));
629 tcs
->cpu_states
[j
].last_irq
= -1;
630 tcs
->cpu_states
[j
].last_soft_irq
= -1;
631 tcs
->cpu_states
[j
].last_trap
= -1;
632 g_assert(tcs
->cpu_states
[j
].mode_stack
!= NULL
);
635 /* init irq resource stuff */
636 tcs
->irq_states
= g_new(LttvIRQState
, nb_irq
);
637 for(j
= 0; j
<nb_irq
; j
++) {
638 tcs
->irq_states
[j
].mode_stack
= g_array_new(FALSE
, FALSE
, sizeof(LttvIRQMode
));
639 g_assert(tcs
->irq_states
[j
].mode_stack
!= NULL
);
642 /* init soft irq stuff */
643 /* the kernel has a statically fixed max of 32 softirqs */
644 tcs
->soft_irq_states
= g_new(LttvSoftIRQState
, tcs
->nb_soft_irqs
);
646 /* init trap stuff */
647 tcs
->trap_states
= g_new(LttvTrapState
, tcs
->nb_traps
);
649 /* init bdev resource stuff */
650 tcs
->bdev_states
= g_hash_table_new(g_int_hash
, g_int_equal
);
652 restore_init_state(tcs
);
653 for(j
= 0 ; j
< nb_tracefile
; j
++) {
655 LTTV_TRACEFILE_STATE(g_array_index(tc
->tracefiles
,
656 LttvTracefileContext
*, j
));
657 tfcs
->tracefile_name
= ltt_tracefile_name(tfcs
->parent
.tf
);
658 tfcs
->cpu
= ltt_tracefile_cpu(tfcs
->parent
.tf
);
659 tfcs
->cpu_state
= &(tcs
->cpu_states
[tfcs
->cpu
]);
660 if(ltt_tracefile_tid(tfcs
->parent
.tf
) != 0) {
661 /* It's a Usertrace */
662 guint tid
= ltt_tracefile_tid(tfcs
->parent
.tf
);
663 GTree
*usertrace_tree
= (GTree
*)g_hash_table_lookup(tcs
->usertraces
,
664 GUINT_TO_POINTER(tid
));
665 if(!usertrace_tree
) {
666 usertrace_tree
= g_tree_new_full(compare_usertraces
,
667 NULL
, free_usertrace_key
, NULL
);
668 g_hash_table_insert(tcs
->usertraces
,
669 GUINT_TO_POINTER(tid
), usertrace_tree
);
671 LttTime
*timestamp
= g_new(LttTime
, 1);
672 *timestamp
= ltt_interpolate_time_from_tsc(tfcs
->parent
.tf
,
673 ltt_tracefile_creation(tfcs
->parent
.tf
));
674 g_tree_insert(usertrace_tree
, timestamp
, tfcs
);
678 /* See if the trace has saved states */
679 state_load_saved_states(tcs
);
684 fini(LttvTracesetState
*self
)
690 //LttvTracefileState *tfcs;
692 LttvAttributeValue v
;
694 nb_trace
= lttv_traceset_number(LTTV_TRACESET_CONTEXT(self
)->ts
);
695 for(i
= 0 ; i
< nb_trace
; i
++) {
696 tcs
= (LttvTraceState
*)(LTTV_TRACESET_CONTEXT(self
)->traces
[i
]);
697 lttv_attribute_find(tcs
->parent
.t_a
, LTTV_STATE_TRACE_STATE_USE_COUNT
,
700 g_assert(*(v
.v_uint
) != 0);
703 if(*(v
.v_uint
) == 0) {
704 free_name_tables(tcs
);
706 free_saved_state(tcs
);
708 g_free(tcs
->running_process
);
709 tcs
->running_process
= NULL
;
710 lttv_state_free_process_table(tcs
->processes
);
711 lttv_state_free_usertraces(tcs
->usertraces
);
712 tcs
->processes
= NULL
;
713 tcs
->usertraces
= NULL
;
715 LTTV_TRACESET_CONTEXT_CLASS(g_type_class_peek(LTTV_TRACESET_CONTEXT_TYPE
))->
716 fini((LttvTracesetContext
*)self
);
720 static LttvTracesetContext
*
721 new_traceset_context(LttvTracesetContext
*self
)
723 return LTTV_TRACESET_CONTEXT(g_object_new(LTTV_TRACESET_STATE_TYPE
, NULL
));
727 static LttvTraceContext
*
728 new_trace_context(LttvTracesetContext
*self
)
730 return LTTV_TRACE_CONTEXT(g_object_new(LTTV_TRACE_STATE_TYPE
, NULL
));
734 static LttvTracefileContext
*
735 new_tracefile_context(LttvTracesetContext
*self
)
737 return LTTV_TRACEFILE_CONTEXT(g_object_new(LTTV_TRACEFILE_STATE_TYPE
, NULL
));
741 /* Write the process state of the trace */
743 static void write_process_state(gpointer key
, gpointer value
,
746 LttvProcessState
*process
;
748 LttvExecutionState
*es
;
750 FILE *fp
= (FILE *)user_data
;
755 process
= (LttvProcessState
*)value
;
757 " <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",
758 process
, process
->pid
, process
->tgid
, process
->ppid
,
759 g_quark_to_string(process
->type
),
760 process
->creation_time
.tv_sec
,
761 process
->creation_time
.tv_nsec
,
762 process
->insertion_time
.tv_sec
,
763 process
->insertion_time
.tv_nsec
,
764 g_quark_to_string(process
->name
),
765 g_quark_to_string(process
->brand
),
766 process
->cpu
, process
->free_events
);
768 for(i
= 0 ; i
< process
->execution_stack
->len
; i
++) {
769 es
= &g_array_index(process
->execution_stack
, LttvExecutionState
, i
);
770 fprintf(fp
, " <ES MODE=\"%s\" SUBMODE=\"%s\" ENTRY_S=%lu ENTRY_NS=%lu",
771 g_quark_to_string(es
->t
), g_quark_to_string(es
->n
),
772 es
->entry
.tv_sec
, es
->entry
.tv_nsec
);
773 fprintf(fp
, " CHANGE_S=%lu CHANGE_NS=%lu STATUS=\"%s\"/>\n",
774 es
->change
.tv_sec
, es
->change
.tv_nsec
, g_quark_to_string(es
->s
));
777 for(i
= 0 ; i
< process
->user_stack
->len
; i
++) {
778 address
= g_array_index(process
->user_stack
, guint64
, i
);
779 fprintf(fp
, " <USER_STACK ADDRESS=\"%" PRIu64
"\"/>\n",
783 if(process
->usertrace
) {
784 fprintf(fp
, " <USERTRACE NAME=\"%s\" CPU=%u\n/>",
785 g_quark_to_string(process
->usertrace
->tracefile_name
),
786 process
->usertrace
->cpu
);
790 fprintf(fp
, " </PROCESS>\n");
794 void lttv_state_write(LttvTraceState
*self
, LttTime t
, FILE *fp
)
796 guint i
, nb_tracefile
, nb_block
, offset
;
799 LttvTracefileState
*tfcs
;
803 LttEventPosition
*ep
;
807 ep
= ltt_event_position_new();
809 fprintf(fp
,"<PROCESS_STATE TIME_S=%lu TIME_NS=%lu>\n", t
.tv_sec
, t
.tv_nsec
);
811 g_hash_table_foreach(self
->processes
, write_process_state
, fp
);
813 nb_cpus
= ltt_trace_get_num_cpu(self
->parent
.t
);
814 for(i
=0;i
<nb_cpus
;i
++) {
815 fprintf(fp
," <CPU NUM=%u RUNNING_PROCESS=%u>\n",
816 i
, self
->running_process
[i
]->pid
);
819 nb_tracefile
= self
->parent
.tracefiles
->len
;
821 for(i
= 0 ; i
< nb_tracefile
; i
++) {
823 LTTV_TRACEFILE_STATE(g_array_index(self
->parent
.tracefiles
,
824 LttvTracefileContext
*, i
));
825 fprintf(fp
, " <TRACEFILE TIMESTAMP_S=%lu TIMESTAMP_NS=%lu",
826 tfcs
->parent
.timestamp
.tv_sec
,
827 tfcs
->parent
.timestamp
.tv_nsec
);
828 LttEvent
*e
= ltt_tracefile_get_event(tfcs
->parent
.tf
);
829 if(e
== NULL
) fprintf(fp
,"/>\n");
831 ltt_event_position(e
, ep
);
832 ltt_event_position_get(ep
, &tf
, &nb_block
, &offset
, &tsc
);
833 fprintf(fp
, " BLOCK=%u OFFSET=%u TSC=%" PRIu64
"/>\n", nb_block
, offset
,
838 fprintf(fp
,"</PROCESS_STATE>\n");
842 static void write_process_state_raw(gpointer key
, gpointer value
,
845 LttvProcessState
*process
;
847 LttvExecutionState
*es
;
849 FILE *fp
= (FILE *)user_data
;
854 process
= (LttvProcessState
*)value
;
855 fputc(HDR_PROCESS
, fp
);
856 //fwrite(&header, sizeof(header), 1, fp);
857 //fprintf(fp, "%s", g_quark_to_string(process->type));
859 fwrite(&process
->type
, sizeof(process
->type
), 1, fp
);
860 //fprintf(fp, "%s", g_quark_to_string(process->name));
862 fwrite(&process
->name
, sizeof(process
->name
), 1, fp
);
863 //fprintf(fp, "%s", g_quark_to_string(process->brand));
865 fwrite(&process
->brand
, sizeof(process
->brand
), 1, fp
);
866 fwrite(&process
->pid
, sizeof(process
->pid
), 1, fp
);
867 fwrite(&process
->free_events
, sizeof(process
->free_events
), 1, fp
);
868 fwrite(&process
->tgid
, sizeof(process
->tgid
), 1, fp
);
869 fwrite(&process
->ppid
, sizeof(process
->ppid
), 1, fp
);
870 fwrite(&process
->cpu
, sizeof(process
->cpu
), 1, fp
);
871 fwrite(&process
->creation_time
, sizeof(process
->creation_time
), 1, fp
);
872 fwrite(&process
->insertion_time
, sizeof(process
->insertion_time
), 1, fp
);
876 " <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",
877 process
, process
->pid
, process
->tgid
, process
->ppid
,
878 g_quark_to_string(process
->type
),
879 process
->creation_time
.tv_sec
,
880 process
->creation_time
.tv_nsec
,
881 process
->insertion_time
.tv_sec
,
882 process
->insertion_time
.tv_nsec
,
883 g_quark_to_string(process
->name
),
884 g_quark_to_string(process
->brand
),
888 for(i
= 0 ; i
< process
->execution_stack
->len
; i
++) {
889 es
= &g_array_index(process
->execution_stack
, LttvExecutionState
, i
);
892 //fprintf(fp, "%s", g_quark_to_string(es->t));
894 fwrite(&es
->t
, sizeof(es
->t
), 1, fp
);
895 //fprintf(fp, "%s", g_quark_to_string(es->n));
897 fwrite(&es
->n
, sizeof(es
->n
), 1, fp
);
898 //fprintf(fp, "%s", g_quark_to_string(es->s));
900 fwrite(&es
->s
, sizeof(es
->s
), 1, fp
);
901 fwrite(&es
->entry
, sizeof(es
->entry
), 1, fp
);
902 fwrite(&es
->change
, sizeof(es
->change
), 1, fp
);
903 fwrite(&es
->cum_cpu_time
, sizeof(es
->cum_cpu_time
), 1, fp
);
905 fprintf(fp
, " <ES MODE=\"%s\" SUBMODE=\"%s\" ENTRY_S=%lu ENTRY_NS=%lu",
906 g_quark_to_string(es
->t
), g_quark_to_string(es
->n
),
907 es
->entry
.tv_sec
, es
->entry
.tv_nsec
);
908 fprintf(fp
, " CHANGE_S=%lu CHANGE_NS=%lu STATUS=\"%s\"/>\n",
909 es
->change
.tv_sec
, es
->change
.tv_nsec
, g_quark_to_string(es
->s
));
913 for(i
= 0 ; i
< process
->user_stack
->len
; i
++) {
914 address
= g_array_index(process
->user_stack
, guint64
, i
);
915 fputc(HDR_USER_STACK
, fp
);
916 fwrite(&address
, sizeof(address
), 1, fp
);
918 fprintf(fp
, " <USER_STACK ADDRESS=\"%llu\"/>\n",
923 if(process
->usertrace
) {
924 fputc(HDR_USERTRACE
, fp
);
925 //fprintf(fp, "%s", g_quark_to_string(process->usertrace->tracefile_name));
927 fwrite(&process
->usertrace
->tracefile_name
,
928 sizeof(process
->usertrace
->tracefile_name
), 1, fp
);
929 fwrite(&process
->usertrace
->cpu
, sizeof(process
->usertrace
->cpu
), 1, fp
);
931 fprintf(fp
, " <USERTRACE NAME=\"%s\" CPU=%u\n/>",
932 g_quark_to_string(process
->usertrace
->tracefile_name
),
933 process
->usertrace
->cpu
);
940 void lttv_state_write_raw(LttvTraceState
*self
, LttTime t
, FILE *fp
)
942 guint i
, nb_tracefile
, nb_block
, offset
;
945 LttvTracefileState
*tfcs
;
949 LttEventPosition
*ep
;
953 ep
= ltt_event_position_new();
955 //fprintf(fp,"<PROCESS_STATE TIME_S=%lu TIME_NS=%lu>\n", t.tv_sec, t.tv_nsec);
956 fputc(HDR_PROCESS_STATE
, fp
);
957 fwrite(&t
, sizeof(t
), 1, fp
);
959 g_hash_table_foreach(self
->processes
, write_process_state_raw
, fp
);
961 nb_cpus
= ltt_trace_get_num_cpu(self
->parent
.t
);
962 for(i
=0;i
<nb_cpus
;i
++) {
964 fwrite(&i
, sizeof(i
), 1, fp
); /* cpu number */
965 fwrite(&self
->running_process
[i
]->pid
,
966 sizeof(self
->running_process
[i
]->pid
), 1, fp
);
967 //fprintf(fp," <CPU NUM=%u RUNNING_PROCESS=%u>\n",
968 // i, self->running_process[i]->pid);
971 nb_tracefile
= self
->parent
.tracefiles
->len
;
973 for(i
= 0 ; i
< nb_tracefile
; i
++) {
975 LTTV_TRACEFILE_STATE(g_array_index(self
->parent
.tracefiles
,
976 LttvTracefileContext
*, i
));
977 // fprintf(fp, " <TRACEFILE TIMESTAMP_S=%lu TIMESTAMP_NS=%lu",
978 // tfcs->parent.timestamp.tv_sec,
979 // tfcs->parent.timestamp.tv_nsec);
980 fputc(HDR_TRACEFILE
, fp
);
981 fwrite(&tfcs
->parent
.timestamp
, sizeof(tfcs
->parent
.timestamp
), 1, fp
);
982 /* Note : if timestamp if LTT_TIME_INFINITE, there will be no
983 * position following : end of trace */
984 LttEvent
*e
= ltt_tracefile_get_event(tfcs
->parent
.tf
);
986 ltt_event_position(e
, ep
);
987 ltt_event_position_get(ep
, &tf
, &nb_block
, &offset
, &tsc
);
988 //fprintf(fp, " BLOCK=%u OFFSET=%u TSC=%llu/>\n", nb_block, offset,
990 fwrite(&nb_block
, sizeof(nb_block
), 1, fp
);
991 fwrite(&offset
, sizeof(offset
), 1, fp
);
992 fwrite(&tsc
, sizeof(tsc
), 1, fp
);
999 /* Read process state from a file */
1001 /* Called because a HDR_PROCESS was found */
1002 static void read_process_state_raw(LttvTraceState
*self
, FILE *fp
,
1003 GPtrArray
*quarktable
)
1005 LttvExecutionState
*es
;
1006 LttvProcessState
*process
, *parent_process
;
1007 LttvProcessState tmp
;
1012 /* TODO : check return value */
1013 fread(&tmp
.type
, sizeof(tmp
.type
), 1, fp
);
1014 fread(&tmp
.name
, sizeof(tmp
.name
), 1, fp
);
1015 fread(&tmp
.brand
, sizeof(tmp
.brand
), 1, fp
);
1016 fread(&tmp
.pid
, sizeof(tmp
.pid
), 1, fp
);
1017 fread(&tmp
.free_events
, sizeof(tmp
.free_events
), 1, fp
);
1018 fread(&tmp
.tgid
, sizeof(tmp
.tgid
), 1, fp
);
1019 fread(&tmp
.ppid
, sizeof(tmp
.ppid
), 1, fp
);
1020 fread(&tmp
.cpu
, sizeof(tmp
.cpu
), 1, fp
);
1021 fread(&tmp
.creation_time
, sizeof(tmp
.creation_time
), 1, fp
);
1022 fread(&tmp
.insertion_time
, sizeof(tmp
.insertion_time
), 1, fp
);
1025 process
= lttv_state_find_process(self
, tmp
.cpu
, tmp
.pid
);
1027 /* We must link to the parent */
1028 parent_process
= lttv_state_find_process_or_create(self
, ANY_CPU
, tmp
.ppid
,
1030 process
= lttv_state_find_process(self
, ANY_CPU
, tmp
.pid
);
1031 if(process
== NULL
) {
1032 process
= lttv_state_create_process(self
, parent_process
, tmp
.cpu
,
1034 g_quark_from_string((gchar
*)g_ptr_array_index(quarktable
, tmp
.name
)),
1035 &tmp
.creation_time
);
1038 process
->insertion_time
= tmp
.insertion_time
;
1039 process
->creation_time
= tmp
.creation_time
;
1040 process
->type
= g_quark_from_string(
1041 (gchar
*)g_ptr_array_index(quarktable
, tmp
.type
));
1042 process
->tgid
= tmp
.tgid
;
1043 process
->ppid
= tmp
.ppid
;
1044 process
->brand
= g_quark_from_string(
1045 (gchar
*)g_ptr_array_index(quarktable
, tmp
.brand
));
1047 g_quark_from_string((gchar
*)g_ptr_array_index(quarktable
, tmp
.name
));
1048 process
->free_events
= tmp
.free_events
;
1051 if(feof(fp
) || ferror(fp
)) goto end_loop
;
1053 gint hdr
= fgetc(fp
);
1054 if(hdr
== EOF
) goto end_loop
;
1058 process
->execution_stack
=
1059 g_array_set_size(process
->execution_stack
,
1060 process
->execution_stack
->len
+ 1);
1061 es
= &g_array_index(process
->execution_stack
, LttvExecutionState
,
1062 process
->execution_stack
->len
-1);
1063 process
->state
= es
;
1065 fread(&es
->t
, sizeof(es
->t
), 1, fp
);
1066 es
->t
= g_quark_from_string(
1067 (gchar
*)g_ptr_array_index(quarktable
, es
->t
));
1068 fread(&es
->n
, sizeof(es
->n
), 1, fp
);
1069 es
->n
= g_quark_from_string(
1070 (gchar
*)g_ptr_array_index(quarktable
, es
->n
));
1071 fread(&es
->s
, sizeof(es
->s
), 1, fp
);
1072 es
->s
= g_quark_from_string(
1073 (gchar
*)g_ptr_array_index(quarktable
, es
->s
));
1074 fread(&es
->entry
, sizeof(es
->entry
), 1, fp
);
1075 fread(&es
->change
, sizeof(es
->change
), 1, fp
);
1076 fread(&es
->cum_cpu_time
, sizeof(es
->cum_cpu_time
), 1, fp
);
1078 case HDR_USER_STACK
:
1079 process
->user_stack
= g_array_set_size(process
->user_stack
,
1080 process
->user_stack
->len
+ 1);
1081 address
= &g_array_index(process
->user_stack
, guint64
,
1082 process
->user_stack
->len
-1);
1083 fread(address
, sizeof(address
), 1, fp
);
1084 process
->current_function
= *address
;
1087 fread(&tmpq
, sizeof(tmpq
), 1, fp
);
1088 fread(&process
->usertrace
->cpu
, sizeof(process
->usertrace
->cpu
), 1, fp
);
1100 /* Called because a HDR_PROCESS_STATE was found */
1101 /* Append a saved state to the trace states */
1102 void lttv_state_read_raw(LttvTraceState
*self
, FILE *fp
, GPtrArray
*quarktable
)
1104 guint i
, nb_tracefile
, nb_block
, offset
;
1106 LttvTracefileState
*tfcs
;
1108 LttEventPosition
*ep
;
1116 LttvAttribute
*saved_states_tree
, *saved_state_tree
;
1118 LttvAttributeValue value
;
1119 GTree
*pqueue
= self
->parent
.ts_context
->pqueue
;
1120 ep
= ltt_event_position_new();
1122 restore_init_state(self
);
1124 fread(&t
, sizeof(t
), 1, fp
);
1127 if(feof(fp
) || ferror(fp
)) goto end_loop
;
1129 if(hdr
== EOF
) goto end_loop
;
1133 /* Call read_process_state_raw */
1134 read_process_state_raw(self
, fp
, quarktable
);
1142 case HDR_USER_STACK
:
1144 case HDR_PROCESS_STATE
:
1150 g_error("Error while parsing saved state file : unknown data header %d",
1156 nb_cpus
= ltt_trace_get_num_cpu(self
->parent
.t
);
1157 for(i
=0;i
<nb_cpus
;i
++) {
1160 g_assert(hdr
== HDR_CPU
);
1161 fread(&cpu_num
, sizeof(cpu_num
), 1, fp
); /* cpu number */
1162 g_assert(i
== cpu_num
);
1163 fread(&self
->running_process
[i
]->pid
,
1164 sizeof(self
->running_process
[i
]->pid
), 1, fp
);
1167 nb_tracefile
= self
->parent
.tracefiles
->len
;
1169 for(i
= 0 ; i
< nb_tracefile
; i
++) {
1171 LTTV_TRACEFILE_STATE(g_array_index(self
->parent
.tracefiles
,
1172 LttvTracefileContext
*, i
));
1173 // fprintf(fp, " <TRACEFILE TIMESTAMP_S=%lu TIMESTAMP_NS=%lu",
1174 // tfcs->parent.timestamp.tv_sec,
1175 // tfcs->parent.timestamp.tv_nsec);
1176 g_tree_remove(pqueue
, &tfcs
->parent
);
1178 g_assert(hdr
== HDR_TRACEFILE
);
1179 fread(&tfcs
->parent
.timestamp
, sizeof(tfcs
->parent
.timestamp
), 1, fp
);
1180 /* Note : if timestamp if LTT_TIME_INFINITE, there will be no
1181 * position following : end of trace */
1182 if(ltt_time_compare(tfcs
->parent
.timestamp
, ltt_time_infinite
) != 0) {
1183 fread(&nb_block
, sizeof(nb_block
), 1, fp
);
1184 fread(&offset
, sizeof(offset
), 1, fp
);
1185 fread(&tsc
, sizeof(tsc
), 1, fp
);
1186 ltt_event_position_set(ep
, tfcs
->parent
.tf
, nb_block
, offset
, tsc
);
1187 gint ret
= ltt_tracefile_seek_position(tfcs
->parent
.tf
, ep
);
1189 g_tree_insert(pqueue
, &tfcs
->parent
, &tfcs
->parent
);
1194 saved_states_tree
= lttv_attribute_find_subdir(self
->parent
.t_a
,
1195 LTTV_STATE_SAVED_STATES
);
1196 saved_state_tree
= g_object_new(LTTV_ATTRIBUTE_TYPE
, NULL
);
1197 value
= lttv_attribute_add(saved_states_tree
,
1198 lttv_attribute_get_number(saved_states_tree
), LTTV_GOBJECT
);
1199 *(value
.v_gobject
) = (GObject
*)saved_state_tree
;
1200 value
= lttv_attribute_add(saved_state_tree
, LTTV_STATE_TIME
, LTTV_TIME
);
1201 *(value
.v_time
) = t
;
1202 lttv_state_save(self
, saved_state_tree
);
1203 g_debug("Saving state at time %lu.%lu", t
.tv_sec
,
1206 *(self
->max_time_state_recomputed_in_seek
) = t
;
1210 /* Called when a HDR_TRACE is found */
1211 void lttv_trace_states_read_raw(LttvTraceState
*tcs
, FILE *fp
,
1212 GPtrArray
*quarktable
)
1217 if(feof(fp
) || ferror(fp
)) goto end_loop
;
1219 if(hdr
== EOF
) goto end_loop
;
1222 case HDR_PROCESS_STATE
:
1223 /* Call read_process_state_raw */
1224 lttv_state_read_raw(tcs
, fp
, quarktable
);
1232 case HDR_USER_STACK
:
1236 g_error("Error while parsing saved state file :"
1237 " unexpected data header %d",
1241 g_error("Error while parsing saved state file : unknown data header %d",
1246 *(tcs
->max_time_state_recomputed_in_seek
) = tcs
->parent
.time_span
.end_time
;
1247 restore_init_state(tcs
);
1248 lttv_process_trace_seek_time(&tcs
->parent
, ltt_time_zero
);
1254 /* Copy each process from an existing hash table to a new one */
1256 static void copy_process_state(gpointer key
, gpointer value
,gpointer user_data
)
1258 LttvProcessState
*process
, *new_process
;
1260 GHashTable
*new_processes
= (GHashTable
*)user_data
;
1264 process
= (LttvProcessState
*)value
;
1265 new_process
= g_new(LttvProcessState
, 1);
1266 *new_process
= *process
;
1267 new_process
->execution_stack
= g_array_sized_new(FALSE
, FALSE
,
1268 sizeof(LttvExecutionState
), PREALLOCATED_EXECUTION_STACK
);
1269 new_process
->execution_stack
=
1270 g_array_set_size(new_process
->execution_stack
,
1271 process
->execution_stack
->len
);
1272 for(i
= 0 ; i
< process
->execution_stack
->len
; i
++) {
1273 g_array_index(new_process
->execution_stack
, LttvExecutionState
, i
) =
1274 g_array_index(process
->execution_stack
, LttvExecutionState
, i
);
1276 new_process
->state
= &g_array_index(new_process
->execution_stack
,
1277 LttvExecutionState
, new_process
->execution_stack
->len
- 1);
1278 new_process
->user_stack
= g_array_sized_new(FALSE
, FALSE
,
1279 sizeof(guint64
), 0);
1280 new_process
->user_stack
=
1281 g_array_set_size(new_process
->user_stack
,
1282 process
->user_stack
->len
);
1283 for(i
= 0 ; i
< process
->user_stack
->len
; i
++) {
1284 g_array_index(new_process
->user_stack
, guint64
, i
) =
1285 g_array_index(process
->user_stack
, guint64
, i
);
1287 new_process
->current_function
= process
->current_function
;
1288 g_hash_table_insert(new_processes
, new_process
, new_process
);
1292 static GHashTable
*lttv_state_copy_process_table(GHashTable
*processes
)
1294 GHashTable
*new_processes
= g_hash_table_new(process_hash
, process_equal
);
1296 g_hash_table_foreach(processes
, copy_process_state
, new_processes
);
1297 return new_processes
;
1300 static LttvCPUState
*lttv_state_copy_cpu_states(LttvCPUState
*states
, guint n
)
1303 LttvCPUState
*retval
;
1305 retval
= g_new(LttvCPUState
, n
);
1307 for(i
=0; i
<n
; i
++) {
1308 retval
[i
].mode_stack
= g_array_new(FALSE
, FALSE
, sizeof(LttvCPUMode
));
1309 retval
[i
].last_irq
= states
[i
].last_irq
;
1310 retval
[i
].last_soft_irq
= states
[i
].last_soft_irq
;
1311 retval
[i
].last_trap
= states
[i
].last_trap
;
1312 g_array_set_size(retval
[i
].mode_stack
, states
[i
].mode_stack
->len
);
1313 for(j
=0; j
<states
[i
].mode_stack
->len
; j
++) {
1314 g_array_index(retval
[i
].mode_stack
, GQuark
, j
) = g_array_index(states
[i
].mode_stack
, GQuark
, j
);
1321 static void lttv_state_free_cpu_states(LttvCPUState
*states
, guint n
)
1325 for(i
=0; i
<n
; i
++) {
1326 g_array_free(states
[i
].mode_stack
, TRUE
);
1332 static LttvIRQState
*lttv_state_copy_irq_states(LttvIRQState
*states
, guint n
)
1335 LttvIRQState
*retval
;
1337 retval
= g_new(LttvIRQState
, n
);
1339 for(i
=0; i
<n
; i
++) {
1340 retval
[i
].mode_stack
= g_array_new(FALSE
, FALSE
, sizeof(LttvIRQMode
));
1341 g_array_set_size(retval
[i
].mode_stack
, states
[i
].mode_stack
->len
);
1342 for(j
=0; j
<states
[i
].mode_stack
->len
; j
++) {
1343 g_array_index(retval
[i
].mode_stack
, GQuark
, j
) = g_array_index(states
[i
].mode_stack
, GQuark
, j
);
1350 static void lttv_state_free_irq_states(LttvIRQState
*states
, guint n
)
1354 for(i
=0; i
<n
; i
++) {
1355 g_array_free(states
[i
].mode_stack
, TRUE
);
1361 static LttvSoftIRQState
*lttv_state_copy_soft_irq_states(LttvSoftIRQState
*states
, guint n
)
1364 LttvSoftIRQState
*retval
;
1366 retval
= g_new(LttvSoftIRQState
, n
);
1368 for(i
=0; i
<n
; i
++) {
1369 retval
[i
].pending
= states
[i
].pending
;
1370 retval
[i
].running
= states
[i
].running
;
1376 static void lttv_state_free_soft_irq_states(LttvSoftIRQState
*states
, guint n
)
1381 static LttvTrapState
*lttv_state_copy_trap_states(LttvTrapState
*states
, guint n
)
1384 LttvTrapState
*retval
;
1386 retval
= g_new(LttvTrapState
, n
);
1388 for(i
=0; i
<n
; i
++) {
1389 retval
[i
].running
= states
[i
].running
;
1395 static void lttv_state_free_trap_states(LttvTrapState
*states
, guint n
)
1400 /* bdevstate stuff */
1402 static LttvBdevState
*get_hashed_bdevstate(LttvTraceState
*ts
, guint16 devcode
)
1404 gint devcode_gint
= devcode
;
1405 gpointer bdev
= g_hash_table_lookup(ts
->bdev_states
, &devcode_gint
);
1407 LttvBdevState
*bdevstate
= g_new(LttvBdevState
, 1);
1408 bdevstate
->mode_stack
= g_array_new(FALSE
, FALSE
, sizeof(GQuark
));
1410 gint
* key
= g_new(gint
, 1);
1412 g_hash_table_insert(ts
->bdev_states
, key
, bdevstate
);
1420 static LttvBdevState
*bdevstate_new(void)
1422 LttvBdevState
*retval
;
1423 retval
= g_new(LttvBdevState
, 1);
1424 retval
->mode_stack
= g_array_new(FALSE
, FALSE
, sizeof(GQuark
));
1429 static void bdevstate_free(LttvBdevState
*bds
)
1431 g_array_free(bds
->mode_stack
, TRUE
);
1435 static void bdevstate_free_cb(gpointer key
, gpointer value
, gpointer user_data
)
1437 LttvBdevState
*bds
= (LttvBdevState
*) value
;
1439 bdevstate_free(bds
);
1442 static LttvBdevState
*bdevstate_copy(LttvBdevState
*bds
)
1444 LttvBdevState
*retval
;
1446 retval
= bdevstate_new();
1447 g_array_insert_vals(retval
->mode_stack
, 0, bds
->mode_stack
->data
, bds
->mode_stack
->len
);
1452 static void insert_and_copy_bdev_state(gpointer k
, gpointer v
, gpointer u
)
1454 //GHashTable *ht = (GHashTable *)u;
1455 LttvBdevState
*bds
= (LttvBdevState
*)v
;
1456 LttvBdevState
*newbds
;
1458 newbds
= bdevstate_copy(bds
);
1460 g_hash_table_insert(u
, k
, newbds
);
1463 static GHashTable
*lttv_state_copy_blkdev_hashtable(GHashTable
*ht
)
1467 retval
= g_hash_table_new(g_int_hash
, g_int_equal
);
1469 g_hash_table_foreach(ht
, insert_and_copy_bdev_state
, retval
);
1474 /* Free a hashtable and the LttvBdevState structures its values
1477 static void lttv_state_free_blkdev_hashtable(GHashTable
*ht
)
1479 g_hash_table_foreach(ht
, bdevstate_free_cb
, NULL
);
1480 g_hash_table_destroy(ht
);
1483 /* The saved state for each trace contains a member "processes", which
1484 stores a copy of the process table, and a member "tracefiles" with
1485 one entry per tracefile. Each tracefile has a "process" member pointing
1486 to the current process and a "position" member storing the tracefile
1487 position (needed to seek to the current "next" event. */
1489 static void state_save(LttvTraceState
*self
, LttvAttribute
*container
)
1491 guint i
, nb_tracefile
, nb_cpus
, nb_irqs
, nb_soft_irqs
, nb_traps
;
1493 LttvTracefileState
*tfcs
;
1495 LttvAttribute
*tracefiles_tree
, *tracefile_tree
;
1497 guint
*running_process
;
1499 LttvAttributeValue value
;
1501 LttEventPosition
*ep
;
1503 tracefiles_tree
= lttv_attribute_find_subdir(container
,
1504 LTTV_STATE_TRACEFILES
);
1506 value
= lttv_attribute_add(container
, LTTV_STATE_PROCESSES
,
1508 *(value
.v_pointer
) = lttv_state_copy_process_table(self
->processes
);
1510 /* Add the currently running processes array */
1511 nb_cpus
= ltt_trace_get_num_cpu(self
->parent
.t
);
1512 running_process
= g_new(guint
, nb_cpus
);
1513 for(i
=0;i
<nb_cpus
;i
++) {
1514 running_process
[i
] = self
->running_process
[i
]->pid
;
1516 value
= lttv_attribute_add(container
, LTTV_STATE_RUNNING_PROCESS
,
1518 *(value
.v_pointer
) = running_process
;
1520 g_info("State save");
1522 nb_tracefile
= self
->parent
.tracefiles
->len
;
1524 for(i
= 0 ; i
< nb_tracefile
; i
++) {
1526 LTTV_TRACEFILE_STATE(g_array_index(self
->parent
.tracefiles
,
1527 LttvTracefileContext
*, i
));
1528 tracefile_tree
= g_object_new(LTTV_ATTRIBUTE_TYPE
, NULL
);
1529 value
= lttv_attribute_add(tracefiles_tree
, i
,
1531 *(value
.v_gobject
) = (GObject
*)tracefile_tree
;
1533 value
= lttv_attribute_add(tracefile_tree
, LTTV_STATE_PROCESS
,
1535 *(value
.v_uint
) = tfcs
->process
->pid
;
1537 value
= lttv_attribute_add(tracefile_tree
, LTTV_STATE_EVENT
,
1539 /* Only save the position if the tfs has not infinite time. */
1540 //if(!g_tree_lookup(self->parent.ts_context->pqueue, &tfcs->parent)
1541 // && current_tfcs != tfcs) {
1542 if(ltt_time_compare(tfcs
->parent
.timestamp
, ltt_time_infinite
) == 0) {
1543 *(value
.v_pointer
) = NULL
;
1545 LttEvent
*e
= ltt_tracefile_get_event(tfcs
->parent
.tf
);
1546 ep
= ltt_event_position_new();
1547 ltt_event_position(e
, ep
);
1548 *(value
.v_pointer
) = ep
;
1550 guint nb_block
, offset
;
1553 ltt_event_position_get(ep
, &tf
, &nb_block
, &offset
, &tsc
);
1554 g_info("Block %u offset %u tsc %" PRIu64
" time %lu.%lu", nb_block
, offset
,
1556 tfcs
->parent
.timestamp
.tv_sec
, tfcs
->parent
.timestamp
.tv_nsec
);
1560 /* save the cpu state */
1562 value
= lttv_attribute_add(container
, LTTV_STATE_RESOURCE_CPUS_COUNT
,
1564 *(value
.v_uint
) = nb_cpus
;
1566 value
= lttv_attribute_add(container
, LTTV_STATE_RESOURCE_CPUS
,
1568 *(value
.v_pointer
) = lttv_state_copy_cpu_states(self
->cpu_states
, nb_cpus
);
1571 /* save the irq state */
1572 nb_irqs
= self
->nb_irqs
;
1574 value
= lttv_attribute_add(container
, LTTV_STATE_RESOURCE_IRQS
,
1576 *(value
.v_pointer
) = lttv_state_copy_irq_states(self
->irq_states
, nb_irqs
);
1579 /* save the soft irq state */
1580 nb_soft_irqs
= self
->nb_soft_irqs
;
1582 value
= lttv_attribute_add(container
, LTTV_STATE_RESOURCE_SOFT_IRQS
,
1584 *(value
.v_pointer
) = lttv_state_copy_soft_irq_states(self
->soft_irq_states
, nb_soft_irqs
);
1587 /* save the trap state */
1588 nb_traps
= self
->nb_traps
;
1590 value
= lttv_attribute_add(container
, LTTV_STATE_RESOURCE_TRAPS
,
1592 *(value
.v_pointer
) = lttv_state_copy_trap_states(self
->trap_states
, nb_traps
);
1595 /* save the blkdev states */
1596 value
= lttv_attribute_add(container
, LTTV_STATE_RESOURCE_BLKDEVS
,
1598 *(value
.v_pointer
) = lttv_state_copy_blkdev_hashtable(self
->bdev_states
);
1602 static void state_restore(LttvTraceState
*self
, LttvAttribute
*container
)
1604 guint i
, nb_tracefile
, pid
, nb_cpus
, nb_irqs
, nb_soft_irqs
, nb_traps
;
1606 LttvTracefileState
*tfcs
;
1608 LttvAttribute
*tracefiles_tree
, *tracefile_tree
;
1610 guint
*running_process
;
1612 LttvAttributeType type
;
1614 LttvAttributeValue value
;
1616 LttvAttributeName name
;
1620 LttEventPosition
*ep
;
1622 LttvTracesetContext
*tsc
= self
->parent
.ts_context
;
1624 tracefiles_tree
= lttv_attribute_find_subdir(container
,
1625 LTTV_STATE_TRACEFILES
);
1627 type
= lttv_attribute_get_by_name(container
, LTTV_STATE_PROCESSES
,
1629 g_assert(type
== LTTV_POINTER
);
1630 lttv_state_free_process_table(self
->processes
);
1631 self
->processes
= lttv_state_copy_process_table(*(value
.v_pointer
));
1633 /* Add the currently running processes array */
1634 nb_cpus
= ltt_trace_get_num_cpu(self
->parent
.t
);
1635 type
= lttv_attribute_get_by_name(container
, LTTV_STATE_RUNNING_PROCESS
,
1637 g_assert(type
== LTTV_POINTER
);
1638 running_process
= *(value
.v_pointer
);
1639 for(i
=0;i
<nb_cpus
;i
++) {
1640 pid
= running_process
[i
];
1641 self
->running_process
[i
] = lttv_state_find_process(self
, i
, pid
);
1642 g_assert(self
->running_process
[i
] != NULL
);
1645 nb_tracefile
= self
->parent
.tracefiles
->len
;
1647 //g_tree_destroy(tsc->pqueue);
1648 //tsc->pqueue = g_tree_new(compare_tracefile);
1650 /* restore cpu resource states */
1651 type
= lttv_attribute_get_by_name(container
, LTTV_STATE_RESOURCE_CPUS
, &value
);
1652 g_assert(type
== LTTV_POINTER
);
1653 lttv_state_free_cpu_states(self
->cpu_states
, nb_cpus
);
1654 self
->cpu_states
= lttv_state_copy_cpu_states(*(value
.v_pointer
), nb_cpus
);
1656 /* restore irq resource states */
1657 nb_irqs
= self
->nb_irqs
;
1658 type
= lttv_attribute_get_by_name(container
, LTTV_STATE_RESOURCE_IRQS
, &value
);
1659 g_assert(type
== LTTV_POINTER
);
1660 lttv_state_free_irq_states(self
->irq_states
, nb_irqs
);
1661 self
->irq_states
= lttv_state_copy_irq_states(*(value
.v_pointer
), nb_irqs
);
1663 /* restore soft irq resource states */
1664 nb_soft_irqs
= self
->nb_soft_irqs
;
1665 type
= lttv_attribute_get_by_name(container
, LTTV_STATE_RESOURCE_SOFT_IRQS
, &value
);
1666 g_assert(type
== LTTV_POINTER
);
1667 lttv_state_free_soft_irq_states(self
->soft_irq_states
, nb_soft_irqs
);
1668 self
->soft_irq_states
= lttv_state_copy_soft_irq_states(*(value
.v_pointer
), nb_soft_irqs
);
1670 /* restore trap resource states */
1671 nb_traps
= self
->nb_traps
;
1672 type
= lttv_attribute_get_by_name(container
, LTTV_STATE_RESOURCE_TRAPS
, &value
);
1673 g_assert(type
== LTTV_POINTER
);
1674 lttv_state_free_trap_states(self
->trap_states
, nb_traps
);
1675 self
->trap_states
= lttv_state_copy_trap_states(*(value
.v_pointer
), nb_traps
);
1677 /* restore the blkdev states */
1678 type
= lttv_attribute_get_by_name(container
, LTTV_STATE_RESOURCE_BLKDEVS
, &value
);
1679 g_assert(type
== LTTV_POINTER
);
1680 lttv_state_free_blkdev_hashtable(self
->bdev_states
);
1681 self
->bdev_states
= lttv_state_copy_blkdev_hashtable(*(value
.v_pointer
));
1683 for(i
= 0 ; i
< nb_tracefile
; i
++) {
1685 LTTV_TRACEFILE_STATE(g_array_index(self
->parent
.tracefiles
,
1686 LttvTracefileContext
*, i
));
1687 type
= lttv_attribute_get(tracefiles_tree
, i
, &name
, &value
, &is_named
);
1688 g_assert(type
== LTTV_GOBJECT
);
1689 tracefile_tree
= *((LttvAttribute
**)(value
.v_gobject
));
1691 type
= lttv_attribute_get_by_name(tracefile_tree
, LTTV_STATE_PROCESS
,
1693 g_assert(type
== LTTV_UINT
);
1694 pid
= *(value
.v_uint
);
1695 tfcs
->process
= lttv_state_find_process_or_create(tfcs
, pid
);
1697 type
= lttv_attribute_get_by_name(tracefile_tree
, LTTV_STATE_EVENT
,
1699 g_assert(type
== LTTV_POINTER
);
1700 //g_assert(*(value.v_pointer) != NULL);
1701 ep
= *(value
.v_pointer
);
1702 g_assert(tfcs
->parent
.t_context
!= NULL
);
1704 tfcs
->cpu_state
= &self
->cpu_states
[tfcs
->cpu
];
1706 LttvTracefileContext
*tfc
= LTTV_TRACEFILE_CONTEXT(tfcs
);
1707 g_tree_remove(tsc
->pqueue
, tfc
);
1710 g_assert(ltt_tracefile_seek_position(tfc
->tf
, ep
) == 0);
1711 tfc
->timestamp
= ltt_event_time(ltt_tracefile_get_event(tfc
->tf
));
1712 g_assert(ltt_time_compare(tfc
->timestamp
, ltt_time_infinite
) != 0);
1713 g_tree_insert(tsc
->pqueue
, tfc
, tfc
);
1714 g_info("Restoring state for a tf at time %lu.%lu", tfc
->timestamp
.tv_sec
, tfc
->timestamp
.tv_nsec
);
1716 tfc
->timestamp
= ltt_time_infinite
;
1722 static void state_saved_free(LttvTraceState
*self
, LttvAttribute
*container
)
1724 guint i
, nb_tracefile
, nb_cpus
, nb_irqs
, nb_softirqs
;
1726 LttvTracefileState
*tfcs
;
1728 LttvAttribute
*tracefiles_tree
, *tracefile_tree
;
1730 guint
*running_process
;
1732 LttvAttributeType type
;
1734 LttvAttributeValue value
;
1736 LttvAttributeName name
;
1740 tracefiles_tree
= lttv_attribute_find_subdir(container
,
1741 LTTV_STATE_TRACEFILES
);
1742 g_object_ref(G_OBJECT(tracefiles_tree
));
1743 lttv_attribute_remove_by_name(container
, LTTV_STATE_TRACEFILES
);
1745 type
= lttv_attribute_get_by_name(container
, LTTV_STATE_PROCESSES
,
1747 g_assert(type
== LTTV_POINTER
);
1748 lttv_state_free_process_table(*(value
.v_pointer
));
1749 *(value
.v_pointer
) = NULL
;
1750 lttv_attribute_remove_by_name(container
, LTTV_STATE_PROCESSES
);
1752 /* Free running processes array */
1753 type
= lttv_attribute_get_by_name(container
, LTTV_STATE_RUNNING_PROCESS
,
1755 g_assert(type
== LTTV_POINTER
);
1756 running_process
= *(value
.v_pointer
);
1757 g_free(running_process
);
1759 /* free cpu resource states */
1760 type
= lttv_attribute_get_by_name(container
, LTTV_STATE_RESOURCE_CPUS_COUNT
, &value
);
1761 g_assert(type
== LTTV_UINT
);
1762 nb_cpus
= *value
.v_uint
;
1763 type
= lttv_attribute_get_by_name(container
, LTTV_STATE_RESOURCE_CPUS
, &value
);
1764 g_assert(type
== LTTV_POINTER
);
1765 lttv_state_free_cpu_states(*(value
.v_pointer
), nb_cpus
);
1767 /* free irq resource states */
1768 nb_irqs
= self
->nb_irqs
;
1769 type
= lttv_attribute_get_by_name(container
, LTTV_STATE_RESOURCE_IRQS
, &value
);
1770 g_assert(type
== LTTV_POINTER
);
1771 lttv_state_free_irq_states(*(value
.v_pointer
), nb_irqs
);
1773 /* free softirq resource states */
1774 nb_softirqs
= self
->nb_irqs
;
1775 type
= lttv_attribute_get_by_name(container
, LTTV_STATE_RESOURCE_SOFT_IRQS
, &value
);
1776 g_assert(type
== LTTV_POINTER
);
1777 lttv_state_free_soft_irq_states(*(value
.v_pointer
), nb_softirqs
);
1779 /* free the blkdev states */
1780 type
= lttv_attribute_get_by_name(container
, LTTV_STATE_RESOURCE_BLKDEVS
, &value
);
1781 g_assert(type
== LTTV_POINTER
);
1782 lttv_state_free_blkdev_hashtable(*(value
.v_pointer
));
1784 nb_tracefile
= self
->parent
.tracefiles
->len
;
1786 for(i
= 0 ; i
< nb_tracefile
; i
++) {
1788 LTTV_TRACEFILE_STATE(g_array_index(self
->parent
.tracefiles
,
1789 LttvTracefileContext
*, i
));
1790 type
= lttv_attribute_get(tracefiles_tree
, i
, &name
, &value
, &is_named
);
1791 g_assert(type
== LTTV_GOBJECT
);
1792 tracefile_tree
= *((LttvAttribute
**)(value
.v_gobject
));
1794 type
= lttv_attribute_get_by_name(tracefile_tree
, LTTV_STATE_EVENT
,
1796 g_assert(type
== LTTV_POINTER
);
1797 if(*(value
.v_pointer
) != NULL
) g_free(*(value
.v_pointer
));
1799 g_object_unref(G_OBJECT(tracefiles_tree
));
1803 static void free_saved_state(LttvTraceState
*self
)
1807 LttvAttributeType type
;
1809 LttvAttributeValue value
;
1811 LttvAttributeName name
;
1815 LttvAttribute
*saved_states
;
1817 saved_states
= lttv_attribute_find_subdir(self
->parent
.t_a
,
1818 LTTV_STATE_SAVED_STATES
);
1820 nb
= lttv_attribute_get_number(saved_states
);
1821 for(i
= 0 ; i
< nb
; i
++) {
1822 type
= lttv_attribute_get(saved_states
, i
, &name
, &value
, &is_named
);
1823 g_assert(type
== LTTV_GOBJECT
);
1824 state_saved_free(self
, *((LttvAttribute
**)value
.v_gobject
));
1827 lttv_attribute_remove_by_name(self
->parent
.t_a
, LTTV_STATE_SAVED_STATES
);
1832 create_max_time(LttvTraceState
*tcs
)
1834 LttvAttributeValue v
;
1836 lttv_attribute_find(tcs
->parent
.t_a
, LTTV_STATE_SAVED_STATES_TIME
,
1838 g_assert(*(v
.v_pointer
) == NULL
);
1839 *(v
.v_pointer
) = g_new(LttTime
,1);
1840 *((LttTime
*)*(v
.v_pointer
)) = ltt_time_zero
;
1845 get_max_time(LttvTraceState
*tcs
)
1847 LttvAttributeValue v
;
1849 lttv_attribute_find(tcs
->parent
.t_a
, LTTV_STATE_SAVED_STATES_TIME
,
1851 g_assert(*(v
.v_pointer
) != NULL
);
1852 tcs
->max_time_state_recomputed_in_seek
= (LttTime
*)*(v
.v_pointer
);
1857 free_max_time(LttvTraceState
*tcs
)
1859 LttvAttributeValue v
;
1861 lttv_attribute_find(tcs
->parent
.t_a
, LTTV_STATE_SAVED_STATES_TIME
,
1863 g_free(*(v
.v_pointer
));
1864 *(v
.v_pointer
) = NULL
;
1868 typedef struct _LttvNameTables
{
1869 // FIXME GQuark *eventtype_names;
1870 GQuark
*syscall_names
;
1876 GQuark
*soft_irq_names
;
1878 GHashTable
*kprobe_hash
;
1883 create_name_tables(LttvTraceState
*tcs
)
1887 GString
*fe_name
= g_string_new("");
1889 LttvNameTables
*name_tables
= g_new(LttvNameTables
, 1);
1891 LttvAttributeValue v
;
1895 lttv_attribute_find(tcs
->parent
.t_a
, LTTV_STATE_NAME_TABLES
,
1897 g_assert(*(v
.v_pointer
) == NULL
);
1898 *(v
.v_pointer
) = name_tables
;
1900 hooks
= g_array_sized_new(FALSE
, FALSE
, sizeof(LttvTraceHook
), 1);
1902 if(!lttv_trace_find_hook(tcs
->parent
.t
,
1904 LTT_EVENT_SYSCALL_ENTRY
,
1905 FIELD_ARRAY(LTT_FIELD_SYSCALL_ID
),
1906 NULL
, NULL
, &hooks
)) {
1908 // th = lttv_trace_hook_get_first(&th);
1910 // t = ltt_field_type(lttv_trace_get_hook_field(th, 0));
1911 // nb = ltt_type_element_number(t);
1913 // name_tables->syscall_names = g_new(GQuark, nb);
1914 // name_tables->nb_syscalls = nb;
1916 // for(i = 0 ; i < nb ; i++) {
1917 // name_tables->syscall_names[i] = ltt_enum_string_get(t, i);
1918 // if(!name_tables->syscall_names[i]) {
1919 // GString *string = g_string_new("");
1920 // g_string_printf(string, "syscall %u", i);
1921 // name_tables->syscall_names[i] = g_quark_from_string(string->str);
1922 // g_string_free(string, TRUE);
1926 name_tables
->nb_syscalls
= 256;
1927 name_tables
->syscall_names
= g_new(GQuark
, 256);
1928 for(i
= 0 ; i
< 256 ; i
++) {
1929 g_string_printf(fe_name
, "syscall %d", i
);
1930 name_tables
->syscall_names
[i
] = g_quark_from_string(fe_name
->str
);
1933 name_tables
->syscall_names
= NULL
;
1934 name_tables
->nb_syscalls
= 0;
1936 lttv_trace_hook_remove_all(&hooks
);
1938 if(!lttv_trace_find_hook(tcs
->parent
.t
,
1940 LTT_EVENT_TRAP_ENTRY
,
1941 FIELD_ARRAY(LTT_FIELD_TRAP_ID
),
1942 NULL
, NULL
, &hooks
)) {
1944 // th = lttv_trace_hook_get_first(&th);
1946 // t = ltt_field_type(lttv_trace_get_hook_field(th, 0));
1947 // //nb = ltt_type_element_number(t);
1949 // name_tables->trap_names = g_new(GQuark, nb);
1950 // for(i = 0 ; i < nb ; i++) {
1951 // name_tables->trap_names[i] = g_quark_from_string(
1952 // ltt_enum_string_get(t, i));
1955 name_tables
->nb_traps
= 256;
1956 name_tables
->trap_names
= g_new(GQuark
, 256);
1957 for(i
= 0 ; i
< 256 ; i
++) {
1958 g_string_printf(fe_name
, "trap %d", i
);
1959 name_tables
->trap_names
[i
] = g_quark_from_string(fe_name
->str
);
1962 name_tables
->trap_names
= NULL
;
1963 name_tables
->nb_traps
= 0;
1965 lttv_trace_hook_remove_all(&hooks
);
1967 if(!lttv_trace_find_hook(tcs
->parent
.t
,
1969 LTT_EVENT_IRQ_ENTRY
,
1970 FIELD_ARRAY(LTT_FIELD_IRQ_ID
),
1971 NULL
, NULL
, &hooks
)) {
1974 name_tables->irq_names = g_new(GQuark, nb);
1975 for(i = 0 ; i < nb ; i++) {
1976 name_tables->irq_names[i] = g_quark_from_string(ltt_enum_string_get(t, i));
1980 name_tables
->nb_irqs
= 256;
1981 name_tables
->irq_names
= g_new(GQuark
, 256);
1982 for(i
= 0 ; i
< 256 ; i
++) {
1983 g_string_printf(fe_name
, "irq %d", i
);
1984 name_tables
->irq_names
[i
] = g_quark_from_string(fe_name
->str
);
1987 name_tables
->nb_irqs
= 0;
1988 name_tables
->irq_names
= NULL
;
1990 lttv_trace_hook_remove_all(&hooks
);
1992 name_tables->soft_irq_names = g_new(GQuark, nb);
1993 for(i = 0 ; i < nb ; i++) {
1994 name_tables->soft_irq_names[i] = g_quark_from_string(ltt_enum_string_get(t, i));
1998 /* the kernel is limited to 32 statically defined softirqs */
1999 name_tables
->nb_softirqs
= 32;
2000 name_tables
->soft_irq_names
= g_new(GQuark
, name_tables
->nb_softirqs
);
2001 for(i
= 0 ; i
< name_tables
->nb_softirqs
; i
++) {
2002 g_string_printf(fe_name
, "softirq %d", i
);
2003 name_tables
->soft_irq_names
[i
] = g_quark_from_string(fe_name
->str
);
2005 g_array_free(hooks
, TRUE
);
2007 g_string_free(fe_name
, TRUE
);
2009 name_tables
->kprobe_hash
= g_hash_table_new(g_direct_hash
, g_direct_equal
);
2014 get_name_tables(LttvTraceState
*tcs
)
2016 LttvNameTables
*name_tables
;
2018 LttvAttributeValue v
;
2020 lttv_attribute_find(tcs
->parent
.t_a
, LTTV_STATE_NAME_TABLES
,
2022 g_assert(*(v
.v_pointer
) != NULL
);
2023 name_tables
= (LttvNameTables
*)*(v
.v_pointer
);
2024 //tcs->eventtype_names = name_tables->eventtype_names;
2025 tcs
->syscall_names
= name_tables
->syscall_names
;
2026 tcs
->nb_syscalls
= name_tables
->nb_syscalls
;
2027 tcs
->trap_names
= name_tables
->trap_names
;
2028 tcs
->nb_traps
= name_tables
->nb_traps
;
2029 tcs
->irq_names
= name_tables
->irq_names
;
2030 tcs
->soft_irq_names
= name_tables
->soft_irq_names
;
2031 tcs
->nb_irqs
= name_tables
->nb_irqs
;
2032 tcs
->nb_soft_irqs
= name_tables
->nb_softirqs
;
2033 tcs
->kprobe_hash
= name_tables
->kprobe_hash
;
2038 free_name_tables(LttvTraceState
*tcs
)
2040 LttvNameTables
*name_tables
;
2042 LttvAttributeValue v
;
2044 lttv_attribute_find(tcs
->parent
.t_a
, LTTV_STATE_NAME_TABLES
,
2046 name_tables
= (LttvNameTables
*)*(v
.v_pointer
);
2047 *(v
.v_pointer
) = NULL
;
2049 // g_free(name_tables->eventtype_names);
2050 if(name_tables
->syscall_names
) g_free(name_tables
->syscall_names
);
2051 if(name_tables
->trap_names
) g_free(name_tables
->trap_names
);
2052 if(name_tables
->irq_names
) g_free(name_tables
->irq_names
);
2053 if(name_tables
->soft_irq_names
) g_free(name_tables
->soft_irq_names
);
2054 if(name_tables
) g_free(name_tables
);
2055 if(name_tables
) g_hash_table_destroy(name_tables
->kprobe_hash
);
2058 #ifdef HASH_TABLE_DEBUG
2060 static void test_process(gpointer key
, gpointer value
, gpointer user_data
)
2062 LttvProcessState
*process
= (LttvProcessState
*)value
;
2064 /* Test for process corruption */
2065 guint stack_len
= process
->execution_stack
->len
;
2068 static void hash_table_check(GHashTable
*table
)
2070 g_hash_table_foreach(table
, test_process
, NULL
);
2076 /* clears the stack and sets the state passed as argument */
2077 static void cpu_set_base_mode(LttvCPUState
*cpust
, LttvCPUMode state
)
2079 g_array_set_size(cpust
->mode_stack
, 1);
2080 ((GQuark
*)cpust
->mode_stack
->data
)[0] = state
;
2083 static void cpu_push_mode(LttvCPUState
*cpust
, LttvCPUMode state
)
2085 g_array_set_size(cpust
->mode_stack
, cpust
->mode_stack
->len
+ 1);
2086 ((GQuark
*)cpust
->mode_stack
->data
)[cpust
->mode_stack
->len
- 1] = state
;
2089 static void cpu_pop_mode(LttvCPUState
*cpust
)
2091 if(cpust
->mode_stack
->len
<= 1)
2092 cpu_set_base_mode(cpust
, LTTV_CPU_UNKNOWN
);
2094 g_array_set_size(cpust
->mode_stack
, cpust
->mode_stack
->len
- 1);
2097 /* clears the stack and sets the state passed as argument */
2098 static void bdev_set_base_mode(LttvBdevState
*bdevst
, LttvBdevMode state
)
2100 g_array_set_size(bdevst
->mode_stack
, 1);
2101 ((GQuark
*)bdevst
->mode_stack
->data
)[0] = state
;
2104 static void bdev_push_mode(LttvBdevState
*bdevst
, LttvBdevMode state
)
2106 g_array_set_size(bdevst
->mode_stack
, bdevst
->mode_stack
->len
+ 1);
2107 ((GQuark
*)bdevst
->mode_stack
->data
)[bdevst
->mode_stack
->len
- 1] = state
;
2110 static void bdev_pop_mode(LttvBdevState
*bdevst
)
2112 if(bdevst
->mode_stack
->len
<= 1)
2113 bdev_set_base_mode(bdevst
, LTTV_BDEV_UNKNOWN
);
2115 g_array_set_size(bdevst
->mode_stack
, bdevst
->mode_stack
->len
- 1);
2118 static void irq_set_base_mode(LttvIRQState
*irqst
, LttvIRQMode state
)
2120 g_array_set_size(irqst
->mode_stack
, 1);
2121 ((GQuark
*)irqst
->mode_stack
->data
)[0] = state
;
2124 static void irq_push_mode(LttvIRQState
*irqst
, LttvIRQMode state
)
2126 g_array_set_size(irqst
->mode_stack
, irqst
->mode_stack
->len
+ 1);
2127 ((GQuark
*)irqst
->mode_stack
->data
)[irqst
->mode_stack
->len
- 1] = state
;
2130 static void irq_pop_mode(LttvIRQState
*irqst
)
2132 if(irqst
->mode_stack
->len
<= 1)
2133 irq_set_base_mode(irqst
, LTTV_IRQ_UNKNOWN
);
2135 g_array_set_size(irqst
->mode_stack
, irqst
->mode_stack
->len
- 1);
2138 static void push_state(LttvTracefileState
*tfs
, LttvExecutionMode t
,
2141 LttvExecutionState
*es
;
2143 LttvTraceState
*ts
= (LttvTraceState
*)tfs
->parent
.t_context
;
2144 guint cpu
= tfs
->cpu
;
2146 #ifdef HASH_TABLE_DEBUG
2147 hash_table_check(ts
->processes
);
2149 LttvProcessState
*process
= ts
->running_process
[cpu
];
2151 guint depth
= process
->execution_stack
->len
;
2153 process
->execution_stack
=
2154 g_array_set_size(process
->execution_stack
, depth
+ 1);
2157 &g_array_index(process
->execution_stack
, LttvExecutionState
, depth
- 1);
2159 es
= &g_array_index(process
->execution_stack
, LttvExecutionState
, depth
);
2162 es
->entry
= es
->change
= tfs
->parent
.timestamp
;
2163 es
->cum_cpu_time
= ltt_time_zero
;
2164 es
->s
= process
->state
->s
;
2165 process
->state
= es
;
2169 * return 1 when empty, else 0 */
2170 int lttv_state_pop_state_cleanup(LttvProcessState
*process
,
2171 LttvTracefileState
*tfs
)
2173 guint depth
= process
->execution_stack
->len
;
2179 process
->execution_stack
=
2180 g_array_set_size(process
->execution_stack
, depth
- 1);
2181 process
->state
= &g_array_index(process
->execution_stack
, LttvExecutionState
,
2183 process
->state
->change
= tfs
->parent
.timestamp
;
2188 static void pop_state(LttvTracefileState
*tfs
, LttvExecutionMode t
)
2190 guint cpu
= tfs
->cpu
;
2191 LttvTraceState
*ts
= (LttvTraceState
*)tfs
->parent
.t_context
;
2192 LttvProcessState
*process
= ts
->running_process
[cpu
];
2194 guint depth
= process
->execution_stack
->len
;
2196 if(process
->state
->t
!= t
){
2197 g_info("Different execution mode type (%lu.%09lu): ignore it\n",
2198 tfs
->parent
.timestamp
.tv_sec
, tfs
->parent
.timestamp
.tv_nsec
);
2199 g_info("process state has %s when pop_int is %s\n",
2200 g_quark_to_string(process
->state
->t
),
2201 g_quark_to_string(t
));
2202 g_info("{ %u, %u, %s, %s, %s }\n",
2205 g_quark_to_string(process
->name
),
2206 g_quark_to_string(process
->brand
),
2207 g_quark_to_string(process
->state
->s
));
2212 g_info("Trying to pop last state on stack (%lu.%09lu): ignore it\n",
2213 tfs
->parent
.timestamp
.tv_sec
, tfs
->parent
.timestamp
.tv_nsec
);
2217 process
->execution_stack
=
2218 g_array_set_size(process
->execution_stack
, depth
- 1);
2219 process
->state
= &g_array_index(process
->execution_stack
, LttvExecutionState
,
2221 process
->state
->change
= tfs
->parent
.timestamp
;
2224 struct search_result
{
2225 const LttTime
*time
; /* Requested time */
2226 LttTime
*best
; /* Best result */
2229 static gint
search_usertrace(gconstpointer a
, gconstpointer b
)
2231 const LttTime
*elem_time
= (const LttTime
*)a
;
2232 /* Explicit non const cast */
2233 struct search_result
*res
= (struct search_result
*)b
;
2235 if(ltt_time_compare(*elem_time
, *(res
->time
)) < 0) {
2236 /* The usertrace was created before the schedchange */
2237 /* Get larger keys */
2239 } else if(ltt_time_compare(*elem_time
, *(res
->time
)) >= 0) {
2240 /* The usertrace was created after the schedchange time */
2241 /* Get smaller keys */
2243 if(ltt_time_compare(*elem_time
, *res
->best
) < 0) {
2244 res
->best
= (LttTime
*)elem_time
;
2247 res
->best
= (LttTime
*)elem_time
;
2254 static LttvTracefileState
*ltt_state_usertrace_find(LttvTraceState
*tcs
,
2255 guint pid
, const LttTime
*timestamp
)
2257 LttvTracefileState
*tfs
= NULL
;
2258 struct search_result res
;
2259 /* Find the usertrace associated with a pid and time interval.
2260 * Search in the usertraces by PID (within a hash) and then, for each
2261 * corresponding element of the array, find the first one with creation
2262 * timestamp the lowest, but higher or equal to "timestamp". */
2263 res
.time
= timestamp
;
2265 GTree
*usertrace_tree
= g_hash_table_lookup(tcs
->usertraces
,
2266 GUINT_TO_POINTER(pid
));
2267 if(usertrace_tree
) {
2268 g_tree_search(usertrace_tree
, search_usertrace
, &res
);
2270 tfs
= g_tree_lookup(usertrace_tree
, res
.best
);
2278 lttv_state_create_process(LttvTraceState
*tcs
, LttvProcessState
*parent
,
2279 guint cpu
, guint pid
, guint tgid
, GQuark name
, const LttTime
*timestamp
)
2281 LttvProcessState
*process
= g_new(LttvProcessState
, 1);
2283 LttvExecutionState
*es
;
2288 process
->tgid
= tgid
;
2290 process
->name
= name
;
2291 process
->brand
= LTTV_STATE_UNBRANDED
;
2292 //process->last_cpu = tfs->cpu_name;
2293 //process->last_cpu_index = ltt_tracefile_num(((LttvTracefileContext*)tfs)->tf);
2294 process
->type
= LTTV_STATE_USER_THREAD
;
2295 process
->usertrace
= ltt_state_usertrace_find(tcs
, pid
, timestamp
);
2296 process
->current_function
= 0; //function 0x0 by default.
2298 g_info("Process %u, core %p", process
->pid
, process
);
2299 g_hash_table_insert(tcs
->processes
, process
, process
);
2302 process
->ppid
= parent
->pid
;
2303 process
->creation_time
= *timestamp
;
2306 /* No parent. This process exists but we are missing all information about
2307 its creation. The birth time is set to zero but we remember the time of
2312 process
->creation_time
= ltt_time_zero
;
2315 process
->insertion_time
= *timestamp
;
2316 sprintf(buffer
,"%d-%lu.%lu",pid
, process
->creation_time
.tv_sec
,
2317 process
->creation_time
.tv_nsec
);
2318 process
->pid_time
= g_quark_from_string(buffer
);
2320 process
->free_events
= 0;
2321 //process->last_cpu = tfs->cpu_name;
2322 //process->last_cpu_index = ltt_tracefile_num(((LttvTracefileContext*)tfs)->tf);
2323 process
->execution_stack
= g_array_sized_new(FALSE
, FALSE
,
2324 sizeof(LttvExecutionState
), PREALLOCATED_EXECUTION_STACK
);
2325 process
->execution_stack
= g_array_set_size(process
->execution_stack
, 2);
2326 es
= process
->state
= &g_array_index(process
->execution_stack
,
2327 LttvExecutionState
, 0);
2328 es
->t
= LTTV_STATE_USER_MODE
;
2329 es
->n
= LTTV_STATE_SUBMODE_NONE
;
2330 es
->entry
= *timestamp
;
2331 //g_assert(timestamp->tv_sec != 0);
2332 es
->change
= *timestamp
;
2333 es
->cum_cpu_time
= ltt_time_zero
;
2334 es
->s
= LTTV_STATE_RUN
;
2336 es
= process
->state
= &g_array_index(process
->execution_stack
,
2337 LttvExecutionState
, 1);
2338 es
->t
= LTTV_STATE_SYSCALL
;
2339 es
->n
= LTTV_STATE_SUBMODE_NONE
;
2340 es
->entry
= *timestamp
;
2341 //g_assert(timestamp->tv_sec != 0);
2342 es
->change
= *timestamp
;
2343 es
->cum_cpu_time
= ltt_time_zero
;
2344 es
->s
= LTTV_STATE_WAIT_FORK
;
2346 /* Allocate an empty function call stack. If it's empty, use 0x0. */
2347 process
->user_stack
= g_array_sized_new(FALSE
, FALSE
,
2348 sizeof(guint64
), 0);
2353 LttvProcessState
*lttv_state_find_process(LttvTraceState
*ts
, guint cpu
,
2356 LttvProcessState key
;
2357 LttvProcessState
*process
;
2361 process
= g_hash_table_lookup(ts
->processes
, &key
);
2366 lttv_state_find_process_or_create(LttvTraceState
*ts
, guint cpu
, guint pid
,
2367 const LttTime
*timestamp
)
2369 LttvProcessState
*process
= lttv_state_find_process(ts
, cpu
, pid
);
2370 LttvExecutionState
*es
;
2372 /* Put ltt_time_zero creation time for unexisting processes */
2373 if(unlikely(process
== NULL
)) {
2374 process
= lttv_state_create_process(ts
,
2375 NULL
, cpu
, pid
, 0, LTTV_STATE_UNNAMED
, timestamp
);
2376 /* We are not sure is it's a kernel thread or normal thread, put the
2377 * bottom stack state to unknown */
2378 process
->execution_stack
=
2379 g_array_set_size(process
->execution_stack
, 1);
2380 process
->state
= es
=
2381 &g_array_index(process
->execution_stack
, LttvExecutionState
, 0);
2382 es
->t
= LTTV_STATE_MODE_UNKNOWN
;
2383 es
->s
= LTTV_STATE_UNNAMED
;
2388 /* FIXME : this function should be called when we receive an event telling that
2389 * release_task has been called in the kernel. In happens generally when
2390 * the parent waits for its child terminaison, but may also happen in special
2391 * cases in the child's exit : when the parent ignores its children SIGCCHLD or
2392 * has the flag SA_NOCLDWAIT. It can also happen when the child is part
2393 * of a killed thread group, but isn't the leader.
2395 static int exit_process(LttvTracefileState
*tfs
, LttvProcessState
*process
)
2397 LttvTraceState
*ts
= LTTV_TRACE_STATE(tfs
->parent
.t_context
);
2398 LttvProcessState key
;
2400 /* Wait for both schedule with exit dead and process free to happen.
2401 * They can happen in any order. */
2402 if (++(process
->free_events
) < 2)
2405 key
.pid
= process
->pid
;
2406 key
.cpu
= process
->cpu
;
2407 g_hash_table_remove(ts
->processes
, &key
);
2408 g_array_free(process
->execution_stack
, TRUE
);
2409 g_array_free(process
->user_stack
, TRUE
);
2415 static void free_process_state(gpointer key
, gpointer value
,gpointer user_data
)
2417 g_array_free(((LttvProcessState
*)value
)->execution_stack
, TRUE
);
2418 g_array_free(((LttvProcessState
*)value
)->user_stack
, TRUE
);
2423 static void lttv_state_free_process_table(GHashTable
*processes
)
2425 g_hash_table_foreach(processes
, free_process_state
, NULL
);
2426 g_hash_table_destroy(processes
);
2430 static gboolean
syscall_entry(void *hook_data
, void *call_data
)
2432 LttvTracefileState
*s
= (LttvTracefileState
*)call_data
;
2434 LttvTraceState
*ts
= (LttvTraceState
*)s
->parent
.t_context
;
2435 LttvProcessState
*process
= ts
->running_process
[cpu
];
2436 LttEvent
*e
= ltt_tracefile_get_event(s
->parent
.tf
);
2437 LttvTraceHook
*th
= (LttvTraceHook
*)hook_data
;
2438 struct marker_field
*f
= lttv_trace_get_hook_field(th
, 0);
2439 LttvExecutionSubmode submode
;
2441 guint syscall
= ltt_event_get_unsigned(e
, f
);
2442 expand_syscall_table(ts
, syscall
);
2443 submode
= ((LttvTraceState
*)(s
->parent
.t_context
))->syscall_names
[syscall
];
2444 /* There can be no system call from PID 0 : unknown state */
2445 if(process
->pid
!= 0)
2446 push_state(s
, LTTV_STATE_SYSCALL
, submode
);
2451 static gboolean
syscall_exit(void *hook_data
, void *call_data
)
2453 LttvTracefileState
*s
= (LttvTracefileState
*)call_data
;
2455 LttvTraceState
*ts
= (LttvTraceState
*)s
->parent
.t_context
;
2456 LttvProcessState
*process
= ts
->running_process
[cpu
];
2458 /* There can be no system call from PID 0 : unknown state */
2459 if(process
->pid
!= 0)
2460 pop_state(s
, LTTV_STATE_SYSCALL
);
2465 static gboolean
trap_entry(void *hook_data
, void *call_data
)
2467 LttvTracefileState
*s
= (LttvTracefileState
*)call_data
;
2468 LttvTraceState
*ts
= (LttvTraceState
*)s
->parent
.t_context
;
2469 LttEvent
*e
= ltt_tracefile_get_event(s
->parent
.tf
);
2470 LttvTraceHook
*th
= (LttvTraceHook
*)hook_data
;
2471 struct marker_field
*f
= lttv_trace_get_hook_field(th
, 0);
2473 LttvExecutionSubmode submode
;
2475 guint64 trap
= ltt_event_get_long_unsigned(e
, f
);
2477 expand_trap_table(ts
, trap
);
2479 submode
= ((LttvTraceState
*)(s
->parent
.t_context
))->trap_names
[trap
];
2481 push_state(s
, LTTV_STATE_TRAP
, submode
);
2483 /* update cpu status */
2484 cpu_push_mode(s
->cpu_state
, LTTV_CPU_TRAP
);
2486 /* update trap status */
2487 s
->cpu_state
->last_trap
= trap
;
2488 ts
->trap_states
[trap
].running
++;
2493 static gboolean
trap_exit(void *hook_data
, void *call_data
)
2495 LttvTracefileState
*s
= (LttvTracefileState
*)call_data
;
2496 LttvTraceState
*ts
= (LttvTraceState
*)s
->parent
.t_context
;
2497 gint trap
= s
->cpu_state
->last_trap
;
2499 pop_state(s
, LTTV_STATE_TRAP
);
2501 /* update cpu status */
2502 cpu_pop_mode(s
->cpu_state
);
2504 /* update trap status */
2506 if(ts
->trap_states
[trap
].running
)
2507 ts
->trap_states
[trap
].running
--;
2512 static gboolean
irq_entry(void *hook_data
, void *call_data
)
2514 LttvTracefileState
*s
= (LttvTracefileState
*)call_data
;
2515 LttvTraceState
*ts
= (LttvTraceState
*)s
->parent
.t_context
;
2516 LttEvent
*e
= ltt_tracefile_get_event(s
->parent
.tf
);
2517 //guint8 ev_id = ltt_event_eventtype_id(e);
2518 LttvTraceHook
*th
= (LttvTraceHook
*)hook_data
;
2519 struct marker_field
*f
= lttv_trace_get_hook_field(th
, 0);
2521 LttvExecutionSubmode submode
;
2522 guint64 irq
= ltt_event_get_long_unsigned(e
, f
);
2524 expand_irq_table(ts
, irq
);
2526 submode
= ((LttvTraceState
*)(s
->parent
.t_context
))->irq_names
[irq
];
2528 /* Do something with the info about being in user or system mode when int? */
2529 push_state(s
, LTTV_STATE_IRQ
, submode
);
2531 /* update cpu status */
2532 cpu_push_mode(s
->cpu_state
, LTTV_CPU_IRQ
);
2534 /* update irq status */
2535 s
->cpu_state
->last_irq
= irq
;
2536 irq_push_mode(&ts
->irq_states
[irq
], LTTV_IRQ_BUSY
);
2541 static gboolean
soft_irq_exit(void *hook_data
, void *call_data
)
2543 LttvTracefileState
*s
= (LttvTracefileState
*)call_data
;
2544 LttvTraceState
*ts
= (LttvTraceState
*)s
->parent
.t_context
;
2545 gint softirq
= s
->cpu_state
->last_soft_irq
;
2547 pop_state(s
, LTTV_STATE_SOFT_IRQ
);
2549 /* update softirq status */
2551 if(ts
->soft_irq_states
[softirq
].running
)
2552 ts
->soft_irq_states
[softirq
].running
--;
2554 /* update cpu status */
2555 cpu_pop_mode(s
->cpu_state
);
2560 static gboolean
irq_exit(void *hook_data
, void *call_data
)
2562 LttvTracefileState
*s
= (LttvTracefileState
*)call_data
;
2563 LttvTraceState
*ts
= (LttvTraceState
*)s
->parent
.t_context
;
2565 pop_state(s
, LTTV_STATE_IRQ
);
2567 /* update cpu status */
2568 cpu_pop_mode(s
->cpu_state
);
2570 /* update irq status */
2571 if (s
->cpu_state
->last_irq
!= -1)
2572 irq_pop_mode(&ts
->irq_states
[s
->cpu_state
->last_irq
]);
2577 static gboolean
soft_irq_raise(void *hook_data
, void *call_data
)
2579 LttvTracefileState
*s
= (LttvTracefileState
*)call_data
;
2580 LttvTraceState
*ts
= (LttvTraceState
*)s
->parent
.t_context
;
2581 LttEvent
*e
= ltt_tracefile_get_event(s
->parent
.tf
);
2582 //guint8 ev_id = ltt_event_eventtype_id(e);
2583 LttvTraceHook
*th
= (LttvTraceHook
*)hook_data
;
2584 struct marker_field
*f
= lttv_trace_get_hook_field(th
, 0);
2586 LttvExecutionSubmode submode
;
2587 guint64 softirq
= ltt_event_get_long_unsigned(e
, f
);
2588 guint64 nb_softirqs
= ((LttvTraceState
*)(s
->parent
.t_context
))->nb_soft_irqs
;
2590 if(softirq
< nb_softirqs
) {
2591 submode
= ((LttvTraceState
*)(s
->parent
.t_context
))->soft_irq_names
[softirq
];
2593 /* Fixup an incomplete irq table */
2594 GString
*string
= g_string_new("");
2595 g_string_printf(string
, "softirq %" PRIu64
, softirq
);
2596 submode
= g_quark_from_string(string
->str
);
2597 g_string_free(string
, TRUE
);
2600 /* update softirq status */
2601 /* a soft irq raises are not cumulative */
2602 ts
->soft_irq_states
[softirq
].pending
=1;
2607 static gboolean
soft_irq_entry(void *hook_data
, void *call_data
)
2609 LttvTracefileState
*s
= (LttvTracefileState
*)call_data
;
2610 LttvTraceState
*ts
= (LttvTraceState
*)s
->parent
.t_context
;
2611 LttEvent
*e
= ltt_tracefile_get_event(s
->parent
.tf
);
2612 //guint8 ev_id = ltt_event_eventtype_id(e);
2613 LttvTraceHook
*th
= (LttvTraceHook
*)hook_data
;
2614 struct marker_field
*f
= lttv_trace_get_hook_field(th
, 0);
2615 LttvExecutionSubmode submode
;
2616 guint64 softirq
= ltt_event_get_long_unsigned(e
, f
);
2617 expand_soft_irq_table(ts
, softirq
);
2618 submode
= ((LttvTraceState
*)(s
->parent
.t_context
))->soft_irq_names
[softirq
];
2620 /* Do something with the info about being in user or system mode when int? */
2621 push_state(s
, LTTV_STATE_SOFT_IRQ
, submode
);
2623 /* update cpu status */
2624 cpu_push_mode(s
->cpu_state
, LTTV_CPU_SOFT_IRQ
);
2626 /* update softirq status */
2627 s
->cpu_state
->last_soft_irq
= softirq
;
2628 if(ts
->soft_irq_states
[softirq
].pending
)
2629 ts
->soft_irq_states
[softirq
].pending
--;
2630 ts
->soft_irq_states
[softirq
].running
++;
2635 static gboolean
enum_interrupt(void *hook_data
, void *call_data
)
2637 LttvTracefileState
*s
= (LttvTracefileState
*)call_data
;
2638 LttvTraceState
*ts
= (LttvTraceState
*)s
->parent
.t_context
;
2639 LttEvent
*e
= ltt_tracefile_get_event(s
->parent
.tf
);
2640 //guint8 ev_id = ltt_event_eventtype_id(e);
2641 LttvTraceHook
*th
= (LttvTraceHook
*)hook_data
;
2643 GQuark action
= g_quark_from_string(ltt_event_get_string(e
,
2644 lttv_trace_get_hook_field(th
, 0)));
2645 guint irq
= ltt_event_get_long_unsigned(e
, lttv_trace_get_hook_field(th
, 1));
2647 expand_irq_table(ts
, irq
);
2648 ts
->irq_names
[irq
] = action
;
2654 static gboolean
bdev_request_issue(void *hook_data
, void *call_data
)
2656 LttvTracefileState
*s
= (LttvTracefileState
*)call_data
;
2657 LttvTraceState
*ts
= (LttvTraceState
*)s
->parent
.t_context
;
2658 LttEvent
*e
= ltt_tracefile_get_event(s
->parent
.tf
);
2659 //guint8 ev_id = ltt_event_eventtype_id(e);
2660 LttvTraceHook
*th
= (LttvTraceHook
*)hook_data
;
2662 guint major
= ltt_event_get_long_unsigned(e
,
2663 lttv_trace_get_hook_field(th
, 0));
2664 guint minor
= ltt_event_get_long_unsigned(e
,
2665 lttv_trace_get_hook_field(th
, 1));
2666 guint oper
= ltt_event_get_long_unsigned(e
,
2667 lttv_trace_get_hook_field(th
, 2));
2668 guint16 devcode
= MKDEV(major
,minor
);
2670 /* have we seen this block device before? */
2671 gpointer bdev
= get_hashed_bdevstate(ts
, devcode
);
2674 bdev_push_mode(bdev
, LTTV_BDEV_BUSY_READING
);
2676 bdev_push_mode(bdev
, LTTV_BDEV_BUSY_WRITING
);
2681 static gboolean
bdev_request_complete(void *hook_data
, void *call_data
)
2683 LttvTracefileState
*s
= (LttvTracefileState
*)call_data
;
2684 LttvTraceState
*ts
= (LttvTraceState
*)s
->parent
.t_context
;
2685 LttEvent
*e
= ltt_tracefile_get_event(s
->parent
.tf
);
2686 LttvTraceHook
*th
= (LttvTraceHook
*)hook_data
;
2688 guint major
= ltt_event_get_long_unsigned(e
,
2689 lttv_trace_get_hook_field(th
, 0));
2690 guint minor
= ltt_event_get_long_unsigned(e
,
2691 lttv_trace_get_hook_field(th
, 1));
2692 //guint oper = ltt_event_get_long_unsigned(e,
2693 // lttv_trace_get_hook_field(th, 2));
2694 guint16 devcode
= MKDEV(major
,minor
);
2696 /* have we seen this block device before? */
2697 gpointer bdev
= get_hashed_bdevstate(ts
, devcode
);
2699 /* update block device */
2700 bdev_pop_mode(bdev
);
2705 static void push_function(LttvTracefileState
*tfs
, guint64 funcptr
)
2709 LttvTraceState
*ts
= (LttvTraceState
*)tfs
->parent
.t_context
;
2710 guint cpu
= tfs
->cpu
;
2711 LttvProcessState
*process
= ts
->running_process
[cpu
];
2713 guint depth
= process
->user_stack
->len
;
2715 process
->user_stack
=
2716 g_array_set_size(process
->user_stack
, depth
+ 1);
2718 new_func
= &g_array_index(process
->user_stack
, guint64
, depth
);
2719 *new_func
= funcptr
;
2720 process
->current_function
= funcptr
;
2723 static void pop_function(LttvTracefileState
*tfs
, guint64 funcptr
)
2725 guint cpu
= tfs
->cpu
;
2726 LttvTraceState
*ts
= (LttvTraceState
*)tfs
->parent
.t_context
;
2727 LttvProcessState
*process
= ts
->running_process
[cpu
];
2729 if(process
->current_function
!= funcptr
){
2730 g_info("Different functions (%lu.%09lu): ignore it\n",
2731 tfs
->parent
.timestamp
.tv_sec
, tfs
->parent
.timestamp
.tv_nsec
);
2732 g_info("process state has %" PRIu64
" when pop_function is %" PRIu64
"\n",
2733 process
->current_function
, funcptr
);
2734 g_info("{ %u, %u, %s, %s, %s }\n",
2737 g_quark_to_string(process
->name
),
2738 g_quark_to_string(process
->brand
),
2739 g_quark_to_string(process
->state
->s
));
2742 guint depth
= process
->user_stack
->len
;
2745 g_info("Trying to pop last function on stack (%lu.%09lu): ignore it\n",
2746 tfs
->parent
.timestamp
.tv_sec
, tfs
->parent
.timestamp
.tv_nsec
);
2750 process
->user_stack
=
2751 g_array_set_size(process
->user_stack
, depth
- 1);
2752 process
->current_function
=
2753 g_array_index(process
->user_stack
, guint64
, depth
- 2);
2757 static gboolean
function_entry(void *hook_data
, void *call_data
)
2759 LttvTracefileState
*s
= (LttvTracefileState
*)call_data
;
2760 LttEvent
*e
= ltt_tracefile_get_event(s
->parent
.tf
);
2761 //guint8 ev_id = ltt_event_eventtype_id(e);
2762 LttvTraceHook
*th
= (LttvTraceHook
*)hook_data
;
2763 struct marker_field
*f
= lttv_trace_get_hook_field(th
, 0);
2764 guint64 funcptr
= ltt_event_get_long_unsigned(e
, f
);
2766 push_function(s
, funcptr
);
2770 static gboolean
function_exit(void *hook_data
, void *call_data
)
2772 LttvTracefileState
*s
= (LttvTracefileState
*)call_data
;
2773 LttEvent
*e
= ltt_tracefile_get_event(s
->parent
.tf
);
2774 //guint8 ev_id = ltt_event_eventtype_id(e);
2775 LttvTraceHook
*th
= (LttvTraceHook
*)hook_data
;
2776 struct marker_field
*f
= lttv_trace_get_hook_field(th
, 0);
2777 guint64 funcptr
= ltt_event_get_long_unsigned(e
, f
);
2779 pop_function(s
, funcptr
);
2783 static gboolean
dump_syscall(void *hook_data
, void *call_data
)
2785 LttvTracefileState
*s
= (LttvTracefileState
*)call_data
;
2786 LttvTraceState
*ts
= (LttvTraceState
*)s
->parent
.t_context
;
2787 LttEvent
*e
= ltt_tracefile_get_event(s
->parent
.tf
);
2788 LttvTraceHook
*th
= (LttvTraceHook
*)hook_data
;
2793 id
= ltt_event_get_unsigned(e
, lttv_trace_get_hook_field(th
, 0));
2794 address
= ltt_event_get_long_unsigned(e
, lttv_trace_get_hook_field(th
, 1));
2795 symbol
= ltt_event_get_string(e
, lttv_trace_get_hook_field(th
, 2));
2797 expand_syscall_table(ts
, id
);
2798 ts
->syscall_names
[id
] = g_quark_from_string(symbol
);
2803 static gboolean
dump_kprobe(void *hook_data
, void *call_data
)
2805 LttvTracefileState
*s
= (LttvTracefileState
*)call_data
;
2806 LttvTraceState
*ts
= (LttvTraceState
*)s
->parent
.t_context
;
2807 LttEvent
*e
= ltt_tracefile_get_event(s
->parent
.tf
);
2808 LttvTraceHook
*th
= (LttvTraceHook
*)hook_data
;
2812 ip
= ltt_event_get_long_unsigned(e
, lttv_trace_get_hook_field(th
, 0));
2813 symbol
= ltt_event_get_string(e
, lttv_trace_get_hook_field(th
, 1));
2815 expand_kprobe_table(ts
, ip
, symbol
);
2820 static gboolean
dump_softirq(void *hook_data
, void *call_data
)
2822 LttvTracefileState
*s
= (LttvTracefileState
*)call_data
;
2823 LttvTraceState
*ts
= (LttvTraceState
*)s
->parent
.t_context
;
2824 LttEvent
*e
= ltt_tracefile_get_event(s
->parent
.tf
);
2825 LttvTraceHook
*th
= (LttvTraceHook
*)hook_data
;
2830 id
= ltt_event_get_unsigned(e
, lttv_trace_get_hook_field(th
, 0));
2831 address
= ltt_event_get_long_unsigned(e
, lttv_trace_get_hook_field(th
, 1));
2832 symbol
= ltt_event_get_string(e
, lttv_trace_get_hook_field(th
, 2));
2834 expand_soft_irq_table(ts
, id
);
2835 ts
->soft_irq_names
[id
] = g_quark_from_string(symbol
);
2840 static gboolean
schedchange(void *hook_data
, void *call_data
)
2842 LttvTracefileState
*s
= (LttvTracefileState
*)call_data
;
2844 LttvTraceState
*ts
= (LttvTraceState
*)s
->parent
.t_context
;
2845 LttvProcessState
*process
= ts
->running_process
[cpu
];
2846 //LttvProcessState *old_process = ts->running_process[cpu];
2848 LttEvent
*e
= ltt_tracefile_get_event(s
->parent
.tf
);
2849 LttvTraceHook
*th
= (LttvTraceHook
*)hook_data
;
2850 guint pid_in
, pid_out
;
2853 pid_out
= ltt_event_get_unsigned(e
, lttv_trace_get_hook_field(th
, 0));
2854 pid_in
= ltt_event_get_unsigned(e
, lttv_trace_get_hook_field(th
, 1));
2855 state_out
= ltt_event_get_long_int(e
, lttv_trace_get_hook_field(th
, 2));
2857 if(likely(process
!= NULL
)) {
2859 /* We could not know but it was not the idle process executing.
2860 This should only happen at the beginning, before the first schedule
2861 event, and when the initial information (current process for each CPU)
2862 is missing. It is not obvious how we could, after the fact, compensate
2863 the wrongly attributed statistics. */
2865 //This test only makes sense once the state is known and if there is no
2866 //missing events. We need to silently ignore schedchange coming after a
2867 //process_free, or it causes glitches. (FIXME)
2868 //if(unlikely(process->pid != pid_out)) {
2869 // g_assert(process->pid == 0);
2871 if(process
->pid
== 0
2872 && process
->state
->t
== LTTV_STATE_MODE_UNKNOWN
) {
2874 /* Scheduling out of pid 0 at beginning of the trace :
2875 * we know for sure it is in syscall mode at this point. */
2876 g_assert(process
->execution_stack
->len
== 1);
2877 process
->state
->t
= LTTV_STATE_SYSCALL
;
2878 process
->state
->s
= LTTV_STATE_WAIT
;
2879 process
->state
->change
= s
->parent
.timestamp
;
2880 process
->state
->entry
= s
->parent
.timestamp
;
2883 if(unlikely(process
->state
->s
== LTTV_STATE_EXIT
)) {
2884 process
->state
->s
= LTTV_STATE_ZOMBIE
;
2885 process
->state
->change
= s
->parent
.timestamp
;
2887 if(unlikely(state_out
== 0)) process
->state
->s
= LTTV_STATE_WAIT_CPU
;
2888 else process
->state
->s
= LTTV_STATE_WAIT
;
2889 process
->state
->change
= s
->parent
.timestamp
;
2892 if(state_out
== 32 || state_out
== 64) { /* EXIT_DEAD || TASK_DEAD */
2893 /* see sched.h for states */
2894 if (!exit_process(s
, process
)) {
2895 process
->state
->s
= LTTV_STATE_DEAD
;
2896 process
->state
->change
= s
->parent
.timestamp
;
2901 process
= ts
->running_process
[cpu
] =
2902 lttv_state_find_process_or_create(
2903 (LttvTraceState
*)s
->parent
.t_context
,
2905 &s
->parent
.timestamp
);
2906 process
->state
->s
= LTTV_STATE_RUN
;
2908 if(process
->usertrace
)
2909 process
->usertrace
->cpu
= cpu
;
2910 // process->last_cpu_index = ltt_tracefile_num(((LttvTracefileContext*)s)->tf);
2911 process
->state
->change
= s
->parent
.timestamp
;
2913 /* update cpu status */
2915 /* going to idle task */
2916 cpu_set_base_mode(s
->cpu_state
, LTTV_CPU_IDLE
);
2918 /* scheduling a real task.
2919 * we must be careful here:
2920 * if we just schedule()'ed to a process that is
2921 * in a trap, we must put the cpu in trap mode
2923 cpu_set_base_mode(s
->cpu_state
, LTTV_CPU_BUSY
);
2924 if(process
->state
->t
== LTTV_STATE_TRAP
)
2925 cpu_push_mode(s
->cpu_state
, LTTV_CPU_TRAP
);
2931 static gboolean
process_fork(void *hook_data
, void *call_data
)
2933 LttvTracefileState
*s
= (LttvTracefileState
*)call_data
;
2934 LttEvent
*e
= ltt_tracefile_get_event(s
->parent
.tf
);
2935 LttvTraceHook
*th
= (LttvTraceHook
*)hook_data
;
2937 guint child_pid
; /* In the Linux Kernel, there is one PID per thread. */
2938 guint child_tgid
; /* tgid in the Linux kernel is the "real" POSIX PID. */
2939 //LttvProcessState *zombie_process;
2941 LttvTraceState
*ts
= (LttvTraceState
*)s
->parent
.t_context
;
2942 LttvProcessState
*process
= ts
->running_process
[cpu
];
2943 LttvProcessState
*child_process
;
2944 struct marker_field
*f
;
2947 parent_pid
= ltt_event_get_unsigned(e
, lttv_trace_get_hook_field(th
, 0));
2950 child_pid
= ltt_event_get_unsigned(e
, lttv_trace_get_hook_field(th
, 1));
2951 s
->parent
.target_pid
= child_pid
;
2954 f
= lttv_trace_get_hook_field(th
, 2);
2956 child_tgid
= ltt_event_get_unsigned(e
, f
);
2960 /* Mathieu : it seems like the process might have been scheduled in before the
2961 * fork, and, in a rare case, might be the current process. This might happen
2962 * in a SMP case where we don't have enough precision on the clocks.
2964 * Test reenabled after precision fixes on time. (Mathieu) */
2966 zombie_process
= lttv_state_find_process(ts
, ANY_CPU
, child_pid
);
2968 if(unlikely(zombie_process
!= NULL
)) {
2969 /* Reutilisation of PID. Only now we are sure that the old PID
2970 * has been released. FIXME : should know when release_task happens instead.
2972 guint num_cpus
= ltt_trace_get_num_cpu(ts
->parent
.t
);
2974 for(i
=0; i
< num_cpus
; i
++) {
2975 g_assert(zombie_process
!= ts
->running_process
[i
]);
2978 exit_process(s
, zombie_process
);
2981 g_assert(process
->pid
!= child_pid
);
2982 // FIXME : Add this test in the "known state" section
2983 // g_assert(process->pid == parent_pid);
2984 child_process
= lttv_state_find_process(ts
, ANY_CPU
, child_pid
);
2985 if(child_process
== NULL
) {
2986 child_process
= lttv_state_create_process(ts
, process
, cpu
,
2987 child_pid
, child_tgid
,
2988 LTTV_STATE_UNNAMED
, &s
->parent
.timestamp
);
2990 /* The process has already been created : due to time imprecision between
2991 * multiple CPUs : it has been scheduled in before creation. Note that we
2992 * shouldn't have this kind of imprecision.
2994 * Simply put a correct parent.
2996 g_error("Process %u has been created at [%lu.%09lu] "
2997 "and inserted at [%lu.%09lu] before \n"
2998 "fork on cpu %u[%lu.%09lu].\n"
2999 "Probably an unsynchronized TSC problem on the traced machine.",
3001 child_process
->creation_time
.tv_sec
,
3002 child_process
->creation_time
.tv_nsec
,
3003 child_process
->insertion_time
.tv_sec
,
3004 child_process
->insertion_time
.tv_nsec
,
3005 cpu
, ltt_event_time(e
).tv_sec
, ltt_event_time(e
).tv_nsec
);
3006 //g_assert(0); /* This is a problematic case : the process has been created
3007 // before the fork event */
3008 child_process
->ppid
= process
->pid
;
3009 child_process
->tgid
= child_tgid
;
3011 g_assert(child_process
->name
== LTTV_STATE_UNNAMED
);
3012 child_process
->name
= process
->name
;
3013 child_process
->brand
= process
->brand
;
3018 /* We stamp a newly created process as kernel_thread.
3019 * The thread should not be running yet. */
3020 static gboolean
process_kernel_thread(void *hook_data
, void *call_data
)
3022 LttvTracefileState
*s
= (LttvTracefileState
*)call_data
;
3023 LttEvent
*e
= ltt_tracefile_get_event(s
->parent
.tf
);
3024 LttvTraceHook
*th
= (LttvTraceHook
*)hook_data
;
3026 LttvTraceState
*ts
= (LttvTraceState
*)s
->parent
.t_context
;
3027 LttvProcessState
*process
;
3028 LttvExecutionState
*es
;
3031 pid
= (guint
)ltt_event_get_long_unsigned(e
, lttv_trace_get_hook_field(th
, 0));
3032 s
->parent
.target_pid
= pid
;
3034 process
= lttv_state_find_process_or_create(ts
, ANY_CPU
, pid
,
3036 if (process
->state
->s
!= LTTV_STATE_DEAD
) {
3037 process
->execution_stack
=
3038 g_array_set_size(process
->execution_stack
, 1);
3039 es
= process
->state
=
3040 &g_array_index(process
->execution_stack
, LttvExecutionState
, 0);
3041 es
->t
= LTTV_STATE_SYSCALL
;
3043 process
->type
= LTTV_STATE_KERNEL_THREAD
;
3048 static gboolean
process_exit(void *hook_data
, void *call_data
)
3050 LttvTracefileState
*s
= (LttvTracefileState
*)call_data
;
3051 LttEvent
*e
= ltt_tracefile_get_event(s
->parent
.tf
);
3052 LttvTraceHook
*th
= (LttvTraceHook
*)hook_data
;
3054 LttvTraceState
*ts
= (LttvTraceState
*)s
->parent
.t_context
;
3055 LttvProcessState
*process
; // = ts->running_process[cpu];
3057 pid
= ltt_event_get_unsigned(e
, lttv_trace_get_hook_field(th
, 0));
3058 s
->parent
.target_pid
= pid
;
3060 // FIXME : Add this test in the "known state" section
3061 // g_assert(process->pid == pid);
3063 process
= lttv_state_find_process(ts
, ANY_CPU
, pid
);
3064 if(likely(process
!= NULL
)) {
3065 process
->state
->s
= LTTV_STATE_EXIT
;
3070 static gboolean
process_free(void *hook_data
, void *call_data
)
3072 LttvTracefileState
*s
= (LttvTracefileState
*)call_data
;
3073 LttvTraceState
*ts
= (LttvTraceState
*)s
->parent
.t_context
;
3074 LttEvent
*e
= ltt_tracefile_get_event(s
->parent
.tf
);
3075 LttvTraceHook
*th
= (LttvTraceHook
*)hook_data
;
3077 LttvProcessState
*process
;
3079 /* PID of the process to release */
3080 release_pid
= ltt_event_get_unsigned(e
, lttv_trace_get_hook_field(th
, 0));
3081 s
->parent
.target_pid
= release_pid
;
3083 g_assert(release_pid
!= 0);
3085 process
= lttv_state_find_process(ts
, ANY_CPU
, release_pid
);
3086 if(likely(process
!= NULL
))
3087 exit_process(s
, process
);
3090 if(likely(process
!= NULL
)) {
3091 /* release_task is happening at kernel level : we can now safely release
3092 * the data structure of the process */
3093 //This test is fun, though, as it may happen that
3094 //at time t : CPU 0 : process_free
3095 //at time t+150ns : CPU 1 : schedule out
3096 //Clearly due to time imprecision, we disable it. (Mathieu)
3097 //If this weird case happen, we have no choice but to put the
3098 //Currently running process on the cpu to 0.
3099 //I re-enable it following time precision fixes. (Mathieu)
3100 //Well, in the case where an process is freed by a process on another CPU
3101 //and still scheduled, it happens that this is the schedchange that will
3102 //drop the last reference count. Do not free it here!
3103 guint num_cpus
= ltt_trace_get_num_cpu(ts
->parent
.t
);
3105 for(i
=0; i
< num_cpus
; i
++) {
3106 //g_assert(process != ts->running_process[i]);
3107 if(process
== ts
->running_process
[i
]) {
3108 //ts->running_process[i] = lttv_state_find_process(ts, i, 0);
3112 if(i
== num_cpus
) /* process is not scheduled */
3113 exit_process(s
, process
);
3120 static gboolean
process_exec(void *hook_data
, void *call_data
)
3122 LttvTracefileState
*s
= (LttvTracefileState
*)call_data
;
3123 LttvTraceState
*ts
= (LttvTraceState
*)s
->parent
.t_context
;
3124 LttEvent
*e
= ltt_tracefile_get_event(s
->parent
.tf
);
3125 LttvTraceHook
*th
= (LttvTraceHook
*)hook_data
;
3128 LttvProcessState
*process
= ts
->running_process
[cpu
];
3130 #if 0//how to use a sequence that must be transformed in a string
3131 /* PID of the process to release */
3132 guint64 name_len
= ltt_event_field_element_number(e
,
3133 lttv_trace_get_hook_field(th
, 0));
3134 //name = ltt_event_get_string(e, lttv_trace_get_hook_field(th, 0));
3135 LttField
*child
= ltt_event_field_element_select(e
,
3136 lttv_trace_get_hook_field(th
, 0), 0);
3138 (gchar
*)(ltt_event_data(e
)+ltt_event_field_offset(e
, child
));
3139 gchar
*null_term_name
= g_new(gchar
, name_len
+1);
3140 memcpy(null_term_name
, name_begin
, name_len
);
3141 null_term_name
[name_len
] = '\0';
3142 process
->name
= g_quark_from_string(null_term_name
);
3145 process
->name
= g_quark_from_string(ltt_event_get_string(e
,
3146 lttv_trace_get_hook_field(th
, 0)));
3147 process
->brand
= LTTV_STATE_UNBRANDED
;
3148 //g_free(null_term_name);
3152 static gboolean
thread_brand(void *hook_data
, void *call_data
)
3154 LttvTracefileState
*s
= (LttvTracefileState
*)call_data
;
3155 LttvTraceState
*ts
= (LttvTraceState
*)s
->parent
.t_context
;
3156 LttEvent
*e
= ltt_tracefile_get_event(s
->parent
.tf
);
3157 LttvTraceHook
*th
= (LttvTraceHook
*)hook_data
;
3160 LttvProcessState
*process
= ts
->running_process
[cpu
];
3162 name
= ltt_event_get_string(e
, lttv_trace_get_hook_field(th
, 0));
3163 process
->brand
= g_quark_from_string(name
);
3168 static void fix_process(gpointer key
, gpointer value
,
3171 LttvProcessState
*process
;
3172 LttvExecutionState
*es
;
3173 process
= (LttvProcessState
*)value
;
3174 LttTime
*timestamp
= (LttTime
*)user_data
;
3176 if(process
->type
== LTTV_STATE_KERNEL_THREAD
) {
3177 es
= &g_array_index(process
->execution_stack
, LttvExecutionState
, 0);
3178 if(es
->t
== LTTV_STATE_MODE_UNKNOWN
) {
3179 es
->t
= LTTV_STATE_SYSCALL
;
3180 es
->n
= LTTV_STATE_SUBMODE_NONE
;
3181 es
->entry
= *timestamp
;
3182 es
->change
= *timestamp
;
3183 es
->cum_cpu_time
= ltt_time_zero
;
3184 if(es
->s
== LTTV_STATE_UNNAMED
)
3185 es
->s
= LTTV_STATE_WAIT
;
3188 es
= &g_array_index(process
->execution_stack
, LttvExecutionState
, 0);
3189 if(es
->t
== LTTV_STATE_MODE_UNKNOWN
) {
3190 es
->t
= LTTV_STATE_USER_MODE
;
3191 es
->n
= LTTV_STATE_SUBMODE_NONE
;
3192 es
->entry
= *timestamp
;
3193 //g_assert(timestamp->tv_sec != 0);
3194 es
->change
= *timestamp
;
3195 es
->cum_cpu_time
= ltt_time_zero
;
3196 if(es
->s
== LTTV_STATE_UNNAMED
)
3197 es
->s
= LTTV_STATE_RUN
;
3199 if(process
->execution_stack
->len
== 1) {
3200 /* Still in bottom unknown mode, means never did a system call
3201 * May be either in user mode, syscall mode, running or waiting.*/
3202 /* FIXME : we may be tagging syscall mode when being user mode */
3203 process
->execution_stack
=
3204 g_array_set_size(process
->execution_stack
, 2);
3205 es
= process
->state
= &g_array_index(process
->execution_stack
,
3206 LttvExecutionState
, 1);
3207 es
->t
= LTTV_STATE_SYSCALL
;
3208 es
->n
= LTTV_STATE_SUBMODE_NONE
;
3209 es
->entry
= *timestamp
;
3210 //g_assert(timestamp->tv_sec != 0);
3211 es
->change
= *timestamp
;
3212 es
->cum_cpu_time
= ltt_time_zero
;
3213 if(es
->s
== LTTV_STATE_WAIT_FORK
)
3214 es
->s
= LTTV_STATE_WAIT
;
3220 static gboolean
statedump_end(void *hook_data
, void *call_data
)
3222 LttvTracefileState
*s
= (LttvTracefileState
*)call_data
;
3223 LttvTraceState
*ts
= (LttvTraceState
*)s
->parent
.t_context
;
3224 LttvTracefileContext
*tfc
= (LttvTracefileContext
*)call_data
;
3225 //LttEvent *e = ltt_tracefile_get_event(s->parent.tf);
3226 //LttvTraceHook *th = (LttvTraceHook *)hook_data;
3228 /* For all processes */
3229 /* if kernel thread, if stack[0] is unknown, set to syscall mode, wait */
3230 /* else, if stack[0] is unknown, set to user mode, running */
3232 g_hash_table_foreach(ts
->processes
, fix_process
, &tfc
->timestamp
);
3237 static gboolean
enum_process_state(void *hook_data
, void *call_data
)
3239 LttvTracefileState
*s
= (LttvTracefileState
*)call_data
;
3240 LttEvent
*e
= ltt_tracefile_get_event(s
->parent
.tf
);
3241 //It's slow : optimise later by doing this before reading trace.
3242 LttvTraceHook
*th
= (LttvTraceHook
*)hook_data
;
3248 LttvTraceState
*ts
= (LttvTraceState
*)s
->parent
.t_context
;
3249 LttvProcessState
*process
= ts
->running_process
[cpu
];
3250 LttvProcessState
*parent_process
;
3251 struct marker_field
*f
;
3252 GQuark type
, mode
, submode
, status
;
3253 LttvExecutionState
*es
;
3257 pid
= ltt_event_get_unsigned(e
, lttv_trace_get_hook_field(th
, 0));
3258 s
->parent
.target_pid
= pid
;
3261 parent_pid
= ltt_event_get_unsigned(e
, lttv_trace_get_hook_field(th
, 1));
3264 command
= ltt_event_get_string(e
, lttv_trace_get_hook_field(th
, 2));
3267 f
= lttv_trace_get_hook_field(th
, 3);
3268 type
= ltt_enum_string_get(f
, ltt_event_get_unsigned(e
, f
));
3270 //FIXME: type is rarely used, enum must match possible types.
3273 f
= lttv_trace_get_hook_field(th
, 4);
3274 mode
= ltt_enum_string_get(f
,ltt_event_get_unsigned(e
, f
));
3277 f
= lttv_trace_get_hook_field(th
, 5);
3278 submode
= ltt_enum_string_get(f
, ltt_event_get_unsigned(e
, f
));
3281 f
= lttv_trace_get_hook_field(th
, 6);
3282 status
= ltt_enum_string_get(f
, ltt_event_get_unsigned(e
, f
));
3285 f
= lttv_trace_get_hook_field(th
, 7);
3287 tgid
= ltt_event_get_unsigned(e
, f
);
3292 nb_cpus
= ltt_trace_get_num_cpu(ts
->parent
.t
);
3293 for(i
=0; i
<nb_cpus
; i
++) {
3294 process
= lttv_state_find_process(ts
, i
, pid
);
3295 g_assert(process
!= NULL
);
3297 process
->ppid
= parent_pid
;
3298 process
->tgid
= tgid
;
3299 process
->name
= g_quark_from_string(command
);
3301 &g_array_index(process
->execution_stack
, LttvExecutionState
, 0);
3302 process
->type
= LTTV_STATE_KERNEL_THREAD
;
3306 /* The process might exist if a process was forked while performing the
3308 process
= lttv_state_find_process(ts
, ANY_CPU
, pid
);
3309 if(process
== NULL
) {
3310 parent_process
= lttv_state_find_process(ts
, ANY_CPU
, parent_pid
);
3311 process
= lttv_state_create_process(ts
, parent_process
, cpu
,
3312 pid
, tgid
, g_quark_from_string(command
),
3313 &s
->parent
.timestamp
);
3315 /* Keep the stack bottom : a running user mode */
3316 /* Disabled because of inconsistencies in the current statedump states. */
3317 if(type
== LTTV_STATE_KERNEL_THREAD
) {
3318 /* Only keep the bottom
3319 * FIXME Kernel thread : can be in syscall or interrupt or trap. */
3320 /* Will cause expected trap when in fact being syscall (even after end of
3322 * Will cause expected interrupt when being syscall. (only before end of
3323 * statedump event) */
3324 // This will cause a "popping last state on stack, ignoring it."
3325 process
->execution_stack
= g_array_set_size(process
->execution_stack
, 1);
3326 es
= process
->state
= &g_array_index(process
->execution_stack
,
3327 LttvExecutionState
, 0);
3328 process
->type
= LTTV_STATE_KERNEL_THREAD
;
3329 es
->t
= LTTV_STATE_MODE_UNKNOWN
;
3330 es
->s
= LTTV_STATE_UNNAMED
;
3331 es
->n
= LTTV_STATE_SUBMODE_UNKNOWN
;
3333 es
->t
= LTTV_STATE_SYSCALL
;
3338 /* User space process :
3339 * bottom : user mode
3340 * either currently running or scheduled out.
3341 * can be scheduled out because interrupted in (user mode or in syscall)
3342 * or because of an explicit call to the scheduler in syscall. Note that
3343 * the scheduler call comes after the irq_exit, so never in interrupt
3345 // temp workaround : set size to 1 : only have user mode bottom of stack.
3346 // will cause g_info message of expected syscall mode when in fact being
3347 // in user mode. Can also cause expected trap when in fact being user
3348 // mode in the event of a page fault reenabling interrupts in the handler.
3349 // Expected syscall and trap can also happen after the end of statedump
3350 // This will cause a "popping last state on stack, ignoring it."
3351 process
->execution_stack
= g_array_set_size(process
->execution_stack
, 1);
3352 es
= process
->state
= &g_array_index(process
->execution_stack
,
3353 LttvExecutionState
, 0);
3354 es
->t
= LTTV_STATE_MODE_UNKNOWN
;
3355 es
->s
= LTTV_STATE_UNNAMED
;
3356 es
->n
= LTTV_STATE_SUBMODE_UNKNOWN
;
3358 es
->t
= LTTV_STATE_USER_MODE
;
3366 es
= process
->state
= &g_array_index(process
->execution_stack
,
3367 LttvExecutionState
, 1);
3368 es
->t
= LTTV_STATE_MODE_UNKNOWN
;
3369 es
->s
= LTTV_STATE_UNNAMED
;
3370 es
->n
= LTTV_STATE_SUBMODE_UNKNOWN
;
3374 /* The process has already been created :
3375 * Probably was forked while dumping the process state or
3376 * was simply scheduled in prior to get the state dump event.
3378 process
->ppid
= parent_pid
;
3379 process
->tgid
= tgid
;
3380 process
->name
= g_quark_from_string(command
);
3381 process
->type
= type
;
3383 &g_array_index(process
->execution_stack
, LttvExecutionState
, 0);
3385 if(es
->t
== LTTV_STATE_MODE_UNKNOWN
) {
3386 if(type
== LTTV_STATE_KERNEL_THREAD
)
3387 es
->t
= LTTV_STATE_SYSCALL
;
3389 es
->t
= LTTV_STATE_USER_MODE
;
3392 /* Don't mess around with the stack, it will eventually become
3393 * ok after the end of state dump. */
3400 gint
lttv_state_hook_add_event_hooks(void *hook_data
, void *call_data
)
3402 LttvTracesetState
*tss
= (LttvTracesetState
*)(call_data
);
3404 lttv_state_add_event_hooks(tss
);
3409 void lttv_state_add_event_hooks(LttvTracesetState
*self
)
3411 LttvTraceset
*traceset
= self
->parent
.ts
;
3413 guint i
, j
, k
, nb_trace
, nb_tracefile
;
3417 LttvTracefileState
*tfs
;
3423 LttvAttributeValue val
;
3425 nb_trace
= lttv_traceset_number(traceset
);
3426 for(i
= 0 ; i
< nb_trace
; i
++) {
3427 ts
= (LttvTraceState
*)self
->parent
.traces
[i
];
3429 /* Find the eventtype id for the following events and register the
3430 associated by id hooks. */
3432 hooks
= g_array_sized_new(FALSE
, FALSE
, sizeof(LttvTraceHook
), 20);
3433 //hooks = g_array_set_size(hooks, 19); // Max possible number of hooks.
3436 lttv_trace_find_hook(ts
->parent
.t
,
3438 LTT_EVENT_SYSCALL_ENTRY
,
3439 FIELD_ARRAY(LTT_FIELD_SYSCALL_ID
),
3440 syscall_entry
, NULL
, &hooks
);
3442 lttv_trace_find_hook(ts
->parent
.t
,
3444 LTT_EVENT_SYSCALL_EXIT
,
3446 syscall_exit
, NULL
, &hooks
);
3448 lttv_trace_find_hook(ts
->parent
.t
,
3450 LTT_EVENT_TRAP_ENTRY
,
3451 FIELD_ARRAY(LTT_FIELD_TRAP_ID
),
3452 trap_entry
, NULL
, &hooks
);
3454 lttv_trace_find_hook(ts
->parent
.t
,
3456 LTT_EVENT_TRAP_EXIT
,
3458 trap_exit
, NULL
, &hooks
);
3460 lttv_trace_find_hook(ts
->parent
.t
,
3462 LTT_EVENT_PAGE_FAULT_ENTRY
,
3463 FIELD_ARRAY(LTT_FIELD_TRAP_ID
),
3464 trap_entry
, NULL
, &hooks
);
3466 lttv_trace_find_hook(ts
->parent
.t
,
3468 LTT_EVENT_PAGE_FAULT_EXIT
,
3470 trap_exit
, NULL
, &hooks
);
3472 lttv_trace_find_hook(ts
->parent
.t
,
3474 LTT_EVENT_PAGE_FAULT_NOSEM_ENTRY
,
3475 FIELD_ARRAY(LTT_FIELD_TRAP_ID
),
3476 trap_entry
, NULL
, &hooks
);
3478 lttv_trace_find_hook(ts
->parent
.t
,
3480 LTT_EVENT_PAGE_FAULT_NOSEM_EXIT
,
3482 trap_exit
, NULL
, &hooks
);
3484 lttv_trace_find_hook(ts
->parent
.t
,
3486 LTT_EVENT_IRQ_ENTRY
,
3487 FIELD_ARRAY(LTT_FIELD_IRQ_ID
),
3488 irq_entry
, NULL
, &hooks
);
3490 lttv_trace_find_hook(ts
->parent
.t
,
3494 irq_exit
, NULL
, &hooks
);
3496 lttv_trace_find_hook(ts
->parent
.t
,
3498 LTT_EVENT_SOFT_IRQ_RAISE
,
3499 FIELD_ARRAY(LTT_FIELD_SOFT_IRQ_ID
),
3500 soft_irq_raise
, NULL
, &hooks
);
3502 lttv_trace_find_hook(ts
->parent
.t
,
3504 LTT_EVENT_SOFT_IRQ_ENTRY
,
3505 FIELD_ARRAY(LTT_FIELD_SOFT_IRQ_ID
),
3506 soft_irq_entry
, NULL
, &hooks
);
3508 lttv_trace_find_hook(ts
->parent
.t
,
3510 LTT_EVENT_SOFT_IRQ_EXIT
,
3512 soft_irq_exit
, NULL
, &hooks
);
3514 lttv_trace_find_hook(ts
->parent
.t
,
3516 LTT_EVENT_SCHED_SCHEDULE
,
3517 FIELD_ARRAY(LTT_FIELD_PREV_PID
, LTT_FIELD_NEXT_PID
,
3518 LTT_FIELD_PREV_STATE
),
3519 schedchange
, NULL
, &hooks
);
3521 lttv_trace_find_hook(ts
->parent
.t
,
3523 LTT_EVENT_PROCESS_FORK
,
3524 FIELD_ARRAY(LTT_FIELD_PARENT_PID
, LTT_FIELD_CHILD_PID
,
3525 LTT_FIELD_CHILD_TGID
),
3526 process_fork
, NULL
, &hooks
);
3528 lttv_trace_find_hook(ts
->parent
.t
,
3530 LTT_EVENT_KTHREAD_CREATE
,
3531 FIELD_ARRAY(LTT_FIELD_PID
),
3532 process_kernel_thread
, NULL
, &hooks
);
3534 lttv_trace_find_hook(ts
->parent
.t
,
3536 LTT_EVENT_PROCESS_EXIT
,
3537 FIELD_ARRAY(LTT_FIELD_PID
),
3538 process_exit
, NULL
, &hooks
);
3540 lttv_trace_find_hook(ts
->parent
.t
,
3542 LTT_EVENT_PROCESS_FREE
,
3543 FIELD_ARRAY(LTT_FIELD_PID
),
3544 process_free
, NULL
, &hooks
);
3546 lttv_trace_find_hook(ts
->parent
.t
,
3549 FIELD_ARRAY(LTT_FIELD_FILENAME
),
3550 process_exec
, NULL
, &hooks
);
3552 lttv_trace_find_hook(ts
->parent
.t
,
3553 LTT_CHANNEL_USERSPACE
,
3554 LTT_EVENT_THREAD_BRAND
,
3555 FIELD_ARRAY(LTT_FIELD_NAME
),
3556 thread_brand
, NULL
, &hooks
);
3558 /* statedump-related hooks */
3559 lttv_trace_find_hook(ts
->parent
.t
,
3560 LTT_CHANNEL_TASK_STATE
,
3561 LTT_EVENT_PROCESS_STATE
,
3562 FIELD_ARRAY(LTT_FIELD_PID
, LTT_FIELD_PARENT_PID
, LTT_FIELD_NAME
,
3563 LTT_FIELD_TYPE
, LTT_FIELD_MODE
, LTT_FIELD_SUBMODE
,
3564 LTT_FIELD_STATUS
, LTT_FIELD_TGID
),
3565 enum_process_state
, NULL
, &hooks
);
3567 lttv_trace_find_hook(ts
->parent
.t
,
3568 LTT_CHANNEL_GLOBAL_STATE
,
3569 LTT_EVENT_STATEDUMP_END
,
3571 statedump_end
, NULL
, &hooks
);
3573 lttv_trace_find_hook(ts
->parent
.t
,
3574 LTT_CHANNEL_IRQ_STATE
,
3575 LTT_EVENT_LIST_INTERRUPT
,
3576 FIELD_ARRAY(LTT_FIELD_ACTION
, LTT_FIELD_IRQ_ID
),
3577 enum_interrupt
, NULL
, &hooks
);
3579 lttv_trace_find_hook(ts
->parent
.t
,
3581 LTT_EVENT_REQUEST_ISSUE
,
3582 FIELD_ARRAY(LTT_FIELD_MAJOR
, LTT_FIELD_MINOR
, LTT_FIELD_OPERATION
),
3583 bdev_request_issue
, NULL
, &hooks
);
3585 lttv_trace_find_hook(ts
->parent
.t
,
3587 LTT_EVENT_REQUEST_COMPLETE
,
3588 FIELD_ARRAY(LTT_FIELD_MAJOR
, LTT_FIELD_MINOR
, LTT_FIELD_OPERATION
),
3589 bdev_request_complete
, NULL
, &hooks
);
3591 lttv_trace_find_hook(ts
->parent
.t
,
3592 LTT_CHANNEL_USERSPACE
,
3593 LTT_EVENT_FUNCTION_ENTRY
,
3594 FIELD_ARRAY(LTT_FIELD_THIS_FN
, LTT_FIELD_CALL_SITE
),
3595 function_entry
, NULL
, &hooks
);
3597 lttv_trace_find_hook(ts
->parent
.t
,
3598 LTT_CHANNEL_USERSPACE
,
3599 LTT_EVENT_FUNCTION_EXIT
,
3600 FIELD_ARRAY(LTT_FIELD_THIS_FN
, LTT_FIELD_CALL_SITE
),
3601 function_exit
, NULL
, &hooks
);
3603 lttv_trace_find_hook(ts
->parent
.t
,
3604 LTT_CHANNEL_SYSCALL_STATE
,
3605 LTT_EVENT_SYS_CALL_TABLE
,
3606 FIELD_ARRAY(LTT_FIELD_ID
, LTT_FIELD_ADDRESS
, LTT_FIELD_SYMBOL
),
3607 dump_syscall
, NULL
, &hooks
);
3609 lttv_trace_find_hook(ts
->parent
.t
,
3610 LTT_CHANNEL_KPROBE_STATE
,
3611 LTT_EVENT_KPROBE_TABLE
,
3612 FIELD_ARRAY(LTT_FIELD_IP
, LTT_FIELD_SYMBOL
),
3613 dump_kprobe
, NULL
, &hooks
);
3615 lttv_trace_find_hook(ts
->parent
.t
,
3616 LTT_CHANNEL_SOFTIRQ_STATE
,
3617 LTT_EVENT_SOFTIRQ_VEC
,
3618 FIELD_ARRAY(LTT_FIELD_ID
, LTT_FIELD_ADDRESS
, LTT_FIELD_SYMBOL
),
3619 dump_softirq
, NULL
, &hooks
);
3621 /* Add these hooks to each event_by_id hooks list */
3623 nb_tracefile
= ts
->parent
.tracefiles
->len
;
3625 for(j
= 0 ; j
< nb_tracefile
; j
++) {
3627 LTTV_TRACEFILE_STATE(g_array_index(ts
->parent
.tracefiles
,
3628 LttvTracefileContext
*, j
));
3630 for(k
= 0 ; k
< hooks
->len
; k
++) {
3631 th
= &g_array_index(hooks
, LttvTraceHook
, k
);
3632 if (th
->mdata
== tfs
->parent
.tf
->mdata
)
3634 lttv_hooks_by_id_find(tfs
->parent
.event_by_id
, th
->id
),
3640 lttv_attribute_find(ts
->parent
.a
, LTTV_STATE_HOOKS
, LTTV_POINTER
, &val
);
3641 *(val
.v_pointer
) = hooks
;
3645 gint
lttv_state_hook_remove_event_hooks(void *hook_data
, void *call_data
)
3647 LttvTracesetState
*tss
= (LttvTracesetState
*)(call_data
);
3649 lttv_state_remove_event_hooks(tss
);
3654 void lttv_state_remove_event_hooks(LttvTracesetState
*self
)
3656 LttvTraceset
*traceset
= self
->parent
.ts
;
3658 guint i
, j
, k
, nb_trace
, nb_tracefile
;
3662 LttvTracefileState
*tfs
;
3668 LttvAttributeValue val
;
3670 nb_trace
= lttv_traceset_number(traceset
);
3671 for(i
= 0 ; i
< nb_trace
; i
++) {
3672 ts
= LTTV_TRACE_STATE(self
->parent
.traces
[i
]);
3674 lttv_attribute_find(ts
->parent
.a
, LTTV_STATE_HOOKS
, LTTV_POINTER
, &val
);
3675 hooks
= *(val
.v_pointer
);
3677 /* Remove these hooks from each event_by_id hooks list */
3679 nb_tracefile
= ts
->parent
.tracefiles
->len
;
3681 for(j
= 0 ; j
< nb_tracefile
; j
++) {
3683 LTTV_TRACEFILE_STATE(g_array_index(ts
->parent
.tracefiles
,
3684 LttvTracefileContext
*, j
));
3686 for(k
= 0 ; k
< hooks
->len
; k
++) {
3687 th
= &g_array_index(hooks
, LttvTraceHook
, k
);
3688 if (th
->mdata
== tfs
->parent
.tf
->mdata
)
3689 lttv_hooks_remove_data(
3690 lttv_hooks_by_id_find(tfs
->parent
.event_by_id
, th
->id
),
3695 lttv_trace_hook_remove_all(&hooks
);
3696 g_array_free(hooks
, TRUE
);
3700 static gboolean
state_save_event_hook(void *hook_data
, void *call_data
)
3702 guint
*event_count
= (guint
*)hook_data
;
3704 /* Only save at LTTV_STATE_SAVE_INTERVAL */
3705 if(likely((*event_count
)++ < LTTV_STATE_SAVE_INTERVAL
))
3710 LttvTracefileState
*self
= (LttvTracefileState
*)call_data
;
3712 LttvTraceState
*tcs
= (LttvTraceState
*)(self
->parent
.t_context
);
3714 LttvAttribute
*saved_states_tree
, *saved_state_tree
;
3716 LttvAttributeValue value
;
3718 saved_states_tree
= lttv_attribute_find_subdir(tcs
->parent
.t_a
,
3719 LTTV_STATE_SAVED_STATES
);
3720 saved_state_tree
= g_object_new(LTTV_ATTRIBUTE_TYPE
, NULL
);
3721 value
= lttv_attribute_add(saved_states_tree
,
3722 lttv_attribute_get_number(saved_states_tree
), LTTV_GOBJECT
);
3723 *(value
.v_gobject
) = (GObject
*)saved_state_tree
;
3724 value
= lttv_attribute_add(saved_state_tree
, LTTV_STATE_TIME
, LTTV_TIME
);
3725 *(value
.v_time
) = self
->parent
.timestamp
;
3726 lttv_state_save(tcs
, saved_state_tree
);
3727 g_debug("Saving state at time %lu.%lu", self
->parent
.timestamp
.tv_sec
,
3728 self
->parent
.timestamp
.tv_nsec
);
3730 *(tcs
->max_time_state_recomputed_in_seek
) = self
->parent
.timestamp
;
3735 static gboolean
state_save_after_trace_hook(void *hook_data
, void *call_data
)
3737 LttvTraceState
*tcs
= (LttvTraceState
*)(call_data
);
3739 *(tcs
->max_time_state_recomputed_in_seek
) = tcs
->parent
.time_span
.end_time
;
3744 guint
lttv_state_current_cpu(LttvTracefileState
*tfs
)
3752 static gboolean
block_start(void *hook_data
, void *call_data
)
3754 LttvTracefileState
*self
= (LttvTracefileState
*)call_data
;
3756 LttvTracefileState
*tfcs
;
3758 LttvTraceState
*tcs
= (LttvTraceState
*)(self
->parent
.t_context
);
3760 LttEventPosition
*ep
;
3762 guint i
, nb_block
, nb_event
, nb_tracefile
;
3766 LttvAttribute
*saved_states_tree
, *saved_state_tree
;
3768 LttvAttributeValue value
;
3770 ep
= ltt_event_position_new();
3772 nb_tracefile
= tcs
->parent
.tracefiles
->len
;
3774 /* Count the number of events added since the last block end in any
3777 for(i
= 0 ; i
< nb_tracefile
; i
++) {
3779 LTTV_TRACEFILE_STATE(&g_array_index(tcs
->parent
.tracefiles
,
3780 LttvTracefileContext
, i
));
3781 ltt_event_position(tfcs
->parent
.e
, ep
);
3782 ltt_event_position_get(ep
, &nb_block
, &nb_event
, &tf
);
3783 tcs
->nb_event
+= nb_event
- tfcs
->saved_position
;
3784 tfcs
->saved_position
= nb_event
;
3788 if(tcs
->nb_event
>= tcs
->save_interval
) {
3789 saved_states_tree
= lttv_attribute_find_subdir(tcs
->parent
.t_a
,
3790 LTTV_STATE_SAVED_STATES
);
3791 saved_state_tree
= g_object_new(LTTV_ATTRIBUTE_TYPE
, NULL
);
3792 value
= lttv_attribute_add(saved_states_tree
,
3793 lttv_attribute_get_number(saved_states_tree
), LTTV_GOBJECT
);
3794 *(value
.v_gobject
) = (GObject
*)saved_state_tree
;
3795 value
= lttv_attribute_add(saved_state_tree
, LTTV_STATE_TIME
, LTTV_TIME
);
3796 *(value
.v_time
) = self
->parent
.timestamp
;
3797 lttv_state_save(tcs
, saved_state_tree
);
3799 g_debug("Saving state at time %lu.%lu", self
->parent
.timestamp
.tv_sec
,
3800 self
->parent
.timestamp
.tv_nsec
);
3802 *(tcs
->max_time_state_recomputed_in_seek
) = self
->parent
.timestamp
;
3808 static gboolean
block_end(void *hook_data
, void *call_data
)
3810 LttvTracefileState
*self
= (LttvTracefileState
*)call_data
;
3812 LttvTraceState
*tcs
= (LttvTraceState
*)(self
->parent
.t_context
);
3816 LttEventPosition
*ep
;
3818 guint nb_block
, nb_event
;
3820 ep
= ltt_event_position_new();
3821 ltt_event_position(self
->parent
.e
, ep
);
3822 ltt_event_position_get(ep
, &nb_block
, &nb_event
, &tf
);
3823 tcs
->nb_event
+= nb_event
- self
->saved_position
+ 1;
3824 self
->saved_position
= 0;
3825 *(tcs
->max_time_state_recomputed_in_seek
) = self
->parent
.timestamp
;
3832 void lttv_state_save_add_event_hooks(LttvTracesetState
*self
)
3834 LttvTraceset
*traceset
= self
->parent
.ts
;
3836 guint i
, j
, nb_trace
, nb_tracefile
;
3840 LttvTracefileState
*tfs
;
3842 LttvTraceHook hook_start
, hook_end
;
3844 nb_trace
= lttv_traceset_number(traceset
);
3845 for(i
= 0 ; i
< nb_trace
; i
++) {
3846 ts
= (LttvTraceState
*)self
->parent
.traces
[i
];
3848 lttv_trace_find_hook(ts
->parent
.t
, "core","block_start",NULL
,
3849 NULL
, NULL
, block_start
, &hook_start
);
3850 lttv_trace_find_hook(ts
->parent
.t
, "core","block_end",NULL
,
3851 NULL
, NULL
, block_end
, &hook_end
);
3853 nb_tracefile
= ts
->parent
.tracefiles
->len
;
3855 for(j
= 0 ; j
< nb_tracefile
; j
++) {
3857 LTTV_TRACEFILE_STATE(&g_array_index(ts
->parent
.tracefiles
,
3858 LttvTracefileContext
, j
));
3859 lttv_hooks_add(lttv_hooks_by_id_find(tfs
->parent
.event_by_id
,
3860 hook_start
.id
), hook_start
.h
, NULL
, LTTV_PRIO_STATE
);
3861 lttv_hooks_add(lttv_hooks_by_id_find(tfs
->parent
.event_by_id
,
3862 hook_end
.id
), hook_end
.h
, NULL
, LTTV_PRIO_STATE
);
3868 void lttv_state_save_add_event_hooks(LttvTracesetState
*self
)
3870 LttvTraceset
*traceset
= self
->parent
.ts
;
3872 guint i
, j
, nb_trace
, nb_tracefile
;
3876 LttvTracefileState
*tfs
;
3879 nb_trace
= lttv_traceset_number(traceset
);
3880 for(i
= 0 ; i
< nb_trace
; i
++) {
3882 ts
= (LttvTraceState
*)self
->parent
.traces
[i
];
3883 nb_tracefile
= ts
->parent
.tracefiles
->len
;
3885 if(ts
->has_precomputed_states
) continue;
3887 guint
*event_count
= g_new(guint
, 1);
3890 for(j
= 0 ; j
< nb_tracefile
; j
++) {
3892 LTTV_TRACEFILE_STATE(g_array_index(ts
->parent
.tracefiles
,
3893 LttvTracefileContext
*, j
));
3894 lttv_hooks_add(tfs
->parent
.event
,
3895 state_save_event_hook
,
3902 lttv_process_traceset_begin(&self
->parent
,
3903 NULL
, NULL
, NULL
, NULL
, NULL
);
3907 gint
lttv_state_save_hook_add_event_hooks(void *hook_data
, void *call_data
)
3909 LttvTracesetState
*tss
= (LttvTracesetState
*)(call_data
);
3911 lttv_state_save_add_event_hooks(tss
);
3918 void lttv_state_save_remove_event_hooks(LttvTracesetState
*self
)
3920 LttvTraceset
*traceset
= self
->parent
.ts
;
3922 guint i
, j
, nb_trace
, nb_tracefile
;
3926 LttvTracefileState
*tfs
;
3928 LttvTraceHook hook_start
, hook_end
;
3930 nb_trace
= lttv_traceset_number(traceset
);
3931 for(i
= 0 ; i
< nb_trace
; i
++) {
3932 ts
= LTTV_TRACE_STATE(self
->parent
.traces
[i
]);
3934 lttv_trace_find_hook(ts
->parent
.t
, "core","block_start",NULL
,
3935 NULL
, NULL
, block_start
, &hook_start
);
3937 lttv_trace_find_hook(ts
->parent
.t
, "core","block_end",NULL
,
3938 NULL
, NULL
, block_end
, &hook_end
);
3940 nb_tracefile
= ts
->parent
.tracefiles
->len
;
3942 for(j
= 0 ; j
< nb_tracefile
; j
++) {
3944 LTTV_TRACEFILE_STATE(&g_array_index(ts
->parent
.tracefiles
,
3945 LttvTracefileContext
, j
));
3946 lttv_hooks_remove_data(lttv_hooks_by_id_find(
3947 tfs
->parent
.event_by_id
, hook_start
.id
), hook_start
.h
, NULL
);
3948 lttv_hooks_remove_data(lttv_hooks_by_id_find(
3949 tfs
->parent
.event_by_id
, hook_end
.id
), hook_end
.h
, NULL
);
3955 void lttv_state_save_remove_event_hooks(LttvTracesetState
*self
)
3957 LttvTraceset
*traceset
= self
->parent
.ts
;
3959 guint i
, j
, nb_trace
, nb_tracefile
;
3963 LttvTracefileState
*tfs
;
3965 LttvHooks
*after_trace
= lttv_hooks_new();
3967 lttv_hooks_add(after_trace
,
3968 state_save_after_trace_hook
,
3973 lttv_process_traceset_end(&self
->parent
,
3974 NULL
, after_trace
, NULL
, NULL
, NULL
);
3976 lttv_hooks_destroy(after_trace
);
3978 nb_trace
= lttv_traceset_number(traceset
);
3979 for(i
= 0 ; i
< nb_trace
; i
++) {
3981 ts
= (LttvTraceState
*)self
->parent
.traces
[i
];
3982 nb_tracefile
= ts
->parent
.tracefiles
->len
;
3984 if(ts
->has_precomputed_states
) continue;
3986 guint
*event_count
= NULL
;
3988 for(j
= 0 ; j
< nb_tracefile
; j
++) {
3990 LTTV_TRACEFILE_STATE(g_array_index(ts
->parent
.tracefiles
,
3991 LttvTracefileContext
*, j
));
3992 event_count
= lttv_hooks_remove(tfs
->parent
.event
,
3993 state_save_event_hook
);
3995 if(event_count
) g_free(event_count
);
3999 gint
lttv_state_save_hook_remove_event_hooks(void *hook_data
, void *call_data
)
4001 LttvTracesetState
*tss
= (LttvTracesetState
*)(call_data
);
4003 lttv_state_save_remove_event_hooks(tss
);
4008 void lttv_state_traceset_seek_time_closest(LttvTracesetState
*self
, LttTime t
)
4010 LttvTraceset
*traceset
= self
->parent
.ts
;
4014 int min_pos
, mid_pos
, max_pos
;
4016 guint call_rest
= 0;
4018 LttvTraceState
*tcs
;
4020 LttvAttributeValue value
;
4022 LttvAttributeType type
;
4024 LttvAttributeName name
;
4028 LttvAttribute
*saved_states_tree
, *saved_state_tree
, *closest_tree
= NULL
;
4030 //g_tree_destroy(self->parent.pqueue);
4031 //self->parent.pqueue = g_tree_new(compare_tracefile);
4033 g_info("Entering seek_time_closest for time %lu.%lu", t
.tv_sec
, t
.tv_nsec
);
4035 nb_trace
= lttv_traceset_number(traceset
);
4036 for(i
= 0 ; i
< nb_trace
; i
++) {
4037 tcs
= (LttvTraceState
*)self
->parent
.traces
[i
];
4039 if(ltt_time_compare(t
, *(tcs
->max_time_state_recomputed_in_seek
)) < 0) {
4040 saved_states_tree
= lttv_attribute_find_subdir(tcs
->parent
.t_a
,
4041 LTTV_STATE_SAVED_STATES
);
4044 if(saved_states_tree
) {
4045 max_pos
= lttv_attribute_get_number(saved_states_tree
) - 1;
4046 mid_pos
= max_pos
/ 2;
4047 while(min_pos
< max_pos
) {
4048 type
= lttv_attribute_get(saved_states_tree
, mid_pos
, &name
, &value
,
4050 g_assert(type
== LTTV_GOBJECT
);
4051 saved_state_tree
= *((LttvAttribute
**)(value
.v_gobject
));
4052 type
= lttv_attribute_get_by_name(saved_state_tree
, LTTV_STATE_TIME
,
4054 g_assert(type
== LTTV_TIME
);
4055 if(ltt_time_compare(*(value
.v_time
), t
) < 0) {
4057 closest_tree
= saved_state_tree
;
4059 else max_pos
= mid_pos
- 1;
4061 mid_pos
= (min_pos
+ max_pos
+ 1) / 2;
4065 /* restore the closest earlier saved state */
4067 lttv_state_restore(tcs
, closest_tree
);
4071 /* There is no saved state, yet we want to have it. Restart at T0 */
4073 restore_init_state(tcs
);
4074 lttv_process_trace_seek_time(&(tcs
->parent
), ltt_time_zero
);
4077 /* We want to seek quickly without restoring/updating the state */
4079 restore_init_state(tcs
);
4080 lttv_process_trace_seek_time(&(tcs
->parent
), t
);
4083 if(!call_rest
) g_info("NOT Calling restore");
4088 traceset_state_instance_init (GTypeInstance
*instance
, gpointer g_class
)
4094 traceset_state_finalize (LttvTracesetState
*self
)
4096 G_OBJECT_CLASS(g_type_class_peek(LTTV_TRACESET_CONTEXT_TYPE
))->
4097 finalize(G_OBJECT(self
));
4102 traceset_state_class_init (LttvTracesetContextClass
*klass
)
4104 GObjectClass
*gobject_class
= G_OBJECT_CLASS(klass
);
4106 gobject_class
->finalize
= (void (*)(GObject
*self
)) traceset_state_finalize
;
4107 klass
->init
= (void (*)(LttvTracesetContext
*self
, LttvTraceset
*ts
))init
;
4108 klass
->fini
= (void (*)(LttvTracesetContext
*self
))fini
;
4109 klass
->new_traceset_context
= new_traceset_context
;
4110 klass
->new_trace_context
= new_trace_context
;
4111 klass
->new_tracefile_context
= new_tracefile_context
;
4116 lttv_traceset_state_get_type(void)
4118 static GType type
= 0;
4120 static const GTypeInfo info
= {
4121 sizeof (LttvTracesetStateClass
),
4122 NULL
, /* base_init */
4123 NULL
, /* base_finalize */
4124 (GClassInitFunc
) traceset_state_class_init
, /* class_init */
4125 NULL
, /* class_finalize */
4126 NULL
, /* class_data */
4127 sizeof (LttvTracesetState
),
4128 0, /* n_preallocs */
4129 (GInstanceInitFunc
) traceset_state_instance_init
, /* instance_init */
4130 NULL
/* value handling */
4133 type
= g_type_register_static (LTTV_TRACESET_CONTEXT_TYPE
, "LttvTracesetStateType",
4141 trace_state_instance_init (GTypeInstance
*instance
, gpointer g_class
)
4147 trace_state_finalize (LttvTraceState
*self
)
4149 G_OBJECT_CLASS(g_type_class_peek(LTTV_TRACE_CONTEXT_TYPE
))->
4150 finalize(G_OBJECT(self
));
4155 trace_state_class_init (LttvTraceStateClass
*klass
)
4157 GObjectClass
*gobject_class
= G_OBJECT_CLASS(klass
);
4159 gobject_class
->finalize
= (void (*)(GObject
*self
)) trace_state_finalize
;
4160 klass
->state_save
= state_save
;
4161 klass
->state_restore
= state_restore
;
4162 klass
->state_saved_free
= state_saved_free
;
4167 lttv_trace_state_get_type(void)
4169 static GType type
= 0;
4171 static const GTypeInfo info
= {
4172 sizeof (LttvTraceStateClass
),
4173 NULL
, /* base_init */
4174 NULL
, /* base_finalize */
4175 (GClassInitFunc
) trace_state_class_init
, /* class_init */
4176 NULL
, /* class_finalize */
4177 NULL
, /* class_data */
4178 sizeof (LttvTraceState
),
4179 0, /* n_preallocs */
4180 (GInstanceInitFunc
) trace_state_instance_init
, /* instance_init */
4181 NULL
/* value handling */
4184 type
= g_type_register_static (LTTV_TRACE_CONTEXT_TYPE
,
4185 "LttvTraceStateType", &info
, 0);
4192 tracefile_state_instance_init (GTypeInstance
*instance
, gpointer g_class
)
4198 tracefile_state_finalize (LttvTracefileState
*self
)
4200 G_OBJECT_CLASS(g_type_class_peek(LTTV_TRACEFILE_CONTEXT_TYPE
))->
4201 finalize(G_OBJECT(self
));
4206 tracefile_state_class_init (LttvTracefileStateClass
*klass
)
4208 GObjectClass
*gobject_class
= G_OBJECT_CLASS(klass
);
4210 gobject_class
->finalize
= (void (*)(GObject
*self
)) tracefile_state_finalize
;
4215 lttv_tracefile_state_get_type(void)
4217 static GType type
= 0;
4219 static const GTypeInfo info
= {
4220 sizeof (LttvTracefileStateClass
),
4221 NULL
, /* base_init */
4222 NULL
, /* base_finalize */
4223 (GClassInitFunc
) tracefile_state_class_init
, /* class_init */
4224 NULL
, /* class_finalize */
4225 NULL
, /* class_data */
4226 sizeof (LttvTracefileState
),
4227 0, /* n_preallocs */
4228 (GInstanceInitFunc
) tracefile_state_instance_init
, /* instance_init */
4229 NULL
/* value handling */
4232 type
= g_type_register_static (LTTV_TRACEFILE_CONTEXT_TYPE
,
4233 "LttvTracefileStateType", &info
, 0);
4239 static void module_init()
4241 LTTV_STATE_UNNAMED
= g_quark_from_string("");
4242 LTTV_STATE_UNBRANDED
= g_quark_from_string("");
4243 LTTV_STATE_MODE_UNKNOWN
= g_quark_from_string("MODE_UNKNOWN");
4244 LTTV_STATE_USER_MODE
= g_quark_from_string("USER_MODE");
4245 LTTV_STATE_SYSCALL
= g_quark_from_string("SYSCALL");
4246 LTTV_STATE_TRAP
= g_quark_from_string("TRAP");
4247 LTTV_STATE_IRQ
= g_quark_from_string("IRQ");
4248 LTTV_STATE_SOFT_IRQ
= g_quark_from_string("SOFTIRQ");
4249 LTTV_STATE_SUBMODE_UNKNOWN
= g_quark_from_string("UNKNOWN");
4250 LTTV_STATE_SUBMODE_NONE
= g_quark_from_string("NONE");
4251 LTTV_STATE_WAIT_FORK
= g_quark_from_string("WAIT_FORK");
4252 LTTV_STATE_WAIT_CPU
= g_quark_from_string("WAIT_CPU");
4253 LTTV_STATE_EXIT
= g_quark_from_string("EXIT");
4254 LTTV_STATE_ZOMBIE
= g_quark_from_string("ZOMBIE");
4255 LTTV_STATE_WAIT
= g_quark_from_string("WAIT");
4256 LTTV_STATE_RUN
= g_quark_from_string("RUN");
4257 LTTV_STATE_DEAD
= g_quark_from_string("DEAD");
4258 LTTV_STATE_USER_THREAD
= g_quark_from_string("USER_THREAD");
4259 LTTV_STATE_KERNEL_THREAD
= g_quark_from_string("KERNEL_THREAD");
4260 LTTV_STATE_TRACEFILES
= g_quark_from_string("tracefiles");
4261 LTTV_STATE_PROCESSES
= g_quark_from_string("processes");
4262 LTTV_STATE_PROCESS
= g_quark_from_string("process");
4263 LTTV_STATE_RUNNING_PROCESS
= g_quark_from_string("running_process");
4264 LTTV_STATE_EVENT
= g_quark_from_string("event");
4265 LTTV_STATE_SAVED_STATES
= g_quark_from_string("saved states");
4266 LTTV_STATE_SAVED_STATES_TIME
= g_quark_from_string("saved states time");
4267 LTTV_STATE_TIME
= g_quark_from_string("time");
4268 LTTV_STATE_HOOKS
= g_quark_from_string("saved state hooks");
4269 LTTV_STATE_NAME_TABLES
= g_quark_from_string("name tables");
4270 LTTV_STATE_TRACE_STATE_USE_COUNT
=
4271 g_quark_from_string("trace_state_use_count");
4272 LTTV_STATE_RESOURCE_CPUS
= g_quark_from_string("cpu resource states");
4273 LTTV_STATE_RESOURCE_CPUS
= g_quark_from_string("cpu count");
4274 LTTV_STATE_RESOURCE_IRQS
= g_quark_from_string("irq resource states");
4275 LTTV_STATE_RESOURCE_SOFT_IRQS
= g_quark_from_string("soft irq resource states");
4276 LTTV_STATE_RESOURCE_TRAPS
= g_quark_from_string("trap resource states");
4277 LTTV_STATE_RESOURCE_BLKDEVS
= g_quark_from_string("blkdevs resource states");
4279 LTT_CHANNEL_FD_STATE
= g_quark_from_string("fd_state");
4280 LTT_CHANNEL_GLOBAL_STATE
= g_quark_from_string("global_state");
4281 LTT_CHANNEL_IRQ_STATE
= g_quark_from_string("irq_state");
4282 LTT_CHANNEL_MODULE_STATE
= g_quark_from_string("module_state");
4283 LTT_CHANNEL_NETIF_STATE
= g_quark_from_string("netif_state");
4284 LTT_CHANNEL_SOFTIRQ_STATE
= g_quark_from_string("softirq_state");
4285 LTT_CHANNEL_SWAP_STATE
= g_quark_from_string("swap_state");
4286 LTT_CHANNEL_SYSCALL_STATE
= g_quark_from_string("syscall_state");
4287 LTT_CHANNEL_TASK_STATE
= g_quark_from_string("task_state");
4288 LTT_CHANNEL_VM_STATE
= g_quark_from_string("vm_state");
4289 LTT_CHANNEL_KPROBE_STATE
= g_quark_from_string("kprobe_state");
4290 LTT_CHANNEL_FS
= g_quark_from_string("fs");
4291 LTT_CHANNEL_KERNEL
= g_quark_from_string("kernel");
4292 LTT_CHANNEL_MM
= g_quark_from_string("mm");
4293 LTT_CHANNEL_USERSPACE
= g_quark_from_string("userspace");
4294 LTT_CHANNEL_BLOCK
= g_quark_from_string("block");
4296 LTT_EVENT_SYSCALL_ENTRY
= g_quark_from_string("syscall_entry");
4297 LTT_EVENT_SYSCALL_EXIT
= g_quark_from_string("syscall_exit");
4298 LTT_EVENT_TRAP_ENTRY
= g_quark_from_string("trap_entry");
4299 LTT_EVENT_TRAP_EXIT
= g_quark_from_string("trap_exit");
4300 LTT_EVENT_PAGE_FAULT_ENTRY
= g_quark_from_string("page_fault_entry");
4301 LTT_EVENT_PAGE_FAULT_EXIT
= g_quark_from_string("page_fault_exit");
4302 LTT_EVENT_PAGE_FAULT_NOSEM_ENTRY
= g_quark_from_string("page_fault_nosem_entry");
4303 LTT_EVENT_PAGE_FAULT_NOSEM_EXIT
= g_quark_from_string("page_fault_nosem_exit");
4304 LTT_EVENT_IRQ_ENTRY
= g_quark_from_string("irq_entry");
4305 LTT_EVENT_IRQ_EXIT
= g_quark_from_string("irq_exit");
4306 LTT_EVENT_SOFT_IRQ_RAISE
= g_quark_from_string("softirq_raise");
4307 LTT_EVENT_SOFT_IRQ_ENTRY
= g_quark_from_string("softirq_entry");
4308 LTT_EVENT_SOFT_IRQ_EXIT
= g_quark_from_string("softirq_exit");
4309 LTT_EVENT_SCHED_SCHEDULE
= g_quark_from_string("sched_schedule");
4310 LTT_EVENT_PROCESS_FORK
= g_quark_from_string("process_fork");
4311 LTT_EVENT_KTHREAD_CREATE
= g_quark_from_string("kthread_create");
4312 LTT_EVENT_PROCESS_EXIT
= g_quark_from_string("process_exit");
4313 LTT_EVENT_PROCESS_FREE
= g_quark_from_string("process_free");
4314 LTT_EVENT_EXEC
= g_quark_from_string("exec");
4315 LTT_EVENT_PROCESS_STATE
= g_quark_from_string("process_state");
4316 LTT_EVENT_STATEDUMP_END
= g_quark_from_string("statedump_end");
4317 LTT_EVENT_FUNCTION_ENTRY
= g_quark_from_string("function_entry");
4318 LTT_EVENT_FUNCTION_EXIT
= g_quark_from_string("function_exit");
4319 LTT_EVENT_THREAD_BRAND
= g_quark_from_string("thread_brand");
4320 LTT_EVENT_REQUEST_ISSUE
= g_quark_from_string("_blk_request_issue");
4321 LTT_EVENT_REQUEST_COMPLETE
= g_quark_from_string("_blk_request_complete");
4322 LTT_EVENT_LIST_INTERRUPT
= g_quark_from_string("interrupt");
4323 LTT_EVENT_SYS_CALL_TABLE
= g_quark_from_string("sys_call_table");
4324 LTT_EVENT_SOFTIRQ_VEC
= g_quark_from_string("softirq_vec");
4325 LTT_EVENT_KPROBE_TABLE
= g_quark_from_string("kprobe_table");
4326 LTT_EVENT_KPROBE
= g_quark_from_string("kprobe");
4328 LTT_FIELD_SYSCALL_ID
= g_quark_from_string("syscall_id");
4329 LTT_FIELD_TRAP_ID
= g_quark_from_string("trap_id");
4330 LTT_FIELD_IRQ_ID
= g_quark_from_string("irq_id");
4331 LTT_FIELD_SOFT_IRQ_ID
= g_quark_from_string("softirq_id");
4332 LTT_FIELD_PREV_PID
= g_quark_from_string("prev_pid");
4333 LTT_FIELD_NEXT_PID
= g_quark_from_string("next_pid");
4334 LTT_FIELD_PREV_STATE
= g_quark_from_string("prev_state");
4335 LTT_FIELD_PARENT_PID
= g_quark_from_string("parent_pid");
4336 LTT_FIELD_CHILD_PID
= g_quark_from_string("child_pid");
4337 LTT_FIELD_PID
= g_quark_from_string("pid");
4338 LTT_FIELD_TGID
= g_quark_from_string("tgid");
4339 LTT_FIELD_CHILD_TGID
= g_quark_from_string("child_tgid");
4340 LTT_FIELD_FILENAME
= g_quark_from_string("filename");
4341 LTT_FIELD_NAME
= g_quark_from_string("name");
4342 LTT_FIELD_TYPE
= g_quark_from_string("type");
4343 LTT_FIELD_MODE
= g_quark_from_string("mode");
4344 LTT_FIELD_SUBMODE
= g_quark_from_string("submode");
4345 LTT_FIELD_STATUS
= g_quark_from_string("status");
4346 LTT_FIELD_THIS_FN
= g_quark_from_string("this_fn");
4347 LTT_FIELD_CALL_SITE
= g_quark_from_string("call_site");
4348 LTT_FIELD_MAJOR
= g_quark_from_string("major");
4349 LTT_FIELD_MINOR
= g_quark_from_string("minor");
4350 LTT_FIELD_OPERATION
= g_quark_from_string("direction");
4351 LTT_FIELD_ACTION
= g_quark_from_string("action");
4352 LTT_FIELD_ID
= g_quark_from_string("id");
4353 LTT_FIELD_ADDRESS
= g_quark_from_string("address");
4354 LTT_FIELD_SYMBOL
= g_quark_from_string("symbol");
4355 LTT_FIELD_IP
= g_quark_from_string("ip");
4357 LTTV_CPU_UNKNOWN
= g_quark_from_string("unknown");
4358 LTTV_CPU_IDLE
= g_quark_from_string("idle");
4359 LTTV_CPU_BUSY
= g_quark_from_string("busy");
4360 LTTV_CPU_IRQ
= g_quark_from_string("irq");
4361 LTTV_CPU_SOFT_IRQ
= g_quark_from_string("softirq");
4362 LTTV_CPU_TRAP
= g_quark_from_string("trap");
4364 LTTV_IRQ_UNKNOWN
= g_quark_from_string("unknown");
4365 LTTV_IRQ_IDLE
= g_quark_from_string("idle");
4366 LTTV_IRQ_BUSY
= g_quark_from_string("busy");
4368 LTTV_BDEV_UNKNOWN
= g_quark_from_string("unknown");
4369 LTTV_BDEV_IDLE
= g_quark_from_string("idle");
4370 LTTV_BDEV_BUSY_READING
= g_quark_from_string("busy_reading");
4371 LTTV_BDEV_BUSY_WRITING
= g_quark_from_string("busy_writing");
4374 static void module_destroy()
4379 LTTV_MODULE("state", "State computation", \
4380 "Update the system state, possibly saving it at intervals", \
4381 module_init
, module_destroy
)