1 /* This file is part of the Linux Trace Toolkit viewer
2 * Copyright (C) 2003-2004 Michel Dagenais
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License Version 2 as
6 * published by the Free Software Foundation;
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
13 * You should have received a copy of the GNU General Public License
14 * along with this program; if not, write to the Free Software
15 * Foundation, Inc., 59 Temple Place - Suite 330, Boston,
25 #include <lttv/lttv.h>
26 #include <lttv/module.h>
27 #include <lttv/state.h>
28 #include <ltt/trace.h>
29 #include <ltt/event.h>
31 #include <ltt/marker-desc.h>
34 #include <ltt/ltt-private.h>
39 * usertrace is there only to be able to update the current CPU of the
40 * usertraces when there is a schedchange. it is a way to link the ProcessState
41 * to the associated usertrace. Link only created upon thread creation.
43 * The cpu id is necessary : it gives us back the current ProcessState when we
44 * are considering data from the usertrace.
47 #define PREALLOCATED_EXECUTION_STACK 10
53 LTT_CHANNEL_GLOBAL_STATE
,
54 LTT_CHANNEL_IRQ_STATE
,
55 LTT_CHANNEL_MODULE_STATE
,
56 LTT_CHANNEL_NETIF_STATE
,
57 LTT_CHANNEL_SOFTIRQ_STATE
,
58 LTT_CHANNEL_SWAP_STATE
,
59 LTT_CHANNEL_SYSCALL_STATE
,
60 LTT_CHANNEL_TASK_STATE
,
62 LTT_CHANNEL_KPROBE_STATE
,
66 LTT_CHANNEL_USERSPACE
,
72 LTT_EVENT_SYSCALL_ENTRY
,
73 LTT_EVENT_SYSCALL_EXIT
,
74 LTT_EVENT_PAGE_FAULT_NOSEM_ENTRY
,
75 LTT_EVENT_PAGE_FAULT_NOSEM_EXIT
,
76 LTT_EVENT_PAGE_FAULT_ENTRY
,
77 LTT_EVENT_PAGE_FAULT_EXIT
,
82 LTT_EVENT_SOFT_IRQ_RAISE
,
83 LTT_EVENT_SOFT_IRQ_ENTRY
,
84 LTT_EVENT_SOFT_IRQ_EXIT
,
85 LTT_EVENT_SCHED_SCHEDULE
,
86 LTT_EVENT_PROCESS_FORK
,
87 LTT_EVENT_KTHREAD_CREATE
,
88 LTT_EVENT_PROCESS_EXIT
,
89 LTT_EVENT_PROCESS_FREE
,
91 LTT_EVENT_PROCESS_STATE
,
92 LTT_EVENT_STATEDUMP_END
,
93 LTT_EVENT_FUNCTION_ENTRY
,
94 LTT_EVENT_FUNCTION_EXIT
,
95 LTT_EVENT_THREAD_BRAND
,
96 LTT_EVENT_REQUEST_ISSUE
,
97 LTT_EVENT_REQUEST_COMPLETE
,
98 LTT_EVENT_LIST_INTERRUPT
,
99 LTT_EVENT_SYS_CALL_TABLE
,
100 LTT_EVENT_SOFTIRQ_VEC
,
101 LTT_EVENT_KPROBE_TABLE
,
107 LTT_FIELD_SYSCALL_ID
,
110 LTT_FIELD_SOFT_IRQ_ID
,
113 LTT_FIELD_PREV_STATE
,
114 LTT_FIELD_PARENT_PID
,
118 LTT_FIELD_CHILD_TGID
,
137 LTTV_STATE_MODE_UNKNOWN
,
138 LTTV_STATE_USER_MODE
,
145 LTTV_STATE_SUBMODE_UNKNOWN
,
146 LTTV_STATE_SUBMODE_NONE
;
150 LTTV_STATE_WAIT_FORK
,
159 LTTV_STATE_UNBRANDED
;
162 LTTV_STATE_USER_THREAD
,
163 LTTV_STATE_KERNEL_THREAD
;
181 LTTV_BDEV_BUSY_READING
,
182 LTTV_BDEV_BUSY_WRITING
;
185 LTTV_STATE_TRACEFILES
,
186 LTTV_STATE_PROCESSES
,
188 LTTV_STATE_RUNNING_PROCESS
,
190 LTTV_STATE_SAVED_STATES
,
191 LTTV_STATE_SAVED_STATES_TIME
,
194 LTTV_STATE_NAME_TABLES
,
195 LTTV_STATE_TRACE_STATE_USE_COUNT
,
196 LTTV_STATE_RESOURCE_CPUS
,
197 LTTV_STATE_RESOURCE_CPUS_COUNT
,
198 LTTV_STATE_RESOURCE_IRQS
,
199 LTTV_STATE_RESOURCE_SOFT_IRQS
,
200 LTTV_STATE_RESOURCE_TRAPS
,
201 LTTV_STATE_RESOURCE_BLKDEVS
;
203 static void create_max_time(LttvTraceState
*tcs
);
205 static void get_max_time(LttvTraceState
*tcs
);
207 static void free_max_time(LttvTraceState
*tcs
);
209 static void create_name_tables(LttvTraceState
*tcs
);
211 static void get_name_tables(LttvTraceState
*tcs
);
213 static void free_name_tables(LttvTraceState
*tcs
);
215 static void free_saved_state(LttvTraceState
*tcs
);
217 static void lttv_state_free_process_table(GHashTable
*processes
);
219 static void lttv_trace_states_read_raw(LttvTraceState
*tcs
, FILE *fp
,
220 GPtrArray
*quarktable
);
222 /* Resource function prototypes */
223 static LttvBdevState
*get_hashed_bdevstate(LttvTraceState
*ts
, guint16 devcode
);
224 static LttvBdevState
*bdevstate_new(void);
225 static void bdevstate_free(LttvBdevState
*);
226 static void bdevstate_free_cb(gpointer key
, gpointer value
, gpointer user_data
);
227 static LttvBdevState
*bdevstate_copy(LttvBdevState
*bds
);
230 #if (__SIZEOF_LONG__ == 4)
231 guint
guint64_hash(gconstpointer key
)
233 guint64 ukey
= *(const guint64
*)key
;
235 return (guint
)ukey
^ (guint
)(ukey
>> 32);
238 gboolean
guint64_equal(gconstpointer a
, gconstpointer b
)
240 guint64 ua
= *(const guint64
*)a
;
241 guint64 ub
= *(const guint64
*)b
;
247 void lttv_state_save(LttvTraceState
*self
, LttvAttribute
*container
)
249 LTTV_TRACE_STATE_GET_CLASS(self
)->state_save(self
, container
);
253 void lttv_state_restore(LttvTraceState
*self
, LttvAttribute
*container
)
255 LTTV_TRACE_STATE_GET_CLASS(self
)->state_restore(self
, container
);
259 void lttv_state_state_saved_free(LttvTraceState
*self
,
260 LttvAttribute
*container
)
262 LTTV_TRACE_STATE_GET_CLASS(self
)->state_saved_free(self
, container
);
266 guint
process_hash(gconstpointer key
)
268 guint pid
= ((const LttvProcessState
*)key
)->pid
;
269 return (pid
>>8 ^ pid
>>4 ^ pid
>>2 ^ pid
) ;
273 /* If the hash table hash function is well distributed,
274 * the process_equal should compare different pid */
275 gboolean
process_equal(gconstpointer a
, gconstpointer b
)
277 const LttvProcessState
*process_a
, *process_b
;
280 process_a
= (const LttvProcessState
*)a
;
281 process_b
= (const LttvProcessState
*)b
;
283 if(likely(process_a
->pid
!= process_b
->pid
)) ret
= FALSE
;
284 else if(likely(process_a
->pid
== 0 &&
285 process_a
->cpu
!= process_b
->cpu
)) ret
= FALSE
;
290 static void delete_usertrace(gpointer key
, gpointer value
, gpointer user_data
)
292 g_tree_destroy((GTree
*)value
);
295 static void lttv_state_free_usertraces(GHashTable
*usertraces
)
297 g_hash_table_foreach(usertraces
, delete_usertrace
, NULL
);
298 g_hash_table_destroy(usertraces
);
301 gboolean
rettrue(gpointer key
, gpointer value
, gpointer user_data
)
306 static guint
check_expand(nb
, id
)
311 return max(id
+ 1, nb
* 2);
314 static void expand_name_table(LttvTraceState
*ts
, GQuark
**table
,
315 guint nb
, guint new_nb
)
317 /* Expand an incomplete table */
318 GQuark
*old_table
= *table
;
319 *table
= g_new(GQuark
, new_nb
);
320 memcpy(*table
, old_table
, nb
* sizeof(GQuark
));
323 static void fill_name_table(LttvTraceState
*ts
, GQuark
*table
, guint nb
,
324 guint new_nb
, const char *def_string
)
327 GString
*fe_name
= g_string_new("");
328 for(i
= nb
; i
< new_nb
; i
++) {
329 g_string_printf(fe_name
, "%s %d", def_string
, i
);
330 table
[i
] = g_quark_from_string(fe_name
->str
);
332 g_string_free(fe_name
, TRUE
);
335 static void expand_syscall_table(LttvTraceState
*ts
, int id
)
337 guint new_nb
= check_expand(ts
->nb_syscalls
, id
);
338 if(likely(new_nb
== ts
->nb_syscalls
))
340 expand_name_table(ts
, &ts
->syscall_names
, ts
->nb_syscalls
, new_nb
);
341 fill_name_table(ts
, ts
->syscall_names
, ts
->nb_syscalls
, new_nb
, "syscall");
342 /* Update the table size */
343 ts
->nb_syscalls
= new_nb
;
346 static void expand_kprobe_table(LttvTraceState
*ts
, guint64 ip
, char *symbol
)
348 #if (__SIZEOF_LONG__ == 4)
349 guint64
*ip_ptr
= g_new(guint64
, 1);
350 g_hash_table_insert(ts
->kprobe_hash
, ip_ptr
,
351 (gpointer
)(glong
)g_quark_from_string(symbol
));
353 g_hash_table_insert(ts
->kprobe_hash
, (gpointer
)ip
,
354 (gpointer
)(glong
)g_quark_from_string(symbol
));
358 static void expand_trap_table(LttvTraceState
*ts
, int id
)
360 guint new_nb
= check_expand(ts
->nb_traps
, id
);
362 if(likely(new_nb
== ts
->nb_traps
))
364 expand_name_table(ts
, &ts
->trap_names
, ts
->nb_traps
, new_nb
);
365 fill_name_table(ts
, ts
->trap_names
, ts
->nb_traps
, new_nb
, "trap");
366 /* Update the table size */
367 ts
->nb_traps
= new_nb
;
369 LttvTrapState
*old_table
= ts
->trap_states
;
370 ts
->trap_states
= g_new(LttvTrapState
, new_nb
);
371 memcpy(ts
->trap_states
, old_table
,
372 ts
->nb_traps
* sizeof(LttvTrapState
));
373 for(i
= ts
->nb_traps
; i
< new_nb
; i
++)
374 ts
->trap_states
[i
].running
= 0;
377 static void expand_irq_table(LttvTraceState
*ts
, int id
)
379 guint new_nb
= check_expand(ts
->nb_irqs
, id
);
381 if(likely(new_nb
== ts
->nb_irqs
))
383 expand_name_table(ts
, &ts
->irq_names
, ts
->nb_irqs
, new_nb
);
384 fill_name_table(ts
, ts
->irq_names
, ts
->nb_irqs
, new_nb
, "irq");
386 LttvIRQState
*old_table
= ts
->irq_states
;
387 ts
->irq_states
= g_new(LttvIRQState
, new_nb
);
388 memcpy(ts
->irq_states
, old_table
, ts
->nb_irqs
* sizeof(LttvIRQState
));
389 for(i
= ts
->nb_irqs
; i
< new_nb
; i
++) {
390 ts
->irq_states
[i
].mode_stack
= g_array_new(FALSE
, FALSE
, sizeof(LttvIRQMode
));
393 /* Update the table size */
394 ts
->nb_irqs
= new_nb
;
397 static void expand_soft_irq_table(LttvTraceState
*ts
, int id
)
399 guint new_nb
= check_expand(ts
->nb_soft_irqs
, id
);
401 if(likely(new_nb
== ts
->nb_soft_irqs
))
403 expand_name_table(ts
, &ts
->soft_irq_names
, ts
->nb_soft_irqs
, new_nb
);
404 fill_name_table(ts
, ts
->soft_irq_names
, ts
->nb_soft_irqs
, new_nb
, "softirq");
406 LttvSoftIRQState
*old_table
= ts
->soft_irq_states
;
407 ts
->soft_irq_states
= g_new(LttvSoftIRQState
, new_nb
);
408 memcpy(ts
->soft_irq_states
, old_table
,
409 ts
->nb_soft_irqs
* sizeof(LttvSoftIRQState
));
410 for(i
= ts
->nb_soft_irqs
; i
< new_nb
; i
++)
411 ts
->soft_irq_states
[i
].running
= 0;
413 /* Update the table size */
414 ts
->nb_soft_irqs
= new_nb
;
418 restore_init_state(LttvTraceState
*self
)
420 guint i
, nb_cpus
, nb_irqs
, nb_soft_irqs
, nb_traps
;
422 //LttvTracefileState *tfcs;
424 LttTime start_time
, end_time
;
426 /* Free the process tables */
427 if(self
->processes
!= NULL
) lttv_state_free_process_table(self
->processes
);
428 if(self
->usertraces
!= NULL
) lttv_state_free_usertraces(self
->usertraces
);
429 self
->processes
= g_hash_table_new(process_hash
, process_equal
);
430 self
->usertraces
= g_hash_table_new(g_direct_hash
, g_direct_equal
);
433 /* Seek time to beginning */
434 // Mathieu : fix : don't seek traceset here : causes inconsistency in seek
435 // closest. It's the tracecontext job to seek the trace to the beginning
436 // anyway : the init state might be used at the middle of the trace as well...
437 //g_tree_destroy(self->parent.ts_context->pqueue);
438 //self->parent.ts_context->pqueue = g_tree_new(compare_tracefile);
440 ltt_trace_time_span_get(self
->parent
.t
, &start_time
, &end_time
);
442 //lttv_process_trace_seek_time(&self->parent, ltt_time_zero);
444 nb_cpus
= ltt_trace_get_num_cpu(self
->parent
.t
);
445 nb_irqs
= self
->nb_irqs
;
446 nb_soft_irqs
= self
->nb_soft_irqs
;
447 nb_traps
= self
->nb_traps
;
449 /* Put the per cpu running_process to beginning state : process 0. */
450 for(i
=0; i
< nb_cpus
; i
++) {
451 LttvExecutionState
*es
;
452 self
->running_process
[i
] = lttv_state_create_process(self
, NULL
, i
, 0, 0,
453 LTTV_STATE_UNNAMED
, &start_time
);
454 /* We are not sure is it's a kernel thread or normal thread, put the
455 * bottom stack state to unknown */
456 self
->running_process
[i
]->execution_stack
=
457 g_array_set_size(self
->running_process
[i
]->execution_stack
, 1);
458 es
= self
->running_process
[i
]->state
=
459 &g_array_index(self
->running_process
[i
]->execution_stack
,
460 LttvExecutionState
, 0);
461 es
->t
= LTTV_STATE_MODE_UNKNOWN
;
462 es
->s
= LTTV_STATE_UNNAMED
;
464 //self->running_process[i]->state->s = LTTV_STATE_RUN;
465 self
->running_process
[i
]->cpu
= i
;
467 /* reset cpu states */
468 if(self
->cpu_states
[i
].mode_stack
->len
> 0) {
469 g_array_remove_range(self
->cpu_states
[i
].mode_stack
, 0, self
->cpu_states
[i
].mode_stack
->len
);
470 if(self
->cpu_states
[i
].irq_stack
->len
)
471 g_array_remove_range(self
->cpu_states
[i
].irq_stack
, 0, self
->cpu_states
[i
].irq_stack
->len
);
472 self
->cpu_states
[i
].last_soft_irq
= -1;
473 self
->cpu_states
[i
].last_trap
= -1;
477 /* reset irq states */
478 for(i
=0; i
<nb_irqs
; i
++) {
479 if(self
->irq_states
[i
].mode_stack
->len
> 0)
480 g_array_remove_range(self
->irq_states
[i
].mode_stack
, 0, self
->irq_states
[i
].mode_stack
->len
);
483 /* reset softirq states */
484 for(i
=0; i
<nb_soft_irqs
; i
++) {
485 self
->soft_irq_states
[i
].pending
= 0;
486 self
->soft_irq_states
[i
].running
= 0;
489 /* reset trap states */
490 for(i
=0; i
<nb_traps
; i
++) {
491 self
->trap_states
[i
].running
= 0;
494 /* reset bdev states */
495 g_hash_table_foreach(self
->bdev_states
, bdevstate_free_cb
, NULL
);
496 //g_hash_table_steal_all(self->bdev_states);
497 g_hash_table_foreach_steal(self
->bdev_states
, rettrue
, NULL
);
500 nb_tracefile
= self
->parent
.tracefiles
->len
;
502 for(i
= 0 ; i
< nb_tracefile
; i
++) {
504 LTTV_TRACEFILE_STATE(g_array_index(self
->parent
.tracefiles
,
505 LttvTracefileContext
*, i
));
506 ltt_trace_time_span_get(self
->parent
.t
, &tfcs
->parent
.timestamp
, NULL
);
507 // tfcs->saved_position = 0;
508 tfcs
->process
= lttv_state_create_process(tfcs
, NULL
,0);
509 tfcs
->process
->state
->s
= LTTV_STATE_RUN
;
510 tfcs
->process
->last_cpu
= tfcs
->cpu_name
;
511 tfcs
->process
->last_cpu_index
= ltt_tracefile_num(((LttvTracefileContext
*)tfcs
)->tf
);
516 //static LttTime time_zero = {0,0};
518 static gint
compare_usertraces(gconstpointer a
, gconstpointer b
,
521 const LttTime
*t1
= (const LttTime
*)a
;
522 const LttTime
*t2
= (const LttTime
*)b
;
524 return ltt_time_compare(*t1
, *t2
);
527 static void free_usertrace_key(gpointer data
)
532 #define MAX_STRING_LEN 4096
535 state_load_saved_states(LttvTraceState
*tcs
)
538 GPtrArray
*quarktable
;
539 const char *trace_path
;
543 tcs
->has_precomputed_states
= FALSE
;
547 gchar buf
[MAX_STRING_LEN
];
550 trace_path
= g_quark_to_string(ltt_trace_name(tcs
->parent
.t
));
551 strncpy(path
, trace_path
, PATH_MAX
-1);
552 count
= strnlen(trace_path
, PATH_MAX
-1);
553 // quarktable : open, test
554 strncat(path
, "/precomputed/quarktable", PATH_MAX
-count
-1);
555 fp
= fopen(path
, "r");
557 quarktable
= g_ptr_array_sized_new(4096);
559 /* Index 0 is null */
561 if(hdr
== EOF
) return;
562 g_assert(hdr
== HDR_QUARKS
);
566 if(hdr
== EOF
) break;
567 g_assert(hdr
== HDR_QUARK
);
568 g_ptr_array_set_size(quarktable
, q
+1);
571 fread(&buf
[i
], sizeof(gchar
), 1, fp
);
572 if(buf
[i
] == '\0' || feof(fp
)) break;
575 len
= strnlen(buf
, MAX_STRING_LEN
-1);
576 g_ptr_array_index (quarktable
, q
) = g_new(gchar
, len
+1);
577 strncpy(g_ptr_array_index (quarktable
, q
), buf
, len
+1);
583 // saved_states : open, test
584 strncpy(path
, trace_path
, PATH_MAX
-1);
585 count
= strnlen(trace_path
, PATH_MAX
-1);
586 strncat(path
, "/precomputed/states", PATH_MAX
-count
-1);
587 fp
= fopen(path
, "r");
591 if(hdr
!= HDR_TRACE
) goto end
;
593 lttv_trace_states_read_raw(tcs
, fp
, quarktable
);
595 tcs
->has_precomputed_states
= TRUE
;
600 /* Free the quarktable */
601 for(i
=0; i
<quarktable
->len
; i
++) {
602 string
= g_ptr_array_index (quarktable
, i
);
605 g_ptr_array_free(quarktable
, TRUE
);
610 init(LttvTracesetState
*self
, LttvTraceset
*ts
)
612 guint i
, j
, nb_trace
, nb_tracefile
, nb_cpu
;
615 LttvTraceContext
*tc
;
619 LttvTracefileState
*tfcs
;
621 LttvAttributeValue v
;
623 LTTV_TRACESET_CONTEXT_CLASS(g_type_class_peek(LTTV_TRACESET_CONTEXT_TYPE
))->
624 init((LttvTracesetContext
*)self
, ts
);
626 nb_trace
= lttv_traceset_number(ts
);
627 for(i
= 0 ; i
< nb_trace
; i
++) {
628 tc
= self
->parent
.traces
[i
];
629 tcs
= LTTV_TRACE_STATE(tc
);
630 tcs
->save_interval
= LTTV_STATE_SAVE_INTERVAL
;
631 lttv_attribute_find(tcs
->parent
.t_a
, LTTV_STATE_TRACE_STATE_USE_COUNT
,
635 if(*(v
.v_uint
) == 1) {
636 create_name_tables(tcs
);
637 create_max_time(tcs
);
639 get_name_tables(tcs
);
642 nb_tracefile
= tc
->tracefiles
->len
;
643 nb_cpu
= ltt_trace_get_num_cpu(tc
->t
);
644 nb_irq
= tcs
->nb_irqs
;
645 tcs
->processes
= NULL
;
646 tcs
->usertraces
= NULL
;
647 tcs
->running_process
= g_new(LttvProcessState
*, nb_cpu
);
649 /* init cpu resource stuff */
650 tcs
->cpu_states
= g_new(LttvCPUState
, nb_cpu
);
651 for(j
= 0; j
<nb_cpu
; j
++) {
652 tcs
->cpu_states
[j
].mode_stack
= g_array_new(FALSE
, FALSE
, sizeof(LttvCPUMode
));
653 tcs
->cpu_states
[j
].irq_stack
= g_array_new(FALSE
, FALSE
, sizeof(gint
));
654 tcs
->cpu_states
[j
].last_soft_irq
= -1;
655 tcs
->cpu_states
[j
].last_trap
= -1;
656 g_assert(tcs
->cpu_states
[j
].mode_stack
!= NULL
);
659 /* init irq resource stuff */
660 tcs
->irq_states
= g_new(LttvIRQState
, nb_irq
);
661 for(j
= 0; j
<nb_irq
; j
++) {
662 tcs
->irq_states
[j
].mode_stack
= g_array_new(FALSE
, FALSE
, sizeof(LttvIRQMode
));
663 g_assert(tcs
->irq_states
[j
].mode_stack
!= NULL
);
666 /* init soft irq stuff */
667 /* the kernel has a statically fixed max of 32 softirqs */
668 tcs
->soft_irq_states
= g_new(LttvSoftIRQState
, tcs
->nb_soft_irqs
);
670 /* init trap stuff */
671 tcs
->trap_states
= g_new(LttvTrapState
, tcs
->nb_traps
);
673 /* init bdev resource stuff */
674 tcs
->bdev_states
= g_hash_table_new(g_int_hash
, g_int_equal
);
676 restore_init_state(tcs
);
677 for(j
= 0 ; j
< nb_tracefile
; j
++) {
679 LTTV_TRACEFILE_STATE(g_array_index(tc
->tracefiles
,
680 LttvTracefileContext
*, j
));
681 tfcs
->tracefile_name
= ltt_tracefile_name(tfcs
->parent
.tf
);
682 tfcs
->cpu
= ltt_tracefile_cpu(tfcs
->parent
.tf
);
683 tfcs
->cpu_state
= &(tcs
->cpu_states
[tfcs
->cpu
]);
684 if(ltt_tracefile_tid(tfcs
->parent
.tf
) != 0) {
685 /* It's a Usertrace */
686 guint tid
= ltt_tracefile_tid(tfcs
->parent
.tf
);
687 GTree
*usertrace_tree
= (GTree
*)g_hash_table_lookup(tcs
->usertraces
,
688 GUINT_TO_POINTER(tid
));
689 if(!usertrace_tree
) {
690 usertrace_tree
= g_tree_new_full(compare_usertraces
,
691 NULL
, free_usertrace_key
, NULL
);
692 g_hash_table_insert(tcs
->usertraces
,
693 GUINT_TO_POINTER(tid
), usertrace_tree
);
695 LttTime
*timestamp
= g_new(LttTime
, 1);
696 *timestamp
= ltt_interpolate_time_from_tsc(tfcs
->parent
.tf
,
697 ltt_tracefile_creation(tfcs
->parent
.tf
));
698 g_tree_insert(usertrace_tree
, timestamp
, tfcs
);
702 /* See if the trace has saved states */
703 state_load_saved_states(tcs
);
708 fini(LttvTracesetState
*self
)
714 //LttvTracefileState *tfcs;
716 LttvAttributeValue v
;
718 nb_trace
= lttv_traceset_number(LTTV_TRACESET_CONTEXT(self
)->ts
);
719 for(i
= 0 ; i
< nb_trace
; i
++) {
720 tcs
= (LttvTraceState
*)(LTTV_TRACESET_CONTEXT(self
)->traces
[i
]);
721 lttv_attribute_find(tcs
->parent
.t_a
, LTTV_STATE_TRACE_STATE_USE_COUNT
,
724 g_assert(*(v
.v_uint
) != 0);
727 if(*(v
.v_uint
) == 0) {
728 free_name_tables(tcs
);
730 free_saved_state(tcs
);
732 g_free(tcs
->running_process
);
733 tcs
->running_process
= NULL
;
734 lttv_state_free_process_table(tcs
->processes
);
735 lttv_state_free_usertraces(tcs
->usertraces
);
736 tcs
->processes
= NULL
;
737 tcs
->usertraces
= NULL
;
739 LTTV_TRACESET_CONTEXT_CLASS(g_type_class_peek(LTTV_TRACESET_CONTEXT_TYPE
))->
740 fini((LttvTracesetContext
*)self
);
744 static LttvTracesetContext
*
745 new_traceset_context(LttvTracesetContext
*self
)
747 return LTTV_TRACESET_CONTEXT(g_object_new(LTTV_TRACESET_STATE_TYPE
, NULL
));
751 static LttvTraceContext
*
752 new_trace_context(LttvTracesetContext
*self
)
754 return LTTV_TRACE_CONTEXT(g_object_new(LTTV_TRACE_STATE_TYPE
, NULL
));
758 static LttvTracefileContext
*
759 new_tracefile_context(LttvTracesetContext
*self
)
761 return LTTV_TRACEFILE_CONTEXT(g_object_new(LTTV_TRACEFILE_STATE_TYPE
, NULL
));
765 /* Write the process state of the trace */
767 static void write_process_state(gpointer key
, gpointer value
,
770 LttvProcessState
*process
;
772 LttvExecutionState
*es
;
774 FILE *fp
= (FILE *)user_data
;
779 process
= (LttvProcessState
*)value
;
781 " <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",
782 process
, process
->pid
, process
->tgid
, process
->ppid
,
783 g_quark_to_string(process
->type
),
784 process
->creation_time
.tv_sec
,
785 process
->creation_time
.tv_nsec
,
786 process
->insertion_time
.tv_sec
,
787 process
->insertion_time
.tv_nsec
,
788 g_quark_to_string(process
->name
),
789 g_quark_to_string(process
->brand
),
790 process
->cpu
, process
->free_events
);
792 for(i
= 0 ; i
< process
->execution_stack
->len
; i
++) {
793 es
= &g_array_index(process
->execution_stack
, LttvExecutionState
, i
);
794 fprintf(fp
, " <ES MODE=\"%s\" SUBMODE=\"%s\" ENTRY_S=%lu ENTRY_NS=%lu",
795 g_quark_to_string(es
->t
), g_quark_to_string(es
->n
),
796 es
->entry
.tv_sec
, es
->entry
.tv_nsec
);
797 fprintf(fp
, " CHANGE_S=%lu CHANGE_NS=%lu STATUS=\"%s\"/>\n",
798 es
->change
.tv_sec
, es
->change
.tv_nsec
, g_quark_to_string(es
->s
));
801 for(i
= 0 ; i
< process
->user_stack
->len
; i
++) {
802 address
= g_array_index(process
->user_stack
, guint64
, i
);
803 fprintf(fp
, " <USER_STACK ADDRESS=\"%" PRIu64
"\"/>\n",
807 if(process
->usertrace
) {
808 fprintf(fp
, " <USERTRACE NAME=\"%s\" CPU=%u\n/>",
809 g_quark_to_string(process
->usertrace
->tracefile_name
),
810 process
->usertrace
->cpu
);
814 fprintf(fp
, " </PROCESS>\n");
818 void lttv_state_write(LttvTraceState
*self
, LttTime t
, FILE *fp
)
820 guint i
, nb_tracefile
, nb_block
, offset
;
823 LttvTracefileState
*tfcs
;
827 LttEventPosition
*ep
;
831 ep
= ltt_event_position_new();
833 fprintf(fp
,"<PROCESS_STATE TIME_S=%lu TIME_NS=%lu>\n", t
.tv_sec
, t
.tv_nsec
);
835 g_hash_table_foreach(self
->processes
, write_process_state
, fp
);
837 nb_cpus
= ltt_trace_get_num_cpu(self
->parent
.t
);
838 for(i
=0;i
<nb_cpus
;i
++) {
839 fprintf(fp
," <CPU NUM=%u RUNNING_PROCESS=%u>\n",
840 i
, self
->running_process
[i
]->pid
);
843 nb_tracefile
= self
->parent
.tracefiles
->len
;
845 for(i
= 0 ; i
< nb_tracefile
; i
++) {
847 LTTV_TRACEFILE_STATE(g_array_index(self
->parent
.tracefiles
,
848 LttvTracefileContext
*, i
));
849 fprintf(fp
, " <TRACEFILE TIMESTAMP_S=%lu TIMESTAMP_NS=%lu",
850 tfcs
->parent
.timestamp
.tv_sec
,
851 tfcs
->parent
.timestamp
.tv_nsec
);
852 LttEvent
*e
= ltt_tracefile_get_event(tfcs
->parent
.tf
);
853 if(e
== NULL
) fprintf(fp
,"/>\n");
855 ltt_event_position(e
, ep
);
856 ltt_event_position_get(ep
, &tf
, &nb_block
, &offset
, &tsc
);
857 fprintf(fp
, " BLOCK=%u OFFSET=%u TSC=%" PRIu64
"/>\n", nb_block
, offset
,
862 fprintf(fp
,"</PROCESS_STATE>\n");
866 static void write_process_state_raw(gpointer key
, gpointer value
,
869 LttvProcessState
*process
;
871 LttvExecutionState
*es
;
873 FILE *fp
= (FILE *)user_data
;
878 process
= (LttvProcessState
*)value
;
879 fputc(HDR_PROCESS
, fp
);
880 //fwrite(&header, sizeof(header), 1, fp);
881 //fprintf(fp, "%s", g_quark_to_string(process->type));
883 fwrite(&process
->type
, sizeof(process
->type
), 1, fp
);
884 //fprintf(fp, "%s", g_quark_to_string(process->name));
886 fwrite(&process
->name
, sizeof(process
->name
), 1, fp
);
887 //fprintf(fp, "%s", g_quark_to_string(process->brand));
889 fwrite(&process
->brand
, sizeof(process
->brand
), 1, fp
);
890 fwrite(&process
->pid
, sizeof(process
->pid
), 1, fp
);
891 fwrite(&process
->free_events
, sizeof(process
->free_events
), 1, fp
);
892 fwrite(&process
->tgid
, sizeof(process
->tgid
), 1, fp
);
893 fwrite(&process
->ppid
, sizeof(process
->ppid
), 1, fp
);
894 fwrite(&process
->cpu
, sizeof(process
->cpu
), 1, fp
);
895 fwrite(&process
->creation_time
, sizeof(process
->creation_time
), 1, fp
);
896 fwrite(&process
->insertion_time
, sizeof(process
->insertion_time
), 1, fp
);
900 " <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",
901 process
, process
->pid
, process
->tgid
, process
->ppid
,
902 g_quark_to_string(process
->type
),
903 process
->creation_time
.tv_sec
,
904 process
->creation_time
.tv_nsec
,
905 process
->insertion_time
.tv_sec
,
906 process
->insertion_time
.tv_nsec
,
907 g_quark_to_string(process
->name
),
908 g_quark_to_string(process
->brand
),
912 for(i
= 0 ; i
< process
->execution_stack
->len
; i
++) {
913 es
= &g_array_index(process
->execution_stack
, LttvExecutionState
, i
);
916 //fprintf(fp, "%s", g_quark_to_string(es->t));
918 fwrite(&es
->t
, sizeof(es
->t
), 1, fp
);
919 //fprintf(fp, "%s", g_quark_to_string(es->n));
921 fwrite(&es
->n
, sizeof(es
->n
), 1, fp
);
922 //fprintf(fp, "%s", g_quark_to_string(es->s));
924 fwrite(&es
->s
, sizeof(es
->s
), 1, fp
);
925 fwrite(&es
->entry
, sizeof(es
->entry
), 1, fp
);
926 fwrite(&es
->change
, sizeof(es
->change
), 1, fp
);
927 fwrite(&es
->cum_cpu_time
, sizeof(es
->cum_cpu_time
), 1, fp
);
929 fprintf(fp
, " <ES MODE=\"%s\" SUBMODE=\"%s\" ENTRY_S=%lu ENTRY_NS=%lu",
930 g_quark_to_string(es
->t
), g_quark_to_string(es
->n
),
931 es
->entry
.tv_sec
, es
->entry
.tv_nsec
);
932 fprintf(fp
, " CHANGE_S=%lu CHANGE_NS=%lu STATUS=\"%s\"/>\n",
933 es
->change
.tv_sec
, es
->change
.tv_nsec
, g_quark_to_string(es
->s
));
937 for(i
= 0 ; i
< process
->user_stack
->len
; i
++) {
938 address
= g_array_index(process
->user_stack
, guint64
, i
);
939 fputc(HDR_USER_STACK
, fp
);
940 fwrite(&address
, sizeof(address
), 1, fp
);
942 fprintf(fp
, " <USER_STACK ADDRESS=\"%llu\"/>\n",
947 if(process
->usertrace
) {
948 fputc(HDR_USERTRACE
, fp
);
949 //fprintf(fp, "%s", g_quark_to_string(process->usertrace->tracefile_name));
951 fwrite(&process
->usertrace
->tracefile_name
,
952 sizeof(process
->usertrace
->tracefile_name
), 1, fp
);
953 fwrite(&process
->usertrace
->cpu
, sizeof(process
->usertrace
->cpu
), 1, fp
);
955 fprintf(fp
, " <USERTRACE NAME=\"%s\" CPU=%u\n/>",
956 g_quark_to_string(process
->usertrace
->tracefile_name
),
957 process
->usertrace
->cpu
);
964 void lttv_state_write_raw(LttvTraceState
*self
, LttTime t
, FILE *fp
)
966 guint i
, nb_tracefile
, nb_block
, offset
;
969 LttvTracefileState
*tfcs
;
973 LttEventPosition
*ep
;
977 ep
= ltt_event_position_new();
979 //fprintf(fp,"<PROCESS_STATE TIME_S=%lu TIME_NS=%lu>\n", t.tv_sec, t.tv_nsec);
980 fputc(HDR_PROCESS_STATE
, fp
);
981 fwrite(&t
, sizeof(t
), 1, fp
);
983 g_hash_table_foreach(self
->processes
, write_process_state_raw
, fp
);
985 nb_cpus
= ltt_trace_get_num_cpu(self
->parent
.t
);
986 for(i
=0;i
<nb_cpus
;i
++) {
988 fwrite(&i
, sizeof(i
), 1, fp
); /* cpu number */
989 fwrite(&self
->running_process
[i
]->pid
,
990 sizeof(self
->running_process
[i
]->pid
), 1, fp
);
991 //fprintf(fp," <CPU NUM=%u RUNNING_PROCESS=%u>\n",
992 // i, self->running_process[i]->pid);
995 nb_tracefile
= self
->parent
.tracefiles
->len
;
997 for(i
= 0 ; i
< nb_tracefile
; i
++) {
999 LTTV_TRACEFILE_STATE(g_array_index(self
->parent
.tracefiles
,
1000 LttvTracefileContext
*, i
));
1001 // fprintf(fp, " <TRACEFILE TIMESTAMP_S=%lu TIMESTAMP_NS=%lu",
1002 // tfcs->parent.timestamp.tv_sec,
1003 // tfcs->parent.timestamp.tv_nsec);
1004 fputc(HDR_TRACEFILE
, fp
);
1005 fwrite(&tfcs
->parent
.timestamp
, sizeof(tfcs
->parent
.timestamp
), 1, fp
);
1006 /* Note : if timestamp if LTT_TIME_INFINITE, there will be no
1007 * position following : end of trace */
1008 LttEvent
*e
= ltt_tracefile_get_event(tfcs
->parent
.tf
);
1010 ltt_event_position(e
, ep
);
1011 ltt_event_position_get(ep
, &tf
, &nb_block
, &offset
, &tsc
);
1012 //fprintf(fp, " BLOCK=%u OFFSET=%u TSC=%llu/>\n", nb_block, offset,
1014 fwrite(&nb_block
, sizeof(nb_block
), 1, fp
);
1015 fwrite(&offset
, sizeof(offset
), 1, fp
);
1016 fwrite(&tsc
, sizeof(tsc
), 1, fp
);
1023 /* Read process state from a file */
1025 /* Called because a HDR_PROCESS was found */
1026 static void read_process_state_raw(LttvTraceState
*self
, FILE *fp
,
1027 GPtrArray
*quarktable
)
1029 LttvExecutionState
*es
;
1030 LttvProcessState
*process
, *parent_process
;
1031 LttvProcessState tmp
;
1036 /* TODO : check return value */
1037 fread(&tmp
.type
, sizeof(tmp
.type
), 1, fp
);
1038 fread(&tmp
.name
, sizeof(tmp
.name
), 1, fp
);
1039 fread(&tmp
.brand
, sizeof(tmp
.brand
), 1, fp
);
1040 fread(&tmp
.pid
, sizeof(tmp
.pid
), 1, fp
);
1041 fread(&tmp
.free_events
, sizeof(tmp
.free_events
), 1, fp
);
1042 fread(&tmp
.tgid
, sizeof(tmp
.tgid
), 1, fp
);
1043 fread(&tmp
.ppid
, sizeof(tmp
.ppid
), 1, fp
);
1044 fread(&tmp
.cpu
, sizeof(tmp
.cpu
), 1, fp
);
1045 fread(&tmp
.creation_time
, sizeof(tmp
.creation_time
), 1, fp
);
1046 fread(&tmp
.insertion_time
, sizeof(tmp
.insertion_time
), 1, fp
);
1049 process
= lttv_state_find_process(self
, tmp
.cpu
, tmp
.pid
);
1051 /* We must link to the parent */
1052 parent_process
= lttv_state_find_process_or_create(self
, ANY_CPU
, tmp
.ppid
,
1054 process
= lttv_state_find_process(self
, ANY_CPU
, tmp
.pid
);
1055 if(process
== NULL
) {
1056 process
= lttv_state_create_process(self
, parent_process
, tmp
.cpu
,
1058 g_quark_from_string((gchar
*)g_ptr_array_index(quarktable
, tmp
.name
)),
1059 &tmp
.creation_time
);
1062 process
->insertion_time
= tmp
.insertion_time
;
1063 process
->creation_time
= tmp
.creation_time
;
1064 process
->type
= g_quark_from_string(
1065 (gchar
*)g_ptr_array_index(quarktable
, tmp
.type
));
1066 process
->tgid
= tmp
.tgid
;
1067 process
->ppid
= tmp
.ppid
;
1068 process
->brand
= g_quark_from_string(
1069 (gchar
*)g_ptr_array_index(quarktable
, tmp
.brand
));
1071 g_quark_from_string((gchar
*)g_ptr_array_index(quarktable
, tmp
.name
));
1072 process
->free_events
= tmp
.free_events
;
1075 if(feof(fp
) || ferror(fp
)) goto end_loop
;
1077 gint hdr
= fgetc(fp
);
1078 if(hdr
== EOF
) goto end_loop
;
1082 process
->execution_stack
=
1083 g_array_set_size(process
->execution_stack
,
1084 process
->execution_stack
->len
+ 1);
1085 es
= &g_array_index(process
->execution_stack
, LttvExecutionState
,
1086 process
->execution_stack
->len
-1);
1087 process
->state
= es
;
1089 fread(&es
->t
, sizeof(es
->t
), 1, fp
);
1090 es
->t
= g_quark_from_string(
1091 (gchar
*)g_ptr_array_index(quarktable
, es
->t
));
1092 fread(&es
->n
, sizeof(es
->n
), 1, fp
);
1093 es
->n
= g_quark_from_string(
1094 (gchar
*)g_ptr_array_index(quarktable
, es
->n
));
1095 fread(&es
->s
, sizeof(es
->s
), 1, fp
);
1096 es
->s
= g_quark_from_string(
1097 (gchar
*)g_ptr_array_index(quarktable
, es
->s
));
1098 fread(&es
->entry
, sizeof(es
->entry
), 1, fp
);
1099 fread(&es
->change
, sizeof(es
->change
), 1, fp
);
1100 fread(&es
->cum_cpu_time
, sizeof(es
->cum_cpu_time
), 1, fp
);
1102 case HDR_USER_STACK
:
1103 process
->user_stack
= g_array_set_size(process
->user_stack
,
1104 process
->user_stack
->len
+ 1);
1105 address
= &g_array_index(process
->user_stack
, guint64
,
1106 process
->user_stack
->len
-1);
1107 fread(address
, sizeof(address
), 1, fp
);
1108 process
->current_function
= *address
;
1111 fread(&tmpq
, sizeof(tmpq
), 1, fp
);
1112 fread(&process
->usertrace
->cpu
, sizeof(process
->usertrace
->cpu
), 1, fp
);
1124 /* Called because a HDR_PROCESS_STATE was found */
1125 /* Append a saved state to the trace states */
1126 void lttv_state_read_raw(LttvTraceState
*self
, FILE *fp
, GPtrArray
*quarktable
)
1128 guint i
, nb_tracefile
, nb_block
, offset
;
1130 LttvTracefileState
*tfcs
;
1132 LttEventPosition
*ep
;
1140 LttvAttribute
*saved_states_tree
, *saved_state_tree
;
1142 LttvAttributeValue value
;
1143 GTree
*pqueue
= self
->parent
.ts_context
->pqueue
;
1144 ep
= ltt_event_position_new();
1146 restore_init_state(self
);
1148 fread(&t
, sizeof(t
), 1, fp
);
1151 if(feof(fp
) || ferror(fp
)) goto end_loop
;
1153 if(hdr
== EOF
) goto end_loop
;
1157 /* Call read_process_state_raw */
1158 read_process_state_raw(self
, fp
, quarktable
);
1166 case HDR_USER_STACK
:
1168 case HDR_PROCESS_STATE
:
1174 g_error("Error while parsing saved state file : unknown data header %d",
1180 nb_cpus
= ltt_trace_get_num_cpu(self
->parent
.t
);
1181 for(i
=0;i
<nb_cpus
;i
++) {
1184 g_assert(hdr
== HDR_CPU
);
1185 fread(&cpu_num
, sizeof(cpu_num
), 1, fp
); /* cpu number */
1186 g_assert(i
== cpu_num
);
1187 fread(&self
->running_process
[i
]->pid
,
1188 sizeof(self
->running_process
[i
]->pid
), 1, fp
);
1191 nb_tracefile
= self
->parent
.tracefiles
->len
;
1193 for(i
= 0 ; i
< nb_tracefile
; i
++) {
1195 LTTV_TRACEFILE_STATE(g_array_index(self
->parent
.tracefiles
,
1196 LttvTracefileContext
*, i
));
1197 // fprintf(fp, " <TRACEFILE TIMESTAMP_S=%lu TIMESTAMP_NS=%lu",
1198 // tfcs->parent.timestamp.tv_sec,
1199 // tfcs->parent.timestamp.tv_nsec);
1200 g_tree_remove(pqueue
, &tfcs
->parent
);
1202 g_assert(hdr
== HDR_TRACEFILE
);
1203 fread(&tfcs
->parent
.timestamp
, sizeof(tfcs
->parent
.timestamp
), 1, fp
);
1204 /* Note : if timestamp if LTT_TIME_INFINITE, there will be no
1205 * position following : end of trace */
1206 if(ltt_time_compare(tfcs
->parent
.timestamp
, ltt_time_infinite
) != 0) {
1207 fread(&nb_block
, sizeof(nb_block
), 1, fp
);
1208 fread(&offset
, sizeof(offset
), 1, fp
);
1209 fread(&tsc
, sizeof(tsc
), 1, fp
);
1210 ltt_event_position_set(ep
, tfcs
->parent
.tf
, nb_block
, offset
, tsc
);
1211 gint ret
= ltt_tracefile_seek_position(tfcs
->parent
.tf
, ep
);
1213 g_tree_insert(pqueue
, &tfcs
->parent
, &tfcs
->parent
);
1218 saved_states_tree
= lttv_attribute_find_subdir(self
->parent
.t_a
,
1219 LTTV_STATE_SAVED_STATES
);
1220 saved_state_tree
= g_object_new(LTTV_ATTRIBUTE_TYPE
, NULL
);
1221 value
= lttv_attribute_add(saved_states_tree
,
1222 lttv_attribute_get_number(saved_states_tree
), LTTV_GOBJECT
);
1223 *(value
.v_gobject
) = (GObject
*)saved_state_tree
;
1224 value
= lttv_attribute_add(saved_state_tree
, LTTV_STATE_TIME
, LTTV_TIME
);
1225 *(value
.v_time
) = t
;
1226 lttv_state_save(self
, saved_state_tree
);
1227 g_debug("Saving state at time %lu.%lu", t
.tv_sec
,
1230 *(self
->max_time_state_recomputed_in_seek
) = t
;
1234 /* Called when a HDR_TRACE is found */
1235 void lttv_trace_states_read_raw(LttvTraceState
*tcs
, FILE *fp
,
1236 GPtrArray
*quarktable
)
1241 if(feof(fp
) || ferror(fp
)) goto end_loop
;
1243 if(hdr
== EOF
) goto end_loop
;
1246 case HDR_PROCESS_STATE
:
1247 /* Call read_process_state_raw */
1248 lttv_state_read_raw(tcs
, fp
, quarktable
);
1256 case HDR_USER_STACK
:
1260 g_error("Error while parsing saved state file :"
1261 " unexpected data header %d",
1265 g_error("Error while parsing saved state file : unknown data header %d",
1270 *(tcs
->max_time_state_recomputed_in_seek
) = tcs
->parent
.time_span
.end_time
;
1271 restore_init_state(tcs
);
1272 lttv_process_trace_seek_time(&tcs
->parent
, ltt_time_zero
);
1278 /* Copy each process from an existing hash table to a new one */
1280 static void copy_process_state(gpointer key
, gpointer value
,gpointer user_data
)
1282 LttvProcessState
*process
, *new_process
;
1284 GHashTable
*new_processes
= (GHashTable
*)user_data
;
1288 process
= (LttvProcessState
*)value
;
1289 new_process
= g_new(LttvProcessState
, 1);
1290 *new_process
= *process
;
1291 new_process
->execution_stack
= g_array_sized_new(FALSE
, FALSE
,
1292 sizeof(LttvExecutionState
), PREALLOCATED_EXECUTION_STACK
);
1293 new_process
->execution_stack
=
1294 g_array_set_size(new_process
->execution_stack
,
1295 process
->execution_stack
->len
);
1296 for(i
= 0 ; i
< process
->execution_stack
->len
; i
++) {
1297 g_array_index(new_process
->execution_stack
, LttvExecutionState
, i
) =
1298 g_array_index(process
->execution_stack
, LttvExecutionState
, i
);
1300 new_process
->state
= &g_array_index(new_process
->execution_stack
,
1301 LttvExecutionState
, new_process
->execution_stack
->len
- 1);
1302 new_process
->user_stack
= g_array_sized_new(FALSE
, FALSE
,
1303 sizeof(guint64
), 0);
1304 new_process
->user_stack
=
1305 g_array_set_size(new_process
->user_stack
,
1306 process
->user_stack
->len
);
1307 for(i
= 0 ; i
< process
->user_stack
->len
; i
++) {
1308 g_array_index(new_process
->user_stack
, guint64
, i
) =
1309 g_array_index(process
->user_stack
, guint64
, i
);
1311 new_process
->current_function
= process
->current_function
;
1312 g_hash_table_insert(new_processes
, new_process
, new_process
);
1316 static GHashTable
*lttv_state_copy_process_table(GHashTable
*processes
)
1318 GHashTable
*new_processes
= g_hash_table_new(process_hash
, process_equal
);
1320 g_hash_table_foreach(processes
, copy_process_state
, new_processes
);
1321 return new_processes
;
1324 static LttvCPUState
*lttv_state_copy_cpu_states(LttvCPUState
*states
, guint n
)
1327 LttvCPUState
*retval
;
1329 retval
= g_new(LttvCPUState
, n
);
1331 for(i
=0; i
<n
; i
++) {
1332 retval
[i
].last_soft_irq
= states
[i
].last_soft_irq
;
1333 retval
[i
].last_trap
= states
[i
].last_trap
;
1335 retval
[i
].irq_stack
= g_array_new(FALSE
, FALSE
, sizeof(gint
));
1336 g_array_set_size(retval
[i
].irq_stack
, states
[i
].irq_stack
->len
);
1337 for(j
=0; j
<states
[i
].irq_stack
->len
; j
++) {
1338 g_array_index(retval
[i
].irq_stack
, gint
, j
) = g_array_index(states
[i
].irq_stack
, gint
, j
);
1341 retval
[i
].mode_stack
= g_array_new(FALSE
, FALSE
, sizeof(LttvCPUMode
));
1342 g_array_set_size(retval
[i
].mode_stack
, states
[i
].mode_stack
->len
);
1343 for(j
=0; j
<states
[i
].mode_stack
->len
; j
++) {
1344 g_array_index(retval
[i
].mode_stack
, GQuark
, j
) = g_array_index(states
[i
].mode_stack
, GQuark
, j
);
1351 static void lttv_state_free_cpu_states(LttvCPUState
*states
, guint n
)
1355 for(i
=0; i
<n
; i
++) {
1356 g_array_free(states
[i
].mode_stack
, TRUE
);
1357 g_array_free(states
[i
].irq_stack
, TRUE
);
1363 static LttvIRQState
*lttv_state_copy_irq_states(LttvIRQState
*states
, guint n
)
1366 LttvIRQState
*retval
;
1368 retval
= g_new(LttvIRQState
, n
);
1370 for(i
=0; i
<n
; i
++) {
1371 retval
[i
].mode_stack
= g_array_new(FALSE
, FALSE
, sizeof(LttvIRQMode
));
1372 g_array_set_size(retval
[i
].mode_stack
, states
[i
].mode_stack
->len
);
1373 for(j
=0; j
<states
[i
].mode_stack
->len
; j
++) {
1374 g_array_index(retval
[i
].mode_stack
, GQuark
, j
) = g_array_index(states
[i
].mode_stack
, GQuark
, j
);
1381 static void lttv_state_free_irq_states(LttvIRQState
*states
, guint n
)
1385 for(i
=0; i
<n
; i
++) {
1386 g_array_free(states
[i
].mode_stack
, TRUE
);
1392 static LttvSoftIRQState
*lttv_state_copy_soft_irq_states(LttvSoftIRQState
*states
, guint n
)
1395 LttvSoftIRQState
*retval
;
1397 retval
= g_new(LttvSoftIRQState
, n
);
1399 for(i
=0; i
<n
; i
++) {
1400 retval
[i
].pending
= states
[i
].pending
;
1401 retval
[i
].running
= states
[i
].running
;
1407 static void lttv_state_free_soft_irq_states(LttvSoftIRQState
*states
, guint n
)
1412 static LttvTrapState
*lttv_state_copy_trap_states(LttvTrapState
*states
, guint n
)
1415 LttvTrapState
*retval
;
1417 retval
= g_new(LttvTrapState
, n
);
1419 for(i
=0; i
<n
; i
++) {
1420 retval
[i
].running
= states
[i
].running
;
1426 static void lttv_state_free_trap_states(LttvTrapState
*states
, guint n
)
1431 /* bdevstate stuff */
1433 static LttvBdevState
*get_hashed_bdevstate(LttvTraceState
*ts
, guint16 devcode
)
1435 gint devcode_gint
= devcode
;
1436 gpointer bdev
= g_hash_table_lookup(ts
->bdev_states
, &devcode_gint
);
1438 LttvBdevState
*bdevstate
= g_new(LttvBdevState
, 1);
1439 bdevstate
->mode_stack
= g_array_new(FALSE
, FALSE
, sizeof(GQuark
));
1441 gint
* key
= g_new(gint
, 1);
1443 g_hash_table_insert(ts
->bdev_states
, key
, bdevstate
);
1451 static LttvBdevState
*bdevstate_new(void)
1453 LttvBdevState
*retval
;
1454 retval
= g_new(LttvBdevState
, 1);
1455 retval
->mode_stack
= g_array_new(FALSE
, FALSE
, sizeof(GQuark
));
1460 static void bdevstate_free(LttvBdevState
*bds
)
1462 g_array_free(bds
->mode_stack
, TRUE
);
1466 static void bdevstate_free_cb(gpointer key
, gpointer value
, gpointer user_data
)
1468 LttvBdevState
*bds
= (LttvBdevState
*) value
;
1470 bdevstate_free(bds
);
1473 static LttvBdevState
*bdevstate_copy(LttvBdevState
*bds
)
1475 LttvBdevState
*retval
;
1477 retval
= bdevstate_new();
1478 g_array_insert_vals(retval
->mode_stack
, 0, bds
->mode_stack
->data
, bds
->mode_stack
->len
);
1483 static void insert_and_copy_bdev_state(gpointer k
, gpointer v
, gpointer u
)
1485 //GHashTable *ht = (GHashTable *)u;
1486 LttvBdevState
*bds
= (LttvBdevState
*)v
;
1487 LttvBdevState
*newbds
;
1489 newbds
= bdevstate_copy(bds
);
1491 g_hash_table_insert(u
, k
, newbds
);
1494 static GHashTable
*lttv_state_copy_blkdev_hashtable(GHashTable
*ht
)
1498 retval
= g_hash_table_new(g_int_hash
, g_int_equal
);
1500 g_hash_table_foreach(ht
, insert_and_copy_bdev_state
, retval
);
1505 /* Free a hashtable and the LttvBdevState structures its values
1508 static void lttv_state_free_blkdev_hashtable(GHashTable
*ht
)
1510 g_hash_table_foreach(ht
, bdevstate_free_cb
, NULL
);
1511 g_hash_table_destroy(ht
);
1514 /* The saved state for each trace contains a member "processes", which
1515 stores a copy of the process table, and a member "tracefiles" with
1516 one entry per tracefile. Each tracefile has a "process" member pointing
1517 to the current process and a "position" member storing the tracefile
1518 position (needed to seek to the current "next" event. */
1520 static void state_save(LttvTraceState
*self
, LttvAttribute
*container
)
1522 guint i
, nb_tracefile
, nb_cpus
, nb_irqs
, nb_soft_irqs
, nb_traps
;
1524 LttvTracefileState
*tfcs
;
1526 LttvAttribute
*tracefiles_tree
, *tracefile_tree
;
1528 guint
*running_process
;
1530 LttvAttributeValue value
;
1532 LttEventPosition
*ep
;
1534 tracefiles_tree
= lttv_attribute_find_subdir(container
,
1535 LTTV_STATE_TRACEFILES
);
1537 value
= lttv_attribute_add(container
, LTTV_STATE_PROCESSES
,
1539 *(value
.v_pointer
) = lttv_state_copy_process_table(self
->processes
);
1541 /* Add the currently running processes array */
1542 nb_cpus
= ltt_trace_get_num_cpu(self
->parent
.t
);
1543 running_process
= g_new(guint
, nb_cpus
);
1544 for(i
=0;i
<nb_cpus
;i
++) {
1545 running_process
[i
] = self
->running_process
[i
]->pid
;
1547 value
= lttv_attribute_add(container
, LTTV_STATE_RUNNING_PROCESS
,
1549 *(value
.v_pointer
) = running_process
;
1551 g_info("State save");
1553 nb_tracefile
= self
->parent
.tracefiles
->len
;
1555 for(i
= 0 ; i
< nb_tracefile
; i
++) {
1557 LTTV_TRACEFILE_STATE(g_array_index(self
->parent
.tracefiles
,
1558 LttvTracefileContext
*, i
));
1559 tracefile_tree
= g_object_new(LTTV_ATTRIBUTE_TYPE
, NULL
);
1560 value
= lttv_attribute_add(tracefiles_tree
, i
,
1562 *(value
.v_gobject
) = (GObject
*)tracefile_tree
;
1564 value
= lttv_attribute_add(tracefile_tree
, LTTV_STATE_PROCESS
,
1566 *(value
.v_uint
) = tfcs
->process
->pid
;
1568 value
= lttv_attribute_add(tracefile_tree
, LTTV_STATE_EVENT
,
1570 /* Only save the position if the tfs has not infinite time. */
1571 //if(!g_tree_lookup(self->parent.ts_context->pqueue, &tfcs->parent)
1572 // && current_tfcs != tfcs) {
1573 if(ltt_time_compare(tfcs
->parent
.timestamp
, ltt_time_infinite
) == 0) {
1574 *(value
.v_pointer
) = NULL
;
1576 LttEvent
*e
= ltt_tracefile_get_event(tfcs
->parent
.tf
);
1577 ep
= ltt_event_position_new();
1578 ltt_event_position(e
, ep
);
1579 *(value
.v_pointer
) = ep
;
1581 guint nb_block
, offset
;
1584 ltt_event_position_get(ep
, &tf
, &nb_block
, &offset
, &tsc
);
1585 g_info("Block %u offset %u tsc %" PRIu64
" time %lu.%lu", nb_block
, offset
,
1587 tfcs
->parent
.timestamp
.tv_sec
, tfcs
->parent
.timestamp
.tv_nsec
);
1591 /* save the cpu state */
1593 value
= lttv_attribute_add(container
, LTTV_STATE_RESOURCE_CPUS_COUNT
,
1595 *(value
.v_uint
) = nb_cpus
;
1597 value
= lttv_attribute_add(container
, LTTV_STATE_RESOURCE_CPUS
,
1599 *(value
.v_pointer
) = lttv_state_copy_cpu_states(self
->cpu_states
, nb_cpus
);
1602 /* save the irq state */
1603 nb_irqs
= self
->nb_irqs
;
1605 value
= lttv_attribute_add(container
, LTTV_STATE_RESOURCE_IRQS
,
1607 *(value
.v_pointer
) = lttv_state_copy_irq_states(self
->irq_states
, nb_irqs
);
1610 /* save the soft irq state */
1611 nb_soft_irqs
= self
->nb_soft_irqs
;
1613 value
= lttv_attribute_add(container
, LTTV_STATE_RESOURCE_SOFT_IRQS
,
1615 *(value
.v_pointer
) = lttv_state_copy_soft_irq_states(self
->soft_irq_states
, nb_soft_irqs
);
1618 /* save the trap state */
1619 nb_traps
= self
->nb_traps
;
1621 value
= lttv_attribute_add(container
, LTTV_STATE_RESOURCE_TRAPS
,
1623 *(value
.v_pointer
) = lttv_state_copy_trap_states(self
->trap_states
, nb_traps
);
1626 /* save the blkdev states */
1627 value
= lttv_attribute_add(container
, LTTV_STATE_RESOURCE_BLKDEVS
,
1629 *(value
.v_pointer
) = lttv_state_copy_blkdev_hashtable(self
->bdev_states
);
1633 static void state_restore(LttvTraceState
*self
, LttvAttribute
*container
)
1635 guint i
, nb_tracefile
, pid
, nb_cpus
, nb_irqs
, nb_soft_irqs
, nb_traps
;
1637 LttvTracefileState
*tfcs
;
1639 LttvAttribute
*tracefiles_tree
, *tracefile_tree
;
1641 guint
*running_process
;
1643 LttvAttributeType type
;
1645 LttvAttributeValue value
;
1647 LttvAttributeName name
;
1651 LttEventPosition
*ep
;
1653 LttvTracesetContext
*tsc
= self
->parent
.ts_context
;
1655 tracefiles_tree
= lttv_attribute_find_subdir(container
,
1656 LTTV_STATE_TRACEFILES
);
1658 type
= lttv_attribute_get_by_name(container
, LTTV_STATE_PROCESSES
,
1660 g_assert(type
== LTTV_POINTER
);
1661 lttv_state_free_process_table(self
->processes
);
1662 self
->processes
= lttv_state_copy_process_table(*(value
.v_pointer
));
1664 /* Add the currently running processes array */
1665 nb_cpus
= ltt_trace_get_num_cpu(self
->parent
.t
);
1666 type
= lttv_attribute_get_by_name(container
, LTTV_STATE_RUNNING_PROCESS
,
1668 g_assert(type
== LTTV_POINTER
);
1669 running_process
= *(value
.v_pointer
);
1670 for(i
=0;i
<nb_cpus
;i
++) {
1671 pid
= running_process
[i
];
1672 self
->running_process
[i
] = lttv_state_find_process(self
, i
, pid
);
1673 g_assert(self
->running_process
[i
] != NULL
);
1676 nb_tracefile
= self
->parent
.tracefiles
->len
;
1678 //g_tree_destroy(tsc->pqueue);
1679 //tsc->pqueue = g_tree_new(compare_tracefile);
1681 /* restore cpu resource states */
1682 type
= lttv_attribute_get_by_name(container
, LTTV_STATE_RESOURCE_CPUS
, &value
);
1683 g_assert(type
== LTTV_POINTER
);
1684 lttv_state_free_cpu_states(self
->cpu_states
, nb_cpus
);
1685 self
->cpu_states
= lttv_state_copy_cpu_states(*(value
.v_pointer
), nb_cpus
);
1687 /* restore irq resource states */
1688 nb_irqs
= self
->nb_irqs
;
1689 type
= lttv_attribute_get_by_name(container
, LTTV_STATE_RESOURCE_IRQS
, &value
);
1690 g_assert(type
== LTTV_POINTER
);
1691 lttv_state_free_irq_states(self
->irq_states
, nb_irqs
);
1692 self
->irq_states
= lttv_state_copy_irq_states(*(value
.v_pointer
), nb_irqs
);
1694 /* restore soft irq resource states */
1695 nb_soft_irqs
= self
->nb_soft_irqs
;
1696 type
= lttv_attribute_get_by_name(container
, LTTV_STATE_RESOURCE_SOFT_IRQS
, &value
);
1697 g_assert(type
== LTTV_POINTER
);
1698 lttv_state_free_soft_irq_states(self
->soft_irq_states
, nb_soft_irqs
);
1699 self
->soft_irq_states
= lttv_state_copy_soft_irq_states(*(value
.v_pointer
), nb_soft_irqs
);
1701 /* restore trap resource states */
1702 nb_traps
= self
->nb_traps
;
1703 type
= lttv_attribute_get_by_name(container
, LTTV_STATE_RESOURCE_TRAPS
, &value
);
1704 g_assert(type
== LTTV_POINTER
);
1705 lttv_state_free_trap_states(self
->trap_states
, nb_traps
);
1706 self
->trap_states
= lttv_state_copy_trap_states(*(value
.v_pointer
), nb_traps
);
1708 /* restore the blkdev states */
1709 type
= lttv_attribute_get_by_name(container
, LTTV_STATE_RESOURCE_BLKDEVS
, &value
);
1710 g_assert(type
== LTTV_POINTER
);
1711 lttv_state_free_blkdev_hashtable(self
->bdev_states
);
1712 self
->bdev_states
= lttv_state_copy_blkdev_hashtable(*(value
.v_pointer
));
1714 for(i
= 0 ; i
< nb_tracefile
; i
++) {
1716 LTTV_TRACEFILE_STATE(g_array_index(self
->parent
.tracefiles
,
1717 LttvTracefileContext
*, i
));
1718 type
= lttv_attribute_get(tracefiles_tree
, i
, &name
, &value
, &is_named
);
1719 g_assert(type
== LTTV_GOBJECT
);
1720 tracefile_tree
= *((LttvAttribute
**)(value
.v_gobject
));
1722 type
= lttv_attribute_get_by_name(tracefile_tree
, LTTV_STATE_PROCESS
,
1724 g_assert(type
== LTTV_UINT
);
1725 pid
= *(value
.v_uint
);
1726 tfcs
->process
= lttv_state_find_process_or_create(tfcs
, pid
);
1728 type
= lttv_attribute_get_by_name(tracefile_tree
, LTTV_STATE_EVENT
,
1730 g_assert(type
== LTTV_POINTER
);
1731 //g_assert(*(value.v_pointer) != NULL);
1732 ep
= *(value
.v_pointer
);
1733 g_assert(tfcs
->parent
.t_context
!= NULL
);
1735 tfcs
->cpu_state
= &self
->cpu_states
[tfcs
->cpu
];
1737 LttvTracefileContext
*tfc
= LTTV_TRACEFILE_CONTEXT(tfcs
);
1738 g_tree_remove(tsc
->pqueue
, tfc
);
1741 g_assert(ltt_tracefile_seek_position(tfc
->tf
, ep
) == 0);
1742 tfc
->timestamp
= ltt_event_time(ltt_tracefile_get_event(tfc
->tf
));
1743 g_assert(ltt_time_compare(tfc
->timestamp
, ltt_time_infinite
) != 0);
1744 g_tree_insert(tsc
->pqueue
, tfc
, tfc
);
1745 g_info("Restoring state for a tf at time %lu.%lu", tfc
->timestamp
.tv_sec
, tfc
->timestamp
.tv_nsec
);
1747 tfc
->timestamp
= ltt_time_infinite
;
1753 static void state_saved_free(LttvTraceState
*self
, LttvAttribute
*container
)
1755 guint i
, nb_tracefile
, nb_cpus
, nb_irqs
, nb_softirqs
;
1757 LttvTracefileState
*tfcs
;
1759 LttvAttribute
*tracefiles_tree
, *tracefile_tree
;
1761 guint
*running_process
;
1763 LttvAttributeType type
;
1765 LttvAttributeValue value
;
1767 LttvAttributeName name
;
1771 tracefiles_tree
= lttv_attribute_find_subdir(container
,
1772 LTTV_STATE_TRACEFILES
);
1773 g_object_ref(G_OBJECT(tracefiles_tree
));
1774 lttv_attribute_remove_by_name(container
, LTTV_STATE_TRACEFILES
);
1776 type
= lttv_attribute_get_by_name(container
, LTTV_STATE_PROCESSES
,
1778 g_assert(type
== LTTV_POINTER
);
1779 lttv_state_free_process_table(*(value
.v_pointer
));
1780 *(value
.v_pointer
) = NULL
;
1781 lttv_attribute_remove_by_name(container
, LTTV_STATE_PROCESSES
);
1783 /* Free running processes array */
1784 type
= lttv_attribute_get_by_name(container
, LTTV_STATE_RUNNING_PROCESS
,
1786 g_assert(type
== LTTV_POINTER
);
1787 running_process
= *(value
.v_pointer
);
1788 g_free(running_process
);
1790 /* free cpu resource states */
1791 type
= lttv_attribute_get_by_name(container
, LTTV_STATE_RESOURCE_CPUS_COUNT
, &value
);
1792 g_assert(type
== LTTV_UINT
);
1793 nb_cpus
= *value
.v_uint
;
1794 type
= lttv_attribute_get_by_name(container
, LTTV_STATE_RESOURCE_CPUS
, &value
);
1795 g_assert(type
== LTTV_POINTER
);
1796 lttv_state_free_cpu_states(*(value
.v_pointer
), nb_cpus
);
1798 /* free irq resource states */
1799 nb_irqs
= self
->nb_irqs
;
1800 type
= lttv_attribute_get_by_name(container
, LTTV_STATE_RESOURCE_IRQS
, &value
);
1801 g_assert(type
== LTTV_POINTER
);
1802 lttv_state_free_irq_states(*(value
.v_pointer
), nb_irqs
);
1804 /* free softirq resource states */
1805 nb_softirqs
= self
->nb_irqs
;
1806 type
= lttv_attribute_get_by_name(container
, LTTV_STATE_RESOURCE_SOFT_IRQS
, &value
);
1807 g_assert(type
== LTTV_POINTER
);
1808 lttv_state_free_soft_irq_states(*(value
.v_pointer
), nb_softirqs
);
1810 /* free the blkdev states */
1811 type
= lttv_attribute_get_by_name(container
, LTTV_STATE_RESOURCE_BLKDEVS
, &value
);
1812 g_assert(type
== LTTV_POINTER
);
1813 lttv_state_free_blkdev_hashtable(*(value
.v_pointer
));
1815 nb_tracefile
= self
->parent
.tracefiles
->len
;
1817 for(i
= 0 ; i
< nb_tracefile
; i
++) {
1819 LTTV_TRACEFILE_STATE(g_array_index(self
->parent
.tracefiles
,
1820 LttvTracefileContext
*, i
));
1821 type
= lttv_attribute_get(tracefiles_tree
, i
, &name
, &value
, &is_named
);
1822 g_assert(type
== LTTV_GOBJECT
);
1823 tracefile_tree
= *((LttvAttribute
**)(value
.v_gobject
));
1825 type
= lttv_attribute_get_by_name(tracefile_tree
, LTTV_STATE_EVENT
,
1827 g_assert(type
== LTTV_POINTER
);
1828 if(*(value
.v_pointer
) != NULL
) g_free(*(value
.v_pointer
));
1830 g_object_unref(G_OBJECT(tracefiles_tree
));
1834 static void free_saved_state(LttvTraceState
*self
)
1838 LttvAttributeType type
;
1840 LttvAttributeValue value
;
1842 LttvAttributeName name
;
1846 LttvAttribute
*saved_states
;
1848 saved_states
= lttv_attribute_find_subdir(self
->parent
.t_a
,
1849 LTTV_STATE_SAVED_STATES
);
1851 nb
= lttv_attribute_get_number(saved_states
);
1852 for(i
= 0 ; i
< nb
; i
++) {
1853 type
= lttv_attribute_get(saved_states
, i
, &name
, &value
, &is_named
);
1854 g_assert(type
== LTTV_GOBJECT
);
1855 state_saved_free(self
, *((LttvAttribute
**)value
.v_gobject
));
1858 lttv_attribute_remove_by_name(self
->parent
.t_a
, LTTV_STATE_SAVED_STATES
);
1863 create_max_time(LttvTraceState
*tcs
)
1865 LttvAttributeValue v
;
1867 lttv_attribute_find(tcs
->parent
.t_a
, LTTV_STATE_SAVED_STATES_TIME
,
1869 g_assert(*(v
.v_pointer
) == NULL
);
1870 *(v
.v_pointer
) = g_new(LttTime
,1);
1871 *((LttTime
*)*(v
.v_pointer
)) = ltt_time_zero
;
1876 get_max_time(LttvTraceState
*tcs
)
1878 LttvAttributeValue v
;
1880 lttv_attribute_find(tcs
->parent
.t_a
, LTTV_STATE_SAVED_STATES_TIME
,
1882 g_assert(*(v
.v_pointer
) != NULL
);
1883 tcs
->max_time_state_recomputed_in_seek
= (LttTime
*)*(v
.v_pointer
);
1888 free_max_time(LttvTraceState
*tcs
)
1890 LttvAttributeValue v
;
1892 lttv_attribute_find(tcs
->parent
.t_a
, LTTV_STATE_SAVED_STATES_TIME
,
1894 g_free(*(v
.v_pointer
));
1895 *(v
.v_pointer
) = NULL
;
1899 typedef struct _LttvNameTables
{
1900 // FIXME GQuark *eventtype_names;
1901 GQuark
*syscall_names
;
1907 GQuark
*soft_irq_names
;
1909 GHashTable
*kprobe_hash
;
1914 create_name_tables(LttvTraceState
*tcs
)
1918 GString
*fe_name
= g_string_new("");
1920 LttvNameTables
*name_tables
= g_new(LttvNameTables
, 1);
1922 LttvAttributeValue v
;
1926 lttv_attribute_find(tcs
->parent
.t_a
, LTTV_STATE_NAME_TABLES
,
1928 g_assert(*(v
.v_pointer
) == NULL
);
1929 *(v
.v_pointer
) = name_tables
;
1931 hooks
= g_array_sized_new(FALSE
, FALSE
, sizeof(LttvTraceHook
), 1);
1933 if(!lttv_trace_find_hook(tcs
->parent
.t
,
1935 LTT_EVENT_SYSCALL_ENTRY
,
1936 FIELD_ARRAY(LTT_FIELD_SYSCALL_ID
),
1937 NULL
, NULL
, &hooks
)) {
1939 // th = lttv_trace_hook_get_first(&th);
1941 // t = ltt_field_type(lttv_trace_get_hook_field(th, 0));
1942 // nb = ltt_type_element_number(t);
1944 // name_tables->syscall_names = g_new(GQuark, nb);
1945 // name_tables->nb_syscalls = nb;
1947 // for(i = 0 ; i < nb ; i++) {
1948 // name_tables->syscall_names[i] = ltt_enum_string_get(t, i);
1949 // if(!name_tables->syscall_names[i]) {
1950 // GString *string = g_string_new("");
1951 // g_string_printf(string, "syscall %u", i);
1952 // name_tables->syscall_names[i] = g_quark_from_string(string->str);
1953 // g_string_free(string, TRUE);
1957 name_tables
->nb_syscalls
= 256;
1958 name_tables
->syscall_names
= g_new(GQuark
, 256);
1959 for(i
= 0 ; i
< 256 ; i
++) {
1960 g_string_printf(fe_name
, "syscall %d", i
);
1961 name_tables
->syscall_names
[i
] = g_quark_from_string(fe_name
->str
);
1964 name_tables
->syscall_names
= NULL
;
1965 name_tables
->nb_syscalls
= 0;
1967 lttv_trace_hook_remove_all(&hooks
);
1969 if(!lttv_trace_find_hook(tcs
->parent
.t
,
1971 LTT_EVENT_TRAP_ENTRY
,
1972 FIELD_ARRAY(LTT_FIELD_TRAP_ID
),
1973 NULL
, NULL
, &hooks
) ||
1974 !lttv_trace_find_hook(tcs
->parent
.t
,
1976 LTT_EVENT_PAGE_FAULT_ENTRY
,
1977 FIELD_ARRAY(LTT_FIELD_TRAP_ID
),
1978 NULL
, NULL
, &hooks
)) {
1980 // th = lttv_trace_hook_get_first(&th);
1982 // t = ltt_field_type(lttv_trace_get_hook_field(th, 0));
1983 // //nb = ltt_type_element_number(t);
1985 // name_tables->trap_names = g_new(GQuark, nb);
1986 // for(i = 0 ; i < nb ; i++) {
1987 // name_tables->trap_names[i] = g_quark_from_string(
1988 // ltt_enum_string_get(t, i));
1991 name_tables
->nb_traps
= 256;
1992 name_tables
->trap_names
= g_new(GQuark
, 256);
1993 for(i
= 0 ; i
< 256 ; i
++) {
1994 g_string_printf(fe_name
, "trap %d", i
);
1995 name_tables
->trap_names
[i
] = g_quark_from_string(fe_name
->str
);
1998 name_tables
->trap_names
= NULL
;
1999 name_tables
->nb_traps
= 0;
2001 lttv_trace_hook_remove_all(&hooks
);
2003 if(!lttv_trace_find_hook(tcs
->parent
.t
,
2005 LTT_EVENT_IRQ_ENTRY
,
2006 FIELD_ARRAY(LTT_FIELD_IRQ_ID
),
2007 NULL
, NULL
, &hooks
)) {
2010 name_tables->irq_names = g_new(GQuark, nb);
2011 for(i = 0 ; i < nb ; i++) {
2012 name_tables->irq_names[i] = g_quark_from_string(ltt_enum_string_get(t, i));
2016 name_tables
->nb_irqs
= 256;
2017 name_tables
->irq_names
= g_new(GQuark
, 256);
2018 for(i
= 0 ; i
< 256 ; i
++) {
2019 g_string_printf(fe_name
, "irq %d", i
);
2020 name_tables
->irq_names
[i
] = g_quark_from_string(fe_name
->str
);
2023 name_tables
->nb_irqs
= 0;
2024 name_tables
->irq_names
= NULL
;
2026 lttv_trace_hook_remove_all(&hooks
);
2028 name_tables->soft_irq_names = g_new(GQuark, nb);
2029 for(i = 0 ; i < nb ; i++) {
2030 name_tables->soft_irq_names[i] = g_quark_from_string(ltt_enum_string_get(t, i));
2034 /* the kernel is limited to 32 statically defined softirqs */
2035 name_tables
->nb_softirqs
= 32;
2036 name_tables
->soft_irq_names
= g_new(GQuark
, name_tables
->nb_softirqs
);
2037 for(i
= 0 ; i
< name_tables
->nb_softirqs
; i
++) {
2038 g_string_printf(fe_name
, "softirq %d", i
);
2039 name_tables
->soft_irq_names
[i
] = g_quark_from_string(fe_name
->str
);
2041 g_array_free(hooks
, TRUE
);
2043 g_string_free(fe_name
, TRUE
);
2045 #if (__SIZEOF_LONG__ == 4)
2046 name_tables
->kprobe_hash
= g_hash_table_new_full(guint64_hash
, guint64_equal
,
2049 name_tables
->kprobe_hash
= g_hash_table_new(g_direct_hash
, g_direct_equal
);
2055 get_name_tables(LttvTraceState
*tcs
)
2057 LttvNameTables
*name_tables
;
2059 LttvAttributeValue v
;
2061 lttv_attribute_find(tcs
->parent
.t_a
, LTTV_STATE_NAME_TABLES
,
2063 g_assert(*(v
.v_pointer
) != NULL
);
2064 name_tables
= (LttvNameTables
*)*(v
.v_pointer
);
2065 //tcs->eventtype_names = name_tables->eventtype_names;
2066 tcs
->syscall_names
= name_tables
->syscall_names
;
2067 tcs
->nb_syscalls
= name_tables
->nb_syscalls
;
2068 tcs
->trap_names
= name_tables
->trap_names
;
2069 tcs
->nb_traps
= name_tables
->nb_traps
;
2070 tcs
->irq_names
= name_tables
->irq_names
;
2071 tcs
->soft_irq_names
= name_tables
->soft_irq_names
;
2072 tcs
->nb_irqs
= name_tables
->nb_irqs
;
2073 tcs
->nb_soft_irqs
= name_tables
->nb_softirqs
;
2074 tcs
->kprobe_hash
= name_tables
->kprobe_hash
;
2079 free_name_tables(LttvTraceState
*tcs
)
2081 LttvNameTables
*name_tables
;
2083 LttvAttributeValue v
;
2085 lttv_attribute_find(tcs
->parent
.t_a
, LTTV_STATE_NAME_TABLES
,
2087 name_tables
= (LttvNameTables
*)*(v
.v_pointer
);
2088 *(v
.v_pointer
) = NULL
;
2090 // g_free(name_tables->eventtype_names);
2091 if(name_tables
->syscall_names
) g_free(name_tables
->syscall_names
);
2092 if(name_tables
->trap_names
) g_free(name_tables
->trap_names
);
2093 if(name_tables
->irq_names
) g_free(name_tables
->irq_names
);
2094 if(name_tables
->soft_irq_names
) g_free(name_tables
->soft_irq_names
);
2095 if(name_tables
) g_free(name_tables
);
2096 if(name_tables
) g_hash_table_destroy(name_tables
->kprobe_hash
);
2099 #ifdef HASH_TABLE_DEBUG
2101 static void test_process(gpointer key
, gpointer value
, gpointer user_data
)
2103 LttvProcessState
*process
= (LttvProcessState
*)value
;
2105 /* Test for process corruption */
2106 guint stack_len
= process
->execution_stack
->len
;
2109 static void hash_table_check(GHashTable
*table
)
2111 g_hash_table_foreach(table
, test_process
, NULL
);
2117 /* clears the stack and sets the state passed as argument */
2118 static void cpu_set_base_mode(LttvCPUState
*cpust
, LttvCPUMode state
)
2120 g_array_set_size(cpust
->mode_stack
, 1);
2121 ((GQuark
*)cpust
->mode_stack
->data
)[0] = state
;
2124 static void cpu_push_mode(LttvCPUState
*cpust
, LttvCPUMode state
)
2126 g_array_set_size(cpust
->mode_stack
, cpust
->mode_stack
->len
+ 1);
2127 ((GQuark
*)cpust
->mode_stack
->data
)[cpust
->mode_stack
->len
- 1] = state
;
2130 static void cpu_pop_mode(LttvCPUState
*cpust
)
2132 if(cpust
->mode_stack
->len
<= 1)
2133 cpu_set_base_mode(cpust
, LTTV_CPU_UNKNOWN
);
2135 g_array_set_size(cpust
->mode_stack
, cpust
->mode_stack
->len
- 1);
2138 /* clears the stack and sets the state passed as argument */
2139 static void bdev_set_base_mode(LttvBdevState
*bdevst
, LttvBdevMode state
)
2141 g_array_set_size(bdevst
->mode_stack
, 1);
2142 ((GQuark
*)bdevst
->mode_stack
->data
)[0] = state
;
2145 static void bdev_push_mode(LttvBdevState
*bdevst
, LttvBdevMode state
)
2147 g_array_set_size(bdevst
->mode_stack
, bdevst
->mode_stack
->len
+ 1);
2148 ((GQuark
*)bdevst
->mode_stack
->data
)[bdevst
->mode_stack
->len
- 1] = state
;
2151 static void bdev_pop_mode(LttvBdevState
*bdevst
)
2153 if(bdevst
->mode_stack
->len
<= 1)
2154 bdev_set_base_mode(bdevst
, LTTV_BDEV_UNKNOWN
);
2156 g_array_set_size(bdevst
->mode_stack
, bdevst
->mode_stack
->len
- 1);
2159 static void irq_set_base_mode(LttvIRQState
*irqst
, LttvIRQMode state
)
2161 g_array_set_size(irqst
->mode_stack
, 1);
2162 ((GQuark
*)irqst
->mode_stack
->data
)[0] = state
;
2165 static void irq_push_mode(LttvIRQState
*irqst
, LttvIRQMode state
)
2167 g_array_set_size(irqst
->mode_stack
, irqst
->mode_stack
->len
+ 1);
2168 ((GQuark
*)irqst
->mode_stack
->data
)[irqst
->mode_stack
->len
- 1] = state
;
2171 static void irq_pop_mode(LttvIRQState
*irqst
)
2173 if(irqst
->mode_stack
->len
<= 1)
2174 irq_set_base_mode(irqst
, LTTV_IRQ_UNKNOWN
);
2176 g_array_set_size(irqst
->mode_stack
, irqst
->mode_stack
->len
- 1);
2179 static void push_state(LttvTracefileState
*tfs
, LttvExecutionMode t
,
2182 LttvExecutionState
*es
;
2184 LttvTraceState
*ts
= (LttvTraceState
*)tfs
->parent
.t_context
;
2185 guint cpu
= tfs
->cpu
;
2187 #ifdef HASH_TABLE_DEBUG
2188 hash_table_check(ts
->processes
);
2190 LttvProcessState
*process
= ts
->running_process
[cpu
];
2192 guint depth
= process
->execution_stack
->len
;
2194 process
->execution_stack
=
2195 g_array_set_size(process
->execution_stack
, depth
+ 1);
2198 &g_array_index(process
->execution_stack
, LttvExecutionState
, depth
- 1);
2200 es
= &g_array_index(process
->execution_stack
, LttvExecutionState
, depth
);
2203 es
->entry
= es
->change
= tfs
->parent
.timestamp
;
2204 es
->cum_cpu_time
= ltt_time_zero
;
2205 es
->s
= process
->state
->s
;
2206 process
->state
= es
;
2210 * return 1 when empty, else 0 */
2211 int lttv_state_pop_state_cleanup(LttvProcessState
*process
,
2212 LttvTracefileState
*tfs
)
2214 guint depth
= process
->execution_stack
->len
;
2220 process
->execution_stack
=
2221 g_array_set_size(process
->execution_stack
, depth
- 1);
2222 process
->state
= &g_array_index(process
->execution_stack
, LttvExecutionState
,
2224 process
->state
->change
= tfs
->parent
.timestamp
;
2229 static void pop_state(LttvTracefileState
*tfs
, LttvExecutionMode t
)
2231 guint cpu
= tfs
->cpu
;
2232 LttvTraceState
*ts
= (LttvTraceState
*)tfs
->parent
.t_context
;
2233 LttvProcessState
*process
= ts
->running_process
[cpu
];
2235 guint depth
= process
->execution_stack
->len
;
2237 if(process
->state
->t
!= t
){
2238 g_info("Different execution mode type (%lu.%09lu): ignore it\n",
2239 tfs
->parent
.timestamp
.tv_sec
, tfs
->parent
.timestamp
.tv_nsec
);
2240 g_info("process state has %s when pop_int is %s\n",
2241 g_quark_to_string(process
->state
->t
),
2242 g_quark_to_string(t
));
2243 g_info("{ %u, %u, %s, %s, %s }\n",
2246 g_quark_to_string(process
->name
),
2247 g_quark_to_string(process
->brand
),
2248 g_quark_to_string(process
->state
->s
));
2253 g_info("Trying to pop last state on stack (%lu.%09lu): ignore it\n",
2254 tfs
->parent
.timestamp
.tv_sec
, tfs
->parent
.timestamp
.tv_nsec
);
2258 process
->execution_stack
=
2259 g_array_set_size(process
->execution_stack
, depth
- 1);
2260 process
->state
= &g_array_index(process
->execution_stack
, LttvExecutionState
,
2262 process
->state
->change
= tfs
->parent
.timestamp
;
2265 struct search_result
{
2266 const LttTime
*time
; /* Requested time */
2267 LttTime
*best
; /* Best result */
2270 static gint
search_usertrace(gconstpointer a
, gconstpointer b
)
2272 const LttTime
*elem_time
= (const LttTime
*)a
;
2273 /* Explicit non const cast */
2274 struct search_result
*res
= (struct search_result
*)b
;
2276 if(ltt_time_compare(*elem_time
, *(res
->time
)) < 0) {
2277 /* The usertrace was created before the schedchange */
2278 /* Get larger keys */
2280 } else if(ltt_time_compare(*elem_time
, *(res
->time
)) >= 0) {
2281 /* The usertrace was created after the schedchange time */
2282 /* Get smaller keys */
2284 if(ltt_time_compare(*elem_time
, *res
->best
) < 0) {
2285 res
->best
= (LttTime
*)elem_time
;
2288 res
->best
= (LttTime
*)elem_time
;
2295 static LttvTracefileState
*ltt_state_usertrace_find(LttvTraceState
*tcs
,
2296 guint pid
, const LttTime
*timestamp
)
2298 LttvTracefileState
*tfs
= NULL
;
2299 struct search_result res
;
2300 /* Find the usertrace associated with a pid and time interval.
2301 * Search in the usertraces by PID (within a hash) and then, for each
2302 * corresponding element of the array, find the first one with creation
2303 * timestamp the lowest, but higher or equal to "timestamp". */
2304 res
.time
= timestamp
;
2306 GTree
*usertrace_tree
= g_hash_table_lookup(tcs
->usertraces
,
2307 GUINT_TO_POINTER(pid
));
2308 if(usertrace_tree
) {
2309 g_tree_search(usertrace_tree
, search_usertrace
, &res
);
2311 tfs
= g_tree_lookup(usertrace_tree
, res
.best
);
2319 lttv_state_create_process(LttvTraceState
*tcs
, LttvProcessState
*parent
,
2320 guint cpu
, guint pid
, guint tgid
, GQuark name
, const LttTime
*timestamp
)
2322 LttvProcessState
*process
= g_new(LttvProcessState
, 1);
2324 LttvExecutionState
*es
;
2329 process
->tgid
= tgid
;
2331 process
->name
= name
;
2332 process
->brand
= LTTV_STATE_UNBRANDED
;
2333 //process->last_cpu = tfs->cpu_name;
2334 //process->last_cpu_index = ltt_tracefile_num(((LttvTracefileContext*)tfs)->tf);
2335 process
->type
= LTTV_STATE_USER_THREAD
;
2336 process
->usertrace
= ltt_state_usertrace_find(tcs
, pid
, timestamp
);
2337 process
->current_function
= 0; //function 0x0 by default.
2339 g_info("Process %u, core %p", process
->pid
, process
);
2340 g_hash_table_insert(tcs
->processes
, process
, process
);
2343 process
->ppid
= parent
->pid
;
2344 process
->creation_time
= *timestamp
;
2347 /* No parent. This process exists but we are missing all information about
2348 its creation. The birth time is set to zero but we remember the time of
2353 process
->creation_time
= ltt_time_zero
;
2356 process
->insertion_time
= *timestamp
;
2357 sprintf(buffer
,"%d-%lu.%lu",pid
, process
->creation_time
.tv_sec
,
2358 process
->creation_time
.tv_nsec
);
2359 process
->pid_time
= g_quark_from_string(buffer
);
2361 process
->free_events
= 0;
2362 //process->last_cpu = tfs->cpu_name;
2363 //process->last_cpu_index = ltt_tracefile_num(((LttvTracefileContext*)tfs)->tf);
2364 process
->execution_stack
= g_array_sized_new(FALSE
, FALSE
,
2365 sizeof(LttvExecutionState
), PREALLOCATED_EXECUTION_STACK
);
2366 process
->execution_stack
= g_array_set_size(process
->execution_stack
, 2);
2367 es
= process
->state
= &g_array_index(process
->execution_stack
,
2368 LttvExecutionState
, 0);
2369 es
->t
= LTTV_STATE_USER_MODE
;
2370 es
->n
= LTTV_STATE_SUBMODE_NONE
;
2371 es
->entry
= *timestamp
;
2372 //g_assert(timestamp->tv_sec != 0);
2373 es
->change
= *timestamp
;
2374 es
->cum_cpu_time
= ltt_time_zero
;
2375 es
->s
= LTTV_STATE_RUN
;
2377 es
= process
->state
= &g_array_index(process
->execution_stack
,
2378 LttvExecutionState
, 1);
2379 es
->t
= LTTV_STATE_SYSCALL
;
2380 es
->n
= LTTV_STATE_SUBMODE_NONE
;
2381 es
->entry
= *timestamp
;
2382 //g_assert(timestamp->tv_sec != 0);
2383 es
->change
= *timestamp
;
2384 es
->cum_cpu_time
= ltt_time_zero
;
2385 es
->s
= LTTV_STATE_WAIT_FORK
;
2387 /* Allocate an empty function call stack. If it's empty, use 0x0. */
2388 process
->user_stack
= g_array_sized_new(FALSE
, FALSE
,
2389 sizeof(guint64
), 0);
2394 LttvProcessState
*lttv_state_find_process(LttvTraceState
*ts
, guint cpu
,
2397 LttvProcessState key
;
2398 LttvProcessState
*process
;
2402 process
= g_hash_table_lookup(ts
->processes
, &key
);
2407 lttv_state_find_process_or_create(LttvTraceState
*ts
, guint cpu
, guint pid
,
2408 const LttTime
*timestamp
)
2410 LttvProcessState
*process
= lttv_state_find_process(ts
, cpu
, pid
);
2411 LttvExecutionState
*es
;
2413 /* Put ltt_time_zero creation time for unexisting processes */
2414 if(unlikely(process
== NULL
)) {
2415 process
= lttv_state_create_process(ts
,
2416 NULL
, cpu
, pid
, 0, LTTV_STATE_UNNAMED
, timestamp
);
2417 /* We are not sure is it's a kernel thread or normal thread, put the
2418 * bottom stack state to unknown */
2419 process
->execution_stack
=
2420 g_array_set_size(process
->execution_stack
, 1);
2421 process
->state
= es
=
2422 &g_array_index(process
->execution_stack
, LttvExecutionState
, 0);
2423 es
->t
= LTTV_STATE_MODE_UNKNOWN
;
2424 es
->s
= LTTV_STATE_UNNAMED
;
2429 /* FIXME : this function should be called when we receive an event telling that
2430 * release_task has been called in the kernel. In happens generally when
2431 * the parent waits for its child terminaison, but may also happen in special
2432 * cases in the child's exit : when the parent ignores its children SIGCCHLD or
2433 * has the flag SA_NOCLDWAIT. It can also happen when the child is part
2434 * of a killed thread group, but isn't the leader.
2436 static int exit_process(LttvTracefileState
*tfs
, LttvProcessState
*process
)
2438 LttvTraceState
*ts
= LTTV_TRACE_STATE(tfs
->parent
.t_context
);
2439 LttvProcessState key
;
2441 /* Wait for both schedule with exit dead and process free to happen.
2442 * They can happen in any order. */
2443 if (++(process
->free_events
) < 2)
2446 key
.pid
= process
->pid
;
2447 key
.cpu
= process
->cpu
;
2448 g_hash_table_remove(ts
->processes
, &key
);
2449 g_array_free(process
->execution_stack
, TRUE
);
2450 g_array_free(process
->user_stack
, TRUE
);
2456 static void free_process_state(gpointer key
, gpointer value
,gpointer user_data
)
2458 g_array_free(((LttvProcessState
*)value
)->execution_stack
, TRUE
);
2459 g_array_free(((LttvProcessState
*)value
)->user_stack
, TRUE
);
2464 static void lttv_state_free_process_table(GHashTable
*processes
)
2466 g_hash_table_foreach(processes
, free_process_state
, NULL
);
2467 g_hash_table_destroy(processes
);
2471 static gboolean
syscall_entry(void *hook_data
, void *call_data
)
2473 LttvTracefileState
*s
= (LttvTracefileState
*)call_data
;
2475 LttvTraceState
*ts
= (LttvTraceState
*)s
->parent
.t_context
;
2476 LttvProcessState
*process
= ts
->running_process
[cpu
];
2477 LttEvent
*e
= ltt_tracefile_get_event(s
->parent
.tf
);
2478 LttvTraceHook
*th
= (LttvTraceHook
*)hook_data
;
2479 struct marker_field
*f
= lttv_trace_get_hook_field(th
, 0);
2480 LttvExecutionSubmode submode
;
2482 guint syscall
= ltt_event_get_unsigned(e
, f
);
2483 expand_syscall_table(ts
, syscall
);
2484 submode
= ((LttvTraceState
*)(s
->parent
.t_context
))->syscall_names
[syscall
];
2485 /* There can be no system call from PID 0 : unknown state */
2486 if(process
->pid
!= 0)
2487 push_state(s
, LTTV_STATE_SYSCALL
, submode
);
2492 static gboolean
syscall_exit(void *hook_data
, void *call_data
)
2494 LttvTracefileState
*s
= (LttvTracefileState
*)call_data
;
2496 LttvTraceState
*ts
= (LttvTraceState
*)s
->parent
.t_context
;
2497 LttvProcessState
*process
= ts
->running_process
[cpu
];
2499 /* There can be no system call from PID 0 : unknown state */
2500 if(process
->pid
!= 0)
2501 pop_state(s
, LTTV_STATE_SYSCALL
);
2506 static gboolean
trap_entry(void *hook_data
, void *call_data
)
2508 LttvTracefileState
*s
= (LttvTracefileState
*)call_data
;
2509 LttvTraceState
*ts
= (LttvTraceState
*)s
->parent
.t_context
;
2510 LttEvent
*e
= ltt_tracefile_get_event(s
->parent
.tf
);
2511 LttvTraceHook
*th
= (LttvTraceHook
*)hook_data
;
2512 struct marker_field
*f
= lttv_trace_get_hook_field(th
, 0);
2514 LttvExecutionSubmode submode
;
2516 guint64 trap
= ltt_event_get_long_unsigned(e
, f
);
2518 expand_trap_table(ts
, trap
);
2520 submode
= ((LttvTraceState
*)(s
->parent
.t_context
))->trap_names
[trap
];
2522 push_state(s
, LTTV_STATE_TRAP
, submode
);
2524 /* update cpu status */
2525 cpu_push_mode(s
->cpu_state
, LTTV_CPU_TRAP
);
2527 /* update trap status */
2528 s
->cpu_state
->last_trap
= trap
;
2529 ts
->trap_states
[trap
].running
++;
2534 static gboolean
trap_exit(void *hook_data
, void *call_data
)
2536 LttvTracefileState
*s
= (LttvTracefileState
*)call_data
;
2537 LttvTraceState
*ts
= (LttvTraceState
*)s
->parent
.t_context
;
2538 gint trap
= s
->cpu_state
->last_trap
;
2540 pop_state(s
, LTTV_STATE_TRAP
);
2542 /* update cpu status */
2543 cpu_pop_mode(s
->cpu_state
);
2545 /* update trap status */
2547 if(ts
->trap_states
[trap
].running
)
2548 ts
->trap_states
[trap
].running
--;
2553 static gboolean
irq_entry(void *hook_data
, void *call_data
)
2555 LttvTracefileState
*s
= (LttvTracefileState
*)call_data
;
2556 LttvTraceState
*ts
= (LttvTraceState
*)s
->parent
.t_context
;
2557 LttEvent
*e
= ltt_tracefile_get_event(s
->parent
.tf
);
2558 //guint8 ev_id = ltt_event_eventtype_id(e);
2559 LttvTraceHook
*th
= (LttvTraceHook
*)hook_data
;
2560 struct marker_field
*f
= lttv_trace_get_hook_field(th
, 0);
2562 LttvExecutionSubmode submode
;
2563 guint64 irq
= ltt_event_get_long_unsigned(e
, f
);
2565 expand_irq_table(ts
, irq
);
2567 submode
= ((LttvTraceState
*)(s
->parent
.t_context
))->irq_names
[irq
];
2569 /* Do something with the info about being in user or system mode when int? */
2570 push_state(s
, LTTV_STATE_IRQ
, submode
);
2572 /* update cpu status */
2573 cpu_push_mode(s
->cpu_state
, LTTV_CPU_IRQ
);
2575 /* update irq status */
2576 g_array_append_val(s
->cpu_state
->irq_stack
, irq
);
2577 irq_push_mode(&ts
->irq_states
[irq
], LTTV_IRQ_BUSY
);
2582 static gboolean
soft_irq_exit(void *hook_data
, void *call_data
)
2584 LttvTracefileState
*s
= (LttvTracefileState
*)call_data
;
2585 LttvTraceState
*ts
= (LttvTraceState
*)s
->parent
.t_context
;
2586 gint softirq
= s
->cpu_state
->last_soft_irq
;
2588 pop_state(s
, LTTV_STATE_SOFT_IRQ
);
2590 /* update softirq status */
2592 if(ts
->soft_irq_states
[softirq
].running
)
2593 ts
->soft_irq_states
[softirq
].running
--;
2595 /* update cpu status */
2596 cpu_pop_mode(s
->cpu_state
);
2601 static gboolean
irq_exit(void *hook_data
, void *call_data
)
2603 LttvTracefileState
*s
= (LttvTracefileState
*)call_data
;
2604 LttvTraceState
*ts
= (LttvTraceState
*)s
->parent
.t_context
;
2606 pop_state(s
, LTTV_STATE_IRQ
);
2608 /* update cpu status */
2609 cpu_pop_mode(s
->cpu_state
);
2611 /* update irq status */
2612 if (s
->cpu_state
->irq_stack
->len
> 0) {
2613 gint last
= g_array_index(s
->cpu_state
->irq_stack
, gint
, s
->cpu_state
->irq_stack
->len
-1);
2614 g_array_remove_index(s
->cpu_state
->irq_stack
, s
->cpu_state
->irq_stack
->len
-1);
2615 irq_pop_mode(&ts
->irq_states
[last
]);
2621 static gboolean
soft_irq_raise(void *hook_data
, void *call_data
)
2623 LttvTracefileState
*s
= (LttvTracefileState
*)call_data
;
2624 LttvTraceState
*ts
= (LttvTraceState
*)s
->parent
.t_context
;
2625 LttEvent
*e
= ltt_tracefile_get_event(s
->parent
.tf
);
2626 //guint8 ev_id = ltt_event_eventtype_id(e);
2627 LttvTraceHook
*th
= (LttvTraceHook
*)hook_data
;
2628 struct marker_field
*f
= lttv_trace_get_hook_field(th
, 0);
2630 LttvExecutionSubmode submode
;
2631 guint64 softirq
= ltt_event_get_long_unsigned(e
, f
);
2632 guint64 nb_softirqs
= ((LttvTraceState
*)(s
->parent
.t_context
))->nb_soft_irqs
;
2634 if(softirq
< nb_softirqs
) {
2635 submode
= ((LttvTraceState
*)(s
->parent
.t_context
))->soft_irq_names
[softirq
];
2637 /* Fixup an incomplete irq table */
2638 GString
*string
= g_string_new("");
2639 g_string_printf(string
, "softirq %" PRIu64
, softirq
);
2640 submode
= g_quark_from_string(string
->str
);
2641 g_string_free(string
, TRUE
);
2644 /* update softirq status */
2645 /* a soft irq raises are not cumulative */
2646 ts
->soft_irq_states
[softirq
].pending
=1;
2651 static gboolean
soft_irq_entry(void *hook_data
, void *call_data
)
2653 LttvTracefileState
*s
= (LttvTracefileState
*)call_data
;
2654 LttvTraceState
*ts
= (LttvTraceState
*)s
->parent
.t_context
;
2655 LttEvent
*e
= ltt_tracefile_get_event(s
->parent
.tf
);
2656 //guint8 ev_id = ltt_event_eventtype_id(e);
2657 LttvTraceHook
*th
= (LttvTraceHook
*)hook_data
;
2658 struct marker_field
*f
= lttv_trace_get_hook_field(th
, 0);
2659 LttvExecutionSubmode submode
;
2660 guint64 softirq
= ltt_event_get_long_unsigned(e
, f
);
2661 expand_soft_irq_table(ts
, softirq
);
2662 submode
= ((LttvTraceState
*)(s
->parent
.t_context
))->soft_irq_names
[softirq
];
2664 /* Do something with the info about being in user or system mode when int? */
2665 push_state(s
, LTTV_STATE_SOFT_IRQ
, submode
);
2667 /* update cpu status */
2668 cpu_push_mode(s
->cpu_state
, LTTV_CPU_SOFT_IRQ
);
2670 /* update softirq status */
2671 s
->cpu_state
->last_soft_irq
= softirq
;
2672 if(ts
->soft_irq_states
[softirq
].pending
)
2673 ts
->soft_irq_states
[softirq
].pending
--;
2674 ts
->soft_irq_states
[softirq
].running
++;
2679 static gboolean
enum_interrupt(void *hook_data
, void *call_data
)
2681 LttvTracefileState
*s
= (LttvTracefileState
*)call_data
;
2682 LttvTraceState
*ts
= (LttvTraceState
*)s
->parent
.t_context
;
2683 LttEvent
*e
= ltt_tracefile_get_event(s
->parent
.tf
);
2684 //guint8 ev_id = ltt_event_eventtype_id(e);
2685 LttvTraceHook
*th
= (LttvTraceHook
*)hook_data
;
2687 GQuark action
= g_quark_from_string(ltt_event_get_string(e
,
2688 lttv_trace_get_hook_field(th
, 0)));
2689 guint irq
= ltt_event_get_long_unsigned(e
, lttv_trace_get_hook_field(th
, 1));
2691 expand_irq_table(ts
, irq
);
2692 ts
->irq_names
[irq
] = action
;
2698 static gboolean
bdev_request_issue(void *hook_data
, void *call_data
)
2700 LttvTracefileState
*s
= (LttvTracefileState
*)call_data
;
2701 LttvTraceState
*ts
= (LttvTraceState
*)s
->parent
.t_context
;
2702 LttEvent
*e
= ltt_tracefile_get_event(s
->parent
.tf
);
2703 //guint8 ev_id = ltt_event_eventtype_id(e);
2704 LttvTraceHook
*th
= (LttvTraceHook
*)hook_data
;
2706 guint major
= ltt_event_get_long_unsigned(e
,
2707 lttv_trace_get_hook_field(th
, 0));
2708 guint minor
= ltt_event_get_long_unsigned(e
,
2709 lttv_trace_get_hook_field(th
, 1));
2710 guint oper
= ltt_event_get_long_unsigned(e
,
2711 lttv_trace_get_hook_field(th
, 2));
2712 guint16 devcode
= MKDEV(major
,minor
);
2714 /* have we seen this block device before? */
2715 gpointer bdev
= get_hashed_bdevstate(ts
, devcode
);
2718 bdev_push_mode(bdev
, LTTV_BDEV_BUSY_READING
);
2720 bdev_push_mode(bdev
, LTTV_BDEV_BUSY_WRITING
);
2725 static gboolean
bdev_request_complete(void *hook_data
, void *call_data
)
2727 LttvTracefileState
*s
= (LttvTracefileState
*)call_data
;
2728 LttvTraceState
*ts
= (LttvTraceState
*)s
->parent
.t_context
;
2729 LttEvent
*e
= ltt_tracefile_get_event(s
->parent
.tf
);
2730 LttvTraceHook
*th
= (LttvTraceHook
*)hook_data
;
2732 guint major
= ltt_event_get_long_unsigned(e
,
2733 lttv_trace_get_hook_field(th
, 0));
2734 guint minor
= ltt_event_get_long_unsigned(e
,
2735 lttv_trace_get_hook_field(th
, 1));
2736 //guint oper = ltt_event_get_long_unsigned(e,
2737 // lttv_trace_get_hook_field(th, 2));
2738 guint16 devcode
= MKDEV(major
,minor
);
2740 /* have we seen this block device before? */
2741 gpointer bdev
= get_hashed_bdevstate(ts
, devcode
);
2743 /* update block device */
2744 bdev_pop_mode(bdev
);
2749 static void push_function(LttvTracefileState
*tfs
, guint64 funcptr
)
2753 LttvTraceState
*ts
= (LttvTraceState
*)tfs
->parent
.t_context
;
2754 guint cpu
= tfs
->cpu
;
2755 LttvProcessState
*process
= ts
->running_process
[cpu
];
2757 guint depth
= process
->user_stack
->len
;
2759 process
->user_stack
=
2760 g_array_set_size(process
->user_stack
, depth
+ 1);
2762 new_func
= &g_array_index(process
->user_stack
, guint64
, depth
);
2763 *new_func
= funcptr
;
2764 process
->current_function
= funcptr
;
2767 static void pop_function(LttvTracefileState
*tfs
, guint64 funcptr
)
2769 guint cpu
= tfs
->cpu
;
2770 LttvTraceState
*ts
= (LttvTraceState
*)tfs
->parent
.t_context
;
2771 LttvProcessState
*process
= ts
->running_process
[cpu
];
2773 if(process
->current_function
!= funcptr
){
2774 g_info("Different functions (%lu.%09lu): ignore it\n",
2775 tfs
->parent
.timestamp
.tv_sec
, tfs
->parent
.timestamp
.tv_nsec
);
2776 g_info("process state has %" PRIu64
" when pop_function is %" PRIu64
"\n",
2777 process
->current_function
, funcptr
);
2778 g_info("{ %u, %u, %s, %s, %s }\n",
2781 g_quark_to_string(process
->name
),
2782 g_quark_to_string(process
->brand
),
2783 g_quark_to_string(process
->state
->s
));
2786 guint depth
= process
->user_stack
->len
;
2789 g_info("Trying to pop last function on stack (%lu.%09lu): ignore it\n",
2790 tfs
->parent
.timestamp
.tv_sec
, tfs
->parent
.timestamp
.tv_nsec
);
2794 process
->user_stack
=
2795 g_array_set_size(process
->user_stack
, depth
- 1);
2796 process
->current_function
=
2797 g_array_index(process
->user_stack
, guint64
, depth
- 2);
2801 static gboolean
function_entry(void *hook_data
, void *call_data
)
2803 LttvTracefileState
*s
= (LttvTracefileState
*)call_data
;
2804 LttEvent
*e
= ltt_tracefile_get_event(s
->parent
.tf
);
2805 //guint8 ev_id = ltt_event_eventtype_id(e);
2806 LttvTraceHook
*th
= (LttvTraceHook
*)hook_data
;
2807 struct marker_field
*f
= lttv_trace_get_hook_field(th
, 0);
2808 guint64 funcptr
= ltt_event_get_long_unsigned(e
, f
);
2810 push_function(s
, funcptr
);
2814 static gboolean
function_exit(void *hook_data
, void *call_data
)
2816 LttvTracefileState
*s
= (LttvTracefileState
*)call_data
;
2817 LttEvent
*e
= ltt_tracefile_get_event(s
->parent
.tf
);
2818 //guint8 ev_id = ltt_event_eventtype_id(e);
2819 LttvTraceHook
*th
= (LttvTraceHook
*)hook_data
;
2820 struct marker_field
*f
= lttv_trace_get_hook_field(th
, 0);
2821 guint64 funcptr
= ltt_event_get_long_unsigned(e
, f
);
2823 pop_function(s
, funcptr
);
2827 static gboolean
dump_syscall(void *hook_data
, void *call_data
)
2829 LttvTracefileState
*s
= (LttvTracefileState
*)call_data
;
2830 LttvTraceState
*ts
= (LttvTraceState
*)s
->parent
.t_context
;
2831 LttEvent
*e
= ltt_tracefile_get_event(s
->parent
.tf
);
2832 LttvTraceHook
*th
= (LttvTraceHook
*)hook_data
;
2837 id
= ltt_event_get_unsigned(e
, lttv_trace_get_hook_field(th
, 0));
2838 address
= ltt_event_get_long_unsigned(e
, lttv_trace_get_hook_field(th
, 1));
2839 symbol
= ltt_event_get_string(e
, lttv_trace_get_hook_field(th
, 2));
2841 expand_syscall_table(ts
, id
);
2842 ts
->syscall_names
[id
] = g_quark_from_string(symbol
);
2847 static gboolean
dump_kprobe(void *hook_data
, void *call_data
)
2849 LttvTracefileState
*s
= (LttvTracefileState
*)call_data
;
2850 LttvTraceState
*ts
= (LttvTraceState
*)s
->parent
.t_context
;
2851 LttEvent
*e
= ltt_tracefile_get_event(s
->parent
.tf
);
2852 LttvTraceHook
*th
= (LttvTraceHook
*)hook_data
;
2856 ip
= ltt_event_get_long_unsigned(e
, lttv_trace_get_hook_field(th
, 0));
2857 symbol
= ltt_event_get_string(e
, lttv_trace_get_hook_field(th
, 1));
2859 expand_kprobe_table(ts
, ip
, symbol
);
2864 static gboolean
dump_softirq(void *hook_data
, void *call_data
)
2866 LttvTracefileState
*s
= (LttvTracefileState
*)call_data
;
2867 LttvTraceState
*ts
= (LttvTraceState
*)s
->parent
.t_context
;
2868 LttEvent
*e
= ltt_tracefile_get_event(s
->parent
.tf
);
2869 LttvTraceHook
*th
= (LttvTraceHook
*)hook_data
;
2874 id
= ltt_event_get_unsigned(e
, lttv_trace_get_hook_field(th
, 0));
2875 address
= ltt_event_get_long_unsigned(e
, lttv_trace_get_hook_field(th
, 1));
2876 symbol
= ltt_event_get_string(e
, lttv_trace_get_hook_field(th
, 2));
2878 expand_soft_irq_table(ts
, id
);
2879 ts
->soft_irq_names
[id
] = g_quark_from_string(symbol
);
2884 static gboolean
schedchange(void *hook_data
, void *call_data
)
2886 LttvTracefileState
*s
= (LttvTracefileState
*)call_data
;
2888 LttvTraceState
*ts
= (LttvTraceState
*)s
->parent
.t_context
;
2889 LttvProcessState
*process
= ts
->running_process
[cpu
];
2890 //LttvProcessState *old_process = ts->running_process[cpu];
2892 LttEvent
*e
= ltt_tracefile_get_event(s
->parent
.tf
);
2893 LttvTraceHook
*th
= (LttvTraceHook
*)hook_data
;
2894 guint pid_in
, pid_out
;
2897 pid_out
= ltt_event_get_unsigned(e
, lttv_trace_get_hook_field(th
, 0));
2898 pid_in
= ltt_event_get_unsigned(e
, lttv_trace_get_hook_field(th
, 1));
2899 state_out
= ltt_event_get_long_int(e
, lttv_trace_get_hook_field(th
, 2));
2901 if(likely(process
!= NULL
)) {
2903 /* We could not know but it was not the idle process executing.
2904 This should only happen at the beginning, before the first schedule
2905 event, and when the initial information (current process for each CPU)
2906 is missing. It is not obvious how we could, after the fact, compensate
2907 the wrongly attributed statistics. */
2909 //This test only makes sense once the state is known and if there is no
2910 //missing events. We need to silently ignore schedchange coming after a
2911 //process_free, or it causes glitches. (FIXME)
2912 //if(unlikely(process->pid != pid_out)) {
2913 // g_assert(process->pid == 0);
2915 if(process
->pid
== 0
2916 && process
->state
->t
== LTTV_STATE_MODE_UNKNOWN
) {
2918 /* Scheduling out of pid 0 at beginning of the trace :
2919 * we know for sure it is in syscall mode at this point. */
2920 g_assert(process
->execution_stack
->len
== 1);
2921 process
->state
->t
= LTTV_STATE_SYSCALL
;
2922 process
->state
->s
= LTTV_STATE_WAIT
;
2923 process
->state
->change
= s
->parent
.timestamp
;
2924 process
->state
->entry
= s
->parent
.timestamp
;
2927 if(unlikely(process
->state
->s
== LTTV_STATE_EXIT
)) {
2928 process
->state
->s
= LTTV_STATE_ZOMBIE
;
2929 process
->state
->change
= s
->parent
.timestamp
;
2931 if(unlikely(state_out
== 0)) process
->state
->s
= LTTV_STATE_WAIT_CPU
;
2932 else process
->state
->s
= LTTV_STATE_WAIT
;
2933 process
->state
->change
= s
->parent
.timestamp
;
2936 if(state_out
== 32 || state_out
== 64) { /* EXIT_DEAD || TASK_DEAD */
2937 /* see sched.h for states */
2938 if (!exit_process(s
, process
)) {
2939 process
->state
->s
= LTTV_STATE_DEAD
;
2940 process
->state
->change
= s
->parent
.timestamp
;
2945 process
= ts
->running_process
[cpu
] =
2946 lttv_state_find_process_or_create(
2947 (LttvTraceState
*)s
->parent
.t_context
,
2949 &s
->parent
.timestamp
);
2950 process
->state
->s
= LTTV_STATE_RUN
;
2952 if(process
->usertrace
)
2953 process
->usertrace
->cpu
= cpu
;
2954 // process->last_cpu_index = ltt_tracefile_num(((LttvTracefileContext*)s)->tf);
2955 process
->state
->change
= s
->parent
.timestamp
;
2957 /* update cpu status */
2959 /* going to idle task */
2960 cpu_set_base_mode(s
->cpu_state
, LTTV_CPU_IDLE
);
2962 /* scheduling a real task.
2963 * we must be careful here:
2964 * if we just schedule()'ed to a process that is
2965 * in a trap, we must put the cpu in trap mode
2967 cpu_set_base_mode(s
->cpu_state
, LTTV_CPU_BUSY
);
2968 if(process
->state
->t
== LTTV_STATE_TRAP
)
2969 cpu_push_mode(s
->cpu_state
, LTTV_CPU_TRAP
);
2975 static gboolean
process_fork(void *hook_data
, void *call_data
)
2977 LttvTracefileState
*s
= (LttvTracefileState
*)call_data
;
2978 LttEvent
*e
= ltt_tracefile_get_event(s
->parent
.tf
);
2979 LttvTraceHook
*th
= (LttvTraceHook
*)hook_data
;
2981 guint child_pid
; /* In the Linux Kernel, there is one PID per thread. */
2982 guint child_tgid
; /* tgid in the Linux kernel is the "real" POSIX PID. */
2983 //LttvProcessState *zombie_process;
2985 LttvTraceState
*ts
= (LttvTraceState
*)s
->parent
.t_context
;
2986 LttvProcessState
*process
= ts
->running_process
[cpu
];
2987 LttvProcessState
*child_process
;
2988 struct marker_field
*f
;
2991 parent_pid
= ltt_event_get_unsigned(e
, lttv_trace_get_hook_field(th
, 0));
2994 child_pid
= ltt_event_get_unsigned(e
, lttv_trace_get_hook_field(th
, 1));
2995 s
->parent
.target_pid
= child_pid
;
2998 f
= lttv_trace_get_hook_field(th
, 2);
3000 child_tgid
= ltt_event_get_unsigned(e
, f
);
3004 /* Mathieu : it seems like the process might have been scheduled in before the
3005 * fork, and, in a rare case, might be the current process. This might happen
3006 * in a SMP case where we don't have enough precision on the clocks.
3008 * Test reenabled after precision fixes on time. (Mathieu) */
3010 zombie_process
= lttv_state_find_process(ts
, ANY_CPU
, child_pid
);
3012 if(unlikely(zombie_process
!= NULL
)) {
3013 /* Reutilisation of PID. Only now we are sure that the old PID
3014 * has been released. FIXME : should know when release_task happens instead.
3016 guint num_cpus
= ltt_trace_get_num_cpu(ts
->parent
.t
);
3018 for(i
=0; i
< num_cpus
; i
++) {
3019 g_assert(zombie_process
!= ts
->running_process
[i
]);
3022 exit_process(s
, zombie_process
);
3025 g_assert(process
->pid
!= child_pid
);
3026 // FIXME : Add this test in the "known state" section
3027 // g_assert(process->pid == parent_pid);
3028 child_process
= lttv_state_find_process(ts
, ANY_CPU
, child_pid
);
3029 if(child_process
== NULL
) {
3030 child_process
= lttv_state_create_process(ts
, process
, cpu
,
3031 child_pid
, child_tgid
,
3032 LTTV_STATE_UNNAMED
, &s
->parent
.timestamp
);
3034 /* The process has already been created : due to time imprecision between
3035 * multiple CPUs : it has been scheduled in before creation. Note that we
3036 * shouldn't have this kind of imprecision.
3038 * Simply put a correct parent.
3040 g_error("Process %u has been created at [%lu.%09lu] "
3041 "and inserted at [%lu.%09lu] before \n"
3042 "fork on cpu %u[%lu.%09lu].\n"
3043 "Probably an unsynchronized TSC problem on the traced machine.",
3045 child_process
->creation_time
.tv_sec
,
3046 child_process
->creation_time
.tv_nsec
,
3047 child_process
->insertion_time
.tv_sec
,
3048 child_process
->insertion_time
.tv_nsec
,
3049 cpu
, ltt_event_time(e
).tv_sec
, ltt_event_time(e
).tv_nsec
);
3050 //g_assert(0); /* This is a problematic case : the process has been created
3051 // before the fork event */
3052 child_process
->ppid
= process
->pid
;
3053 child_process
->tgid
= child_tgid
;
3055 g_assert(child_process
->name
== LTTV_STATE_UNNAMED
);
3056 child_process
->name
= process
->name
;
3057 child_process
->brand
= process
->brand
;
3062 /* We stamp a newly created process as kernel_thread.
3063 * The thread should not be running yet. */
3064 static gboolean
process_kernel_thread(void *hook_data
, void *call_data
)
3066 LttvTracefileState
*s
= (LttvTracefileState
*)call_data
;
3067 LttEvent
*e
= ltt_tracefile_get_event(s
->parent
.tf
);
3068 LttvTraceHook
*th
= (LttvTraceHook
*)hook_data
;
3070 LttvTraceState
*ts
= (LttvTraceState
*)s
->parent
.t_context
;
3071 LttvProcessState
*process
;
3072 LttvExecutionState
*es
;
3075 pid
= (guint
)ltt_event_get_long_unsigned(e
, lttv_trace_get_hook_field(th
, 0));
3076 s
->parent
.target_pid
= pid
;
3078 process
= lttv_state_find_process_or_create(ts
, ANY_CPU
, pid
,
3080 if (process
->state
->s
!= LTTV_STATE_DEAD
) {
3081 process
->execution_stack
=
3082 g_array_set_size(process
->execution_stack
, 1);
3083 es
= process
->state
=
3084 &g_array_index(process
->execution_stack
, LttvExecutionState
, 0);
3085 es
->t
= LTTV_STATE_SYSCALL
;
3087 process
->type
= LTTV_STATE_KERNEL_THREAD
;
3092 static gboolean
process_exit(void *hook_data
, void *call_data
)
3094 LttvTracefileState
*s
= (LttvTracefileState
*)call_data
;
3095 LttEvent
*e
= ltt_tracefile_get_event(s
->parent
.tf
);
3096 LttvTraceHook
*th
= (LttvTraceHook
*)hook_data
;
3098 LttvTraceState
*ts
= (LttvTraceState
*)s
->parent
.t_context
;
3099 LttvProcessState
*process
; // = ts->running_process[cpu];
3101 pid
= ltt_event_get_unsigned(e
, lttv_trace_get_hook_field(th
, 0));
3102 s
->parent
.target_pid
= pid
;
3104 // FIXME : Add this test in the "known state" section
3105 // g_assert(process->pid == pid);
3107 process
= lttv_state_find_process(ts
, ANY_CPU
, pid
);
3108 if(likely(process
!= NULL
)) {
3109 process
->state
->s
= LTTV_STATE_EXIT
;
3114 static gboolean
process_free(void *hook_data
, void *call_data
)
3116 LttvTracefileState
*s
= (LttvTracefileState
*)call_data
;
3117 LttvTraceState
*ts
= (LttvTraceState
*)s
->parent
.t_context
;
3118 LttEvent
*e
= ltt_tracefile_get_event(s
->parent
.tf
);
3119 LttvTraceHook
*th
= (LttvTraceHook
*)hook_data
;
3121 LttvProcessState
*process
;
3123 /* PID of the process to release */
3124 release_pid
= ltt_event_get_unsigned(e
, lttv_trace_get_hook_field(th
, 0));
3125 s
->parent
.target_pid
= release_pid
;
3127 g_assert(release_pid
!= 0);
3129 process
= lttv_state_find_process(ts
, ANY_CPU
, release_pid
);
3130 if(likely(process
!= NULL
))
3131 exit_process(s
, process
);
3134 if(likely(process
!= NULL
)) {
3135 /* release_task is happening at kernel level : we can now safely release
3136 * the data structure of the process */
3137 //This test is fun, though, as it may happen that
3138 //at time t : CPU 0 : process_free
3139 //at time t+150ns : CPU 1 : schedule out
3140 //Clearly due to time imprecision, we disable it. (Mathieu)
3141 //If this weird case happen, we have no choice but to put the
3142 //Currently running process on the cpu to 0.
3143 //I re-enable it following time precision fixes. (Mathieu)
3144 //Well, in the case where an process is freed by a process on another CPU
3145 //and still scheduled, it happens that this is the schedchange that will
3146 //drop the last reference count. Do not free it here!
3147 guint num_cpus
= ltt_trace_get_num_cpu(ts
->parent
.t
);
3149 for(i
=0; i
< num_cpus
; i
++) {
3150 //g_assert(process != ts->running_process[i]);
3151 if(process
== ts
->running_process
[i
]) {
3152 //ts->running_process[i] = lttv_state_find_process(ts, i, 0);
3156 if(i
== num_cpus
) /* process is not scheduled */
3157 exit_process(s
, process
);
3164 static gboolean
process_exec(void *hook_data
, void *call_data
)
3166 LttvTracefileState
*s
= (LttvTracefileState
*)call_data
;
3167 LttvTraceState
*ts
= (LttvTraceState
*)s
->parent
.t_context
;
3168 LttEvent
*e
= ltt_tracefile_get_event(s
->parent
.tf
);
3169 LttvTraceHook
*th
= (LttvTraceHook
*)hook_data
;
3172 LttvProcessState
*process
= ts
->running_process
[cpu
];
3174 #if 0//how to use a sequence that must be transformed in a string
3175 /* PID of the process to release */
3176 guint64 name_len
= ltt_event_field_element_number(e
,
3177 lttv_trace_get_hook_field(th
, 0));
3178 //name = ltt_event_get_string(e, lttv_trace_get_hook_field(th, 0));
3179 LttField
*child
= ltt_event_field_element_select(e
,
3180 lttv_trace_get_hook_field(th
, 0), 0);
3182 (gchar
*)(ltt_event_data(e
)+ltt_event_field_offset(e
, child
));
3183 gchar
*null_term_name
= g_new(gchar
, name_len
+1);
3184 memcpy(null_term_name
, name_begin
, name_len
);
3185 null_term_name
[name_len
] = '\0';
3186 process
->name
= g_quark_from_string(null_term_name
);
3189 process
->name
= g_quark_from_string(ltt_event_get_string(e
,
3190 lttv_trace_get_hook_field(th
, 0)));
3191 process
->brand
= LTTV_STATE_UNBRANDED
;
3192 //g_free(null_term_name);
3196 static gboolean
thread_brand(void *hook_data
, void *call_data
)
3198 LttvTracefileState
*s
= (LttvTracefileState
*)call_data
;
3199 LttvTraceState
*ts
= (LttvTraceState
*)s
->parent
.t_context
;
3200 LttEvent
*e
= ltt_tracefile_get_event(s
->parent
.tf
);
3201 LttvTraceHook
*th
= (LttvTraceHook
*)hook_data
;
3204 LttvProcessState
*process
= ts
->running_process
[cpu
];
3206 name
= ltt_event_get_string(e
, lttv_trace_get_hook_field(th
, 0));
3207 process
->brand
= g_quark_from_string(name
);
3212 static void fix_process(gpointer key
, gpointer value
,
3215 LttvProcessState
*process
;
3216 LttvExecutionState
*es
;
3217 process
= (LttvProcessState
*)value
;
3218 LttTime
*timestamp
= (LttTime
*)user_data
;
3220 if(process
->type
== LTTV_STATE_KERNEL_THREAD
) {
3221 es
= &g_array_index(process
->execution_stack
, LttvExecutionState
, 0);
3222 if(es
->t
== LTTV_STATE_MODE_UNKNOWN
) {
3223 es
->t
= LTTV_STATE_SYSCALL
;
3224 es
->n
= LTTV_STATE_SUBMODE_NONE
;
3225 es
->entry
= *timestamp
;
3226 es
->change
= *timestamp
;
3227 es
->cum_cpu_time
= ltt_time_zero
;
3228 if(es
->s
== LTTV_STATE_UNNAMED
)
3229 es
->s
= LTTV_STATE_WAIT
;
3232 es
= &g_array_index(process
->execution_stack
, LttvExecutionState
, 0);
3233 if(es
->t
== LTTV_STATE_MODE_UNKNOWN
) {
3234 es
->t
= LTTV_STATE_USER_MODE
;
3235 es
->n
= LTTV_STATE_SUBMODE_NONE
;
3236 es
->entry
= *timestamp
;
3237 //g_assert(timestamp->tv_sec != 0);
3238 es
->change
= *timestamp
;
3239 es
->cum_cpu_time
= ltt_time_zero
;
3240 if(es
->s
== LTTV_STATE_UNNAMED
)
3241 es
->s
= LTTV_STATE_RUN
;
3243 if(process
->execution_stack
->len
== 1) {
3244 /* Still in bottom unknown mode, means never did a system call
3245 * May be either in user mode, syscall mode, running or waiting.*/
3246 /* FIXME : we may be tagging syscall mode when being user mode */
3247 process
->execution_stack
=
3248 g_array_set_size(process
->execution_stack
, 2);
3249 es
= process
->state
= &g_array_index(process
->execution_stack
,
3250 LttvExecutionState
, 1);
3251 es
->t
= LTTV_STATE_SYSCALL
;
3252 es
->n
= LTTV_STATE_SUBMODE_NONE
;
3253 es
->entry
= *timestamp
;
3254 //g_assert(timestamp->tv_sec != 0);
3255 es
->change
= *timestamp
;
3256 es
->cum_cpu_time
= ltt_time_zero
;
3257 if(es
->s
== LTTV_STATE_WAIT_FORK
)
3258 es
->s
= LTTV_STATE_WAIT
;
3264 static gboolean
statedump_end(void *hook_data
, void *call_data
)
3266 LttvTracefileState
*s
= (LttvTracefileState
*)call_data
;
3267 LttvTraceState
*ts
= (LttvTraceState
*)s
->parent
.t_context
;
3268 LttvTracefileContext
*tfc
= (LttvTracefileContext
*)call_data
;
3269 //LttEvent *e = ltt_tracefile_get_event(s->parent.tf);
3270 //LttvTraceHook *th = (LttvTraceHook *)hook_data;
3272 /* For all processes */
3273 /* if kernel thread, if stack[0] is unknown, set to syscall mode, wait */
3274 /* else, if stack[0] is unknown, set to user mode, running */
3276 g_hash_table_foreach(ts
->processes
, fix_process
, &tfc
->timestamp
);
3281 static gboolean
enum_process_state(void *hook_data
, void *call_data
)
3283 LttvTracefileState
*s
= (LttvTracefileState
*)call_data
;
3284 LttEvent
*e
= ltt_tracefile_get_event(s
->parent
.tf
);
3285 //It's slow : optimise later by doing this before reading trace.
3286 LttvTraceHook
*th
= (LttvTraceHook
*)hook_data
;
3292 LttvTraceState
*ts
= (LttvTraceState
*)s
->parent
.t_context
;
3293 LttvProcessState
*process
= ts
->running_process
[cpu
];
3294 LttvProcessState
*parent_process
;
3295 struct marker_field
*f
;
3296 GQuark type
, mode
, submode
, status
;
3297 LttvExecutionState
*es
;
3301 pid
= ltt_event_get_unsigned(e
, lttv_trace_get_hook_field(th
, 0));
3302 s
->parent
.target_pid
= pid
;
3305 parent_pid
= ltt_event_get_unsigned(e
, lttv_trace_get_hook_field(th
, 1));
3308 command
= ltt_event_get_string(e
, lttv_trace_get_hook_field(th
, 2));
3311 f
= lttv_trace_get_hook_field(th
, 3);
3312 type
= ltt_enum_string_get(f
, ltt_event_get_unsigned(e
, f
));
3314 //FIXME: type is rarely used, enum must match possible types.
3317 f
= lttv_trace_get_hook_field(th
, 4);
3318 mode
= ltt_enum_string_get(f
,ltt_event_get_unsigned(e
, f
));
3321 f
= lttv_trace_get_hook_field(th
, 5);
3322 submode
= ltt_enum_string_get(f
, ltt_event_get_unsigned(e
, f
));
3325 f
= lttv_trace_get_hook_field(th
, 6);
3326 status
= ltt_enum_string_get(f
, ltt_event_get_unsigned(e
, f
));
3329 f
= lttv_trace_get_hook_field(th
, 7);
3331 tgid
= ltt_event_get_unsigned(e
, f
);
3336 nb_cpus
= ltt_trace_get_num_cpu(ts
->parent
.t
);
3337 for(i
=0; i
<nb_cpus
; i
++) {
3338 process
= lttv_state_find_process(ts
, i
, pid
);
3339 g_assert(process
!= NULL
);
3341 process
->ppid
= parent_pid
;
3342 process
->tgid
= tgid
;
3343 process
->name
= g_quark_from_string(command
);
3345 &g_array_index(process
->execution_stack
, LttvExecutionState
, 0);
3346 process
->type
= LTTV_STATE_KERNEL_THREAD
;
3350 /* The process might exist if a process was forked while performing the
3352 process
= lttv_state_find_process(ts
, ANY_CPU
, pid
);
3353 if(process
== NULL
) {
3354 parent_process
= lttv_state_find_process(ts
, ANY_CPU
, parent_pid
);
3355 process
= lttv_state_create_process(ts
, parent_process
, cpu
,
3356 pid
, tgid
, g_quark_from_string(command
),
3357 &s
->parent
.timestamp
);
3359 /* Keep the stack bottom : a running user mode */
3360 /* Disabled because of inconsistencies in the current statedump states. */
3361 if(type
== LTTV_STATE_KERNEL_THREAD
) {
3362 /* Only keep the bottom
3363 * FIXME Kernel thread : can be in syscall or interrupt or trap. */
3364 /* Will cause expected trap when in fact being syscall (even after end of
3366 * Will cause expected interrupt when being syscall. (only before end of
3367 * statedump event) */
3368 // This will cause a "popping last state on stack, ignoring it."
3369 process
->execution_stack
= g_array_set_size(process
->execution_stack
, 1);
3370 es
= process
->state
= &g_array_index(process
->execution_stack
,
3371 LttvExecutionState
, 0);
3372 process
->type
= LTTV_STATE_KERNEL_THREAD
;
3373 es
->t
= LTTV_STATE_MODE_UNKNOWN
;
3374 es
->s
= LTTV_STATE_UNNAMED
;
3375 es
->n
= LTTV_STATE_SUBMODE_UNKNOWN
;
3377 es
->t
= LTTV_STATE_SYSCALL
;
3382 /* User space process :
3383 * bottom : user mode
3384 * either currently running or scheduled out.
3385 * can be scheduled out because interrupted in (user mode or in syscall)
3386 * or because of an explicit call to the scheduler in syscall. Note that
3387 * the scheduler call comes after the irq_exit, so never in interrupt
3389 // temp workaround : set size to 1 : only have user mode bottom of stack.
3390 // will cause g_info message of expected syscall mode when in fact being
3391 // in user mode. Can also cause expected trap when in fact being user
3392 // mode in the event of a page fault reenabling interrupts in the handler.
3393 // Expected syscall and trap can also happen after the end of statedump
3394 // This will cause a "popping last state on stack, ignoring it."
3395 process
->execution_stack
= g_array_set_size(process
->execution_stack
, 1);
3396 es
= process
->state
= &g_array_index(process
->execution_stack
,
3397 LttvExecutionState
, 0);
3398 es
->t
= LTTV_STATE_MODE_UNKNOWN
;
3399 es
->s
= LTTV_STATE_UNNAMED
;
3400 es
->n
= LTTV_STATE_SUBMODE_UNKNOWN
;
3402 es
->t
= LTTV_STATE_USER_MODE
;
3410 es
= process
->state
= &g_array_index(process
->execution_stack
,
3411 LttvExecutionState
, 1);
3412 es
->t
= LTTV_STATE_MODE_UNKNOWN
;
3413 es
->s
= LTTV_STATE_UNNAMED
;
3414 es
->n
= LTTV_STATE_SUBMODE_UNKNOWN
;
3418 /* The process has already been created :
3419 * Probably was forked while dumping the process state or
3420 * was simply scheduled in prior to get the state dump event.
3422 process
->ppid
= parent_pid
;
3423 process
->tgid
= tgid
;
3424 process
->name
= g_quark_from_string(command
);
3425 process
->type
= type
;
3427 &g_array_index(process
->execution_stack
, LttvExecutionState
, 0);
3429 if(es
->t
== LTTV_STATE_MODE_UNKNOWN
) {
3430 if(type
== LTTV_STATE_KERNEL_THREAD
)
3431 es
->t
= LTTV_STATE_SYSCALL
;
3433 es
->t
= LTTV_STATE_USER_MODE
;
3436 /* Don't mess around with the stack, it will eventually become
3437 * ok after the end of state dump. */
3444 gint
lttv_state_hook_add_event_hooks(void *hook_data
, void *call_data
)
3446 LttvTracesetState
*tss
= (LttvTracesetState
*)(call_data
);
3448 lttv_state_add_event_hooks(tss
);
3453 void lttv_state_add_event_hooks(LttvTracesetState
*self
)
3455 LttvTraceset
*traceset
= self
->parent
.ts
;
3457 guint i
, j
, k
, nb_trace
, nb_tracefile
;
3461 LttvTracefileState
*tfs
;
3467 LttvAttributeValue val
;
3469 nb_trace
= lttv_traceset_number(traceset
);
3470 for(i
= 0 ; i
< nb_trace
; i
++) {
3471 ts
= (LttvTraceState
*)self
->parent
.traces
[i
];
3473 /* Find the eventtype id for the following events and register the
3474 associated by id hooks. */
3476 hooks
= g_array_sized_new(FALSE
, FALSE
, sizeof(LttvTraceHook
), 20);
3477 //hooks = g_array_set_size(hooks, 19); // Max possible number of hooks.
3480 lttv_trace_find_hook(ts
->parent
.t
,
3482 LTT_EVENT_SYSCALL_ENTRY
,
3483 FIELD_ARRAY(LTT_FIELD_SYSCALL_ID
),
3484 syscall_entry
, NULL
, &hooks
);
3486 lttv_trace_find_hook(ts
->parent
.t
,
3488 LTT_EVENT_SYSCALL_EXIT
,
3490 syscall_exit
, NULL
, &hooks
);
3492 lttv_trace_find_hook(ts
->parent
.t
,
3494 LTT_EVENT_TRAP_ENTRY
,
3495 FIELD_ARRAY(LTT_FIELD_TRAP_ID
),
3496 trap_entry
, NULL
, &hooks
);
3498 lttv_trace_find_hook(ts
->parent
.t
,
3500 LTT_EVENT_TRAP_EXIT
,
3502 trap_exit
, NULL
, &hooks
);
3504 lttv_trace_find_hook(ts
->parent
.t
,
3506 LTT_EVENT_PAGE_FAULT_ENTRY
,
3507 FIELD_ARRAY(LTT_FIELD_TRAP_ID
),
3508 trap_entry
, NULL
, &hooks
);
3510 lttv_trace_find_hook(ts
->parent
.t
,
3512 LTT_EVENT_PAGE_FAULT_EXIT
,
3514 trap_exit
, NULL
, &hooks
);
3516 lttv_trace_find_hook(ts
->parent
.t
,
3518 LTT_EVENT_PAGE_FAULT_NOSEM_ENTRY
,
3519 FIELD_ARRAY(LTT_FIELD_TRAP_ID
),
3520 trap_entry
, NULL
, &hooks
);
3522 lttv_trace_find_hook(ts
->parent
.t
,
3524 LTT_EVENT_PAGE_FAULT_NOSEM_EXIT
,
3526 trap_exit
, NULL
, &hooks
);
3528 lttv_trace_find_hook(ts
->parent
.t
,
3530 LTT_EVENT_IRQ_ENTRY
,
3531 FIELD_ARRAY(LTT_FIELD_IRQ_ID
),
3532 irq_entry
, NULL
, &hooks
);
3534 lttv_trace_find_hook(ts
->parent
.t
,
3538 irq_exit
, NULL
, &hooks
);
3540 lttv_trace_find_hook(ts
->parent
.t
,
3542 LTT_EVENT_SOFT_IRQ_RAISE
,
3543 FIELD_ARRAY(LTT_FIELD_SOFT_IRQ_ID
),
3544 soft_irq_raise
, NULL
, &hooks
);
3546 lttv_trace_find_hook(ts
->parent
.t
,
3548 LTT_EVENT_SOFT_IRQ_ENTRY
,
3549 FIELD_ARRAY(LTT_FIELD_SOFT_IRQ_ID
),
3550 soft_irq_entry
, NULL
, &hooks
);
3552 lttv_trace_find_hook(ts
->parent
.t
,
3554 LTT_EVENT_SOFT_IRQ_EXIT
,
3556 soft_irq_exit
, NULL
, &hooks
);
3558 lttv_trace_find_hook(ts
->parent
.t
,
3560 LTT_EVENT_SCHED_SCHEDULE
,
3561 FIELD_ARRAY(LTT_FIELD_PREV_PID
, LTT_FIELD_NEXT_PID
,
3562 LTT_FIELD_PREV_STATE
),
3563 schedchange
, NULL
, &hooks
);
3565 lttv_trace_find_hook(ts
->parent
.t
,
3567 LTT_EVENT_PROCESS_FORK
,
3568 FIELD_ARRAY(LTT_FIELD_PARENT_PID
, LTT_FIELD_CHILD_PID
,
3569 LTT_FIELD_CHILD_TGID
),
3570 process_fork
, NULL
, &hooks
);
3572 lttv_trace_find_hook(ts
->parent
.t
,
3574 LTT_EVENT_KTHREAD_CREATE
,
3575 FIELD_ARRAY(LTT_FIELD_PID
),
3576 process_kernel_thread
, NULL
, &hooks
);
3578 lttv_trace_find_hook(ts
->parent
.t
,
3580 LTT_EVENT_PROCESS_EXIT
,
3581 FIELD_ARRAY(LTT_FIELD_PID
),
3582 process_exit
, NULL
, &hooks
);
3584 lttv_trace_find_hook(ts
->parent
.t
,
3586 LTT_EVENT_PROCESS_FREE
,
3587 FIELD_ARRAY(LTT_FIELD_PID
),
3588 process_free
, NULL
, &hooks
);
3590 lttv_trace_find_hook(ts
->parent
.t
,
3593 FIELD_ARRAY(LTT_FIELD_FILENAME
),
3594 process_exec
, NULL
, &hooks
);
3596 lttv_trace_find_hook(ts
->parent
.t
,
3597 LTT_CHANNEL_USERSPACE
,
3598 LTT_EVENT_THREAD_BRAND
,
3599 FIELD_ARRAY(LTT_FIELD_NAME
),
3600 thread_brand
, NULL
, &hooks
);
3602 /* statedump-related hooks */
3603 lttv_trace_find_hook(ts
->parent
.t
,
3604 LTT_CHANNEL_TASK_STATE
,
3605 LTT_EVENT_PROCESS_STATE
,
3606 FIELD_ARRAY(LTT_FIELD_PID
, LTT_FIELD_PARENT_PID
, LTT_FIELD_NAME
,
3607 LTT_FIELD_TYPE
, LTT_FIELD_MODE
, LTT_FIELD_SUBMODE
,
3608 LTT_FIELD_STATUS
, LTT_FIELD_TGID
),
3609 enum_process_state
, NULL
, &hooks
);
3611 lttv_trace_find_hook(ts
->parent
.t
,
3612 LTT_CHANNEL_GLOBAL_STATE
,
3613 LTT_EVENT_STATEDUMP_END
,
3615 statedump_end
, NULL
, &hooks
);
3617 lttv_trace_find_hook(ts
->parent
.t
,
3618 LTT_CHANNEL_IRQ_STATE
,
3619 LTT_EVENT_LIST_INTERRUPT
,
3620 FIELD_ARRAY(LTT_FIELD_ACTION
, LTT_FIELD_IRQ_ID
),
3621 enum_interrupt
, NULL
, &hooks
);
3623 lttv_trace_find_hook(ts
->parent
.t
,
3625 LTT_EVENT_REQUEST_ISSUE
,
3626 FIELD_ARRAY(LTT_FIELD_MAJOR
, LTT_FIELD_MINOR
, LTT_FIELD_OPERATION
),
3627 bdev_request_issue
, NULL
, &hooks
);
3629 lttv_trace_find_hook(ts
->parent
.t
,
3631 LTT_EVENT_REQUEST_COMPLETE
,
3632 FIELD_ARRAY(LTT_FIELD_MAJOR
, LTT_FIELD_MINOR
, LTT_FIELD_OPERATION
),
3633 bdev_request_complete
, NULL
, &hooks
);
3635 lttv_trace_find_hook(ts
->parent
.t
,
3636 LTT_CHANNEL_USERSPACE
,
3637 LTT_EVENT_FUNCTION_ENTRY
,
3638 FIELD_ARRAY(LTT_FIELD_THIS_FN
, LTT_FIELD_CALL_SITE
),
3639 function_entry
, NULL
, &hooks
);
3641 lttv_trace_find_hook(ts
->parent
.t
,
3642 LTT_CHANNEL_USERSPACE
,
3643 LTT_EVENT_FUNCTION_EXIT
,
3644 FIELD_ARRAY(LTT_FIELD_THIS_FN
, LTT_FIELD_CALL_SITE
),
3645 function_exit
, NULL
, &hooks
);
3647 lttv_trace_find_hook(ts
->parent
.t
,
3648 LTT_CHANNEL_SYSCALL_STATE
,
3649 LTT_EVENT_SYS_CALL_TABLE
,
3650 FIELD_ARRAY(LTT_FIELD_ID
, LTT_FIELD_ADDRESS
, LTT_FIELD_SYMBOL
),
3651 dump_syscall
, NULL
, &hooks
);
3653 lttv_trace_find_hook(ts
->parent
.t
,
3654 LTT_CHANNEL_KPROBE_STATE
,
3655 LTT_EVENT_KPROBE_TABLE
,
3656 FIELD_ARRAY(LTT_FIELD_IP
, LTT_FIELD_SYMBOL
),
3657 dump_kprobe
, NULL
, &hooks
);
3659 lttv_trace_find_hook(ts
->parent
.t
,
3660 LTT_CHANNEL_SOFTIRQ_STATE
,
3661 LTT_EVENT_SOFTIRQ_VEC
,
3662 FIELD_ARRAY(LTT_FIELD_ID
, LTT_FIELD_ADDRESS
, LTT_FIELD_SYMBOL
),
3663 dump_softirq
, NULL
, &hooks
);
3665 /* Add these hooks to each event_by_id hooks list */
3667 nb_tracefile
= ts
->parent
.tracefiles
->len
;
3669 for(j
= 0 ; j
< nb_tracefile
; j
++) {
3671 LTTV_TRACEFILE_STATE(g_array_index(ts
->parent
.tracefiles
,
3672 LttvTracefileContext
*, j
));
3674 for(k
= 0 ; k
< hooks
->len
; k
++) {
3675 th
= &g_array_index(hooks
, LttvTraceHook
, k
);
3676 if (th
->mdata
== tfs
->parent
.tf
->mdata
)
3678 lttv_hooks_by_id_find(tfs
->parent
.event_by_id
, th
->id
),
3684 lttv_attribute_find(ts
->parent
.a
, LTTV_STATE_HOOKS
, LTTV_POINTER
, &val
);
3685 *(val
.v_pointer
) = hooks
;
3689 gint
lttv_state_hook_remove_event_hooks(void *hook_data
, void *call_data
)
3691 LttvTracesetState
*tss
= (LttvTracesetState
*)(call_data
);
3693 lttv_state_remove_event_hooks(tss
);
3698 void lttv_state_remove_event_hooks(LttvTracesetState
*self
)
3700 LttvTraceset
*traceset
= self
->parent
.ts
;
3702 guint i
, j
, k
, nb_trace
, nb_tracefile
;
3706 LttvTracefileState
*tfs
;
3712 LttvAttributeValue val
;
3714 nb_trace
= lttv_traceset_number(traceset
);
3715 for(i
= 0 ; i
< nb_trace
; i
++) {
3716 ts
= LTTV_TRACE_STATE(self
->parent
.traces
[i
]);
3718 lttv_attribute_find(ts
->parent
.a
, LTTV_STATE_HOOKS
, LTTV_POINTER
, &val
);
3719 hooks
= *(val
.v_pointer
);
3721 /* Remove these hooks from each event_by_id hooks list */
3723 nb_tracefile
= ts
->parent
.tracefiles
->len
;
3725 for(j
= 0 ; j
< nb_tracefile
; j
++) {
3727 LTTV_TRACEFILE_STATE(g_array_index(ts
->parent
.tracefiles
,
3728 LttvTracefileContext
*, j
));
3730 for(k
= 0 ; k
< hooks
->len
; k
++) {
3731 th
= &g_array_index(hooks
, LttvTraceHook
, k
);
3732 if (th
->mdata
== tfs
->parent
.tf
->mdata
)
3733 lttv_hooks_remove_data(
3734 lttv_hooks_by_id_find(tfs
->parent
.event_by_id
, th
->id
),
3739 lttv_trace_hook_remove_all(&hooks
);
3740 g_array_free(hooks
, TRUE
);
3744 static gboolean
state_save_event_hook(void *hook_data
, void *call_data
)
3746 guint
*event_count
= (guint
*)hook_data
;
3748 /* Only save at LTTV_STATE_SAVE_INTERVAL */
3749 if(likely((*event_count
)++ < LTTV_STATE_SAVE_INTERVAL
))
3754 LttvTracefileState
*self
= (LttvTracefileState
*)call_data
;
3756 LttvTraceState
*tcs
= (LttvTraceState
*)(self
->parent
.t_context
);
3758 LttvAttribute
*saved_states_tree
, *saved_state_tree
;
3760 LttvAttributeValue value
;
3762 saved_states_tree
= lttv_attribute_find_subdir(tcs
->parent
.t_a
,
3763 LTTV_STATE_SAVED_STATES
);
3764 saved_state_tree
= g_object_new(LTTV_ATTRIBUTE_TYPE
, NULL
);
3765 value
= lttv_attribute_add(saved_states_tree
,
3766 lttv_attribute_get_number(saved_states_tree
), LTTV_GOBJECT
);
3767 *(value
.v_gobject
) = (GObject
*)saved_state_tree
;
3768 value
= lttv_attribute_add(saved_state_tree
, LTTV_STATE_TIME
, LTTV_TIME
);
3769 *(value
.v_time
) = self
->parent
.timestamp
;
3770 lttv_state_save(tcs
, saved_state_tree
);
3771 g_debug("Saving state at time %lu.%lu", self
->parent
.timestamp
.tv_sec
,
3772 self
->parent
.timestamp
.tv_nsec
);
3774 *(tcs
->max_time_state_recomputed_in_seek
) = self
->parent
.timestamp
;
3779 static gboolean
state_save_after_trace_hook(void *hook_data
, void *call_data
)
3781 LttvTraceState
*tcs
= (LttvTraceState
*)(call_data
);
3783 *(tcs
->max_time_state_recomputed_in_seek
) = tcs
->parent
.time_span
.end_time
;
3788 guint
lttv_state_current_cpu(LttvTracefileState
*tfs
)
3796 static gboolean
block_start(void *hook_data
, void *call_data
)
3798 LttvTracefileState
*self
= (LttvTracefileState
*)call_data
;
3800 LttvTracefileState
*tfcs
;
3802 LttvTraceState
*tcs
= (LttvTraceState
*)(self
->parent
.t_context
);
3804 LttEventPosition
*ep
;
3806 guint i
, nb_block
, nb_event
, nb_tracefile
;
3810 LttvAttribute
*saved_states_tree
, *saved_state_tree
;
3812 LttvAttributeValue value
;
3814 ep
= ltt_event_position_new();
3816 nb_tracefile
= tcs
->parent
.tracefiles
->len
;
3818 /* Count the number of events added since the last block end in any
3821 for(i
= 0 ; i
< nb_tracefile
; i
++) {
3823 LTTV_TRACEFILE_STATE(&g_array_index(tcs
->parent
.tracefiles
,
3824 LttvTracefileContext
, i
));
3825 ltt_event_position(tfcs
->parent
.e
, ep
);
3826 ltt_event_position_get(ep
, &nb_block
, &nb_event
, &tf
);
3827 tcs
->nb_event
+= nb_event
- tfcs
->saved_position
;
3828 tfcs
->saved_position
= nb_event
;
3832 if(tcs
->nb_event
>= tcs
->save_interval
) {
3833 saved_states_tree
= lttv_attribute_find_subdir(tcs
->parent
.t_a
,
3834 LTTV_STATE_SAVED_STATES
);
3835 saved_state_tree
= g_object_new(LTTV_ATTRIBUTE_TYPE
, NULL
);
3836 value
= lttv_attribute_add(saved_states_tree
,
3837 lttv_attribute_get_number(saved_states_tree
), LTTV_GOBJECT
);
3838 *(value
.v_gobject
) = (GObject
*)saved_state_tree
;
3839 value
= lttv_attribute_add(saved_state_tree
, LTTV_STATE_TIME
, LTTV_TIME
);
3840 *(value
.v_time
) = self
->parent
.timestamp
;
3841 lttv_state_save(tcs
, saved_state_tree
);
3843 g_debug("Saving state at time %lu.%lu", self
->parent
.timestamp
.tv_sec
,
3844 self
->parent
.timestamp
.tv_nsec
);
3846 *(tcs
->max_time_state_recomputed_in_seek
) = self
->parent
.timestamp
;
3852 static gboolean
block_end(void *hook_data
, void *call_data
)
3854 LttvTracefileState
*self
= (LttvTracefileState
*)call_data
;
3856 LttvTraceState
*tcs
= (LttvTraceState
*)(self
->parent
.t_context
);
3860 LttEventPosition
*ep
;
3862 guint nb_block
, nb_event
;
3864 ep
= ltt_event_position_new();
3865 ltt_event_position(self
->parent
.e
, ep
);
3866 ltt_event_position_get(ep
, &nb_block
, &nb_event
, &tf
);
3867 tcs
->nb_event
+= nb_event
- self
->saved_position
+ 1;
3868 self
->saved_position
= 0;
3869 *(tcs
->max_time_state_recomputed_in_seek
) = self
->parent
.timestamp
;
3876 void lttv_state_save_add_event_hooks(LttvTracesetState
*self
)
3878 LttvTraceset
*traceset
= self
->parent
.ts
;
3880 guint i
, j
, nb_trace
, nb_tracefile
;
3884 LttvTracefileState
*tfs
;
3886 LttvTraceHook hook_start
, hook_end
;
3888 nb_trace
= lttv_traceset_number(traceset
);
3889 for(i
= 0 ; i
< nb_trace
; i
++) {
3890 ts
= (LttvTraceState
*)self
->parent
.traces
[i
];
3892 lttv_trace_find_hook(ts
->parent
.t
, "core","block_start",NULL
,
3893 NULL
, NULL
, block_start
, &hook_start
);
3894 lttv_trace_find_hook(ts
->parent
.t
, "core","block_end",NULL
,
3895 NULL
, NULL
, block_end
, &hook_end
);
3897 nb_tracefile
= ts
->parent
.tracefiles
->len
;
3899 for(j
= 0 ; j
< nb_tracefile
; j
++) {
3901 LTTV_TRACEFILE_STATE(&g_array_index(ts
->parent
.tracefiles
,
3902 LttvTracefileContext
, j
));
3903 lttv_hooks_add(lttv_hooks_by_id_find(tfs
->parent
.event_by_id
,
3904 hook_start
.id
), hook_start
.h
, NULL
, LTTV_PRIO_STATE
);
3905 lttv_hooks_add(lttv_hooks_by_id_find(tfs
->parent
.event_by_id
,
3906 hook_end
.id
), hook_end
.h
, NULL
, LTTV_PRIO_STATE
);
3912 void lttv_state_save_add_event_hooks(LttvTracesetState
*self
)
3914 LttvTraceset
*traceset
= self
->parent
.ts
;
3916 guint i
, j
, nb_trace
, nb_tracefile
;
3920 LttvTracefileState
*tfs
;
3923 nb_trace
= lttv_traceset_number(traceset
);
3924 for(i
= 0 ; i
< nb_trace
; i
++) {
3926 ts
= (LttvTraceState
*)self
->parent
.traces
[i
];
3927 nb_tracefile
= ts
->parent
.tracefiles
->len
;
3929 if(ts
->has_precomputed_states
) continue;
3931 guint
*event_count
= g_new(guint
, 1);
3934 for(j
= 0 ; j
< nb_tracefile
; j
++) {
3936 LTTV_TRACEFILE_STATE(g_array_index(ts
->parent
.tracefiles
,
3937 LttvTracefileContext
*, j
));
3938 lttv_hooks_add(tfs
->parent
.event
,
3939 state_save_event_hook
,
3946 lttv_process_traceset_begin(&self
->parent
,
3947 NULL
, NULL
, NULL
, NULL
, NULL
);
3951 gint
lttv_state_save_hook_add_event_hooks(void *hook_data
, void *call_data
)
3953 LttvTracesetState
*tss
= (LttvTracesetState
*)(call_data
);
3955 lttv_state_save_add_event_hooks(tss
);
3962 void lttv_state_save_remove_event_hooks(LttvTracesetState
*self
)
3964 LttvTraceset
*traceset
= self
->parent
.ts
;
3966 guint i
, j
, nb_trace
, nb_tracefile
;
3970 LttvTracefileState
*tfs
;
3972 LttvTraceHook hook_start
, hook_end
;
3974 nb_trace
= lttv_traceset_number(traceset
);
3975 for(i
= 0 ; i
< nb_trace
; i
++) {
3976 ts
= LTTV_TRACE_STATE(self
->parent
.traces
[i
]);
3978 lttv_trace_find_hook(ts
->parent
.t
, "core","block_start",NULL
,
3979 NULL
, NULL
, block_start
, &hook_start
);
3981 lttv_trace_find_hook(ts
->parent
.t
, "core","block_end",NULL
,
3982 NULL
, NULL
, block_end
, &hook_end
);
3984 nb_tracefile
= ts
->parent
.tracefiles
->len
;
3986 for(j
= 0 ; j
< nb_tracefile
; j
++) {
3988 LTTV_TRACEFILE_STATE(&g_array_index(ts
->parent
.tracefiles
,
3989 LttvTracefileContext
, j
));
3990 lttv_hooks_remove_data(lttv_hooks_by_id_find(
3991 tfs
->parent
.event_by_id
, hook_start
.id
), hook_start
.h
, NULL
);
3992 lttv_hooks_remove_data(lttv_hooks_by_id_find(
3993 tfs
->parent
.event_by_id
, hook_end
.id
), hook_end
.h
, NULL
);
3999 void lttv_state_save_remove_event_hooks(LttvTracesetState
*self
)
4001 LttvTraceset
*traceset
= self
->parent
.ts
;
4003 guint i
, j
, nb_trace
, nb_tracefile
;
4007 LttvTracefileState
*tfs
;
4009 LttvHooks
*after_trace
= lttv_hooks_new();
4011 lttv_hooks_add(after_trace
,
4012 state_save_after_trace_hook
,
4017 lttv_process_traceset_end(&self
->parent
,
4018 NULL
, after_trace
, NULL
, NULL
, NULL
);
4020 lttv_hooks_destroy(after_trace
);
4022 nb_trace
= lttv_traceset_number(traceset
);
4023 for(i
= 0 ; i
< nb_trace
; i
++) {
4025 ts
= (LttvTraceState
*)self
->parent
.traces
[i
];
4026 nb_tracefile
= ts
->parent
.tracefiles
->len
;
4028 if(ts
->has_precomputed_states
) continue;
4030 guint
*event_count
= NULL
;
4032 for(j
= 0 ; j
< nb_tracefile
; j
++) {
4034 LTTV_TRACEFILE_STATE(g_array_index(ts
->parent
.tracefiles
,
4035 LttvTracefileContext
*, j
));
4036 event_count
= lttv_hooks_remove(tfs
->parent
.event
,
4037 state_save_event_hook
);
4039 if(event_count
) g_free(event_count
);
4043 gint
lttv_state_save_hook_remove_event_hooks(void *hook_data
, void *call_data
)
4045 LttvTracesetState
*tss
= (LttvTracesetState
*)(call_data
);
4047 lttv_state_save_remove_event_hooks(tss
);
4052 void lttv_state_traceset_seek_time_closest(LttvTracesetState
*self
, LttTime t
)
4054 LttvTraceset
*traceset
= self
->parent
.ts
;
4058 int min_pos
, mid_pos
, max_pos
;
4060 guint call_rest
= 0;
4062 LttvTraceState
*tcs
;
4064 LttvAttributeValue value
;
4066 LttvAttributeType type
;
4068 LttvAttributeName name
;
4072 LttvAttribute
*saved_states_tree
, *saved_state_tree
, *closest_tree
= NULL
;
4074 //g_tree_destroy(self->parent.pqueue);
4075 //self->parent.pqueue = g_tree_new(compare_tracefile);
4077 g_info("Entering seek_time_closest for time %lu.%lu", t
.tv_sec
, t
.tv_nsec
);
4079 nb_trace
= lttv_traceset_number(traceset
);
4080 for(i
= 0 ; i
< nb_trace
; i
++) {
4081 tcs
= (LttvTraceState
*)self
->parent
.traces
[i
];
4083 if(ltt_time_compare(t
, *(tcs
->max_time_state_recomputed_in_seek
)) < 0) {
4084 saved_states_tree
= lttv_attribute_find_subdir(tcs
->parent
.t_a
,
4085 LTTV_STATE_SAVED_STATES
);
4088 if(saved_states_tree
) {
4089 max_pos
= lttv_attribute_get_number(saved_states_tree
) - 1;
4090 mid_pos
= max_pos
/ 2;
4091 while(min_pos
< max_pos
) {
4092 type
= lttv_attribute_get(saved_states_tree
, mid_pos
, &name
, &value
,
4094 g_assert(type
== LTTV_GOBJECT
);
4095 saved_state_tree
= *((LttvAttribute
**)(value
.v_gobject
));
4096 type
= lttv_attribute_get_by_name(saved_state_tree
, LTTV_STATE_TIME
,
4098 g_assert(type
== LTTV_TIME
);
4099 if(ltt_time_compare(*(value
.v_time
), t
) < 0) {
4101 closest_tree
= saved_state_tree
;
4103 else max_pos
= mid_pos
- 1;
4105 mid_pos
= (min_pos
+ max_pos
+ 1) / 2;
4109 /* restore the closest earlier saved state */
4111 lttv_state_restore(tcs
, closest_tree
);
4115 /* There is no saved state, yet we want to have it. Restart at T0 */
4117 restore_init_state(tcs
);
4118 lttv_process_trace_seek_time(&(tcs
->parent
), ltt_time_zero
);
4121 /* We want to seek quickly without restoring/updating the state */
4123 restore_init_state(tcs
);
4124 lttv_process_trace_seek_time(&(tcs
->parent
), t
);
4127 if(!call_rest
) g_info("NOT Calling restore");
4132 traceset_state_instance_init (GTypeInstance
*instance
, gpointer g_class
)
4138 traceset_state_finalize (LttvTracesetState
*self
)
4140 G_OBJECT_CLASS(g_type_class_peek(LTTV_TRACESET_CONTEXT_TYPE
))->
4141 finalize(G_OBJECT(self
));
4146 traceset_state_class_init (LttvTracesetContextClass
*klass
)
4148 GObjectClass
*gobject_class
= G_OBJECT_CLASS(klass
);
4150 gobject_class
->finalize
= (void (*)(GObject
*self
)) traceset_state_finalize
;
4151 klass
->init
= (void (*)(LttvTracesetContext
*self
, LttvTraceset
*ts
))init
;
4152 klass
->fini
= (void (*)(LttvTracesetContext
*self
))fini
;
4153 klass
->new_traceset_context
= new_traceset_context
;
4154 klass
->new_trace_context
= new_trace_context
;
4155 klass
->new_tracefile_context
= new_tracefile_context
;
4160 lttv_traceset_state_get_type(void)
4162 static GType type
= 0;
4164 static const GTypeInfo info
= {
4165 sizeof (LttvTracesetStateClass
),
4166 NULL
, /* base_init */
4167 NULL
, /* base_finalize */
4168 (GClassInitFunc
) traceset_state_class_init
, /* class_init */
4169 NULL
, /* class_finalize */
4170 NULL
, /* class_data */
4171 sizeof (LttvTracesetState
),
4172 0, /* n_preallocs */
4173 (GInstanceInitFunc
) traceset_state_instance_init
, /* instance_init */
4174 NULL
/* value handling */
4177 type
= g_type_register_static (LTTV_TRACESET_CONTEXT_TYPE
, "LttvTracesetStateType",
4185 trace_state_instance_init (GTypeInstance
*instance
, gpointer g_class
)
4191 trace_state_finalize (LttvTraceState
*self
)
4193 G_OBJECT_CLASS(g_type_class_peek(LTTV_TRACE_CONTEXT_TYPE
))->
4194 finalize(G_OBJECT(self
));
4199 trace_state_class_init (LttvTraceStateClass
*klass
)
4201 GObjectClass
*gobject_class
= G_OBJECT_CLASS(klass
);
4203 gobject_class
->finalize
= (void (*)(GObject
*self
)) trace_state_finalize
;
4204 klass
->state_save
= state_save
;
4205 klass
->state_restore
= state_restore
;
4206 klass
->state_saved_free
= state_saved_free
;
4211 lttv_trace_state_get_type(void)
4213 static GType type
= 0;
4215 static const GTypeInfo info
= {
4216 sizeof (LttvTraceStateClass
),
4217 NULL
, /* base_init */
4218 NULL
, /* base_finalize */
4219 (GClassInitFunc
) trace_state_class_init
, /* class_init */
4220 NULL
, /* class_finalize */
4221 NULL
, /* class_data */
4222 sizeof (LttvTraceState
),
4223 0, /* n_preallocs */
4224 (GInstanceInitFunc
) trace_state_instance_init
, /* instance_init */
4225 NULL
/* value handling */
4228 type
= g_type_register_static (LTTV_TRACE_CONTEXT_TYPE
,
4229 "LttvTraceStateType", &info
, 0);
4236 tracefile_state_instance_init (GTypeInstance
*instance
, gpointer g_class
)
4242 tracefile_state_finalize (LttvTracefileState
*self
)
4244 G_OBJECT_CLASS(g_type_class_peek(LTTV_TRACEFILE_CONTEXT_TYPE
))->
4245 finalize(G_OBJECT(self
));
4250 tracefile_state_class_init (LttvTracefileStateClass
*klass
)
4252 GObjectClass
*gobject_class
= G_OBJECT_CLASS(klass
);
4254 gobject_class
->finalize
= (void (*)(GObject
*self
)) tracefile_state_finalize
;
4259 lttv_tracefile_state_get_type(void)
4261 static GType type
= 0;
4263 static const GTypeInfo info
= {
4264 sizeof (LttvTracefileStateClass
),
4265 NULL
, /* base_init */
4266 NULL
, /* base_finalize */
4267 (GClassInitFunc
) tracefile_state_class_init
, /* class_init */
4268 NULL
, /* class_finalize */
4269 NULL
, /* class_data */
4270 sizeof (LttvTracefileState
),
4271 0, /* n_preallocs */
4272 (GInstanceInitFunc
) tracefile_state_instance_init
, /* instance_init */
4273 NULL
/* value handling */
4276 type
= g_type_register_static (LTTV_TRACEFILE_CONTEXT_TYPE
,
4277 "LttvTracefileStateType", &info
, 0);
4283 static void module_init()
4285 LTTV_STATE_UNNAMED
= g_quark_from_string("");
4286 LTTV_STATE_UNBRANDED
= g_quark_from_string("");
4287 LTTV_STATE_MODE_UNKNOWN
= g_quark_from_string("MODE_UNKNOWN");
4288 LTTV_STATE_USER_MODE
= g_quark_from_string("USER_MODE");
4289 LTTV_STATE_SYSCALL
= g_quark_from_string("SYSCALL");
4290 LTTV_STATE_TRAP
= g_quark_from_string("TRAP");
4291 LTTV_STATE_IRQ
= g_quark_from_string("IRQ");
4292 LTTV_STATE_SOFT_IRQ
= g_quark_from_string("SOFTIRQ");
4293 LTTV_STATE_SUBMODE_UNKNOWN
= g_quark_from_string("UNKNOWN");
4294 LTTV_STATE_SUBMODE_NONE
= g_quark_from_string("NONE");
4295 LTTV_STATE_WAIT_FORK
= g_quark_from_string("WAIT_FORK");
4296 LTTV_STATE_WAIT_CPU
= g_quark_from_string("WAIT_CPU");
4297 LTTV_STATE_EXIT
= g_quark_from_string("EXIT");
4298 LTTV_STATE_ZOMBIE
= g_quark_from_string("ZOMBIE");
4299 LTTV_STATE_WAIT
= g_quark_from_string("WAIT");
4300 LTTV_STATE_RUN
= g_quark_from_string("RUN");
4301 LTTV_STATE_DEAD
= g_quark_from_string("DEAD");
4302 LTTV_STATE_USER_THREAD
= g_quark_from_string("USER_THREAD");
4303 LTTV_STATE_KERNEL_THREAD
= g_quark_from_string("KERNEL_THREAD");
4304 LTTV_STATE_TRACEFILES
= g_quark_from_string("tracefiles");
4305 LTTV_STATE_PROCESSES
= g_quark_from_string("processes");
4306 LTTV_STATE_PROCESS
= g_quark_from_string("process");
4307 LTTV_STATE_RUNNING_PROCESS
= g_quark_from_string("running_process");
4308 LTTV_STATE_EVENT
= g_quark_from_string("event");
4309 LTTV_STATE_SAVED_STATES
= g_quark_from_string("saved states");
4310 LTTV_STATE_SAVED_STATES_TIME
= g_quark_from_string("saved states time");
4311 LTTV_STATE_TIME
= g_quark_from_string("time");
4312 LTTV_STATE_HOOKS
= g_quark_from_string("saved state hooks");
4313 LTTV_STATE_NAME_TABLES
= g_quark_from_string("name tables");
4314 LTTV_STATE_TRACE_STATE_USE_COUNT
=
4315 g_quark_from_string("trace_state_use_count");
4316 LTTV_STATE_RESOURCE_CPUS
= g_quark_from_string("cpu resource states");
4317 LTTV_STATE_RESOURCE_CPUS
= g_quark_from_string("cpu count");
4318 LTTV_STATE_RESOURCE_IRQS
= g_quark_from_string("irq resource states");
4319 LTTV_STATE_RESOURCE_SOFT_IRQS
= g_quark_from_string("soft irq resource states");
4320 LTTV_STATE_RESOURCE_TRAPS
= g_quark_from_string("trap resource states");
4321 LTTV_STATE_RESOURCE_BLKDEVS
= g_quark_from_string("blkdevs resource states");
4323 LTT_CHANNEL_FD_STATE
= g_quark_from_string("fd_state");
4324 LTT_CHANNEL_GLOBAL_STATE
= g_quark_from_string("global_state");
4325 LTT_CHANNEL_IRQ_STATE
= g_quark_from_string("irq_state");
4326 LTT_CHANNEL_MODULE_STATE
= g_quark_from_string("module_state");
4327 LTT_CHANNEL_NETIF_STATE
= g_quark_from_string("netif_state");
4328 LTT_CHANNEL_SOFTIRQ_STATE
= g_quark_from_string("softirq_state");
4329 LTT_CHANNEL_SWAP_STATE
= g_quark_from_string("swap_state");
4330 LTT_CHANNEL_SYSCALL_STATE
= g_quark_from_string("syscall_state");
4331 LTT_CHANNEL_TASK_STATE
= g_quark_from_string("task_state");
4332 LTT_CHANNEL_VM_STATE
= g_quark_from_string("vm_state");
4333 LTT_CHANNEL_KPROBE_STATE
= g_quark_from_string("kprobe_state");
4334 LTT_CHANNEL_FS
= g_quark_from_string("fs");
4335 LTT_CHANNEL_KERNEL
= g_quark_from_string("kernel");
4336 LTT_CHANNEL_MM
= g_quark_from_string("mm");
4337 LTT_CHANNEL_USERSPACE
= g_quark_from_string("userspace");
4338 LTT_CHANNEL_BLOCK
= g_quark_from_string("block");
4340 LTT_EVENT_SYSCALL_ENTRY
= g_quark_from_string("syscall_entry");
4341 LTT_EVENT_SYSCALL_EXIT
= g_quark_from_string("syscall_exit");
4342 LTT_EVENT_TRAP_ENTRY
= g_quark_from_string("trap_entry");
4343 LTT_EVENT_TRAP_EXIT
= g_quark_from_string("trap_exit");
4344 LTT_EVENT_PAGE_FAULT_ENTRY
= g_quark_from_string("page_fault_entry");
4345 LTT_EVENT_PAGE_FAULT_EXIT
= g_quark_from_string("page_fault_exit");
4346 LTT_EVENT_PAGE_FAULT_NOSEM_ENTRY
= g_quark_from_string("page_fault_nosem_entry");
4347 LTT_EVENT_PAGE_FAULT_NOSEM_EXIT
= g_quark_from_string("page_fault_nosem_exit");
4348 LTT_EVENT_IRQ_ENTRY
= g_quark_from_string("irq_entry");
4349 LTT_EVENT_IRQ_EXIT
= g_quark_from_string("irq_exit");
4350 LTT_EVENT_SOFT_IRQ_RAISE
= g_quark_from_string("softirq_raise");
4351 LTT_EVENT_SOFT_IRQ_ENTRY
= g_quark_from_string("softirq_entry");
4352 LTT_EVENT_SOFT_IRQ_EXIT
= g_quark_from_string("softirq_exit");
4353 LTT_EVENT_SCHED_SCHEDULE
= g_quark_from_string("sched_schedule");
4354 LTT_EVENT_PROCESS_FORK
= g_quark_from_string("process_fork");
4355 LTT_EVENT_KTHREAD_CREATE
= g_quark_from_string("kthread_create");
4356 LTT_EVENT_PROCESS_EXIT
= g_quark_from_string("process_exit");
4357 LTT_EVENT_PROCESS_FREE
= g_quark_from_string("process_free");
4358 LTT_EVENT_EXEC
= g_quark_from_string("exec");
4359 LTT_EVENT_PROCESS_STATE
= g_quark_from_string("process_state");
4360 LTT_EVENT_STATEDUMP_END
= g_quark_from_string("statedump_end");
4361 LTT_EVENT_FUNCTION_ENTRY
= g_quark_from_string("function_entry");
4362 LTT_EVENT_FUNCTION_EXIT
= g_quark_from_string("function_exit");
4363 LTT_EVENT_THREAD_BRAND
= g_quark_from_string("thread_brand");
4364 LTT_EVENT_REQUEST_ISSUE
= g_quark_from_string("_blk_request_issue");
4365 LTT_EVENT_REQUEST_COMPLETE
= g_quark_from_string("_blk_request_complete");
4366 LTT_EVENT_LIST_INTERRUPT
= g_quark_from_string("interrupt");
4367 LTT_EVENT_SYS_CALL_TABLE
= g_quark_from_string("sys_call_table");
4368 LTT_EVENT_SOFTIRQ_VEC
= g_quark_from_string("softirq_vec");
4369 LTT_EVENT_KPROBE_TABLE
= g_quark_from_string("kprobe_table");
4370 LTT_EVENT_KPROBE
= g_quark_from_string("kprobe");
4372 LTT_FIELD_SYSCALL_ID
= g_quark_from_string("syscall_id");
4373 LTT_FIELD_TRAP_ID
= g_quark_from_string("trap_id");
4374 LTT_FIELD_IRQ_ID
= g_quark_from_string("irq_id");
4375 LTT_FIELD_SOFT_IRQ_ID
= g_quark_from_string("softirq_id");
4376 LTT_FIELD_PREV_PID
= g_quark_from_string("prev_pid");
4377 LTT_FIELD_NEXT_PID
= g_quark_from_string("next_pid");
4378 LTT_FIELD_PREV_STATE
= g_quark_from_string("prev_state");
4379 LTT_FIELD_PARENT_PID
= g_quark_from_string("parent_pid");
4380 LTT_FIELD_CHILD_PID
= g_quark_from_string("child_pid");
4381 LTT_FIELD_PID
= g_quark_from_string("pid");
4382 LTT_FIELD_TGID
= g_quark_from_string("tgid");
4383 LTT_FIELD_CHILD_TGID
= g_quark_from_string("child_tgid");
4384 LTT_FIELD_FILENAME
= g_quark_from_string("filename");
4385 LTT_FIELD_NAME
= g_quark_from_string("name");
4386 LTT_FIELD_TYPE
= g_quark_from_string("type");
4387 LTT_FIELD_MODE
= g_quark_from_string("mode");
4388 LTT_FIELD_SUBMODE
= g_quark_from_string("submode");
4389 LTT_FIELD_STATUS
= g_quark_from_string("status");
4390 LTT_FIELD_THIS_FN
= g_quark_from_string("this_fn");
4391 LTT_FIELD_CALL_SITE
= g_quark_from_string("call_site");
4392 LTT_FIELD_MAJOR
= g_quark_from_string("major");
4393 LTT_FIELD_MINOR
= g_quark_from_string("minor");
4394 LTT_FIELD_OPERATION
= g_quark_from_string("direction");
4395 LTT_FIELD_ACTION
= g_quark_from_string("action");
4396 LTT_FIELD_ID
= g_quark_from_string("id");
4397 LTT_FIELD_ADDRESS
= g_quark_from_string("address");
4398 LTT_FIELD_SYMBOL
= g_quark_from_string("symbol");
4399 LTT_FIELD_IP
= g_quark_from_string("ip");
4401 LTTV_CPU_UNKNOWN
= g_quark_from_string("unknown");
4402 LTTV_CPU_IDLE
= g_quark_from_string("idle");
4403 LTTV_CPU_BUSY
= g_quark_from_string("busy");
4404 LTTV_CPU_IRQ
= g_quark_from_string("irq");
4405 LTTV_CPU_SOFT_IRQ
= g_quark_from_string("softirq");
4406 LTTV_CPU_TRAP
= g_quark_from_string("trap");
4408 LTTV_IRQ_UNKNOWN
= g_quark_from_string("unknown");
4409 LTTV_IRQ_IDLE
= g_quark_from_string("idle");
4410 LTTV_IRQ_BUSY
= g_quark_from_string("busy");
4412 LTTV_BDEV_UNKNOWN
= g_quark_from_string("unknown");
4413 LTTV_BDEV_IDLE
= g_quark_from_string("idle");
4414 LTTV_BDEV_BUSY_READING
= g_quark_from_string("busy_reading");
4415 LTTV_BDEV_BUSY_WRITING
= g_quark_from_string("busy_writing");
4418 static void module_destroy()
4423 LTTV_MODULE("state", "State computation", \
4424 "Update the system state, possibly saving it at intervals", \
4425 module_init
, module_destroy
)