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 <lttv/compiler.h>
29 #include <lttv/traceset.h>
34 #define PREALLOCATED_EXECUTION_STACK 10
40 LTT_CHANNEL_GLOBAL_STATE
,
41 LTT_CHANNEL_IRQ_STATE
,
42 LTT_CHANNEL_MODULE_STATE
,
43 LTT_CHANNEL_NETIF_STATE
,
44 LTT_CHANNEL_SOFTIRQ_STATE
,
45 LTT_CHANNEL_SWAP_STATE
,
46 LTT_CHANNEL_SYSCALL_STATE
,
47 LTT_CHANNEL_TASK_STATE
,
49 LTT_CHANNEL_KPROBE_STATE
,
53 LTT_CHANNEL_USERSPACE
,
59 LTT_EVENT_SYSCALL_ENTRY
,
60 LTT_EVENT_SYSCALL_EXIT
,
61 LTT_EVENT_PAGE_FAULT_NOSEM_ENTRY
,
62 LTT_EVENT_PAGE_FAULT_NOSEM_EXIT
,
63 LTT_EVENT_PAGE_FAULT_ENTRY
,
64 LTT_EVENT_PAGE_FAULT_EXIT
,
65 //LTT_EVENT_TRAP_ENTRY,
66 //LTT_EVENT_TRAP_EXIT,
69 LTT_EVENT_SOFT_IRQ_RAISE
,
70 LTT_EVENT_SOFT_IRQ_ENTRY
,
71 LTT_EVENT_SOFT_IRQ_EXIT
,
72 LTT_EVENT_SCHED_SCHEDULE
,
73 LTT_EVENT_SCHED_TRY_WAKEUP
,
74 LTT_EVENT_PROCESS_FORK
,
75 LTT_EVENT_KTHREAD_CREATE
,
76 LTT_EVENT_PROCESS_EXIT
,
77 LTT_EVENT_PROCESS_FREE
,
79 LTT_EVENT_PROCESS_STATE
,
80 LTT_EVENT_STATEDUMP_END
,
81 LTT_EVENT_FUNCTION_ENTRY
,
82 LTT_EVENT_FUNCTION_EXIT
,
83 LTT_EVENT_THREAD_BRAND
,
84 LTT_EVENT_REQUEST_ISSUE
,
85 LTT_EVENT_REQUEST_COMPLETE
,
86 LTT_EVENT_LIST_INTERRUPT
,
87 LTT_EVENT_SYS_CALL_TABLE
,
88 LTT_EVENT_SOFTIRQ_VEC
,
89 LTT_EVENT_KPROBE_TABLE
,
101 LTT_FIELD_SOFT_IRQ_ID
,
104 LTT_FIELD_PREV_STATE
,
105 LTT_FIELD_PARENT_PID
,
109 LTT_FIELD_CHILD_TGID
,
131 LTTV_STATE_MODE_UNKNOWN
,
132 LTTV_STATE_USER_MODE
,
133 LTTV_STATE_MAYBE_USER_MODE
,
135 LTTV_STATE_MAYBE_SYSCALL
,
137 LTTV_STATE_MAYBE_TRAP
,
142 LTTV_STATE_SUBMODE_UNKNOWN
,
143 LTTV_STATE_SUBMODE_NONE
;
147 LTTV_STATE_WAIT_FORK
,
156 LTTV_STATE_UNBRANDED
;
159 LTTV_STATE_USER_THREAD
,
160 LTTV_STATE_KERNEL_THREAD
;
178 LTTV_BDEV_BUSY_READING
,
179 LTTV_BDEV_BUSY_WRITING
;
182 LTTV_STATE_TRACEFILES
,
183 LTTV_STATE_PROCESSES
,
185 LTTV_STATE_RUNNING_PROCESS
,
187 LTTV_STATE_SAVED_STATES
,
188 LTTV_STATE_SAVED_STATES_TIME
,
191 LTTV_STATE_NAME_TABLES
,
192 LTTV_STATE_TRACE_STATE_USE_COUNT
,
193 LTTV_STATE_RESOURCE_CPUS
,
194 LTTV_STATE_RESOURCE_CPUS_COUNT
,
195 LTTV_STATE_RESOURCE_IRQS
,
196 LTTV_STATE_RESOURCE_SOFT_IRQS
,
197 LTTV_STATE_RESOURCE_TRAPS
,
198 LTTV_STATE_RESOURCE_BLKDEVS
;
200 static void create_max_time(LttvTraceState
*tcs
);
202 static void get_max_time(LttvTraceState
*tcs
);
204 static void free_max_time(LttvTraceState
*tcs
);
206 static void create_name_tables(LttvTraceState
*tcs
);
208 static void get_name_tables(LttvTraceState
*tcs
);
210 static void free_name_tables(LttvTraceState
*tcs
);
212 static void free_saved_state(LttvTraceState
*tcs
);
214 static void lttv_state_free_process_table(GHashTable
*processes
);
216 static void lttv_trace_states_read_raw(LttvTraceState
*tcs
, FILE *fp
,
217 GPtrArray
*quarktable
);
219 /* Resource function prototypes */
220 static LttvBdevState
*get_hashed_bdevstate(LttvTraceState
*ts
, guint32 devcode
);
221 static LttvBdevState
*bdevstate_new(void);
222 static void bdevstate_free(LttvBdevState
*);
223 static void bdevstate_free_cb(gpointer key
, gpointer value
, gpointer user_data
);
224 static LttvBdevState
*bdevstate_copy(LttvBdevState
*bds
);
225 void lttv_state_add_event_hooks(LttvTraceset
*traceset
);
227 #if (__WORDSIZE == 32)
228 guint
guint64_hash(gconstpointer key
)
230 guint64 ukey
= *(const guint64
*)key
;
232 return (guint
)ukey
^ (guint
)(ukey
>> 32);
235 gboolean
guint64_equal(gconstpointer a
, gconstpointer b
)
237 guint64 ua
= *(const guint64
*)a
;
238 guint64 ub
= *(const guint64
*)b
;
244 guint
process_hash(gconstpointer key
)
246 guint pid
= ((const LttvProcessState
*)key
)->pid
;
247 return (pid
>>8 ^ pid
>>4 ^ pid
>>2 ^ pid
) ;
251 /* If the hash table hash function is well distributed,
252 * the process_equal should compare different pid */
253 gboolean
process_equal(gconstpointer a
, gconstpointer b
)
255 const LttvProcessState
*process_a
, *process_b
;
258 process_a
= (const LttvProcessState
*)a
;
259 process_b
= (const LttvProcessState
*)b
;
261 if(likely(process_a
->pid
!= process_b
->pid
)) ret
= FALSE
;
262 else if(likely(process_a
->pid
== 0 &&
263 process_a
->cpu
!= process_b
->cpu
)) ret
= FALSE
;
268 gboolean
rettrue(gpointer key
, gpointer value
, gpointer user_data
)
273 static guint
check_expand(nb
, id
)
278 return max(id
+ 1, nb
* 2);
281 static void expand_name_table(LttvTraceState
*ts
, GQuark
**table
,
282 guint nb
, guint new_nb
)
284 /* Expand an incomplete table */
285 GQuark
*old_table
= *table
;
286 *table
= g_new(GQuark
, new_nb
);
287 memcpy(*table
, old_table
, nb
* sizeof(GQuark
));
291 static void fill_name_table(LttvTraceState
*ts
, GQuark
*table
, guint nb
,
292 guint new_nb
, const char *def_string
)
295 GString
*fe_name
= g_string_new("");
296 for(i
= nb
; i
< new_nb
; i
++) {
297 g_string_printf(fe_name
, "%s %d", def_string
, i
);
298 table
[i
] = g_quark_from_string(fe_name
->str
);
300 g_string_free(fe_name
, TRUE
);
303 static void expand_kprobe_table(LttvTraceState
*ts
, guint64 ip
, char *symbol
)
305 LttvNameTables
*nt
= ts
->name_tables
;
306 #if (__WORDSIZE == 32)
307 guint64
*ip_ptr
= g_new(guint64
, 1);
308 g_hash_table_insert(nt
->kprobe_hash
, ip_ptr
,
309 (gpointer
)(glong
)g_quark_from_string(symbol
));
311 g_hash_table_insert(nt
->kprobe_hash
, (gpointer
)ip
,
312 (gpointer
)(glong
)g_quark_from_string(symbol
));
316 static void expand_trap_table(LttvTraceState
*ts
, int id
)
318 LttvNameTables
*nt
= ts
->name_tables
;
319 LttvTrapState
*old_table
;
322 new_nb
= check_expand(nt
->nb_traps
, id
);
323 if(likely(new_nb
== nt
->nb_traps
))
326 expand_name_table(ts
, &nt
->trap_names
, nt
->nb_traps
, new_nb
);
327 fill_name_table(ts
, nt
->trap_names
, nt
->nb_traps
, new_nb
, "trap");
329 old_table
= ts
->trap_states
;
330 ts
->trap_states
= g_new(LttvTrapState
, new_nb
);
331 memcpy(ts
->trap_states
, old_table
, nt
->nb_traps
* sizeof(LttvTrapState
));
333 for(i
= nt
->nb_traps
; i
< new_nb
; i
++)
334 ts
->trap_states
[i
].running
= 0;
336 /* Update the table size */
337 nt
->nb_traps
= new_nb
;
340 static void expand_irq_table(LttvTraceState
*ts
, int id
)
342 LttvNameTables
*nt
= ts
->name_tables
;
343 LttvIRQState
*old_table
;
346 new_nb
= check_expand(nt
->nb_irqs
, id
);
347 if(likely(new_nb
== nt
->nb_irqs
))
350 expand_name_table(ts
, &nt
->irq_names
, nt
->nb_irqs
, new_nb
);
351 fill_name_table(ts
, nt
->irq_names
, nt
->nb_irqs
, new_nb
, "irq");
353 old_table
= ts
->irq_states
;
354 ts
->irq_states
= g_new(LttvIRQState
, new_nb
);
355 memcpy(ts
->irq_states
, old_table
, nt
->nb_irqs
* sizeof(LttvIRQState
));
357 for(i
= nt
->nb_irqs
; i
< new_nb
; i
++)
358 ts
->irq_states
[i
].mode_stack
=
359 g_array_new(FALSE
, FALSE
, sizeof(LttvIRQMode
));
361 /* Update the table size */
362 nt
->nb_irqs
= new_nb
;
365 static void expand_soft_irq_table(LttvTraceState
*ts
, int id
)
367 LttvNameTables
*nt
= ts
->name_tables
;
368 LttvSoftIRQState
*old_table
;
371 new_nb
= check_expand(nt
->nb_soft_irqs
, id
);
372 if(likely(new_nb
== nt
->nb_soft_irqs
))
375 expand_name_table(ts
, &nt
->soft_irq_names
, nt
->nb_soft_irqs
, new_nb
);
376 fill_name_table(ts
, nt
->soft_irq_names
, nt
->nb_soft_irqs
, new_nb
, "softirq");
378 old_table
= ts
->soft_irq_states
;
379 ts
->soft_irq_states
= g_new(LttvSoftIRQState
, new_nb
);
380 memcpy(ts
->soft_irq_states
, old_table
,
381 nt
->nb_soft_irqs
* sizeof(LttvSoftIRQState
));
383 for(i
= nt
->nb_soft_irqs
; i
< new_nb
; i
++)
384 ts
->soft_irq_states
[i
].running
= 0;
386 /* Update the table size */
387 nt
->nb_soft_irqs
= new_nb
;
390 static void restore_init_state(LttvTraceState
*self
)
392 guint i
, nb_cpus
, nb_irqs
, nb_soft_irqs
, nb_traps
;
394 //LttvTracefileState *tfcs;
398 /* Free the process tables */
399 if(self
->processes
!= NULL
) lttv_state_free_process_table(self
->processes
);
400 self
->processes
= g_hash_table_new(process_hash
, process_equal
);
403 /* Seek time to beginning */
404 // Mathieu : fix : don't seek traceset here : causes inconsistency in seek
405 // closest. It's the tracecontext job to seek the trace to the beginning
406 // anyway : the init state might be used at the middle of the trace as well...
407 //g_tree_destroy(self->parent.ts_context->pqueue);
408 //self->parent.ts_context->pqueue = g_tree_new(compare_tracefile);
410 start_time
= ltt_time_from_uint64(
411 bt_trace_handle_get_timestamp_begin(self
->trace
->traceset
->context
,
415 //lttv_process_trace_seek_time(&self->parent, ltt_time_zero);
417 nb_cpus
= lttv_trace_get_num_cpu(self
->trace
);
418 nb_irqs
= self
->name_tables
->nb_irqs
;
419 nb_soft_irqs
= self
->name_tables
->nb_soft_irqs
;
420 nb_traps
= self
->name_tables
->nb_traps
;
422 /* Put the per cpu running_process to beginning state : process 0. */
423 for(i
=0; i
< nb_cpus
; i
++) {
424 LttvExecutionState
*es
;
425 self
->running_process
[i
] = lttv_state_create_process(self
, NULL
, i
, 0, 0,
426 LTTV_STATE_UNNAMED
, &start_time
);
427 /* We are not sure is it's a kernel thread or normal thread, put the
428 * bottom stack state to unknown */
429 self
->running_process
[i
]->execution_stack
=
430 g_array_set_size(self
->running_process
[i
]->execution_stack
, 1);
431 es
= self
->running_process
[i
]->state
=
432 &g_array_index(self
->running_process
[i
]->execution_stack
,
433 LttvExecutionState
, 0);
434 es
->t
= LTTV_STATE_MODE_UNKNOWN
;
435 es
->s
= LTTV_STATE_UNNAMED
;
437 //self->running_process[i]->state->s = LTTV_STATE_RUN;
438 self
->running_process
[i
]->cpu
= i
;
440 /* reset cpu states */
441 if(self
->cpu_states
[i
].mode_stack
->len
> 0) {
442 g_array_remove_range(self
->cpu_states
[i
].mode_stack
, 0,
443 self
->cpu_states
[i
].mode_stack
->len
);
444 if(self
->cpu_states
[i
].irq_stack
->len
)
445 g_array_remove_range(self
->cpu_states
[i
].irq_stack
, 0,
446 self
->cpu_states
[i
].irq_stack
->len
);
447 if(self
->cpu_states
[i
].softirq_stack
->len
)
448 g_array_remove_range(self
->cpu_states
[i
].softirq_stack
, 0,
449 self
->cpu_states
[i
].softirq_stack
->len
);
450 if(self
->cpu_states
[i
].trap_stack
->len
)
451 g_array_remove_range(self
->cpu_states
[i
].trap_stack
, 0,
452 self
->cpu_states
[i
].trap_stack
->len
);
456 /* reset irq states */
457 for(i
=0; i
<nb_irqs
; i
++) {
458 if(self
->irq_states
[i
].mode_stack
->len
> 0)
459 g_array_remove_range(self
->irq_states
[i
].mode_stack
, 0,
460 self
->irq_states
[i
].mode_stack
->len
);
463 /* reset softirq states */
464 for(i
=0; i
<nb_soft_irqs
; i
++) {
465 self
->soft_irq_states
[i
].pending
= 0;
466 self
->soft_irq_states
[i
].running
= 0;
469 /* reset trap states */
470 for(i
=0; i
<nb_traps
; i
++) {
471 self
->trap_states
[i
].running
= 0;
474 /* reset bdev states */
475 g_hash_table_foreach(self
->bdev_states
, bdevstate_free_cb
, NULL
);
476 //g_hash_table_steal_all(self->bdev_states);
477 g_hash_table_foreach_steal(self
->bdev_states
, rettrue
, NULL
);
480 nb_tracefile
= self
->parent
.tracefiles
->len
;
482 for(i
= 0 ; i
< nb_tracefile
; i
++) {
484 LTTV_TRACEFILE_STATE(g_array_index(self
->parent
.tracefiles
,
485 LttvTracefileContext
*, i
));
486 ltt_trace_time_span_get(self
->parent
.t
, &tfcs
->parent
.timestamp
, NULL
);
487 // tfcs->saved_position = 0;
488 tfcs
->process
= lttv_state_create_process(tfcs
, NULL
,0);
489 tfcs
->process
->state
->s
= LTTV_STATE_RUN
;
490 tfcs
->process
->last_cpu
= tfcs
->cpu_name
;
491 tfcs
->process
->last_cpu_index
= ltt_tracefile_num(((LttvTracefileContext
*)tfcs
)->tf
);
496 //static LttTime time_zero = {0,0};
500 #define MAX_STRING_LEN 4096
502 static void state_load_saved_states(LttvTraceState
*tcs
)
505 GPtrArray
*quarktable
;
506 const char *trace_path
;
510 tcs
->has_precomputed_states
= FALSE
;
514 gchar buf
[MAX_STRING_LEN
];
518 trace_path
= g_quark_to_string(ltt_trace_name(tcs
->parent
.t
));
519 strncpy(path
, trace_path
, PATH_MAX
-1);
520 count
= strnlen(trace_path
, PATH_MAX
-1);
521 // quarktable : open, test
522 strncat(path
, "/precomputed/quarktable", PATH_MAX
-count
-1);
523 fp
= fopen(path
, "r");
525 quarktable
= g_ptr_array_sized_new(4096);
527 /* Index 0 is null */
529 if(hdr
== EOF
) return;
530 g_assert(hdr
== HDR_QUARKS
);
534 if(hdr
== EOF
) break;
535 g_assert(hdr
== HDR_QUARK
);
536 g_ptr_array_set_size(quarktable
, q
+1);
539 res
= fread(&buf
[i
], sizeof(gchar
), 1, fp
);
541 if(buf
[i
] == '\0' || feof(fp
)) break;
544 len
= strnlen(buf
, MAX_STRING_LEN
-1);
545 g_ptr_array_index (quarktable
, q
) = g_new(gchar
, len
+1);
546 strncpy(g_ptr_array_index (quarktable
, q
), buf
, len
+1);
552 // saved_states : open, test
553 strncpy(path
, trace_path
, PATH_MAX
-1);
554 count
= strnlen(trace_path
, PATH_MAX
-1);
555 strncat(path
, "/precomputed/states", PATH_MAX
-count
-1);
556 fp
= fopen(path
, "r");
560 if(hdr
!= HDR_TRACE
) goto end
;
562 lttv_trace_states_read_raw(tcs
, fp
, quarktable
);
564 tcs
->has_precomputed_states
= TRUE
;
569 /* Free the quarktable */
570 for(i
=0; i
<quarktable
->len
; i
++) {
571 string
= g_ptr_array_index (quarktable
, i
);
574 g_ptr_array_free(quarktable
, TRUE
);
577 #endif /* BABEL_CLEANUP */
579 void lttv_trace_state_init(LttvTraceState
*trace_state
, LttvTrace
*trace
)
583 LttvAttributeValue v
;
585 trace_state
->trace
= trace
;
587 trace_state
->save_interval
= LTTV_STATE_SAVE_INTERVAL
;
588 lttv_attribute_find(lttv_trace_attribute(trace
), LTTV_STATE_TRACE_STATE_USE_COUNT
,
592 if (*(v
.v_uint
) == 1) {
593 create_name_tables(trace_state
);
594 create_max_time(trace_state
);
596 get_name_tables(trace_state
);
597 get_max_time(trace_state
);
599 nb_cpu
= lttv_trace_get_num_cpu(trace
);
600 nb_irq
= trace_state
->name_tables
->nb_irqs
;
601 trace_state
->processes
= NULL
;
602 trace_state
->running_process
= g_new(LttvProcessState
*, nb_cpu
);
604 /* init cpu resource stuff */
605 trace_state
->cpu_states
= g_new(LttvCPUState
, nb_cpu
);
606 for (j
= 0; j
< nb_cpu
; j
++) {
607 trace_state
->cpu_states
[j
].mode_stack
= g_array_new(FALSE
, FALSE
, sizeof(LttvCPUMode
));
608 trace_state
->cpu_states
[j
].irq_stack
= g_array_new(FALSE
, FALSE
, sizeof(gint
));
609 trace_state
->cpu_states
[j
].softirq_stack
= g_array_new(FALSE
, FALSE
, sizeof(gint
));
610 trace_state
->cpu_states
[j
].trap_stack
= g_array_new(FALSE
, FALSE
, sizeof(gint
));
611 g_assert(trace_state
->cpu_states
[j
].mode_stack
!= NULL
);
614 /* init irq resource stuff */
615 trace_state
->irq_states
= g_new(LttvIRQState
, nb_irq
);
616 for (j
= 0; j
< nb_irq
; j
++) {
617 trace_state
->irq_states
[j
].mode_stack
= g_array_new(FALSE
, FALSE
, sizeof(LttvIRQMode
));
618 g_assert(trace_state
->irq_states
[j
].mode_stack
!= NULL
);
621 /* init soft irq stuff */
622 /* the kernel has a statically fixed max of 32 softirqs */
623 trace_state
->soft_irq_states
= g_new(LttvSoftIRQState
, trace_state
->name_tables
->nb_soft_irqs
);
625 /* init trap stuff */
626 trace_state
->trap_states
= g_new(LttvTrapState
, trace_state
->name_tables
->nb_traps
);
628 /* init bdev resource stuff */
629 trace_state
->bdev_states
= g_hash_table_new(g_int_hash
, g_int_equal
);
631 restore_init_state(trace_state
);
633 /* See if the trace has saved states */
634 //state_load_saved_states(trace_state);
637 void lttv_trace_state_fini(LttvTraceState
*trace_state
)
639 LttvTrace
*trace
= trace_state
->trace
;
640 LttvAttributeValue v
;
642 lttv_attribute_find(lttv_trace_attribute(trace
), LTTV_STATE_TRACE_STATE_USE_COUNT
,
645 g_assert(*(v
.v_uint
) != 0);
648 if (*(v
.v_uint
) == 0) {
649 free_name_tables(trace_state
);
650 free_max_time(trace_state
);
651 free_saved_state(trace_state
);
653 g_free(trace_state
->running_process
);
654 trace_state
->running_process
= NULL
;
655 lttv_state_free_process_table(trace_state
->processes
);
656 trace_state
->processes
= NULL
;
661 /* Write the process state of the trace */
663 static void write_process_state(gpointer key
, gpointer value
,
666 LttvProcessState
*process
;
668 LttvExecutionState
*es
;
670 FILE *fp
= (FILE *)user_data
;
675 process
= (LttvProcessState
*)value
;
676 fprintf(fp
," <PROCESS CORE=%p PID=%u TGID=%u PPID=%u TYPE=\"%s\" CTIME_S=%lu CTIME_NS=%lu ITIME_S=%lu ITIME_NS=%lu NAME=\"%s\" BRAND=\"%s\" CPU=\"%u\" FREE_EVENTS=\"%u\">\n",
677 process
, process
->pid
, process
->tgid
, process
->ppid
,
678 g_quark_to_string(process
->type
),
679 process
->creation_time
.tv_sec
,
680 process
->creation_time
.tv_nsec
,
681 process
->insertion_time
.tv_sec
,
682 process
->insertion_time
.tv_nsec
,
683 g_quark_to_string(process
->name
),
684 g_quark_to_string(process
->brand
),
685 process
->cpu
, process
->free_events
);
687 for(i
= 0 ; i
< process
->execution_stack
->len
; i
++) {
688 es
= &g_array_index(process
->execution_stack
, LttvExecutionState
, i
);
689 fprintf(fp
, " <ES MODE=\"%s\" SUBMODE=\"%s\" ENTRY_S=%lu ENTRY_NS=%lu",
690 g_quark_to_string(es
->t
), g_quark_to_string(es
->n
),
691 es
->entry
.tv_sec
, es
->entry
.tv_nsec
);
692 fprintf(fp
, " CHANGE_S=%lu CHANGE_NS=%lu STATUS=\"%s\"/>\n",
693 es
->change
.tv_sec
, es
->change
.tv_nsec
, g_quark_to_string(es
->s
));
696 for(i
= 0 ; i
< process
->user_stack
->len
; i
++) {
697 address
= g_array_index(process
->user_stack
, guint64
, i
);
698 fprintf(fp
, " <USER_STACK ADDRESS=\"%" PRIu64
"\"/>\n", address
);
701 fprintf(fp
, " </PROCESS>\n");
705 void lttv_state_write(LttvTraceState
*self
, LttTime t
, FILE *fp
)
707 guint i
, nb_tracefile
, nb_block
, offset
;
710 LttvTracefileState
*tfcs
;
714 LttEventPosition
*ep
;
718 ep
= ltt_event_position_new();
720 fprintf(fp
,"<PROCESS_STATE TIME_S=%lu TIME_NS=%lu>\n", t
.tv_sec
, t
.tv_nsec
);
722 g_hash_table_foreach(self
->processes
, write_process_state
, fp
);
724 nb_cpus
= ltt_trace_get_num_cpu(self
->parent
.t
);
725 for(i
=0;i
<nb_cpus
;i
++) {
726 fprintf(fp
," <CPU NUM=%u RUNNING_PROCESS=%u>\n",
727 i
, self
->running_process
[i
]->pid
);
730 nb_tracefile
= self
->parent
.tracefiles
->len
;
732 for(i
= 0 ; i
< nb_tracefile
; i
++) {
734 LTTV_TRACEFILE_STATE(g_array_index(self
->parent
.tracefiles
,
735 LttvTracefileContext
*, i
));
736 fprintf(fp
, " <TRACEFILE TIMESTAMP_S=%lu TIMESTAMP_NS=%lu",
737 tfcs
->parent
.timestamp
.tv_sec
,
738 tfcs
->parent
.timestamp
.tv_nsec
);
739 LttEvent
*e
= ltt_tracefile_get_event(tfcs
->parent
.tf
);
740 if(e
== NULL
) fprintf(fp
,"/>\n");
742 ltt_event_position(e
, ep
);
743 ltt_event_position_get(ep
, &tf
, &nb_block
, &offset
, &tsc
);
744 fprintf(fp
, " BLOCK=%u OFFSET=%u TSC=%" PRIu64
"/>\n", nb_block
, offset
,
749 fprintf(fp
,"</PROCESS_STATE>\n");
753 static void write_process_state_raw(gpointer key
, gpointer value
,
756 LttvProcessState
*process
;
758 LttvExecutionState
*es
;
760 FILE *fp
= (FILE *)user_data
;
765 process
= (LttvProcessState
*)value
;
766 fputc(HDR_PROCESS
, fp
);
767 //fwrite(&header, sizeof(header), 1, fp);
768 //fprintf(fp, "%s", g_quark_to_string(process->type));
770 fwrite(&process
->type
, sizeof(process
->type
), 1, fp
);
771 //fprintf(fp, "%s", g_quark_to_string(process->name));
773 fwrite(&process
->name
, sizeof(process
->name
), 1, fp
);
774 //fprintf(fp, "%s", g_quark_to_string(process->brand));
776 fwrite(&process
->brand
, sizeof(process
->brand
), 1, fp
);
777 fwrite(&process
->pid
, sizeof(process
->pid
), 1, fp
);
778 fwrite(&process
->free_events
, sizeof(process
->free_events
), 1, fp
);
779 fwrite(&process
->tgid
, sizeof(process
->tgid
), 1, fp
);
780 fwrite(&process
->ppid
, sizeof(process
->ppid
), 1, fp
);
781 fwrite(&process
->cpu
, sizeof(process
->cpu
), 1, fp
);
782 fwrite(&process
->creation_time
, sizeof(process
->creation_time
), 1, fp
);
783 fwrite(&process
->insertion_time
, sizeof(process
->insertion_time
), 1, fp
);
786 fprintf(fp
," <PROCESS CORE=%p PID=%u TGID=%u PPID=%u TYPE=\"%s\" CTIME_S=%lu CTIME_NS=%lu ITIME_S=%lu ITIME_NS=%lu NAME=\"%s\" BRAND=\"%s\" CPU=\"%u\" PROCESS_TYPE=%u>\n",
787 process
, process
->pid
, process
->tgid
, process
->ppid
,
788 g_quark_to_string(process
->type
),
789 process
->creation_time
.tv_sec
,
790 process
->creation_time
.tv_nsec
,
791 process
->insertion_time
.tv_sec
,
792 process
->insertion_time
.tv_nsec
,
793 g_quark_to_string(process
->name
),
794 g_quark_to_string(process
->brand
),
798 for(i
= 0 ; i
< process
->execution_stack
->len
; i
++) {
799 es
= &g_array_index(process
->execution_stack
, LttvExecutionState
, i
);
802 //fprintf(fp, "%s", g_quark_to_string(es->t));
804 fwrite(&es
->t
, sizeof(es
->t
), 1, fp
);
805 //fprintf(fp, "%s", g_quark_to_string(es->n));
807 fwrite(&es
->n
, sizeof(es
->n
), 1, fp
);
808 //fprintf(fp, "%s", g_quark_to_string(es->s));
810 fwrite(&es
->s
, sizeof(es
->s
), 1, fp
);
811 fwrite(&es
->entry
, sizeof(es
->entry
), 1, fp
);
812 fwrite(&es
->change
, sizeof(es
->change
), 1, fp
);
813 fwrite(&es
->cum_cpu_time
, sizeof(es
->cum_cpu_time
), 1, fp
);
815 fprintf(fp
, " <ES MODE=\"%s\" SUBMODE=\"%s\" ENTRY_S=%lu ENTRY_NS=%lu",
816 g_quark_to_string(es
->t
), g_quark_to_string(es
->n
),
817 es
->entry
.tv_sec
, es
->entry
.tv_nsec
);
818 fprintf(fp
, " CHANGE_S=%lu CHANGE_NS=%lu STATUS=\"%s\"/>\n",
819 es
->change
.tv_sec
, es
->change
.tv_nsec
, g_quark_to_string(es
->s
));
823 for(i
= 0 ; i
< process
->user_stack
->len
; i
++) {
824 address
= g_array_index(process
->user_stack
, guint64
, i
);
825 fputc(HDR_USER_STACK
, fp
);
826 fwrite(&address
, sizeof(address
), 1, fp
);
828 fprintf(fp
, " <USER_STACK ADDRESS=\"%llu\"/>\n", address
);
834 void lttv_state_write_raw(LttvTraceState
*self
, LttTime t
, FILE *fp
)
836 guint i
, nb_tracefile
, nb_block
, offset
;
839 LttvTracefileState
*tfcs
;
843 LttEventPosition
*ep
;
847 ep
= ltt_event_position_new();
849 //fprintf(fp,"<PROCESS_STATE TIME_S=%lu TIME_NS=%lu>\n", t.tv_sec, t.tv_nsec);
850 fputc(HDR_PROCESS_STATE
, fp
);
851 fwrite(&t
, sizeof(t
), 1, fp
);
853 g_hash_table_foreach(self
->processes
, write_process_state_raw
, fp
);
855 nb_cpus
= ltt_trace_get_num_cpu(self
->parent
.t
);
856 for(i
=0;i
<nb_cpus
;i
++) {
858 fwrite(&i
, sizeof(i
), 1, fp
); /* cpu number */
859 fwrite(&self
->running_process
[i
]->pid
,
860 sizeof(self
->running_process
[i
]->pid
), 1, fp
);
861 //fprintf(fp," <CPU NUM=%u RUNNING_PROCESS=%u>\n",
862 // i, self->running_process[i]->pid);
865 nb_tracefile
= self
->parent
.tracefiles
->len
;
867 for(i
= 0 ; i
< nb_tracefile
; i
++) {
869 LTTV_TRACEFILE_STATE(g_array_index(self
->parent
.tracefiles
,
870 LttvTracefileContext
*, i
));
871 // fprintf(fp, " <TRACEFILE TIMESTAMP_S=%lu TIMESTAMP_NS=%lu",
872 // tfcs->parent.timestamp.tv_sec,
873 // tfcs->parent.timestamp.tv_nsec);
874 fputc(HDR_TRACEFILE
, fp
);
875 fwrite(&tfcs
->parent
.timestamp
, sizeof(tfcs
->parent
.timestamp
), 1, fp
);
876 /* Note : if timestamp if LTT_TIME_INFINITE, there will be no
877 * position following : end of trace */
878 LttEvent
*e
= ltt_tracefile_get_event(tfcs
->parent
.tf
);
880 ltt_event_position(e
, ep
);
881 ltt_event_position_get(ep
, &tf
, &nb_block
, &offset
, &tsc
);
882 //fprintf(fp, " BLOCK=%u OFFSET=%u TSC=%llu/>\n", nb_block, offset,
884 fwrite(&nb_block
, sizeof(nb_block
), 1, fp
);
885 fwrite(&offset
, sizeof(offset
), 1, fp
);
886 fwrite(&tsc
, sizeof(tsc
), 1, fp
);
893 /* Read process state from a file */
895 /* Called because a HDR_PROCESS was found */
896 static void read_process_state_raw(LttvTraceState
*self
, FILE *fp
,
897 GPtrArray
*quarktable
)
899 LttvExecutionState
*es
;
900 LttvProcessState
*process
, *parent_process
;
901 LttvProcessState tmp
;
907 res
= fread(&tmp
.type
, sizeof(tmp
.type
), 1, fp
);
908 res
+= fread(&tmp
.name
, sizeof(tmp
.name
), 1, fp
);
909 res
+= fread(&tmp
.brand
, sizeof(tmp
.brand
), 1, fp
);
910 res
+= fread(&tmp
.pid
, sizeof(tmp
.pid
), 1, fp
);
911 res
+= fread(&tmp
.free_events
, sizeof(tmp
.free_events
), 1, fp
);
912 res
+= fread(&tmp
.tgid
, sizeof(tmp
.tgid
), 1, fp
);
913 res
+= fread(&tmp
.ppid
, sizeof(tmp
.ppid
), 1, fp
);
914 res
+= fread(&tmp
.cpu
, sizeof(tmp
.cpu
), 1, fp
);
915 res
+= fread(&tmp
.creation_time
, sizeof(tmp
.creation_time
), 1, fp
);
916 res
+= fread(&tmp
.insertion_time
, sizeof(tmp
.insertion_time
), 1, fp
);
920 process
= lttv_state_find_process(self
, tmp
.cpu
, tmp
.pid
);
922 /* We must link to the parent */
923 parent_process
= lttv_state_find_process_or_create(self
, ANY_CPU
, tmp
.ppid
,
925 process
= lttv_state_find_process(self
, ANY_CPU
, tmp
.pid
);
926 if(process
== NULL
) {
927 process
= lttv_state_create_process(self
, parent_process
, tmp
.cpu
,
929 g_quark_from_string((gchar
*)g_ptr_array_index(quarktable
, tmp
.name
)),
933 process
->insertion_time
= tmp
.insertion_time
;
934 process
->creation_time
= tmp
.creation_time
;
935 process
->type
= g_quark_from_string(
936 (gchar
*)g_ptr_array_index(quarktable
, tmp
.type
));
937 process
->tgid
= tmp
.tgid
;
938 process
->ppid
= tmp
.ppid
;
939 process
->brand
= g_quark_from_string(
940 (gchar
*)g_ptr_array_index(quarktable
, tmp
.brand
));
942 g_quark_from_string((gchar
*)g_ptr_array_index(quarktable
, tmp
.name
));
943 process
->free_events
= tmp
.free_events
;
946 if(feof(fp
) || ferror(fp
)) goto end_loop
;
948 gint hdr
= fgetc(fp
);
949 if(hdr
== EOF
) goto end_loop
;
953 process
->execution_stack
=
954 g_array_set_size(process
->execution_stack
,
955 process
->execution_stack
->len
+ 1);
956 es
= &g_array_index(process
->execution_stack
, LttvExecutionState
,
957 process
->execution_stack
->len
-1);
960 res
= fread(&es
->t
, sizeof(es
->t
), 1, fp
);
962 es
->t
= g_quark_from_string(
963 (gchar
*)g_ptr_array_index(quarktable
, es
->t
));
964 res
= fread(&es
->n
, sizeof(es
->n
), 1, fp
);
966 es
->n
= g_quark_from_string(
967 (gchar
*)g_ptr_array_index(quarktable
, es
->n
));
968 res
= fread(&es
->s
, sizeof(es
->s
), 1, fp
);
970 es
->s
= g_quark_from_string(
971 (gchar
*)g_ptr_array_index(quarktable
, es
->s
));
972 res
= fread(&es
->entry
, sizeof(es
->entry
), 1, fp
);
973 res
+= fread(&es
->change
, sizeof(es
->change
), 1, fp
);
974 res
+= fread(&es
->cum_cpu_time
, sizeof(es
->cum_cpu_time
), 1, fp
);
979 process
->user_stack
= g_array_set_size(process
->user_stack
,
980 process
->user_stack
->len
+ 1);
981 address
= &g_array_index(process
->user_stack
, guint64
,
982 process
->user_stack
->len
-1);
983 res
= fread(address
, sizeof(address
), 1, fp
);
985 process
->current_function
= *address
;
998 /* Called because a HDR_PROCESS_STATE was found */
999 /* Append a saved state to the trace states */
1000 void lttv_state_read_raw(LttvTraceState
*self
, FILE *fp
, GPtrArray
*quarktable
)
1002 guint i
, nb_tracefile
, nb_block
, offset
;
1004 LttvTracefileState
*tfcs
;
1006 LttEventPosition
*ep
;
1015 LttvAttribute
*saved_states_tree
, *saved_state_tree
;
1017 LttvAttributeValue value
;
1018 GTree
*pqueue
= self
->parent
.ts_context
->pqueue
;
1019 ep
= ltt_event_position_new();
1021 restore_init_state(self
);
1023 res
= fread(&t
, sizeof(t
), 1, fp
);
1027 if(feof(fp
) || ferror(fp
)) goto end_loop
;
1029 if(hdr
== EOF
) goto end_loop
;
1033 /* Call read_process_state_raw */
1034 read_process_state_raw(self
, fp
, quarktable
);
1042 case HDR_USER_STACK
:
1043 case HDR_PROCESS_STATE
:
1049 g_error("Error while parsing saved state file : unknown data header %d",
1055 nb_cpus
= ltt_trace_get_num_cpu(self
->parent
.t
);
1056 for(i
=0;i
<nb_cpus
;i
++) {
1059 g_assert(hdr
== HDR_CPU
);
1060 res
= fread(&cpu_num
, sizeof(cpu_num
), 1, fp
); /* cpu number */
1062 g_assert(i
== cpu_num
);
1063 res
= fread(&self
->running_process
[i
]->pid
,
1064 sizeof(self
->running_process
[i
]->pid
), 1, fp
);
1068 nb_tracefile
= self
->parent
.tracefiles
->len
;
1070 for(i
= 0 ; i
< nb_tracefile
; i
++) {
1072 LTTV_TRACEFILE_STATE(g_array_index(self
->parent
.tracefiles
,
1073 LttvTracefileContext
*, i
));
1074 // fprintf(fp, " <TRACEFILE TIMESTAMP_S=%lu TIMESTAMP_NS=%lu",
1075 // tfcs->parent.timestamp.tv_sec,
1076 // tfcs->parent.timestamp.tv_nsec);
1077 g_tree_remove(pqueue
, &tfcs
->parent
);
1079 g_assert(hdr
== HDR_TRACEFILE
);
1080 res
= fread(&tfcs
->parent
.timestamp
, sizeof(tfcs
->parent
.timestamp
), 1, fp
);
1082 /* Note : if timestamp if LTT_TIME_INFINITE, there will be no
1083 * position following : end of trace */
1084 if(ltt_time_compare(tfcs
->parent
.timestamp
, ltt_time_infinite
) != 0) {
1085 res
= fread(&nb_block
, sizeof(nb_block
), 1, fp
);
1086 res
+= fread(&offset
, sizeof(offset
), 1, fp
);
1087 res
+= fread(&tsc
, sizeof(tsc
), 1, fp
);
1089 ltt_event_position_set(ep
, tfcs
->parent
.tf
, nb_block
, offset
, tsc
);
1090 gint ret
= ltt_tracefile_seek_position(tfcs
->parent
.tf
, ep
);
1092 g_tree_insert(pqueue
, &tfcs
->parent
, &tfcs
->parent
);
1097 saved_states_tree
= lttv_attribute_find_subdir(self
->parent
.t_a
,
1098 LTTV_STATE_SAVED_STATES
);
1099 saved_state_tree
= g_object_new(LTTV_ATTRIBUTE_TYPE
, NULL
);
1100 value
= lttv_attribute_add(saved_states_tree
,
1101 lttv_attribute_get_number(saved_states_tree
), LTTV_GOBJECT
);
1102 *(value
.v_gobject
) = (GObject
*)saved_state_tree
;
1103 value
= lttv_attribute_add(saved_state_tree
, LTTV_STATE_TIME
, LTTV_TIME
);
1104 *(value
.v_time
) = t
;
1105 lttv_state_save(self
, saved_state_tree
);
1106 g_debug("Saving state at time %lu.%lu", t
.tv_sec
,
1109 *(self
->max_time_state_recomputed_in_seek
) = t
;
1113 /* Called when a HDR_TRACE is found */
1114 void lttv_trace_states_read_raw(LttvTraceState
*tcs
, FILE *fp
,
1115 GPtrArray
*quarktable
)
1120 if(feof(fp
) || ferror(fp
)) goto end_loop
;
1122 if(hdr
== EOF
) goto end_loop
;
1125 case HDR_PROCESS_STATE
:
1126 /* Call read_process_state_raw */
1127 lttv_state_read_raw(tcs
, fp
, quarktable
);
1135 case HDR_USER_STACK
:
1138 g_error("Error while parsing saved state file :"
1139 " unexpected data header %d",
1143 g_error("Error while parsing saved state file : unknown data header %d",
1148 *(tcs
->max_time_state_recomputed_in_seek
) = tcs
->parent
.time_span
.end_time
;
1149 restore_init_state(tcs
);
1150 lttv_process_trace_seek_time(&tcs
->parent
, ltt_time_zero
);
1153 #endif /* BABEL_CLEANUP */
1156 /* Copy each process from an existing hash table to a new one */
1158 static void copy_process_state(gpointer key
, gpointer value
,gpointer user_data
)
1160 LttvProcessState
*process
, *new_process
;
1162 GHashTable
*new_processes
= (GHashTable
*)user_data
;
1166 process
= (LttvProcessState
*)value
;
1167 new_process
= g_new(LttvProcessState
, 1);
1168 *new_process
= *process
;
1169 new_process
->execution_stack
= g_array_sized_new(FALSE
, FALSE
,
1170 sizeof(LttvExecutionState
), PREALLOCATED_EXECUTION_STACK
);
1171 new_process
->execution_stack
=
1172 g_array_set_size(new_process
->execution_stack
,
1173 process
->execution_stack
->len
);
1174 for(i
= 0 ; i
< process
->execution_stack
->len
; i
++) {
1175 g_array_index(new_process
->execution_stack
, LttvExecutionState
, i
) =
1176 g_array_index(process
->execution_stack
, LttvExecutionState
, i
);
1178 new_process
->state
= &g_array_index(new_process
->execution_stack
,
1179 LttvExecutionState
, new_process
->execution_stack
->len
- 1);
1180 #ifdef BABEL_CLEANUP
1181 new_process
->user_stack
= g_array_sized_new(FALSE
, FALSE
,
1182 sizeof(guint64
), 0);
1183 new_process
->user_stack
= g_array_set_size(new_process
->user_stack
,
1184 process
->user_stack
->len
);
1185 for(i
= 0 ; i
< process
->user_stack
->len
; i
++) {
1186 g_array_index(new_process
->user_stack
, guint64
, i
) =
1187 g_array_index(process
->user_stack
, guint64
, i
);
1189 new_process
->current_function
= process
->current_function
;
1190 #endif /* BABEL_CLEANUP */
1192 /* fd hash table stuff */
1198 /* copy every item in the hash table */
1199 new_process
->fds
= g_hash_table_new(g_direct_hash
, g_direct_equal
);
1201 g_hash_table_iter_init(&it
, process
->fds
);
1202 while (g_hash_table_iter_next (&it
, (void *)&key
, (void *)&value
)) {
1203 g_hash_table_insert(new_process
->fds
, key
, value
);
1207 /* When done creating the new process state, insert it in the
1209 g_hash_table_insert(new_processes
, new_process
, new_process
);
1213 static GHashTable
*lttv_state_copy_process_table(GHashTable
*processes
)
1215 GHashTable
*new_processes
= g_hash_table_new(process_hash
, process_equal
);
1217 g_hash_table_foreach(processes
, copy_process_state
, new_processes
);
1218 return new_processes
;
1221 static LttvCPUState
*lttv_state_copy_cpu_states(LttvCPUState
*states
, guint n
)
1224 LttvCPUState
*retval
;
1226 retval
= g_new(LttvCPUState
, n
);
1228 for(i
=0; i
<n
; i
++) {
1229 retval
[i
].irq_stack
= g_array_new(FALSE
, FALSE
, sizeof(gint
));
1230 g_array_set_size(retval
[i
].irq_stack
, states
[i
].irq_stack
->len
);
1231 for(j
=0; j
<states
[i
].irq_stack
->len
; j
++) {
1232 g_array_index(retval
[i
].irq_stack
, gint
, j
) =
1233 g_array_index(states
[i
].irq_stack
, gint
, j
);
1236 retval
[i
].softirq_stack
= g_array_new(FALSE
, FALSE
, sizeof(gint
));
1237 g_array_set_size(retval
[i
].softirq_stack
, states
[i
].softirq_stack
->len
);
1238 for(j
=0; j
<states
[i
].softirq_stack
->len
; j
++) {
1239 g_array_index(retval
[i
].softirq_stack
, gint
, j
) =
1240 g_array_index(states
[i
].softirq_stack
, gint
, j
);
1243 retval
[i
].trap_stack
= g_array_new(FALSE
, FALSE
, sizeof(gint
));
1244 g_array_set_size(retval
[i
].trap_stack
, states
[i
].trap_stack
->len
);
1245 for(j
=0; j
<states
[i
].trap_stack
->len
; j
++) {
1246 g_array_index(retval
[i
].trap_stack
, gint
, j
) =
1247 g_array_index(states
[i
].trap_stack
, gint
, j
);
1250 retval
[i
].mode_stack
= g_array_new(FALSE
, FALSE
, sizeof(LttvCPUMode
));
1251 g_array_set_size(retval
[i
].mode_stack
, states
[i
].mode_stack
->len
);
1252 for(j
=0; j
<states
[i
].mode_stack
->len
; j
++) {
1253 g_array_index(retval
[i
].mode_stack
, GQuark
, j
) =
1254 g_array_index(states
[i
].mode_stack
, GQuark
, j
);
1261 static void lttv_state_free_cpu_states(LttvCPUState
*states
, guint n
)
1265 for(i
=0; i
<n
; i
++) {
1266 g_array_free(states
[i
].mode_stack
, TRUE
);
1267 g_array_free(states
[i
].irq_stack
, TRUE
);
1268 g_array_free(states
[i
].softirq_stack
, TRUE
);
1269 g_array_free(states
[i
].trap_stack
, TRUE
);
1275 static LttvIRQState
*lttv_state_copy_irq_states(LttvIRQState
*states
, guint n
)
1278 LttvIRQState
*retval
;
1280 retval
= g_new(LttvIRQState
, n
);
1282 for(i
=0; i
<n
; i
++) {
1283 retval
[i
].mode_stack
= g_array_new(FALSE
, FALSE
, sizeof(LttvIRQMode
));
1284 g_array_set_size(retval
[i
].mode_stack
, states
[i
].mode_stack
->len
);
1285 for(j
=0; j
<states
[i
].mode_stack
->len
; j
++) {
1286 g_array_index(retval
[i
].mode_stack
, GQuark
, j
) =
1287 g_array_index(states
[i
].mode_stack
, GQuark
, j
);
1294 static void lttv_state_free_irq_states(LttvIRQState
*states
, guint n
)
1298 for(i
=0; i
<n
; i
++) {
1299 g_array_free(states
[i
].mode_stack
, TRUE
);
1305 static LttvSoftIRQState
*
1306 lttv_state_copy_soft_irq_states(LttvSoftIRQState
*states
, guint n
)
1309 LttvSoftIRQState
*retval
;
1311 retval
= g_new(LttvSoftIRQState
, n
);
1313 for(i
=0; i
<n
; i
++) {
1314 retval
[i
].pending
= states
[i
].pending
;
1315 retval
[i
].running
= states
[i
].running
;
1321 static void lttv_state_free_soft_irq_states(LttvSoftIRQState
*states
, guint n
)
1326 static LttvTrapState
*
1327 lttv_state_copy_trap_states(LttvTrapState
*states
, guint n
)
1330 LttvTrapState
*retval
;
1332 retval
= g_new(LttvTrapState
, n
);
1334 for(i
=0; i
<n
; i
++) {
1335 retval
[i
].running
= states
[i
].running
;
1341 static void lttv_state_free_trap_states(LttvTrapState
*states
, guint n
)
1346 /* bdevstate stuff */
1348 static LttvBdevState
*get_hashed_bdevstate(LttvTraceState
*ts
, guint32 devcode
)
1350 gint devcode_gint
= devcode
;
1351 gpointer bdev
= g_hash_table_lookup(ts
->bdev_states
, &devcode_gint
);
1353 LttvBdevState
*bdevstate
= g_new(LttvBdevState
, 1);
1354 bdevstate
->mode_stack
= g_array_new(FALSE
, FALSE
, sizeof(GQuark
));
1356 gint
* key
= g_new(gint
, 1);
1358 g_hash_table_insert(ts
->bdev_states
, key
, bdevstate
);
1366 static LttvBdevState
*bdevstate_new(void)
1368 LttvBdevState
*retval
;
1369 retval
= g_new(LttvBdevState
, 1);
1370 retval
->mode_stack
= g_array_new(FALSE
, FALSE
, sizeof(GQuark
));
1375 static void bdevstate_free(LttvBdevState
*bds
)
1377 g_array_free(bds
->mode_stack
, TRUE
);
1381 static void bdevstate_free_cb(gpointer key
, gpointer value
, gpointer user_data
)
1383 LttvBdevState
*bds
= (LttvBdevState
*) value
;
1385 bdevstate_free(bds
);
1388 static LttvBdevState
*bdevstate_copy(LttvBdevState
*bds
)
1390 LttvBdevState
*retval
;
1392 retval
= bdevstate_new();
1393 g_array_insert_vals(retval
->mode_stack
, 0, bds
->mode_stack
->data
,
1394 bds
->mode_stack
->len
);
1399 static void insert_and_copy_bdev_state(gpointer k
, gpointer v
, gpointer u
)
1401 //GHashTable *ht = (GHashTable *)u;
1402 LttvBdevState
*bds
= (LttvBdevState
*)v
;
1403 LttvBdevState
*newbds
;
1405 newbds
= bdevstate_copy(bds
);
1407 g_hash_table_insert(u
, k
, newbds
);
1410 static GHashTable
*lttv_state_copy_blkdev_hashtable(GHashTable
*ht
)
1414 retval
= g_hash_table_new(g_int_hash
, g_int_equal
);
1416 g_hash_table_foreach(ht
, insert_and_copy_bdev_state
, retval
);
1421 /* Free a hashtable and the LttvBdevState structures its values
1424 static void lttv_state_free_blkdev_hashtable(GHashTable
*ht
)
1426 g_hash_table_foreach(ht
, bdevstate_free_cb
, NULL
);
1427 g_hash_table_destroy(ht
);
1430 /* The saved state for each trace contains a member "processes", which
1431 stores a copy of the process table, and a member "tracefiles" with
1432 one entry per tracefile. Each tracefile has a "process" member pointing
1433 to the current process and a "position" member storing the tracefile
1434 position (needed to seek to the current "next" event. */
1436 void lttv_state_save(LttvTraceState
*self
, LttvAttribute
*container
)
1438 guint i
, nb_cpus
, nb_irqs
, nb_soft_irqs
, nb_traps
;
1440 guint
*running_process
;
1442 LttvAttributeValue value
;
1444 value
= lttv_attribute_add(container
, LTTV_STATE_PROCESSES
,
1446 *(value
.v_pointer
) = lttv_state_copy_process_table(self
->processes
);
1448 /* Add the currently running processes array */
1449 nb_cpus
= lttv_trace_get_num_cpu(self
->trace
);
1450 running_process
= g_new(guint
, nb_cpus
);
1451 for(i
=0;i
<nb_cpus
;i
++) {
1452 running_process
[i
] = self
->running_process
[i
]->pid
;
1454 value
= lttv_attribute_add(container
, LTTV_STATE_RUNNING_PROCESS
,
1456 *(value
.v_pointer
) = running_process
;
1458 g_info("State save");
1460 /* Save the current position */
1461 value
= lttv_attribute_add(container
, LTTV_STATE_POSITION
,
1463 *(value
.v_pointer
) = lttv_traceset_create_current_position(lttv_trace_get_traceset(self
->trace
));
1465 #ifdef BABEL_CLEANUP
1466 nb_tracefile
= self
->parent
.tracefiles
->len
;
1467 for(i
= 0 ; i
< nb_tracefile
; i
++) {
1469 LTTV_TRACEFILE_STATE(g_array_index(self
->parent
.tracefiles
,
1470 LttvTracefileContext
*, i
));
1471 tracefile_tree
= g_object_new(LTTV_ATTRIBUTE_TYPE
, NULL
);
1472 value
= lttv_attribute_add(tracefiles_tree
, i
,
1474 *(value
.v_gobject
) = (GObject
*)tracefile_tree
;
1476 value
= lttv_attribute_add(tracefile_tree
, LTTV_STATE_PROCESS
,
1478 *(value
.v_uint
) = tfcs
->process
->pid
;
1480 value
= lttv_attribute_add(tracefile_tree
, LTTV_STATE_EVENT
,
1482 /* Only save the position if the tfs has not infinite time. */
1483 //if(!g_tree_lookup(self->parent.ts_context->pqueue, &tfcs->parent)
1484 // && current_tfcs != tfcs) {
1485 if(ltt_time_compare(tfcs
->parent
.timestamp
, ltt_time_infinite
) == 0) {
1486 *(value
.v_pointer
) = NULL
;
1488 LttEvent
*e
= ltt_tracefile_get_event(tfcs
->parent
.tf
);
1489 ep
= ltt_event_position_new();
1490 ltt_event_position(e
, ep
);
1491 *(value
.v_pointer
) = ep
;
1493 guint nb_block
, offset
;
1496 ltt_event_position_get(ep
, &tf
, &nb_block
, &offset
, &tsc
);
1497 g_info("Block %u offset %u tsc %" PRIu64
" time %lu.%lu", nb_block
,
1498 offset
, tsc
, tfcs
->parent
.timestamp
.tv_sec
,
1499 tfcs
->parent
.timestamp
.tv_nsec
);
1502 #endif /* BABEL_CLEANUP */
1504 /* save the cpu state */
1506 value
= lttv_attribute_add(container
, LTTV_STATE_RESOURCE_CPUS_COUNT
,
1508 *(value
.v_uint
) = nb_cpus
;
1510 value
= lttv_attribute_add(container
, LTTV_STATE_RESOURCE_CPUS
,
1512 *(value
.v_pointer
) = lttv_state_copy_cpu_states(self
->cpu_states
, nb_cpus
);
1515 /* save the irq state */
1516 nb_irqs
= self
->name_tables
->nb_irqs
;
1518 value
= lttv_attribute_add(container
, LTTV_STATE_RESOURCE_IRQS
,
1520 *(value
.v_pointer
) = lttv_state_copy_irq_states(self
->irq_states
, nb_irqs
);
1523 /* save the soft irq state */
1524 nb_soft_irqs
= self
->name_tables
->nb_soft_irqs
;
1526 value
= lttv_attribute_add(container
, LTTV_STATE_RESOURCE_SOFT_IRQS
,
1528 *(value
.v_pointer
) = lttv_state_copy_soft_irq_states(self
->soft_irq_states
, nb_soft_irqs
);
1531 /* save the trap state */
1532 nb_traps
= self
->name_tables
->nb_traps
;
1534 value
= lttv_attribute_add(container
, LTTV_STATE_RESOURCE_TRAPS
,
1536 *(value
.v_pointer
) = lttv_state_copy_trap_states(self
->trap_states
, nb_traps
);
1539 /* save the blkdev states */
1540 value
= lttv_attribute_add(container
, LTTV_STATE_RESOURCE_BLKDEVS
,
1542 *(value
.v_pointer
) = lttv_state_copy_blkdev_hashtable(self
->bdev_states
);
1545 void lttv_state_restore(LttvTraceState
*self
, LttvAttribute
*container
)
1547 guint i
, pid
, nb_cpus
, nb_irqs
, nb_soft_irqs
, nb_traps
;
1548 guint
*running_process
;
1549 LttvAttributeType type
;
1550 LttvAttributeValue value
;
1552 type
= lttv_attribute_get_by_name(container
, LTTV_STATE_PROCESSES
,
1554 g_assert(type
== LTTV_POINTER
);
1555 lttv_state_free_process_table(self
->processes
);
1556 self
->processes
= lttv_state_copy_process_table(*(value
.v_pointer
));
1558 /* Add the currently running processes array */
1559 nb_cpus
= lttv_trace_get_num_cpu(self
->trace
);
1560 type
= lttv_attribute_get_by_name(container
, LTTV_STATE_RUNNING_PROCESS
,
1562 g_assert(type
== LTTV_POINTER
);
1563 running_process
= *(value
.v_pointer
);
1564 for(i
=0;i
<nb_cpus
;i
++) {
1565 pid
= running_process
[i
];
1566 self
->running_process
[i
] = lttv_state_find_process(self
, i
, pid
);
1567 g_assert(self
->running_process
[i
] != NULL
);
1570 //nb_tracefile = self->parent.tracefiles->len;
1572 //g_tree_destroy(tsc->pqueue);
1573 //tsc->pqueue = g_tree_new(compare_tracefile);
1575 /* restore cpu resource states */
1576 type
= lttv_attribute_get_by_name(container
, LTTV_STATE_RESOURCE_CPUS
, &value
);
1577 g_assert(type
== LTTV_POINTER
);
1578 lttv_state_free_cpu_states(self
->cpu_states
, nb_cpus
);
1579 self
->cpu_states
= lttv_state_copy_cpu_states(*(value
.v_pointer
), nb_cpus
);
1581 /* restore irq resource states */
1582 nb_irqs
= self
->name_tables
->nb_irqs
;
1583 type
= lttv_attribute_get_by_name(container
, LTTV_STATE_RESOURCE_IRQS
, &value
);
1584 g_assert(type
== LTTV_POINTER
);
1585 lttv_state_free_irq_states(self
->irq_states
, nb_irqs
);
1586 self
->irq_states
= lttv_state_copy_irq_states(*(value
.v_pointer
), nb_irqs
);
1588 /* restore soft irq resource states */
1589 nb_soft_irqs
= self
->name_tables
->nb_soft_irqs
;
1590 type
= lttv_attribute_get_by_name(container
, LTTV_STATE_RESOURCE_SOFT_IRQS
, &value
);
1591 g_assert(type
== LTTV_POINTER
);
1592 lttv_state_free_soft_irq_states(self
->soft_irq_states
, nb_soft_irqs
);
1593 self
->soft_irq_states
= lttv_state_copy_soft_irq_states(*(value
.v_pointer
), nb_soft_irqs
);
1595 /* restore trap resource states */
1596 nb_traps
= self
->name_tables
->nb_traps
;
1597 type
= lttv_attribute_get_by_name(container
, LTTV_STATE_RESOURCE_TRAPS
, &value
);
1598 g_assert(type
== LTTV_POINTER
);
1599 lttv_state_free_trap_states(self
->trap_states
, nb_traps
);
1600 self
->trap_states
= lttv_state_copy_trap_states(*(value
.v_pointer
), nb_traps
);
1602 /* restore the blkdev states */
1603 type
= lttv_attribute_get_by_name(container
, LTTV_STATE_RESOURCE_BLKDEVS
, &value
);
1604 g_assert(type
== LTTV_POINTER
);
1605 lttv_state_free_blkdev_hashtable(self
->bdev_states
);
1606 self
->bdev_states
= lttv_state_copy_blkdev_hashtable(*(value
.v_pointer
));
1608 #ifdef BABEL_CLEANUP
1609 for(i
= 0 ; i
< nb_tracefile
; i
++) {
1611 LTTV_TRACEFILE_STATE(g_array_index(self
->parent
.tracefiles
,
1612 LttvTracefileContext
*, i
));
1613 type
= lttv_attribute_get(tracefiles_tree
, i
, &name
, &value
, &is_named
);
1614 g_assert(type
== LTTV_GOBJECT
);
1615 tracefile_tree
= *((LttvAttribute
**)(value
.v_gobject
));
1617 type
= lttv_attribute_get_by_name(tracefile_tree
, LTTV_STATE_PROCESS
,
1619 g_assert(type
== LTTV_UINT
);
1620 pid
= *(value
.v_uint
);
1621 tfcs
->process
= lttv_state_find_process_or_create(tfcs
, pid
);
1623 type
= lttv_attribute_get_by_name(tracefile_tree
, LTTV_STATE_EVENT
,
1625 g_assert(type
== LTTV_POINTER
);
1626 //g_assert(*(value.v_pointer) != NULL);
1627 ep
= *(value
.v_pointer
);
1628 g_assert(tfcs
->parent
.t_context
!= NULL
);
1630 tfcs
->cpu_state
= &self
->cpu_states
[tfcs
->cpu
];
1632 LttvTracefileContext
*tfc
= LTTV_TRACEFILE_CONTEXT(tfcs
);
1633 g_tree_remove(tsc
->pqueue
, tfc
);
1636 retval
= ltt_tracefile_seek_position(tfc
->tf
, ep
);
1637 g_assert_cmpint(retval
, ==, 0);
1638 tfc
->timestamp
= ltt_event_time(ltt_tracefile_get_event(tfc
->tf
));
1639 g_assert_cmpint(ltt_time_compare(tfc
->timestamp
, ltt_time_infinite
),
1641 g_tree_insert(tsc
->pqueue
, tfc
, tfc
);
1642 g_info("Restoring state for a tf at time %lu.%lu",
1643 tfc
->timestamp
.tv_sec
, tfc
->timestamp
.tv_nsec
);
1645 tfc
->timestamp
= ltt_time_infinite
;
1648 #endif /* BABEL_CLEANUP */
1652 * Note: the position must be explicitely set on the entire traceset to
1653 * match the trace states.
1655 LttvTracesetPosition
*lttv_trace_state_get_position(LttvAttribute
*container
)
1657 LttvAttributeType type
;
1658 LttvAttributeValue value
;
1660 type
= lttv_attribute_get_by_name(container
, LTTV_STATE_POSITION
, &value
);
1661 g_assert(type
== LTTV_POINTER
);
1662 return *(value
.v_pointer
);
1665 void lttv_state_saved_free(LttvTraceState
*self
, LttvAttribute
*container
)
1667 guint nb_cpus
, nb_irqs
, nb_soft_irqs
;
1668 guint
*running_process
;
1669 LttvAttributeType type
;
1670 LttvAttributeValue value
;
1672 type
= lttv_attribute_get_by_name(container
, LTTV_STATE_PROCESSES
,
1674 g_assert(type
== LTTV_POINTER
);
1675 lttv_state_free_process_table(*(value
.v_pointer
));
1676 *(value
.v_pointer
) = NULL
;
1677 lttv_attribute_remove_by_name(container
, LTTV_STATE_PROCESSES
);
1679 /* Free running processes array */
1680 type
= lttv_attribute_get_by_name(container
, LTTV_STATE_RUNNING_PROCESS
,
1682 g_assert(type
== LTTV_POINTER
);
1683 running_process
= *(value
.v_pointer
);
1684 g_free(running_process
);
1686 /* free cpu resources */
1687 type
= lttv_attribute_get_by_name(container
, LTTV_STATE_RESOURCE_CPUS_COUNT
, &value
);
1688 g_assert(type
== LTTV_UINT
);
1689 nb_cpus
= *value
.v_uint
;
1690 type
= lttv_attribute_get_by_name(container
, LTTV_STATE_RESOURCE_CPUS
, &value
);
1691 g_assert(type
== LTTV_POINTER
);
1692 lttv_state_free_cpu_states(*(value
.v_pointer
), nb_cpus
);
1694 /* free irq resource states */
1695 nb_irqs
= self
->name_tables
->nb_irqs
;
1696 type
= lttv_attribute_get_by_name(container
, LTTV_STATE_RESOURCE_IRQS
, &value
);
1697 g_assert(type
== LTTV_POINTER
);
1698 lttv_state_free_irq_states(*(value
.v_pointer
), nb_irqs
);
1700 /* free softirq resource states */
1701 nb_soft_irqs
= self
->name_tables
->nb_soft_irqs
;
1702 type
= lttv_attribute_get_by_name(container
, LTTV_STATE_RESOURCE_SOFT_IRQS
, &value
);
1703 g_assert(type
== LTTV_POINTER
);
1704 lttv_state_free_soft_irq_states(*(value
.v_pointer
), nb_soft_irqs
);
1706 /* free the blkdev states */
1707 type
= lttv_attribute_get_by_name(container
, LTTV_STATE_RESOURCE_BLKDEVS
, &value
);
1708 g_assert(type
== LTTV_POINTER
);
1709 lttv_state_free_blkdev_hashtable(*(value
.v_pointer
));
1711 /* remove the position */
1712 type
= lttv_attribute_get_by_name(container
, LTTV_STATE_POSITION
, &value
);
1713 g_assert(type
== LTTV_POINTER
);
1714 lttv_traceset_destroy_position(*(value
.v_pointer
));
1716 #ifdef BABEL_CLEANUP
1717 nb_tracefile
= self
->parent
.tracefiles
->len
;
1719 for(i
= 0 ; i
< nb_tracefile
; i
++) {
1721 type
= lttv_attribute_get(tracefiles_tree
, i
, &name
, &value
, &is_named
);
1722 g_assert(type
== LTTV_GOBJECT
);
1723 tracefile_tree
= *((LttvAttribute
**)(value
.v_gobject
));
1725 type
= lttv_attribute_get_by_name(tracefile_tree
, LTTV_STATE_EVENT
,
1727 g_assert(type
== LTTV_POINTER
);
1728 if(*(value
.v_pointer
) != NULL
) g_free(*(value
.v_pointer
));
1730 g_object_unref(G_OBJECT(tracefiles_tree
));
1731 #endif /* BABEL_CLEANUP */
1735 static void free_saved_state(LttvTraceState
*self
)
1738 LttvAttributeType type
;
1739 LttvAttributeValue value
;
1740 LttvAttributeName name
;
1742 LttvAttribute
*saved_states
;
1744 saved_states
= lttv_attribute_find_subdir(lttv_trace_attribute(self
->trace
),
1745 LTTV_STATE_SAVED_STATES
);
1747 nb
= lttv_attribute_get_number(saved_states
);
1748 for(i
= 0 ; i
< nb
; i
++) {
1749 type
= lttv_attribute_get(saved_states
, i
, &name
, &value
, &is_named
);
1750 g_assert(type
== LTTV_GOBJECT
);
1751 lttv_state_saved_free(self
, *((LttvAttribute
**)value
.v_gobject
));
1754 lttv_attribute_remove_by_name(lttv_trace_attribute(self
->trace
),
1755 LTTV_STATE_SAVED_STATES
);
1759 static void create_max_time(LttvTraceState
*trace_state
)
1761 LttvAttributeValue v
;
1763 lttv_attribute_find(lttv_trace_attribute(trace_state
->trace
),
1764 LTTV_STATE_SAVED_STATES_TIME
,
1766 g_assert(*(v
.v_pointer
) == NULL
);
1767 *(v
.v_pointer
) = g_new(LttTime
,1);
1768 *((LttTime
*)*(v
.v_pointer
)) = ltt_time_zero
;
1772 static void get_max_time(LttvTraceState
*trace_state
)
1774 LttvAttributeValue v
;
1776 lttv_attribute_find(lttv_trace_attribute(trace_state
->trace
),
1777 LTTV_STATE_SAVED_STATES_TIME
,
1779 g_assert(*(v
.v_pointer
) != NULL
);
1780 trace_state
->max_time_state_recomputed_in_seek
= (LttTime
*)*(v
.v_pointer
);
1784 static void free_max_time(LttvTraceState
*trace_state
)
1786 LttvAttributeValue v
;
1788 lttv_attribute_find(lttv_trace_attribute(trace_state
->trace
),
1789 LTTV_STATE_SAVED_STATES_TIME
,
1791 g_free(*(v
.v_pointer
));
1792 *(v
.v_pointer
) = NULL
;
1795 static void create_name_tables(LttvTraceState
*tcs
)
1799 GString
*fe_name
= g_string_new("");
1801 LttvNameTables
*name_tables
= g_new(LttvNameTables
, 1);
1803 LttvAttributeValue v
;
1807 lttv_attribute_find(lttv_trace_attribute(tcs
->trace
), LTTV_STATE_NAME_TABLES
,
1809 g_assert(*(v
.v_pointer
) == NULL
);
1810 *(v
.v_pointer
) = name_tables
;
1812 #ifdef BABEL_CLEANUP
1813 hooks
= g_array_sized_new(FALSE
, FALSE
, sizeof(LttvTraceHook
), 1);
1815 if(!lttv_trace_find_hook(tcs
->parent
.t
,
1817 LTT_EVENT_SYSCALL_ENTRY
,
1818 FIELD_ARRAY(LTT_FIELD_SYSCALL_ID
),
1819 NULL
, NULL
, &hooks
)) {
1821 // th = lttv_trace_hook_get_first(&th);
1823 // t = ltt_field_type(lttv_trace_get_hook_field(th, 0));
1824 // nb = ltt_type_element_number(t);
1826 // name_tables->syscall_names = g_new(GQuark, nb);
1827 // name_tables->nb_syscalls = nb;
1829 // for(i = 0 ; i < nb ; i++) {
1830 // name_tables->syscall_names[i] = ltt_enum_string_get(t, i);
1831 // if(!name_tables->syscall_names[i]) {
1832 // GString *string = g_string_new("");
1833 // g_string_printf(string, "syscall %u", i);
1834 // name_tables->syscall_names[i] = g_quark_from_string(string->str);
1835 // g_string_free(string, TRUE);
1838 #endif /* BABEL_CLEANUP */
1840 name_tables
->nb_syscalls
= PREALLOC_NB_SYSCALLS
;
1841 name_tables
->syscall_names
= g_new(GQuark
, name_tables
->nb_syscalls
);
1842 for(i
= 0 ; i
< name_tables
->nb_syscalls
; i
++) {
1843 g_string_printf(fe_name
, "syscall %d", i
);
1844 name_tables
->syscall_names
[i
] = g_quark_from_string(fe_name
->str
);
1846 #ifdef BABEL_CLEANUP
1848 name_tables
->syscall_names
= NULL
;
1849 name_tables
->nb_syscalls
= 0;
1851 lttv_trace_hook_remove_all(&hooks
);
1852 #endif /* BABEL_CLEANUP */
1854 #ifdef BABEL_CLEANUP
1855 if(!lttv_trace_find_hook(tcs
->parent
.t
,
1857 LTT_EVENT_TRAP_ENTRY
,
1858 FIELD_ARRAY(LTT_FIELD_TRAP_ID
),
1859 NULL
, NULL
, &hooks
) ||
1860 !lttv_trace_find_hook(tcs
->parent
.t
,
1862 LTT_EVENT_PAGE_FAULT_ENTRY
,
1863 FIELD_ARRAY(LTT_FIELD_TRAP_ID
),
1864 NULL
, NULL
, &hooks
)) {
1866 // th = lttv_trace_hook_get_first(&th);
1868 // t = ltt_field_type(lttv_trace_get_hook_field(th, 0));
1869 // //nb = ltt_type_element_number(t);
1871 // name_tables->trap_names = g_new(GQuark, nb);
1872 // for(i = 0 ; i < nb ; i++) {
1873 // name_tables->trap_names[i] = g_quark_from_string(
1874 // ltt_enum_string_get(t, i));
1877 #endif /* BABEL_CLEANUP */
1878 name_tables
->nb_traps
= PREALLOC_NB_TRAPS
;
1879 name_tables
->trap_names
= g_new(GQuark
, name_tables
->nb_traps
);
1880 for(i
= 0 ; i
< name_tables
->nb_traps
; i
++) {
1881 g_string_printf(fe_name
, "trap %d", i
);
1882 name_tables
->trap_names
[i
] = g_quark_from_string(fe_name
->str
);
1884 #ifdef BABEL_CLEANUP
1886 name_tables
->trap_names
= NULL
;
1887 name_tables
->nb_traps
= 0;
1889 lttv_trace_hook_remove_all(&hooks
);
1890 #endif /* BABEL_CLEANUP */
1892 #ifdef BABEL_CLEANUP
1893 if(!lttv_trace_find_hook(tcs
->parent
.t
,
1895 LTT_EVENT_IRQ_ENTRY
,
1896 FIELD_ARRAY(LTT_FIELD_IRQ_ID
),
1897 NULL
, NULL
, &hooks
)) {
1900 name_tables->irq_names = g_new(GQuark, nb);
1901 for(i = 0 ; i < nb ; i++) {
1902 name_tables->irq_names[i] = g_quark_from_string(ltt_enum_string_get(t, i));
1905 /* FIXME: LttvIRQState *irq_states should become a g_array */
1907 #endif /* BABEL_CLEANUP */
1908 name_tables
->nb_irqs
= PREALLOC_NB_IRQS
;
1909 name_tables
->irq_names
= g_new(GQuark
, name_tables
->nb_irqs
);
1910 for(i
= 0 ; i
< name_tables
->nb_irqs
; i
++) {
1911 g_string_printf(fe_name
, "irq %d", i
);
1912 name_tables
->irq_names
[i
] = g_quark_from_string(fe_name
->str
);
1914 #ifdef BABEL_CLEANUP
1916 name_tables
->nb_irqs
= 0;
1917 name_tables
->irq_names
= NULL
;
1919 lttv_trace_hook_remove_all(&hooks
);
1920 #endif /* BABEL_CLEANUP */
1922 name_tables->soft_irq_names = g_new(GQuark, nb);
1923 for(i = 0 ; i < nb ; i++) {
1924 name_tables->soft_irq_names[i] = g_quark_from_string(ltt_enum_string_get(t, i));
1928 name_tables
->nb_soft_irqs
= PREALLOC_NB_SOFT_IRQS
;
1929 name_tables
->soft_irq_names
= g_new(GQuark
, name_tables
->nb_soft_irqs
);
1930 for(i
= 0 ; i
< name_tables
->nb_soft_irqs
; i
++) {
1931 g_string_printf(fe_name
, "softirq %d", i
);
1932 name_tables
->soft_irq_names
[i
] = g_quark_from_string(fe_name
->str
);
1934 // g_array_free(hooks, TRUE);
1936 g_string_free(fe_name
, TRUE
);
1938 #if (__WORDSIZE == 32)
1939 name_tables
->kprobe_hash
= g_hash_table_new_full(guint64_hash
, guint64_equal
,
1942 name_tables
->kprobe_hash
= g_hash_table_new(g_direct_hash
, g_direct_equal
);
1947 static void get_name_tables(LttvTraceState
*tcs
)
1949 LttvAttributeValue v
;
1951 lttv_attribute_find(lttv_trace_attribute(tcs
->trace
), LTTV_STATE_NAME_TABLES
,
1953 g_assert(*(v
.v_pointer
) != NULL
);
1954 tcs
->name_tables
= (LttvNameTables
*)*(v
.v_pointer
);
1958 static void free_name_tables(LttvTraceState
*tcs
)
1960 LttvNameTables
*name_tables
;
1962 LttvAttributeValue v
;
1964 lttv_attribute_find(lttv_trace_attribute(tcs
->trace
), LTTV_STATE_NAME_TABLES
,
1966 name_tables
= (LttvNameTables
*)*(v
.v_pointer
);
1967 *(v
.v_pointer
) = NULL
;
1969 // g_free(name_tables->eventtype_names);
1970 if(name_tables
->syscall_names
) g_free(name_tables
->syscall_names
);
1971 if(name_tables
->trap_names
) g_free(name_tables
->trap_names
);
1972 if(name_tables
->irq_names
) g_free(name_tables
->irq_names
);
1973 if(name_tables
->soft_irq_names
) g_free(name_tables
->soft_irq_names
);
1974 g_hash_table_destroy(name_tables
->kprobe_hash
);
1975 g_free(name_tables
);
1978 #ifdef HASH_TABLE_DEBUG
1980 static void test_process(gpointer key
, gpointer value
, gpointer user_data
)
1982 LttvProcessState
*process
= (LttvProcessState
*)value
;
1984 /* Test for process corruption */
1985 guint stack_len
= process
->execution_stack
->len
;
1988 static void hash_table_check(GHashTable
*table
)
1990 g_hash_table_foreach(table
, test_process
, NULL
);
1996 /* clears the stack and sets the state passed as argument */
1997 static void cpu_set_base_mode(LttvCPUState
*cpust
, LttvCPUMode state
)
1999 g_array_set_size(cpust
->mode_stack
, 1);
2000 ((GQuark
*)cpust
->mode_stack
->data
)[0] = state
;
2003 static void cpu_push_mode(LttvCPUState
*cpust
, LttvCPUMode state
)
2005 g_array_set_size(cpust
->mode_stack
, cpust
->mode_stack
->len
+ 1);
2006 ((GQuark
*)cpust
->mode_stack
->data
)[cpust
->mode_stack
->len
- 1] = state
;
2009 static void cpu_pop_mode(LttvCPUState
*cpust
)
2011 if(cpust
->mode_stack
->len
<= 1)
2012 cpu_set_base_mode(cpust
, LTTV_CPU_UNKNOWN
);
2014 g_array_set_size(cpust
->mode_stack
, cpust
->mode_stack
->len
- 1);
2017 /* clears the stack and sets the state passed as argument */
2018 static void bdev_set_base_mode(LttvBdevState
*bdevst
, LttvBdevMode state
)
2020 g_array_set_size(bdevst
->mode_stack
, 1);
2021 ((GQuark
*)bdevst
->mode_stack
->data
)[0] = state
;
2024 static void bdev_push_mode(LttvBdevState
*bdevst
, LttvBdevMode state
)
2026 g_array_set_size(bdevst
->mode_stack
, bdevst
->mode_stack
->len
+ 1);
2027 ((GQuark
*)bdevst
->mode_stack
->data
)[bdevst
->mode_stack
->len
- 1] = state
;
2030 static void bdev_pop_mode(LttvBdevState
*bdevst
)
2032 if(bdevst
->mode_stack
->len
<= 1)
2033 bdev_set_base_mode(bdevst
, LTTV_BDEV_UNKNOWN
);
2035 g_array_set_size(bdevst
->mode_stack
, bdevst
->mode_stack
->len
- 1);
2038 static void irq_set_base_mode(LttvIRQState
*irqst
, LttvIRQMode state
)
2040 g_array_set_size(irqst
->mode_stack
, 1);
2041 ((GQuark
*)irqst
->mode_stack
->data
)[0] = state
;
2044 static void irq_push_mode(LttvIRQState
*irqst
, LttvIRQMode state
)
2046 g_array_set_size(irqst
->mode_stack
, irqst
->mode_stack
->len
+ 1);
2047 ((GQuark
*)irqst
->mode_stack
->data
)[irqst
->mode_stack
->len
- 1] = state
;
2050 static void irq_pop_mode(LttvIRQState
*irqst
)
2052 if(irqst
->mode_stack
->len
<= 1)
2053 irq_set_base_mode(irqst
, LTTV_IRQ_UNKNOWN
);
2055 g_array_set_size(irqst
->mode_stack
, irqst
->mode_stack
->len
- 1);
2058 static void push_state(LttvEvent
*event
,
2059 LttvTraceState
*ts
, LttvExecutionMode t
,
2062 LttvExecutionState
*es
;
2065 cpu
= lttv_traceset_get_cpuid_from_event(event
);
2068 #ifdef HASH_TABLE_DEBUG
2069 hash_table_check(ts
->processes
);
2071 LttvProcessState
*process
= ts
->running_process
[cpu
];
2073 guint depth
= process
->execution_stack
->len
;
2075 process
->execution_stack
=
2076 g_array_set_size(process
->execution_stack
, depth
+ 1);
2079 &g_array_index(process
->execution_stack
, LttvExecutionState
, depth
- 1);
2081 es
= &g_array_index(process
->execution_stack
, LttvExecutionState
, depth
);
2084 es
->entry
= es
->change
= lttv_event_get_timestamp(event
);
2085 es
->cum_cpu_time
= ltt_time_zero
;
2086 es
->s
= process
->state
->s
;
2087 process
->state
= es
;
2091 * return 1 when empty, else 0 */
2093 lttv_state_pop_state_cleanup(LttvProcessState
*process
, LttvEvent
*event
)
2095 guint depth
= process
->execution_stack
->len
;
2101 process
->execution_stack
=
2102 g_array_set_size(process
->execution_stack
, depth
- 1);
2103 process
->state
= &g_array_index(process
->execution_stack
, LttvExecutionState
,
2105 process
->state
->change
= lttv_event_get_timestamp(event
);
2110 static void pop_state(LttvEvent
*event
,
2111 LttvTraceState
*ts
, LttvExecutionMode t
)
2113 LttvProcessState
*process
;
2116 cpu
= lttv_traceset_get_cpuid_from_event(event
);
2118 process
= ts
->running_process
[cpu
];
2120 guint depth
= process
->execution_stack
->len
;
2122 if(process
->state
->t
!= t
){
2123 g_info("Different execution mode type: ignore it\n"
2126 g_info("process state has %s when pop_int is %s\n",
2127 g_quark_to_string(process
->state
->t
),
2128 g_quark_to_string(t
));
2129 g_info("{ %u, %u, %s, %s, %s }\n",
2132 g_quark_to_string(process
->name
),
2133 g_quark_to_string(process
->brand
),
2134 g_quark_to_string(process
->state
->s
));
2139 //TODO ybrosseau readd debug
2140 //g_info("Trying to pop last state on stack (%lu.%09lu): ignore it\n",
2141 // tfs->parent.timestamp.tv_sec, tfs->parent.timestamp.tv_nsec);
2142 g_info("Trying to pop last state on stack: ignore it\n");
2146 process
->execution_stack
=
2147 g_array_set_size(process
->execution_stack
, depth
- 1);
2148 process
->state
= &g_array_index(process
->execution_stack
, LttvExecutionState
,
2150 process
->state
->change
= lttv_event_get_timestamp(event
);
2153 struct search_result
{
2154 const LttTime
*time
; /* Requested time */
2155 LttTime
*best
; /* Best result */
2158 /* Return a new and initialized LttvProcessState structure */
2160 LttvProcessState
*lttv_state_create_process(LttvTraceState
*tcs
,
2161 LttvProcessState
*parent
, guint cpu
, guint pid
,
2162 guint tgid
, GQuark name
, const LttTime
*timestamp
)
2164 LttvProcessState
*process
= g_new(LttvProcessState
, 1);
2166 LttvExecutionState
*es
;
2171 process
->tgid
= tgid
;
2173 process
->name
= name
;
2174 process
->brand
= LTTV_STATE_UNBRANDED
;
2175 //process->last_cpu = tfs->cpu_name;
2176 //process->last_cpu_index = ltt_tracefile_num(((LttvTracefileContext*)tfs)->tf);
2177 process
->type
= LTTV_STATE_USER_THREAD
;
2179 g_info("Process %u, core %p", process
->pid
, process
);
2180 g_hash_table_insert(tcs
->processes
, process
, process
);
2183 process
->ppid
= parent
->pid
;
2184 process
->creation_time
= *timestamp
;
2187 /* No parent. This process exists but we are missing all information about
2188 its creation. The birth time is set to zero but we remember the time of
2193 process
->creation_time
= ltt_time_zero
;
2196 process
->insertion_time
= *timestamp
;
2197 sprintf(buffer
,"%d-%lu.%lu",pid
, process
->creation_time
.tv_sec
,
2198 process
->creation_time
.tv_nsec
);
2199 process
->pid_time
= g_quark_from_string(buffer
);
2201 process
->free_events
= 0;
2202 //process->last_cpu = tfs->cpu_name;
2203 //process->last_cpu_index = ltt_tracefile_num(((LttvTracefileContext*)tfs)->tf);
2204 process
->execution_stack
= g_array_sized_new(FALSE
, FALSE
,
2205 sizeof(LttvExecutionState
), PREALLOCATED_EXECUTION_STACK
);
2206 process
->execution_stack
= g_array_set_size(process
->execution_stack
, 2);
2207 es
= process
->state
= &g_array_index(process
->execution_stack
,
2208 LttvExecutionState
, 0);
2209 es
->t
= LTTV_STATE_USER_MODE
;
2210 es
->n
= LTTV_STATE_SUBMODE_NONE
;
2211 es
->entry
= *timestamp
;
2212 //g_assert(timestamp->tv_sec != 0);
2213 es
->change
= *timestamp
;
2214 es
->cum_cpu_time
= ltt_time_zero
;
2215 es
->s
= LTTV_STATE_RUN
;
2217 es
= process
->state
= &g_array_index(process
->execution_stack
,
2218 LttvExecutionState
, 1);
2219 es
->t
= LTTV_STATE_SYSCALL
;
2220 es
->n
= LTTV_STATE_SUBMODE_NONE
;
2221 es
->entry
= *timestamp
;
2222 //g_assert(timestamp->tv_sec != 0);
2223 es
->change
= *timestamp
;
2224 es
->cum_cpu_time
= ltt_time_zero
;
2225 es
->s
= LTTV_STATE_WAIT_FORK
;
2227 /* Allocate an empty function call stack. If it's empty, use 0x0. */
2228 #ifdef BABEL_CLEANUP
2229 //process->user_stack = g_array_sized_new(FALSE, FALSE,
2230 // sizeof(guint64), 0);
2232 process
->fds
= g_hash_table_new(g_direct_hash
, g_direct_equal
);
2238 lttv_state_find_process(LttvTraceState
*ts
, guint cpu
, guint pid
)
2240 LttvProcessState key
;
2241 LttvProcessState
*process
;
2245 process
= g_hash_table_lookup(ts
->processes
, &key
);
2249 LttvProcessState
*lttv_state_find_process_or_create(LttvTraceState
*ts
,
2250 guint cpu
, guint pid
, const LttTime
*timestamp
)
2252 LttvProcessState
*process
= lttv_state_find_process(ts
, cpu
, pid
);
2253 LttvExecutionState
*es
;
2255 /* Put ltt_time_zero creation time for unexisting processes */
2256 if(unlikely(process
== NULL
)) {
2257 process
= lttv_state_create_process(ts
,
2258 NULL
, cpu
, pid
, 0, LTTV_STATE_UNNAMED
, timestamp
);
2259 /* We are not sure is it's a kernel thread or normal thread, put the
2260 * bottom stack state to unknown */
2261 process
->execution_stack
=
2262 g_array_set_size(process
->execution_stack
, 1);
2263 process
->state
= es
=
2264 &g_array_index(process
->execution_stack
, LttvExecutionState
, 0);
2265 es
->t
= LTTV_STATE_MODE_UNKNOWN
;
2266 es
->s
= LTTV_STATE_UNNAMED
;
2271 /* FIXME : this function should be called when we receive an event telling that
2272 * release_task has been called in the kernel. In happens generally when
2273 * the parent waits for its child termination, but may also happens in special
2274 * cases in the child's exit : when the parent ignores its children SIGCCHLD or
2275 * has the flag SA_NOCLDWAIT. It can also happen when the child is part
2276 * of a killed thread group, but isn't the leader.
2278 static int exit_process(LttvEvent
*event
, LttvProcessState
*process
)
2280 LttvTraceState
*ts
= event
->state
;
2281 LttvProcessState key
;
2283 /* Wait for both schedule with exit dead and process free to happen.
2284 * They can happen in any order. */
2285 if (++(process
->free_events
) < 2)
2288 key
.pid
= process
->pid
;
2289 key
.cpu
= process
->cpu
;
2290 g_hash_table_remove(ts
->processes
, &key
);
2291 g_array_free(process
->execution_stack
, TRUE
);
2293 /* the following also clears the content */
2294 g_hash_table_destroy(process
->fds
);
2301 static void free_process_state(gpointer key
, gpointer value
,gpointer user_data
)
2303 g_array_free(((LttvProcessState
*)value
)->execution_stack
, TRUE
);
2305 /* the following also clears the content */
2306 g_hash_table_destroy(((LttvProcessState
*)value
)->fds
);
2312 static void lttv_state_free_process_table(GHashTable
*processes
)
2314 g_hash_table_foreach(processes
, free_process_state
, NULL
);
2315 g_hash_table_destroy(processes
);
2319 static gboolean
syscall_entry(void *hook_data
, void *call_data
)
2324 LttvProcessState
*process
;
2325 LttvExecutionSubmode submode
;
2326 char syscall_name
[200];
2328 event
= (LttvEvent
*) call_data
;
2329 if (strncmp(lttv_traceset_get_name_from_event(event
),
2330 "sys_", sizeof("sys_") - 1) != 0)
2333 strncpy(syscall_name
,lttv_traceset_get_name_from_event(event
)+4,200);
2335 cpu
= lttv_traceset_get_cpuid_from_event(event
);
2337 process
= ts
->running_process
[cpu
];
2339 submode
= g_quark_from_string(syscall_name
);
2340 /* There can be no system call from PID 0 : unknown state */
2341 if(process
->pid
!= 0)
2342 push_state(event
, ts
, LTTV_STATE_SYSCALL
, submode
);
2347 static gboolean
syscall_exit(void *hook_data
, void *call_data
)
2352 LttvProcessState
*process
;
2355 event
= (LttvEvent
*) call_data
;
2356 if (strcmp(lttv_traceset_get_name_from_event(event
),
2357 "exit_syscall") != 0)
2360 cpu
= lttv_traceset_get_cpuid_from_event(event
);
2362 process
= ts
->running_process
[cpu
];
2364 /* There can be no system call from PID 0 : unknown state */
2365 if (process
->pid
!= 0)
2366 pop_state(event
, ts
, LTTV_STATE_SYSCALL
);
2370 #ifdef BABEL_CLEANUP
2371 static gboolean
trap_entry(void *hook_data
, void *call_data
)
2373 LttvTracefileState
*s
= (LttvTracefileState
*)call_data
;
2374 LttvTraceState
*ts
= (LttvTraceState
*)s
->parent
.t_context
;
2375 LttEvent
*e
= ltt_tracefile_get_event(s
->parent
.tf
);
2376 LttvTraceHook
*th
= (LttvTraceHook
*)hook_data
;
2377 struct marker_field
*f
= lttv_trace_get_hook_field(th
, 0);
2378 LttvNameTables
*nt
= ((LttvTraceState
*)(s
->parent
.t_context
))->name_tables
;
2380 LttvExecutionSubmode submode
;
2382 guint64 trap
= ltt_event_get_long_unsigned(e
, f
);
2384 expand_trap_table(ts
, trap
);
2386 submode
= nt
->trap_names
[trap
];
2388 push_state(s
, LTTV_STATE_TRAP
, submode
);
2390 /* update cpu status */
2391 cpu_push_mode(s
->cpu_state
, LTTV_CPU_TRAP
);
2393 /* update trap status */
2394 g_array_append_val(s
->cpu_state
->trap_stack
, trap
);
2395 ts
->trap_states
[trap
].running
++;
2400 static gboolean
trap_exit(void *hook_data
, void *call_data
)
2402 LttvTracefileState
*s
= (LttvTracefileState
*)call_data
;
2403 LttvTraceState
*ts
= (LttvTraceState
*)s
->parent
.t_context
;
2405 pop_state(s
, LTTV_STATE_TRAP
);
2407 /* update cpu status */
2408 cpu_pop_mode(s
->cpu_state
);
2410 /* update trap status */
2411 if (s
->cpu_state
->trap_stack
->len
> 0) {
2412 gint last
= g_array_index(s
->cpu_state
->trap_stack
, gint
,
2413 s
->cpu_state
->trap_stack
->len
-1);
2414 if(ts
->trap_states
[last
].running
)
2415 ts
->trap_states
[last
].running
--;
2416 g_array_remove_index(s
->cpu_state
->trap_stack
,
2417 s
->cpu_state
->trap_stack
->len
-1);
2421 #endif /* BABEL_CLEANUP */
2423 static gboolean
irq_entry(void *hook_data
, void *call_data
)
2429 LttvExecutionSubmode submode
;
2433 event
= (LttvEvent
*) call_data
;
2434 if (strcmp(lttv_traceset_get_name_from_event(event
),
2435 "irq_handler_entry") != 0)
2438 cpu
= lttv_traceset_get_cpuid_from_event(event
);
2441 nt
= ts
->name_tables
;
2442 irq
= lttv_event_get_long_unsigned(event
, "irq");
2444 expand_irq_table(ts
, irq
);
2446 submode
= nt
->irq_names
[irq
];
2448 /* Do something with the info about being in user or system mode when int? */
2449 push_state(event
, ts
, LTTV_STATE_IRQ
, submode
);
2451 /* update cpu status */
2452 cpu_push_mode(&(ts
->cpu_states
[cpu
]), LTTV_CPU_IRQ
);
2454 /* update irq status */
2455 g_array_append_val(ts
->cpu_states
[cpu
].irq_stack
, irq
);
2456 irq_push_mode(&ts
->irq_states
[irq
], LTTV_IRQ_BUSY
);
2461 static gboolean
soft_irq_exit(void *hook_data
, void *call_data
)
2467 LttvCPUState
*cpu_state
;
2469 event
= (LttvEvent
*) call_data
;
2470 if (strcmp(lttv_traceset_get_name_from_event(event
),
2471 "softirq_exit") != 0)
2474 cpu
= lttv_traceset_get_cpuid_from_event(event
);
2477 cpu_state
= &(ts
->cpu_states
[cpu
]);
2478 pop_state(event
, ts
, LTTV_STATE_SOFT_IRQ
);
2480 /* update cpu status */
2481 cpu_pop_mode(cpu_state
);
2483 /* update softirq status */
2484 if (cpu_state
->softirq_stack
->len
> 0) {
2485 gint last
= g_array_index(cpu_state
->softirq_stack
, gint
, cpu_state
->softirq_stack
->len
-1);
2486 if(ts
->soft_irq_states
[last
].running
)
2487 ts
->soft_irq_states
[last
].running
--;
2488 g_array_remove_index(cpu_state
->softirq_stack
, cpu_state
->softirq_stack
->len
-1);
2493 static gboolean
irq_exit(void *hook_data
, void *call_data
)
2499 LttvCPUState
*cpu_state
;
2501 event
= (LttvEvent
*) call_data
;
2502 if (strcmp(lttv_traceset_get_name_from_event(event
),
2503 "irq_handler_exit") != 0)
2506 cpu
= lttv_traceset_get_cpuid_from_event(event
);
2508 cpu_state
= &(ts
->cpu_states
[cpu
]);
2510 pop_state(event
, ts
, LTTV_STATE_IRQ
);
2512 /* update cpu status */
2513 cpu_pop_mode(cpu_state
);
2515 /* update irq status */
2516 if (cpu_state
->irq_stack
->len
> 0) {
2517 gint last
= g_array_index(cpu_state
->irq_stack
, gint
, cpu_state
->irq_stack
->len
-1);
2518 g_array_remove_index(cpu_state
->irq_stack
, cpu_state
->irq_stack
->len
-1);
2519 irq_pop_mode(&ts
->irq_states
[last
]);
2525 static gboolean
soft_irq_raise(void *hook_data
, void *call_data
)
2533 event
= (LttvEvent
*) call_data
;
2534 if (strcmp(lttv_traceset_get_name_from_event(event
),
2535 "softirq_raise") != 0)
2538 //cpu = lttv_traceset_get_cpuid_from_event(event);
2540 softirq
= lttv_event_get_long_unsigned(event
, "vec");
2542 expand_soft_irq_table(ts
, softirq
);
2544 /* update softirq status */
2545 /* a soft irq raises are not cumulative */
2546 ts
->soft_irq_states
[softirq
].pending
=1;
2551 static gboolean
soft_irq_entry(void *hook_data
, void *call_data
)
2556 LttvExecutionSubmode submode
;
2560 event
= (LttvEvent
*) call_data
;
2561 if (strcmp(lttv_traceset_get_name_from_event(event
),
2562 "softirq_entry") != 0)
2565 cpu
= lttv_traceset_get_cpuid_from_event(event
);
2571 softirq
= lttv_event_get_long_unsigned(event
, "vec");
2572 expand_soft_irq_table(ts
, softirq
);
2573 nt
= ts
->name_tables
;
2574 submode
= nt
->soft_irq_names
[softirq
];
2576 /* Do something with the info about being in user or system mode when int? */
2577 push_state(event
, ts
, LTTV_STATE_SOFT_IRQ
, submode
);
2579 /* update cpu status */
2580 cpu_push_mode(&(ts
->cpu_states
[cpu
]), LTTV_CPU_SOFT_IRQ
);
2582 /* update softirq status */
2583 g_array_append_val(ts
->cpu_states
[cpu
].softirq_stack
, softirq
);
2584 if (ts
->soft_irq_states
[softirq
].pending
)
2585 ts
->soft_irq_states
[softirq
].pending
--;
2586 ts
->soft_irq_states
[softirq
].running
++;
2591 static gboolean
enum_interrupt(void *hook_data
, void *call_data
)
2601 event
= (LttvEvent
*) call_data
;
2602 if (strcmp(lttv_traceset_get_name_from_event(event
),
2603 "lttng_statedump_interrupt") != 0)
2607 nt
= ts
->name_tables
;
2608 irq
= lttv_event_get_long_unsigned(event
, "irq");
2609 action
= g_quark_from_string(lttv_event_get_string(event
,
2611 expand_irq_table(ts
, irq
);
2612 nt
->irq_names
[irq
] = action
;
2617 #ifdef BABEL_CLEANUP
2618 static gboolean
bdev_request_issue(void *hook_data
, void *call_data
)
2629 event
= (LttvEvent
*) call_data
;
2630 if (strcmp(lttv_traceset_get_name_from_event(event
),
2631 "block_rq_issue") != 0)
2635 major
= lttv_event_get_long_unsigned(event
,);
2637 minor
= lttv_event_get_long_unsigned(event
,);
2639 oper
= lttv_event_get_long_unsigned(event
,);
2641 devcode
= MKDEV(major
,minor
);
2643 /* have we seen this block device before? */
2644 bdev
= get_hashed_bdevstate(ts
, devcode
);
2646 bdev_push_mode(bdev
, LTTV_BDEV_BUSY_READING
);
2648 bdev_push_mode(bdev
, LTTV_BDEV_BUSY_WRITING
);
2653 static gboolean
bdev_request_complete(void *hook_data
, void *call_data
)
2655 LttvTracefileState
*s
= (LttvTracefileState
*)call_data
;
2656 LttvTraceState
*ts
= (LttvTraceState
*)s
->parent
.t_context
;
2657 LttEvent
*e
= ltt_tracefile_get_event(s
->parent
.tf
);
2658 LttvTraceHook
*th
= (LttvTraceHook
*)hook_data
;
2660 guint major
= ltt_event_get_long_unsigned(e
,
2661 lttv_trace_get_hook_field(th
, 0));
2662 guint minor
= ltt_event_get_long_unsigned(e
,
2663 lttv_trace_get_hook_field(th
, 1));
2664 //guint oper = ltt_event_get_long_unsigned(e,
2665 // lttv_trace_get_hook_field(th, 2));
2666 guint32 devcode
= MKDEV(major
,minor
);
2668 /* have we seen this block device before? */
2669 gpointer bdev
= get_hashed_bdevstate(ts
, devcode
);
2671 /* update block device */
2672 bdev_pop_mode(bdev
);
2677 #ifdef BABEL_CLEANUP
2678 // We dont have the syscall table in LTTng 2.0
2679 static gboolean
dump_syscall(void *hook_data
, void *call_data
)
2681 LttvTracefileState
*s
= (LttvTracefileState
*)call_data
;
2682 LttvTraceState
*ts
= (LttvTraceState
*)s
->parent
.t_context
;
2683 LttvNameTables
*nt
= ts
->name_tables
;
2684 LttEvent
*e
= ltt_tracefile_get_event(s
->parent
.tf
);
2685 LttvTraceHook
*th
= (LttvTraceHook
*)hook_data
;
2689 id
= ltt_event_get_unsigned(e
, lttv_trace_get_hook_field(th
, 0));
2690 symbol
= ltt_event_get_string(e
, lttv_trace_get_hook_field(th
, 2));
2692 expand_syscall_table(ts
, id
);
2693 nt
->syscall_names
[id
] = g_quark_from_string(symbol
);
2698 static gboolean
dump_kprobe(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 LttvTraceHook
*th
= (LttvTraceHook
*)hook_data
;
2707 ip
= ltt_event_get_long_unsigned(e
, lttv_trace_get_hook_field(th
, 0));
2708 symbol
= ltt_event_get_string(e
, lttv_trace_get_hook_field(th
, 1));
2710 expand_kprobe_table(ts
, ip
, symbol
);
2715 #ifdef BABEL_CLEANUP
2716 static gboolean
dump_softirq(void *hook_data
, void *call_data
)
2719 LttvTracefileState
*s
= (LttvTracefileState
*)call_data
;
2720 LttvTraceState
*ts
= (LttvTraceState
*)s
->parent
.t_context
;
2721 LttvNameTables
*nt
= ts
->name_tables
;
2722 LttEvent
*e
= ltt_tracefile_get_event(s
->parent
.tf
);
2723 LttvTraceHook
*th
= (LttvTraceHook
*)hook_data
;
2727 id
= ltt_event_get_unsigned(e
, lttv_trace_get_hook_field(th
, 0));
2728 symbol
= ltt_event_get_string(e
, lttv_trace_get_hook_field(th
, 2));
2730 expand_soft_irq_table(ts
, id
);
2731 nt
->soft_irq_names
[id
] = g_quark_from_string(symbol
);
2737 static gboolean
sched_try_wakeup(void *hook_data
, void *call_data
)
2741 LttvProcessState
*process
;
2746 event
= (LttvEvent
*) call_data
;
2747 if (strcmp(lttv_traceset_get_name_from_event(event
),
2748 "sched_wakeup") != 0)
2753 woken_pid
= lttv_event_get_long(event
, "tid");
2754 woken_cpu
= lttv_event_get_long_unsigned(event
, "target_cpu");
2756 timestamp
= lttv_event_get_timestamp(event
);
2757 process
= lttv_state_find_process_or_create(
2759 woken_cpu
, woken_pid
,
2762 if (process
->state
->s
== LTTV_STATE_WAIT
|| process
->state
->s
== LTTV_STATE_WAIT_FORK
)
2764 process
->state
->s
= LTTV_STATE_WAIT_CPU
;
2765 process
->state
->change
= timestamp
;
2768 g_debug("Wakeup: process %d on CPU %u\n", woken_pid
, woken_cpu
);
2773 static gboolean
schedchange(void *hook_data
, void *call_data
)
2778 LttvProcessState
*process
;
2781 //LttvProcessState *old_process = ts->running_process[cpu];
2783 guint pid_in
, pid_out
;
2785 //TODO ybrosseau 2012-07-13: manage this 20 in a constact or dynamically
2788 event
= (LttvEvent
*) call_data
;
2789 if (strcmp(lttv_traceset_get_name_from_event(event
),
2790 "sched_switch") != 0)
2793 cpu
= lttv_traceset_get_cpuid_from_event(event
);
2795 process
= ts
->running_process
[cpu
];
2796 pid_out
= lttv_event_get_long(event
, "prev_tid");
2797 pid_in
= lttv_event_get_long(event
, "next_tid");
2798 state_out
= lttv_event_get_long(event
, "prev_state");
2800 strncpy(next_comm
, lttv_event_get_string(event
, "next_comm"), 20);
2801 next_comm
[20-1] = '\0';
2803 timestamp
= lttv_event_get_timestamp(event
);
2805 if(likely(process
!= NULL
)) {
2807 /* We could not know but it was not the idle process executing.
2808 This should only happen at the beginning, before the first schedule
2809 event, and when the initial information (current process for each CPU)
2810 is missing. It is not obvious how we could, after the fact, compensate
2811 the wrongly attributed statistics. */
2813 //This test only makes sense once the state is known and if there is no
2814 //missing events. We need to silently ignore schedchange coming after a
2815 //process_free, or it causes glitches. (FIXME)
2816 //if(unlikely(process->pid != pid_out)) {
2817 // g_assert(process->pid == 0);
2819 if(process
->pid
== 0
2820 && process
->state
->t
== LTTV_STATE_MODE_UNKNOWN
) {
2823 * Scheduling out of pid 0 at beginning of the trace.
2824 * We are typically in system call mode at this point although
2825 * (FIXME) we might be in a trap handler.
2827 g_assert(process
->execution_stack
->len
== 1);
2828 process
->state
->t
= LTTV_STATE_SYSCALL
;
2829 process
->state
->s
= LTTV_STATE_WAIT
;
2830 process
->state
->change
= timestamp
;
2831 process
->state
->entry
= timestamp
;
2834 if(unlikely(process
->state
->s
== LTTV_STATE_EXIT
)) {
2835 process
->state
->s
= LTTV_STATE_ZOMBIE
;
2836 process
->state
->change
= timestamp
;
2838 if(unlikely(state_out
== 0)) process
->state
->s
= LTTV_STATE_WAIT_CPU
;
2839 else process
->state
->s
= LTTV_STATE_WAIT
;
2840 process
->state
->change
= timestamp
;
2843 if(state_out
== 32 || state_out
== 64) { /* EXIT_DEAD || TASK_DEAD */
2844 /* see sched.h for states */
2845 if (!exit_process(event
, process
)) {
2846 process
->state
->s
= LTTV_STATE_DEAD
;
2847 process
->state
->change
= timestamp
;
2852 process
= ts
->running_process
[cpu
] = lttv_state_find_process_or_create(
2856 process
->state
->s
= LTTV_STATE_RUN
;
2858 // process->last_cpu_index = ltt_tracefile_num(((LttvTracefileContext*)s)->tf);
2859 process
->state
->change
= timestamp
;
2860 process
->name
= g_quark_from_string(next_comm
);
2862 /* update cpu status */
2864 /* going to idle task */
2865 cpu_set_base_mode(&(ts
->cpu_states
[cpu
]), LTTV_CPU_IDLE
);
2867 /* scheduling a real task.
2868 * we must be careful here:
2869 * if we just schedule()'ed to a process that is
2870 * in a trap, we must put the cpu in trap mode
2872 cpu_set_base_mode(&(ts
->cpu_states
[cpu
]), LTTV_CPU_BUSY
);
2873 if(process
->state
->t
== LTTV_STATE_TRAP
)
2874 cpu_push_mode(&(ts
->cpu_states
[cpu
]), LTTV_CPU_TRAP
);
2880 static gboolean
process_fork(void *hook_data
, void *call_data
)
2884 LttvProcessState
*process
;
2885 LttvProcessState
*child_process
;
2886 guint child_pid
; /* In the Linux Kernel, there is one PID per thread. */
2887 guint child_tgid
; /* tgid in the Linux kernel is the "real" POSIX PID. */
2888 //LttvProcessState *zombie_process;
2892 event
= (LttvEvent
*) call_data
;
2893 if (strcmp(lttv_traceset_get_name_from_event(event
),
2894 "sched_process_fork") != 0)
2896 cpu
= lttv_traceset_get_cpuid_from_event(event
);
2898 process
= ts
->running_process
[cpu
];
2899 timestamp
= lttv_event_get_timestamp(event
);
2901 /* Skip Parent PID param */
2904 child_pid
= lttv_event_get_long_unsigned(event
, "child_tid");
2905 //ts->target_pid = child_pid;
2911 /* Mathieu : it seems like the process might have been scheduled in before the
2912 * fork, and, in a rare case, might be the current process. This might happen
2913 * in a SMP case where we don't have enough precision on the clocks.
2915 * Test reenabled after precision fixes on time. (Mathieu) */
2917 zombie_process
= lttv_state_find_process(ts
, ANY_CPU
, child_pid
);
2919 if(unlikely(zombie_process
!= NULL
)) {
2920 /* Reutilisation of PID. Only now we are sure that the old PID
2921 * has been released. FIXME : should know when release_task happens instead.
2923 guint num_cpus
= ltt_trace_get_num_cpu(ts
->parent
.t
);
2925 for(i
=0; i
< num_cpus
; i
++) {
2926 g_assert(zombie_process
!= ts
->running_process
[i
]);
2929 exit_process(s
, zombie_process
);
2932 g_assert(process
->pid
!= child_pid
);
2933 // FIXME : Add this test in the "known state" section
2934 // g_assert(process->pid == parent_pid);
2935 child_process
= lttv_state_find_process(ts
, ANY_CPU
, child_pid
);
2936 if(child_process
== NULL
) {
2937 child_process
= lttv_state_create_process(ts
, process
, cpu
,
2938 child_pid
, child_tgid
,
2939 LTTV_STATE_UNNAMED
, ×tamp
);
2941 /* The process has already been created : due to time imprecision between
2942 * multiple CPUs : it has been scheduled in before creation. Note that we
2943 * shouldn't have this kind of imprecision.
2945 * Simply put a correct parent.
2947 g_error("Process %u has been created at [%lu.%09lu] "
2948 "and inserted at [%lu.%09lu] before \n"
2949 "fork on cpu %u[%lu.%09lu].\n"
2950 "Probably an unsynchronized TSC problem on the traced machine.",
2952 child_process
->creation_time
.tv_sec
,
2953 child_process
->creation_time
.tv_nsec
,
2954 child_process
->insertion_time
.tv_sec
,
2955 child_process
->insertion_time
.tv_nsec
,
2956 cpu
, timestamp
.tv_sec
, timestamp
.tv_nsec
);
2957 //g_assert(0); /* This is a problematic case : the process has been created
2958 // before the fork event */
2959 child_process
->ppid
= process
->pid
;
2960 child_process
->tgid
= child_tgid
;
2962 g_assert(child_process
->name
== LTTV_STATE_UNNAMED
);
2963 child_process
->name
= process
->name
;
2964 child_process
->brand
= process
->brand
;
2969 #ifdef BABEL_CLEANUP
2970 //NO KTHREAD_CREATE in LTTng 2.0
2971 /* We stamp a newly created process as kernel_thread.
2972 * The thread should not be running yet. */
2973 static gboolean
process_kernel_thread(void *hook_data
, void *call_data
)
2975 LttvTracefileState
*s
= (LttvTracefileState
*)call_data
;
2976 LttEvent
*e
= ltt_tracefile_get_event(s
->parent
.tf
);
2977 LttvTraceHook
*th
= (LttvTraceHook
*)hook_data
;
2979 LttvTraceState
*ts
= (LttvTraceState
*)s
->parent
.t_context
;
2980 LttvProcessState
*process
;
2981 LttvExecutionState
*es
;
2984 pid
= (guint
)ltt_event_get_long_unsigned(e
, lttv_trace_get_hook_field(th
, 0));
2985 //s->parent.target_pid = pid;
2987 process
= lttv_state_find_process_or_create(ts
, ANY_CPU
, pid
,
2989 if (process
->state
->s
!= LTTV_STATE_DEAD
) {
2990 process
->execution_stack
=
2991 g_array_set_size(process
->execution_stack
, 1);
2992 es
= process
->state
=
2993 &g_array_index(process
->execution_stack
, LttvExecutionState
, 0);
2994 es
->t
= LTTV_STATE_SYSCALL
;
2996 process
->type
= LTTV_STATE_KERNEL_THREAD
;
3001 static gboolean
process_exit(void *hook_data
, void *call_data
)
3007 LttvProcessState
*process
; // = ts->running_process[cpu];
3009 event
= (LttvEvent
*) call_data
;
3010 if (strcmp(lttv_traceset_get_name_from_event(event
),
3011 "sched_process_exit") != 0)
3013 cpu
= lttv_traceset_get_cpuid_from_event(event
);
3015 process
= ts
->running_process
[cpu
];
3017 pid
= lttv_event_get_long_unsigned(event
, "tid");
3018 //s->parent.target_pid = pid;
3020 // FIXME : Add this test in the "known state" section
3021 // g_assert(process->pid == pid);
3023 process
= lttv_state_find_process(ts
, ANY_CPU
, pid
);
3024 if(likely(process
!= NULL
)) {
3025 process
->state
->s
= LTTV_STATE_EXIT
;
3030 static gboolean
process_free(void *hook_data
, void *call_data
)
3036 LttvProcessState
*process
;
3038 event
= (LttvEvent
*) call_data
;
3039 if (strcmp(lttv_traceset_get_name_from_event(event
),
3040 "sched_process_free") != 0)
3042 cpu
= lttv_traceset_get_cpuid_from_event(event
);
3044 process
= ts
->running_process
[cpu
];
3046 /* PID of the process to release */
3047 release_pid
= lttv_event_get_long_unsigned(event
, "_tid");
3048 //s->parent.target_pid = release_pid;
3050 g_assert(release_pid
!= 0);
3052 process
= lttv_state_find_process(ts
, ANY_CPU
, release_pid
);
3053 if(likely(process
!= NULL
))
3054 exit_process(event
, process
);
3058 if(likely(process
!= NULL
)) {
3059 /* release_task is happening at kernel level : we can now safely release
3060 * the data structure of the process */
3061 //This test is fun, though, as it may happen that
3062 //at time t : CPU 0 : process_free
3063 //at time t+150ns : CPU 1 : schedule out
3064 //Clearly due to time imprecision, we disable it. (Mathieu)
3065 //If this weird case happen, we have no choice but to put the
3066 //Currently running process on the cpu to 0.
3067 //I re-enable it following time precision fixes. (Mathieu)
3068 //Well, in the case where an process is freed by a process on another CPU
3069 //and still scheduled, it happens that this is the schedchange that will
3070 //drop the last reference count. Do not free it here!
3071 guint num_cpus
= ltt_trace_get_num_cpu(ts
->parent
.t
);
3073 for(i
=0; i
< num_cpus
; i
++) {
3074 //g_assert(process != ts->running_process[i]);
3075 if(process
== ts
->running_process
[i
]) {
3076 //ts->running_process[i] = lttv_state_find_process(ts, i, 0);
3080 if(i
== num_cpus
) /* process is not scheduled */
3081 exit_process(s
, process
);
3089 static gboolean
process_exec(void *hook_data
, void *call_data
)
3095 LttvProcessState
*process
;
3097 event
= (LttvEvent
*) call_data
;
3098 if (strcmp(lttv_traceset_get_name_from_event(event
),
3101 cpu
= lttv_traceset_get_cpuid_from_event(event
);
3103 process
= ts
->running_process
[cpu
];
3105 #if 0//how to use a sequence that must be transformed in a string
3106 /* PID of the process to release */
3107 guint64 name_len
= ltt_event_field_element_number(e
,
3108 lttv_trace_get_hook_field(th
, 0));
3109 //name = ltt_event_get_string(e, lttv_trace_get_hook_field(th, 0));
3110 LttField
*child
= ltt_event_field_element_select(e
,
3111 lttv_trace_get_hook_field(th
, 0), 0);
3113 (gchar
*)(ltt_event_data(e
)+ltt_event_field_offset(e
, child
));
3114 gchar
*null_term_name
= g_new(gchar
, name_len
+1);
3115 memcpy(null_term_name
, name_begin
, name_len
);
3116 null_term_name
[name_len
] = '\0';
3117 process
->name
= g_quark_from_string(null_term_name
);
3120 process
->name
= g_quark_from_string(lttv_event_get_string(event
,
3122 process
->brand
= LTTV_STATE_UNBRANDED
;
3123 //g_free(null_term_name);
3126 #ifdef BABEL_CLEANUP
3127 static gboolean
thread_brand(void *hook_data
, void *call_data
)
3129 LttvTracefileState
*s
= (LttvTracefileState
*)call_data
;
3130 LttvTraceState
*ts
= (LttvTraceState
*)s
->parent
.t_context
;
3131 LttEvent
*e
= ltt_tracefile_get_event(s
->parent
.tf
);
3132 LttvTraceHook
*th
= (LttvTraceHook
*)hook_data
;
3135 LttvProcessState
*process
= ts
->running_process
[cpu
];
3137 name
= ltt_event_get_string(e
, lttv_trace_get_hook_field(th
, 0));
3138 process
->brand
= g_quark_from_string(name
);
3144 // TODO We only have sys_open, without the FD
3145 // manage to do somehting better
3146 static gboolean
fs_open(void *hook_data
, void *call_data
)
3148 LttvTracefileState
*s
= (LttvTracefileState
*)call_data
;
3149 LttvTraceState
*ts
= (LttvTraceState
*)s
->parent
.t_context
;
3150 LttEvent
*e
= ltt_tracefile_get_event(s
->parent
.tf
);
3151 LttvTraceHook
*th
= (LttvTraceHook
*)hook_data
;
3152 struct marker_field
*f
;
3156 LttvProcessState
*process
= ts
->running_process
[cpu
];
3158 f
= lttv_trace_get_hook_field(th
, 0);
3159 fd
= ltt_event_get_int(e
, f
);
3161 f
= lttv_trace_get_hook_field(th
, 1);
3162 filename
= ltt_event_get_string(e
, f
);
3164 g_hash_table_insert(process
->fds
, (gpointer
)(long)fd
,
3165 (gpointer
)(unsigned long)g_quark_from_string(filename
));
3170 static void print_stack(LttvProcessState
*process
)
3172 LttvExecutionState
*es
;
3175 g_debug("Execution stack for process %u %s:\n",
3176 process
->pid
, g_quark_to_string(process
->name
));
3178 for (i
= 0; i
< process
->execution_stack
->len
; i
++) {
3179 es
= &g_array_index(process
->execution_stack
,
3180 LttvExecutionState
, i
);
3181 g_debug("Depth %d mode %s submode %s status %s\n",
3182 i
, g_quark_to_string(es
->t
),
3183 g_quark_to_string(es
->n
),
3184 g_quark_to_string(es
->s
));
3189 static void fix_process(gpointer key
, gpointer value
, gpointer user_data
)
3191 LttvProcessState
*process
;
3192 LttvExecutionState
*es
;
3193 process
= (LttvProcessState
*)value
;
3194 LttTime
*timestamp
= (LttTime
*)user_data
;
3196 print_stack(process
);
3198 if(process
->type
== LTTV_STATE_KERNEL_THREAD
) {
3199 es
= &g_array_index(process
->execution_stack
, LttvExecutionState
, 0);
3200 if(es
->t
== LTTV_STATE_MAYBE_SYSCALL
) {
3201 es
->t
= LTTV_STATE_SYSCALL
;
3202 es
->n
= LTTV_STATE_SUBMODE_NONE
;
3203 es
->entry
= *timestamp
;
3204 es
->change
= *timestamp
;
3205 es
->cum_cpu_time
= ltt_time_zero
;
3206 if(es
->s
== LTTV_STATE_UNNAMED
)
3207 es
->s
= LTTV_STATE_WAIT
;
3210 es
= &g_array_index(process
->execution_stack
, LttvExecutionState
, 0);
3211 if(es
->t
== LTTV_STATE_MAYBE_USER_MODE
) {
3212 es
->t
= LTTV_STATE_USER_MODE
;
3213 es
->n
= LTTV_STATE_SUBMODE_NONE
;
3214 es
->entry
= *timestamp
;
3215 //g_assert(timestamp->tv_sec != 0);
3216 es
->change
= *timestamp
;
3217 es
->cum_cpu_time
= ltt_time_zero
;
3218 if(es
->s
== LTTV_STATE_UNNAMED
)
3219 es
->s
= LTTV_STATE_RUN
;
3221 if(process
->execution_stack
->len
== 1) {
3222 /* Still in bottom unknown mode, means we either:
3223 * - never did a system call
3224 * - are scheduled out from user mode.
3225 * May be either in user mode, syscall mode, running or waiting.*/
3226 /* CHECK : we may be tagging syscall mode when being user mode
3227 * (should be fixed now) */
3228 if (es
->s
== LTTV_STATE_WAIT_CPU
) {
3229 /* nothing to do: scheduled out from userspace */
3231 process
->execution_stack
=
3232 g_array_set_size(process
->execution_stack
, 2);
3233 es
= process
->state
= &g_array_index(process
->execution_stack
,
3234 LttvExecutionState
, 1);
3235 es
->t
= LTTV_STATE_SYSCALL
;
3236 es
->n
= LTTV_STATE_SUBMODE_NONE
;
3237 es
->entry
= *timestamp
;
3238 //g_assert(timestamp->tv_sec != 0);
3239 es
->change
= *timestamp
;
3240 es
->cum_cpu_time
= ltt_time_zero
;
3241 if(es
->s
== LTTV_STATE_WAIT_FORK
)
3242 es
->s
= LTTV_STATE_WAIT
;
3249 static gboolean
statedump_end(void *hook_data
, void *call_data
)
3254 //LttEvent *e = ltt_tracefile_get_event(s->parent.tf);
3255 //LttvTraceHook *th = (LttvTraceHook *)hook_data;
3256 event
= (LttvEvent
*) call_data
;
3257 if (strcmp(lttv_traceset_get_name_from_event(event
),
3258 "lttng_statedump_end") != 0)
3262 timestamp
= lttv_event_get_timestamp(event
);
3264 /* For all processes */
3265 /* if kernel thread, if stack[0] is unknown, set to syscall mode, wait */
3266 /* else, if stack[0] is unknown, set to user mode, running */
3268 g_hash_table_foreach(ts
->processes
, fix_process
, ×tamp
);
3273 static gboolean
enum_process_state(void *hook_data
, void *call_data
)
3283 LttvProcessState
*parent_process
;
3284 LttvProcessState
*process
;
3287 LttvExecutionState
*es
;
3290 event
= (LttvEvent
*) call_data
;
3291 if (strcmp(lttv_traceset_get_name_from_event(event
),
3292 "lttng_statedump_process_state") != 0)
3294 cpu
= lttv_traceset_get_cpuid_from_event(event
);
3296 process
= ts
->running_process
[cpu
];
3297 timestamp
= lttv_event_get_timestamp(event
);
3300 pid
= lttv_event_get_long_unsigned(event
, "tid");
3301 //s->parent.target_pid = pid;
3304 parent_pid
= lttv_event_get_long_unsigned(event
, "ppid");
3307 command
= lttv_event_get_string(event
, "name");
3311 type
= lttv_event_get_long_unsigned(event
, "type");
3313 //FIXME: type is rarely used, enum must match possible types.
3315 /* Skip mode 4th param */
3317 /* Skip submode 5th param */
3319 /* Skip status 6th param */
3322 tgid
= lttv_event_get_long_unsigned(event
, "pid");
3325 nb_cpus
= lttv_trace_get_num_cpu(ts
->trace
);
3326 for(i
=0; i
<nb_cpus
; i
++) {
3327 process
= lttv_state_find_process(ts
, i
, pid
);
3328 g_assert(process
!= NULL
);
3330 process
->ppid
= parent_pid
;
3331 process
->tgid
= tgid
;
3332 process
->name
= g_quark_from_string(command
);
3333 es
= &g_array_index(process
->execution_stack
, LttvExecutionState
, 0);
3334 process
->type
= LTTV_STATE_KERNEL_THREAD
;
3338 /* The process might exist if a process was forked while performing the
3340 process
= lttv_state_find_process(ts
, ANY_CPU
, pid
);
3341 if(process
== NULL
) {
3342 parent_process
= lttv_state_find_process(ts
, ANY_CPU
, parent_pid
);
3343 process
= lttv_state_create_process(ts
, parent_process
, cpu
,
3344 pid
, tgid
, g_quark_from_string(command
),
3347 /* Keep the stack bottom : a running user mode */
3348 /* Disabled because of inconsistencies in the current statedump states. */
3349 //if(type == LTTV_STATE_KERNEL_THREAD) {
3351 /* Only keep the bottom
3352 * FIXME Kernel thread : can be in syscall or interrupt or trap. */
3353 /* Will cause expected trap when in fact being syscall (even after end of
3355 * Will cause expected interrupt when being syscall. (only before end of
3356 * statedump event) */
3357 // This will cause a "popping last state on stack, ignoring it."
3358 process
->execution_stack
= g_array_set_size(process
->execution_stack
, 1);
3359 es
= process
->state
= &g_array_index(process
->execution_stack
,
3360 LttvExecutionState
, 0);
3361 process
->type
= LTTV_STATE_KERNEL_THREAD
;
3362 es
->t
= LTTV_STATE_MAYBE_SYSCALL
;
3363 es
->s
= LTTV_STATE_UNNAMED
;
3364 es
->n
= LTTV_STATE_SUBMODE_UNKNOWN
;
3368 /* User space process :
3369 * bottom : user mode
3370 * either currently running or scheduled out.
3371 * can be scheduled out because interrupted in (user mode or in syscall)
3372 * or because of an explicit call to the scheduler in syscall. Note that
3373 * the scheduler call comes after the irq_exit, so never in interrupt
3375 // temp workaround : set size to 1 : only have user mode bottom of stack.
3376 // will cause g_info message of expected syscall mode when in fact being
3377 // in user mode. Can also cause expected trap when in fact being user
3378 // mode in the event of a page fault reenabling interrupts in the handler.
3379 // Expected syscall and trap can also happen after the end of statedump
3380 // This will cause a "popping last state on stack, ignoring it."
3381 process
->execution_stack
= g_array_set_size(process
->execution_stack
, 1);
3382 es
= process
->state
= &g_array_index(process
->execution_stack
,
3383 LttvExecutionState
, 0);
3384 es
->t
= LTTV_STATE_MAYBE_USER_MODE
;
3385 es
->s
= LTTV_STATE_UNNAMED
;
3386 es
->n
= LTTV_STATE_SUBMODE_UNKNOWN
;
3393 es
= process
->state
= &g_array_index(process
->execution_stack
,
3394 LttvExecutionState
, 1);
3395 es
->t
= LTTV_STATE_MODE_UNKNOWN
;
3396 es
->s
= LTTV_STATE_UNNAMED
;
3397 es
->n
= LTTV_STATE_SUBMODE_UNKNOWN
;
3401 /* The process has already been created :
3402 * Probably was forked while dumping the process state or
3403 * was simply scheduled in prior to get the state dump event.
3405 process
->ppid
= parent_pid
;
3406 process
->tgid
= tgid
;
3407 process
->name
= g_quark_from_string(command
);
3408 process
->type
= type
;
3409 es
= &g_array_index(process
->execution_stack
, LttvExecutionState
, 0);
3411 if(es
->t
== LTTV_STATE_MODE_UNKNOWN
) {
3412 if(type
== LTTV_STATE_KERNEL_THREAD
)
3413 es
->t
= LTTV_STATE_SYSCALL
;
3415 es
->t
= LTTV_STATE_USER_MODE
;
3418 /* Don't mess around with the stack, it will eventually become
3419 * ok after the end of state dump. */
3428 gint
lttv_state_hook_add_event_hooks(void *hook_data
, void *call_data
)
3430 LttvTraceset
*traceset
= (LttvTraceset
*)(call_data
);
3432 lttv_state_add_event_hooks(traceset
);
3437 void lttv_state_add_event_hooks(LttvTraceset
*traceset
)
3441 LttvAttributeValue value
;
3442 LttvHooks
*event_hook
;
3443 #ifdef BABEL_CLEANUP
3444 LttvIAttribute
*attributes
= LTTV_IATTRIBUTE(lttv_global_attributes());
3445 result
= lttv_iattribute_find_by_path(attributes
, "hooks/event",
3446 LTTV_POINTER
, &value
);
3448 event_hook
= *(value
.v_pointer
);
3450 //TODO ybrosseau 2012-07-12: Validate that using traceset hooks instead of the global one is valid
3451 //Use traceset hooks
3452 event_hook
= lttv_traceset_get_hooks(traceset
);
3453 g_assert(event_hook
);
3455 lttv_hooks_add(event_hook
,syscall_entry
, NULL
, LTTV_PRIO_STATE
);
3456 lttv_hooks_add(event_hook
,syscall_exit
, NULL
, LTTV_PRIO_STATE
);
3457 lttv_hooks_add(event_hook
,irq_entry
, NULL
, LTTV_PRIO_STATE
);
3458 lttv_hooks_add(event_hook
,irq_exit
, NULL
, LTTV_PRIO_STATE
);
3459 lttv_hooks_add(event_hook
,soft_irq_raise
, NULL
, LTTV_PRIO_STATE
);
3460 lttv_hooks_add(event_hook
,soft_irq_entry
, NULL
, LTTV_PRIO_STATE
);
3461 lttv_hooks_add(event_hook
,soft_irq_exit
, NULL
, LTTV_PRIO_STATE
);
3462 lttv_hooks_add(event_hook
,schedchange
, NULL
, LTTV_PRIO_STATE
);
3463 lttv_hooks_add(event_hook
,sched_try_wakeup
, NULL
, LTTV_PRIO_STATE
);
3464 lttv_hooks_add(event_hook
,process_exit
, NULL
, LTTV_PRIO_STATE
);
3465 lttv_hooks_add(event_hook
,process_free
, NULL
, LTTV_PRIO_STATE
);
3466 lttv_hooks_add(event_hook
,process_exec
, NULL
, LTTV_PRIO_STATE
);
3467 lttv_hooks_add(event_hook
,enum_process_state
, NULL
, LTTV_PRIO_STATE
);
3468 lttv_hooks_add(event_hook
,statedump_end
, NULL
, LTTV_PRIO_STATE
);
3469 lttv_hooks_add(event_hook
,enum_interrupt
, NULL
, LTTV_PRIO_STATE
);
3471 #ifdef BABEL_CLEANUP //For the whole function this time
3472 guint i
, j
, k
, nb_trace
;
3475 // LttvTraceHook *th;
3476 LttvAttributeValue val
;
3478 nb_trace
= lttv_traceset_number(traceset
);
3479 for (i
= 0 ; i
< nb_trace
; i
++) {
3480 ts
= lttv_traceset_get(traceset
, i
)-;
3482 /* Find the eventtype id for the following events and register the
3483 associated by id hooks. */
3485 hooks
= g_array_sized_new(FALSE
, FALSE
, sizeof(LttvTraceHook
), 20);
3486 //hooks = g_array_set_size(hooks, 19); // Max possible number of hooks.
3489 lttv_trace_find_hook(tss
->parent
.t
,
3491 LTT_EVENT_SYSCALL_ENTRY
,
3492 FIELD_ARRAY(LTT_FIELD_SYSCALL_ID
),
3493 syscall_entry
, NULL
, &hooks
);
3495 lttv_trace_find_hook(ts
->parent
.t
,
3497 LTT_EVENT_SYSCALL_EXIT
,
3499 syscall_exit
, NULL
, &hooks
);
3501 #ifdef BABEL_CLEANUP
3502 lttv_trace_find_hook(ts
->parent
.t
,
3504 LTT_EVENT_TRAP_ENTRY
,
3505 FIELD_ARRAY(LTT_FIELD_TRAP_ID
),
3506 trap_entry
, NULL
, &hooks
);
3508 lttv_trace_find_hook(ts
->parent
.t
,
3510 LTT_EVENT_TRAP_EXIT
,
3512 trap_exit
, NULL
, &hooks
);
3513 #endif /* BABEL_CLEANUP */
3515 lttv_trace_find_hook(ts
->parent
.t
,
3517 LTT_EVENT_PAGE_FAULT_ENTRY
,
3518 FIELD_ARRAY(LTT_FIELD_TRAP_ID
),
3519 trap_entry
, NULL
, &hooks
);
3521 lttv_trace_find_hook(ts
->parent
.t
,
3523 LTT_EVENT_PAGE_FAULT_EXIT
,
3525 trap_exit
, NULL
, &hooks
);
3527 #ifdef BABEL_CLEANUP
3528 lttv_trace_find_hook(ts
->parent
.t
,
3530 LTT_EVENT_PAGE_FAULT_NOSEM_ENTRY
,
3531 FIELD_ARRAY(LTT_FIELD_TRAP_ID
),
3532 trap_entry
, NULL
, &hooks
);
3534 lttv_trace_find_hook(ts
->parent
.t
,
3536 LTT_EVENT_PAGE_FAULT_NOSEM_EXIT
,
3538 trap_exit
, NULL
, &hooks
);
3539 #endif /* BABEL_CLEANUP */
3541 lttv_trace_find_hook(ts
->parent
.t
,
3543 LTT_EVENT_IRQ_ENTRY
,
3544 FIELD_ARRAY(LTT_FIELD_IRQ_ID
),
3545 irq_entry
, NULL
, &hooks
);
3547 lttv_trace_find_hook(ts
->parent
.t
,
3551 irq_exit
, NULL
, &hooks
);
3553 lttv_trace_find_hook(ts
->parent
.t
,
3555 LTT_EVENT_SOFT_IRQ_RAISE
,
3556 FIELD_ARRAY(LTT_FIELD_SOFT_IRQ_ID
),
3557 soft_irq_raise
, NULL
, &hooks
);
3559 lttv_trace_find_hook(ts
->parent
.t
,
3561 LTT_EVENT_SOFT_IRQ_ENTRY
,
3562 FIELD_ARRAY(LTT_FIELD_SOFT_IRQ_ID
),
3563 soft_irq_entry
, NULL
, &hooks
);
3565 lttv_trace_find_hook(ts
->parent
.t
,
3567 LTT_EVENT_SOFT_IRQ_EXIT
,
3569 soft_irq_exit
, NULL
, &hooks
);
3571 lttv_trace_find_hook(ts
->parent
.t
,
3573 LTT_EVENT_SCHED_SCHEDULE
,
3574 FIELD_ARRAY(LTT_FIELD_PREV_PID
, LTT_FIELD_NEXT_PID
,
3575 LTT_FIELD_PREV_STATE
),
3576 schedchange
, NULL
, &hooks
);
3578 lttv_trace_find_hook(ts
->parent
.t
,
3580 LTT_EVENT_SCHED_TRY_WAKEUP
,
3581 FIELD_ARRAY(LTT_FIELD_PID
, LTT_FIELD_CPU_ID
, LTT_FIELD_STATE
),
3582 sched_try_wakeup
, NULL
, &hooks
);
3584 lttv_trace_find_hook(ts
->parent
.t
,
3586 LTT_EVENT_PROCESS_FORK
,
3587 FIELD_ARRAY(LTT_FIELD_PARENT_PID
, LTT_FIELD_CHILD_PID
,
3588 LTT_FIELD_CHILD_TGID
),
3589 process_fork
, NULL
, &hooks
);
3591 lttv_trace_find_hook(ts
->parent
.t
,
3593 LTT_EVENT_KTHREAD_CREATE
,
3594 FIELD_ARRAY(LTT_FIELD_PID
),
3595 process_kernel_thread
, NULL
, &hooks
);
3597 lttv_trace_find_hook(ts
->parent
.t
,
3599 LTT_EVENT_PROCESS_EXIT
,
3600 FIELD_ARRAY(LTT_FIELD_PID
),
3601 process_exit
, NULL
, &hooks
);
3603 lttv_trace_find_hook(ts
->parent
.t
,
3605 LTT_EVENT_PROCESS_FREE
,
3606 FIELD_ARRAY(LTT_FIELD_PID
),
3607 process_free
, NULL
, &hooks
);
3609 lttv_trace_find_hook(ts
->parent
.t
,
3612 FIELD_ARRAY(LTT_FIELD_FILENAME
),
3613 process_exec
, NULL
, &hooks
);
3615 lttv_trace_find_hook(ts
->parent
.t
,
3616 LTT_CHANNEL_USERSPACE
,
3617 LTT_EVENT_THREAD_BRAND
,
3618 FIELD_ARRAY(LTT_FIELD_NAME
),
3619 thread_brand
, NULL
, &hooks
);
3621 /* statedump-related hooks */
3622 lttv_trace_find_hook(ts
->parent
.t
,
3623 LTT_CHANNEL_TASK_STATE
,
3624 LTT_EVENT_PROCESS_STATE
,
3625 FIELD_ARRAY(LTT_FIELD_PID
, LTT_FIELD_PARENT_PID
, LTT_FIELD_NAME
,
3626 LTT_FIELD_TYPE
, LTT_FIELD_MODE
, LTT_FIELD_SUBMODE
,
3627 LTT_FIELD_STATUS
, LTT_FIELD_TGID
),
3628 enum_process_state
, NULL
, &hooks
);
3630 lttv_trace_find_hook(ts
->parent
.t
,
3631 LTT_CHANNEL_GLOBAL_STATE
,
3632 LTT_EVENT_STATEDUMP_END
,
3634 statedump_end
, NULL
, &hooks
);
3636 lttv_trace_find_hook(ts
->parent
.t
,
3637 LTT_CHANNEL_IRQ_STATE
,
3638 LTT_EVENT_LIST_INTERRUPT
,
3639 FIELD_ARRAY(LTT_FIELD_ACTION
, LTT_FIELD_IRQ_ID
),
3640 enum_interrupt
, NULL
, &hooks
);
3642 lttv_trace_find_hook(ts
->parent
.t
,
3644 LTT_EVENT_REQUEST_ISSUE
,
3645 FIELD_ARRAY(LTT_FIELD_MAJOR
, LTT_FIELD_MINOR
, LTT_FIELD_OPERATION
),
3646 bdev_request_issue
, NULL
, &hooks
);
3648 lttv_trace_find_hook(ts
->parent
.t
,
3650 LTT_EVENT_REQUEST_COMPLETE
,
3651 FIELD_ARRAY(LTT_FIELD_MAJOR
, LTT_FIELD_MINOR
, LTT_FIELD_OPERATION
),
3652 bdev_request_complete
, NULL
, &hooks
);
3654 lttv_trace_find_hook(ts
->parent
.t
,
3655 LTT_CHANNEL_USERSPACE
,
3656 LTT_EVENT_FUNCTION_ENTRY
,
3657 FIELD_ARRAY(LTT_FIELD_THIS_FN
, LTT_FIELD_CALL_SITE
),
3658 function_entry
, NULL
, &hooks
);
3660 lttv_trace_find_hook(ts
->parent
.t
,
3661 LTT_CHANNEL_USERSPACE
,
3662 LTT_EVENT_FUNCTION_EXIT
,
3663 FIELD_ARRAY(LTT_FIELD_THIS_FN
, LTT_FIELD_CALL_SITE
),
3664 function_exit
, NULL
, &hooks
);
3666 lttv_trace_find_hook(ts
->parent
.t
,
3667 LTT_CHANNEL_SYSCALL_STATE
,
3668 LTT_EVENT_SYS_CALL_TABLE
,
3669 FIELD_ARRAY(LTT_FIELD_ID
, LTT_FIELD_ADDRESS
, LTT_FIELD_SYMBOL
),
3670 dump_syscall
, NULL
, &hooks
);
3672 lttv_trace_find_hook(ts
->parent
.t
,
3673 LTT_CHANNEL_KPROBE_STATE
,
3674 LTT_EVENT_KPROBE_TABLE
,
3675 FIELD_ARRAY(LTT_FIELD_IP
, LTT_FIELD_SYMBOL
),
3676 dump_kprobe
, NULL
, &hooks
);
3678 lttv_trace_find_hook(ts
->parent
.t
,
3679 LTT_CHANNEL_SOFTIRQ_STATE
,
3680 LTT_EVENT_SOFTIRQ_VEC
,
3681 FIELD_ARRAY(LTT_FIELD_ID
, LTT_FIELD_ADDRESS
, LTT_FIELD_SYMBOL
),
3682 dump_softirq
, NULL
, &hooks
);
3684 lttv_trace_find_hook(ts
->parent
.t
,
3687 FIELD_ARRAY(LTT_FIELD_FD
, LTT_FIELD_FILENAME
),
3688 fs_open
, NULL
, &hooks
);
3690 /* Add these hooks to each event_by_id hooks list */
3692 nb_tracefile
= ts
->parent
.tracefiles
->len
;
3694 for(j
= 0 ; j
< nb_tracefile
; j
++) {
3696 LTTV_TRACEFILE_STATE(g_array_index(ts
->parent
.tracefiles
,
3697 LttvTracefileContext
*, j
));
3699 for(k
= 0 ; k
< hooks
->len
; k
++) {
3700 th
= &g_array_index(hooks
, LttvTraceHook
, k
);
3701 if (th
->mdata
== tfs
->parent
.tf
->mdata
)
3703 lttv_hooks_by_id_find(tfs
->parent
.event_by_id
, th
->id
),
3709 lttv_attribute_find(ts
->parent
.a
, LTTV_STATE_HOOKS
, LTTV_POINTER
, &val
);
3710 *(val
.v_pointer
) = hooks
;
3715 gint
lttv_state_hook_remove_event_hooks(void *hook_data
, void *call_data
)
3718 LttvTraceset
*traceset
= (LttvTraceset
*)(call_data
);
3720 lttv_state_remove_event_hooks(traceset
);
3725 void lttv_state_remove_event_hooks(LttvTraceset
*traceset
)
3728 guint i
, j
, k
, nb_trace
, nb_tracefile
;
3730 //LttvTraceState *ts;
3734 //LttvTraceHook *th;
3736 //LttvAttributeValue val;
3738 LttvHooks
*event_hook
;
3739 //TODO ybrosseau 2012-07-17 validate this. Reversed what's done in the add
3740 event_hook
= lttv_traceset_get_hooks(traceset
);
3742 g_assert(event_hook
);
3745 lttv_hooks_remove(event_hook
,syscall_entry
);
3746 lttv_hooks_remove(event_hook
,syscall_exit
);
3747 lttv_hooks_remove(event_hook
,irq_entry
);
3748 lttv_hooks_remove(event_hook
,irq_exit
);
3749 lttv_hooks_remove(event_hook
,soft_irq_raise
);
3750 lttv_hooks_remove(event_hook
,soft_irq_entry
);
3751 lttv_hooks_remove(event_hook
,soft_irq_exit
);
3752 lttv_hooks_remove(event_hook
,schedchange
);
3753 lttv_hooks_remove(event_hook
,sched_try_wakeup
);
3754 lttv_hooks_remove(event_hook
,process_exit
);
3755 lttv_hooks_remove(event_hook
,process_free
);
3756 lttv_hooks_remove(event_hook
,process_exec
);
3757 lttv_hooks_remove(event_hook
,enum_process_state
);
3758 lttv_hooks_remove(event_hook
,statedump_end
);
3759 lttv_hooks_remove(event_hook
,enum_interrupt
);
3760 #ifdef BABEL_CLEANUP
3761 nb_trace
= lttv_traceset_number(traceset
);
3762 for(i
= 0 ; i
< nb_trace
; i
++) {
3763 ts
= lttv_traceset_get(i
);
3765 lttv_attribute_find(ts
->parent
.a
, LTTV_STATE_HOOKS
, LTTV_POINTER
, &val
);
3766 hooks
= *(val
.v_pointer
);
3768 /* Remove these hooks from each event_by_id hooks list */
3770 nb_tracefile
= ts
->parent
.tracefiles
->len
;
3772 for(j
= 0 ; j
< nb_tracefile
; j
++) {
3774 LTTV_TRACEFILE_STATE(g_array_index(ts
->parent
.tracefiles
,
3775 LttvTracefileContext
*, j
));
3777 for(k
= 0 ; k
< hooks
->len
; k
++) {
3778 th
= &g_array_index(hooks
, LttvTraceHook
, k
);
3779 if (th
->mdata
== tfs
->parent
.tf
->mdata
)
3780 lttv_hooks_remove_data(
3781 lttv_hooks_by_id_find(tfs
->parent
.event_by_id
, th
->id
),
3786 lttv_trace_hook_remove_all(&hooks
);
3787 g_array_free(hooks
, TRUE
);
3793 static gboolean
state_save_event_hook(void *hook_data
, void *call_data
)
3795 guint
*event_count
= (guint
*)hook_data
;
3797 /* Only save at LTTV_STATE_SAVE_INTERVAL */
3798 if(likely((*event_count
)++ < LTTV_STATE_SAVE_INTERVAL
))
3803 LttvEvent
*event
= (LttvEvent
*)call_data
;
3805 LttvTraceset
*traceset
= lttv_trace_get_traceset(event
->state
->trace
);
3807 LttvAttribute
*saved_states_tree
, *saved_state_tree
;
3809 LttvAttributeValue value
;
3810 LttTime currentTime
;
3812 currentTime
= lttv_event_get_timestamp(event
);
3813 int nb_trace
= lttv_traceset_number(traceset
);
3814 for(i
= 0 ; i
< nb_trace
; i
++) {
3816 LttvTrace
*trace
= lttv_traceset_get(traceset
, i
);
3817 LttvTraceState
*tstate
= trace
->state
;
3818 saved_states_tree
= lttv_attribute_find_subdir(trace
->a
,
3819 LTTV_STATE_SAVED_STATES
);
3821 saved_state_tree
= g_object_new(LTTV_ATTRIBUTE_TYPE
, NULL
);
3822 value
= lttv_attribute_add(saved_states_tree
,
3823 lttv_attribute_get_number(saved_states_tree
), LTTV_GOBJECT
);
3824 *(value
.v_gobject
) = (GObject
*)saved_state_tree
;
3827 value
= lttv_attribute_add(saved_state_tree
, LTTV_STATE_TIME
, LTTV_TIME
);
3828 *(value
.v_time
) = currentTime
;
3830 lttv_state_save(tstate
, saved_state_tree
);
3831 g_debug("Saving state at time %lu.%lu", currentTime
.tv_sec
,
3832 currentTime
.tv_nsec
);
3834 *(tstate
->max_time_state_recomputed_in_seek
) = currentTime
;
3839 static gboolean
state_save_after_trace_hook(void *hook_data
, void *call_data
)
3841 #warning "Would we move max_time to traceset"
3842 LttvTrace
*trace
= (LttvTrace
*)(call_data
);
3843 LttvTraceState
*tcs
= trace
->state
;
3844 TimeInterval time_span
= lttv_traceset_get_time_span_real(lttv_trace_get_traceset(trace
));
3846 *(tcs
->max_time_state_recomputed_in_seek
) = time_span
.end_time
;
3850 #ifdef BABEL_CLEANUP
3851 guint
lttv_state_current_cpu(LttvTracefileState
*tfs
)
3856 #endif //BABEL_CLEANUP
3859 static gboolean
block_start(void *hook_data
, void *call_data
)
3861 LttvTracefileState
*self
= (LttvTracefileState
*)call_data
;
3863 LttvTracefileState
*tfcs
;
3865 LttvTraceState
*tcs
= (LttvTraceState
*)(self
->parent
.t_context
);
3867 LttEventPosition
*ep
;
3869 guint i
, nb_block
, nb_event
, nb_tracefile
;
3873 LttvAttribute
*saved_states_tree
, *saved_state_tree
;
3875 LttvAttributeValue value
;
3877 ep
= ltt_event_position_new();
3879 nb_tracefile
= tcs
->parent
.tracefiles
->len
;
3881 /* Count the number of events added since the last block end in any
3884 for(i
= 0 ; i
< nb_tracefile
; i
++) {
3886 LTTV_TRACEFILE_STATE(&g_array_index(tcs
->parent
.tracefiles
,
3887 LttvTracefileContext
, i
));
3888 ltt_event_position(tfcs
->parent
.e
, ep
);
3889 ltt_event_position_get(ep
, &nb_block
, &nb_event
, &tf
);
3890 tcs
->nb_event
+= nb_event
- tfcs
->saved_position
;
3891 tfcs
->saved_position
= nb_event
;
3895 if(tcs
->nb_event
>= tcs
->save_interval
) {
3896 saved_states_tree
= lttv_attribute_find_subdir(tcs
->parent
.t_a
,
3897 LTTV_STATE_SAVED_STATES
);
3898 saved_state_tree
= g_object_new(LTTV_ATTRIBUTE_TYPE
, NULL
);
3899 value
= lttv_attribute_add(saved_states_tree
,
3900 lttv_attribute_get_number(saved_states_tree
), LTTV_GOBJECT
);
3901 *(value
.v_gobject
) = (GObject
*)saved_state_tree
;
3902 value
= lttv_attribute_add(saved_state_tree
, LTTV_STATE_TIME
, LTTV_TIME
);
3903 *(value
.v_time
) = self
->parent
.timestamp
;
3904 lttv_state_save(tcs
, saved_state_tree
);
3906 g_debug("Saving state at time %lu.%lu", self
->parent
.timestamp
.tv_sec
,
3907 self
->parent
.timestamp
.tv_nsec
);
3909 *(tcs
->max_time_state_recomputed_in_seek
) = self
->parent
.timestamp
;
3915 static gboolean
block_end(void *hook_data
, void *call_data
)
3917 LttvTracefileState
*self
= (LttvTracefileState
*)call_data
;
3919 LttvTraceState
*tcs
= (LttvTraceState
*)(self
->parent
.t_context
);
3923 LttEventPosition
*ep
;
3925 guint nb_block
, nb_event
;
3927 ep
= ltt_event_position_new();
3928 ltt_event_position(self
->parent
.e
, ep
);
3929 ltt_event_position_get(ep
, &nb_block
, &nb_event
, &tf
);
3930 tcs
->nb_event
+= nb_event
- self
->saved_position
+ 1;
3931 self
->saved_position
= 0;
3932 *(tcs
->max_time_state_recomputed_in_seek
) = self
->parent
.timestamp
;
3939 void lttv_state_save_add_event_hooks(LttvTracesetState
*self
)
3941 LttvTraceset
*traceset
= self
->parent
.ts
;
3943 guint i
, j
, nb_trace
, nb_tracefile
;
3947 LttvTracefileState
*tfs
;
3949 LttvTraceHook hook_start
, hook_end
;
3951 nb_trace
= lttv_traceset_number(traceset
);
3952 for(i
= 0 ; i
< nb_trace
; i
++) {
3953 ts
= (LttvTraceState
*)self
->parent
.traces
[i
];
3955 lttv_trace_find_hook(ts
->parent
.t
, "core","block_start",NULL
,
3956 NULL
, NULL
, block_start
, &hook_start
);
3957 lttv_trace_find_hook(ts
->parent
.t
, "core","block_end",NULL
,
3958 NULL
, NULL
, block_end
, &hook_end
);
3960 nb_tracefile
= ts
->parent
.tracefiles
->len
;
3962 for(j
= 0 ; j
< nb_tracefile
; j
++) {
3964 LTTV_TRACEFILE_STATE(&g_array_index(ts
->parent
.tracefiles
,
3965 LttvTracefileContext
, j
));
3966 lttv_hooks_add(lttv_hooks_by_id_find(tfs
->parent
.event_by_id
,
3967 hook_start
.id
), hook_start
.h
, NULL
, LTTV_PRIO_STATE
);
3968 lttv_hooks_add(lttv_hooks_by_id_find(tfs
->parent
.event_by_id
,
3969 hook_end
.id
), hook_end
.h
, NULL
, LTTV_PRIO_STATE
);
3975 void lttv_state_save_add_event_hooks(LttvTraceset
*traceset
)
3978 guint i
, j
, nb_trace
, nb_tracefile
;
3982 LttvTracefileState
*tfs
;
3985 if(!traceset
->has_precomputed_states
) {
3986 guint
*event_count
= g_new(guint
, 1);
3989 lttv_hooks_add(traceset
->event_hooks
,
3990 state_save_event_hook
,
3994 #ifdef BABEL_CLEANUP
3995 nb_trace
= lttv_traceset_number(traceset
);
3996 for(i
= 0 ; i
< nb_trace
; i
++) {
3998 ts
= (LttvTraceState
*)self
->parent
.traces
[i
];
3999 nb_tracefile
= ts
->parent
.tracefiles
->len
;
4001 if(ts
->has_precomputed_states
) continue;
4003 guint
*event_count
= g_new(guint
, 1);
4006 for(j
= 0 ; j
< nb_tracefile
; j
++) {
4008 LTTV_TRACEFILE_STATE(g_array_index(ts
->parent
.tracefiles
,
4009 LttvTracefileContext
*, j
));
4010 lttv_hooks_add(tfs
->parent
.event
,
4011 state_save_event_hook
,
4018 lttv_process_traceset_begin(traceset
,
4019 NULL
, NULL
, NULL
, NULL
, NULL
);
4024 gint
lttv_state_save_hook_add_event_hooks(void *hook_data
, void *call_data
)
4026 LttvTraceset
*ts
= (LttvTraceset
*)(call_data
);
4028 lttv_state_save_add_event_hooks(ts
);
4035 void lttv_state_save_remove_event_hooks(LttvTracesetState
*self
)
4037 LttvTraceset
*traceset
= self
->parent
.ts
;
4039 guint i
, j
, nb_trace
, nb_tracefile
;
4043 LttvTracefileState
*tfs
;
4045 LttvTraceHook hook_start
, hook_end
;
4047 nb_trace
= lttv_traceset_number(traceset
);
4048 for(i
= 0 ; i
< nb_trace
; i
++) {
4049 ts
= LTTV_TRACE_STATE(self
->parent
.traces
[i
]);
4051 lttv_trace_find_hook(ts
->parent
.t
, "core","block_start",NULL
,
4052 NULL
, NULL
, block_start
, &hook_start
);
4054 lttv_trace_find_hook(ts
->parent
.t
, "core","block_end",NULL
,
4055 NULL
, NULL
, block_end
, &hook_end
);
4057 nb_tracefile
= ts
->parent
.tracefiles
->len
;
4059 for(j
= 0 ; j
< nb_tracefile
; j
++) {
4061 LTTV_TRACEFILE_STATE(&g_array_index(ts
->parent
.tracefiles
,
4062 LttvTracefileContext
, j
));
4063 lttv_hooks_remove_data(lttv_hooks_by_id_find(
4064 tfs
->parent
.event_by_id
, hook_start
.id
), hook_start
.h
, NULL
);
4065 lttv_hooks_remove_data(lttv_hooks_by_id_find(
4066 tfs
->parent
.event_by_id
, hook_end
.id
), hook_end
.h
, NULL
);
4072 void lttv_state_save_remove_event_hooks(LttvTraceset
*traceset
)
4075 guint i
, j
, nb_trace
, nb_tracefile
;
4079 LttvTracefileState
*tfs
;
4081 LttvHooks
*after_trace
= lttv_hooks_new();
4082 guint
*event_count
= NULL
;
4084 lttv_hooks_add(after_trace
,
4085 state_save_after_trace_hook
,
4090 lttv_process_traceset_end(traceset
,
4091 NULL
, after_trace
, NULL
, NULL
);
4093 lttv_hooks_destroy(after_trace
);
4095 //nb_trace = lttv_traceset_number(traceset);
4097 event_count
= lttv_hooks_remove(traceset
->event_hooks
,
4098 state_save_event_hook
);
4100 if(event_count
) g_free(event_count
);
4102 #ifdef BABEL_CLEANUP
4103 for(i
= 0 ; i
< nb_trace
; i
++) {
4105 ts
= (LttvTraceState
*)self
->parent
.traces
[i
];
4106 nb_tracefile
= ts
->parent
.tracefiles
->len
;
4108 if(ts
->has_precomputed_states
) continue;
4110 guint
*event_count
= NULL
;
4112 for(j
= 0 ; j
< nb_tracefile
; j
++) {
4114 LTTV_TRACEFILE_STATE(g_array_index(ts
->parent
.tracefiles
,
4115 LttvTracefileContext
*, j
));
4116 event_count
= lttv_hooks_remove(tfs
->parent
.event
,
4117 state_save_event_hook
);
4119 if(event_count
) g_free(event_count
);
4124 gint
lttv_state_save_hook_remove_event_hooks(void *hook_data
, void *call_data
)
4126 LttvTraceset
*ts
= (LttvTraceset
*)(call_data
);
4128 lttv_state_save_remove_event_hooks(ts
);
4134 void lttv_state_traceset_seek_time(LttvTraceset
*traceset
, LttTime t
)
4136 lttv_state_traceset_seek_time_closest(traceset
,
4138 lttv_process_traceset_middle(traceset
, t
, G_MAXUINT
,
4142 void lttv_state_traceset_seek_position(LttvTraceset
*traceset
, LttvTracesetPosition
*position
)
4144 LttTime t
= lttv_traceset_position_get_time(position
);
4146 lttv_state_traceset_seek_time_closest(traceset
,
4148 lttv_process_traceset_middle(traceset
,
4154 void lttv_state_traceset_seek_time_closest(LttvTraceset
*traceset
, LttTime t
)
4158 int min_pos
, mid_pos
, max_pos
;
4160 guint call_rest
= 0;
4161 guint resto_start
= 0;
4164 LttvAttributeValue value
;
4166 LttvAttributeType type
;
4168 LttvAttributeName name
;
4172 LttvAttribute
*saved_states_tree
, *saved_state_tree
, *closest_tree
= NULL
;
4174 LttTime closest_tree_time
, restored_time
;
4176 //g_tree_destroy(self->parent.pqueue);
4177 //self->parent.pqueue = g_tree_new(compare_tracefile);
4179 g_info("Entering seek_time_closest for time %lu.%lu", t
.tv_sec
, t
.tv_nsec
);
4181 nb_trace
= lttv_traceset_number(traceset
);
4182 for(i
= 0 ; i
< nb_trace
; i
++) {
4184 LttvTrace
*trace
= lttv_traceset_get(traceset
, i
);
4185 LttvTraceState
*tstate
= trace
->state
;
4187 if(ltt_time_compare(t
, *(tstate
->max_time_state_recomputed_in_seek
)) < 0) {
4188 saved_states_tree
= lttv_attribute_find_subdir(trace
->a
,
4189 LTTV_STATE_SAVED_STATES
);
4192 if(saved_states_tree
) {
4193 max_pos
= lttv_attribute_get_number(saved_states_tree
) - 1;
4194 mid_pos
= max_pos
/ 2;
4195 while(min_pos
< max_pos
) {
4196 type
= lttv_attribute_get(saved_states_tree
, mid_pos
,
4197 &name
, &value
, &is_named
);
4198 g_assert(type
== LTTV_GOBJECT
);
4199 saved_state_tree
= *((LttvAttribute
**)(value
.v_gobject
));
4200 type
= lttv_attribute_get_by_name(saved_state_tree
,
4201 LTTV_STATE_TIME
, &value
);
4202 g_assert(type
== LTTV_TIME
);
4203 if(ltt_time_compare(*(value
.v_time
), t
) < 0) {
4205 closest_tree
= saved_state_tree
;
4206 closest_tree_time
= *(value
.v_time
);
4208 else max_pos
= mid_pos
- 1;
4210 mid_pos
= (min_pos
+ max_pos
+ 1) / 2;
4214 /* restore the closest earlier saved state */
4216 if(ltt_time_compare(restored_time
, closest_tree_time
) == 0) {
4218 lttv_state_restore(tstate
, closest_tree
);
4220 restored_time
= closest_tree_time
;
4223 g_debug("State: restored time mismatch between traces");
4230 /* There is no saved state, yet we want to have it. Restart at T0 */
4236 /* We want to seek quickly without restoring/updating the state */
4243 if(resto_start
|| resto_at
) {
4244 // Restore init state and seek so
4245 for(i
= 0 ; i
< nb_trace
; i
++) {
4247 LttvTrace
*trace
= lttv_traceset_get(traceset
, i
);
4248 LttvTraceState
*tstate
= trace
->state
;
4250 restore_init_state(tstate
);
4253 // If t > max saved state
4255 lttv_process_traceset_seek_time(traceset
, t
);
4256 } else if (resto_start
) {
4257 // If no saved state
4258 lttv_process_traceset_seek_time(traceset
, ltt_time_zero
);
4262 g_info("NOT Calling restore");
4265 // Seek at checkpoint
4266 lttv_process_traceset_seek_time(traceset
, restored_time
);
4274 #ifdef BABEL_CLEANUP
4275 static void traceset_state_instance_init (GTypeInstance
*instance
, gpointer g_class
)
4280 static void traceset_state_finalize (LttvTracesetState
*self
)
4282 G_OBJECT_CLASS(g_type_class_peek(LTTV_TRACESET_CONTEXT_TYPE
))->
4283 finalize(G_OBJECT(self
));
4287 static void traceset_state_class_init (LttvTracesetContextClass
*klass
)
4289 GObjectClass
*gobject_class
= G_OBJECT_CLASS(klass
);
4291 gobject_class
->finalize
= (void (*)(GObject
*self
)) traceset_state_finalize
;
4292 klass
->init
= (void (*)(LttvTracesetContext
*self
, LttvTraceset
*ts
))init
;
4293 klass
->fini
= (void (*)(LttvTracesetContext
*self
))fini
;
4294 klass
->new_traceset_context
= new_traceset_context
;
4295 klass
->new_trace_context
= new_trace_context
;
4296 klass
->new_tracefile_context
= new_tracefile_context
;
4300 GType
lttv_traceset_state_get_type(void)
4302 static GType type
= 0;
4304 static const GTypeInfo info
= {
4305 sizeof (LttvTracesetStateClass
),
4306 NULL
, /* base_init */
4307 NULL
, /* base_finalize */
4308 (GClassInitFunc
) traceset_state_class_init
, /* class_init */
4309 NULL
, /* class_finalize */
4310 NULL
, /* class_data */
4311 sizeof (LttvTracesetState
),
4312 0, /* n_preallocs */
4313 (GInstanceInitFunc
) traceset_state_instance_init
, /* instance_init */
4314 NULL
/* value handling */
4317 type
= g_type_register_static (LTTV_TRACESET_CONTEXT_TYPE
, "LttvTracesetStateType",
4325 static void trace_state_instance_init (GTypeInstance
*instance
, gpointer g_class
)
4330 static void trace_state_finalize (LttvTraceState
*self
)
4332 G_OBJECT_CLASS(g_type_class_peek(LTTV_TRACE_CONTEXT_TYPE
))->
4333 finalize(G_OBJECT(self
));
4337 static void trace_state_class_init (LttvTraceStateClass
*klass
)
4339 GObjectClass
*gobject_class
= G_OBJECT_CLASS(klass
);
4341 gobject_class
->finalize
= (void (*)(GObject
*self
)) trace_state_finalize
;
4342 klass
->state_save
= state_save
;
4343 klass
->state_restore
= state_restore
;
4344 klass
->state_saved_free
= state_saved_free
;
4348 GType
lttv_trace_state_get_type(void)
4350 static GType type
= 0;
4352 static const GTypeInfo info
= {
4353 sizeof (LttvTraceStateClass
),
4354 NULL
, /* base_init */
4355 NULL
, /* base_finalize */
4356 (GClassInitFunc
) trace_state_class_init
, /* class_init */
4357 NULL
, /* class_finalize */
4358 NULL
, /* class_data */
4359 sizeof (LttvTraceState
),
4360 0, /* n_preallocs */
4361 (GInstanceInitFunc
) trace_state_instance_init
, /* instance_init */
4362 NULL
/* value handling */
4365 type
= g_type_register_static (LTTV_TRACE_CONTEXT_TYPE
,
4366 "LttvTraceStateType", &info
, 0);
4372 static void tracefile_state_instance_init (GTypeInstance
*instance
,
4378 static void tracefile_state_finalize (LttvTracefileState
*self
)
4380 G_OBJECT_CLASS(g_type_class_peek(LTTV_TRACEFILE_CONTEXT_TYPE
))->
4381 finalize(G_OBJECT(self
));
4385 static void tracefile_state_class_init (LttvTracefileStateClass
*klass
)
4387 GObjectClass
*gobject_class
= G_OBJECT_CLASS(klass
);
4389 gobject_class
->finalize
= (void (*)(GObject
*self
)) tracefile_state_finalize
;
4393 GType
lttv_tracefile_state_get_type(void)
4395 static GType type
= 0;
4397 static const GTypeInfo info
= {
4398 sizeof (LttvTracefileStateClass
),
4399 NULL
, /* base_init */
4400 NULL
, /* base_finalize */
4401 (GClassInitFunc
) tracefile_state_class_init
, /* class_init */
4402 NULL
, /* class_finalize */
4403 NULL
, /* class_data */
4404 sizeof (LttvTracefileState
),
4405 0, /* n_preallocs */
4406 (GInstanceInitFunc
) tracefile_state_instance_init
, /* instance_init */
4407 NULL
/* value handling */
4410 type
= g_type_register_static (LTTV_TRACEFILE_CONTEXT_TYPE
,
4411 "LttvTracefileStateType", &info
, 0);
4417 static void module_init(void)
4419 LTTV_STATE_UNNAMED
= g_quark_from_string("");
4420 LTTV_STATE_UNBRANDED
= g_quark_from_string("");
4421 LTTV_STATE_MODE_UNKNOWN
= g_quark_from_string("MODE_UNKNOWN");
4422 LTTV_STATE_USER_MODE
= g_quark_from_string("USER_MODE");
4423 LTTV_STATE_MAYBE_USER_MODE
= g_quark_from_string("MAYBE_USER_MODE");
4424 LTTV_STATE_SYSCALL
= g_quark_from_string("SYSCALL");
4425 LTTV_STATE_MAYBE_SYSCALL
= g_quark_from_string("MAYBE_SYSCALL");
4426 LTTV_STATE_TRAP
= g_quark_from_string("TRAP");
4427 LTTV_STATE_MAYBE_TRAP
= g_quark_from_string("MAYBE_TRAP");
4428 LTTV_STATE_IRQ
= g_quark_from_string("IRQ");
4429 LTTV_STATE_SOFT_IRQ
= g_quark_from_string("SOFTIRQ");
4430 LTTV_STATE_SUBMODE_UNKNOWN
= g_quark_from_string("UNKNOWN");
4431 LTTV_STATE_SUBMODE_NONE
= g_quark_from_string("NONE");
4432 LTTV_STATE_WAIT_FORK
= g_quark_from_string("WAIT_FORK");
4433 LTTV_STATE_WAIT_CPU
= g_quark_from_string("WAIT_CPU");
4434 LTTV_STATE_EXIT
= g_quark_from_string("EXIT");
4435 LTTV_STATE_ZOMBIE
= g_quark_from_string("ZOMBIE");
4436 LTTV_STATE_WAIT
= g_quark_from_string("WAIT");
4437 LTTV_STATE_RUN
= g_quark_from_string("RUN");
4438 LTTV_STATE_DEAD
= g_quark_from_string("DEAD");
4439 LTTV_STATE_USER_THREAD
= g_quark_from_string("USER_THREAD");
4440 LTTV_STATE_KERNEL_THREAD
= g_quark_from_string("KERNEL_THREAD");
4441 LTTV_STATE_TRACEFILES
= g_quark_from_string("tracefiles");
4442 LTTV_STATE_PROCESSES
= g_quark_from_string("processes");
4443 LTTV_STATE_PROCESS
= g_quark_from_string("process");
4444 LTTV_STATE_RUNNING_PROCESS
= g_quark_from_string("running_process");
4445 LTTV_STATE_POSITION
= g_quark_from_string("position");
4446 LTTV_STATE_SAVED_STATES
= g_quark_from_string("saved states");
4447 LTTV_STATE_SAVED_STATES_TIME
= g_quark_from_string("saved states time");
4448 LTTV_STATE_TIME
= g_quark_from_string("time");
4449 LTTV_STATE_HOOKS
= g_quark_from_string("saved state hooks");
4450 LTTV_STATE_NAME_TABLES
= g_quark_from_string("name tables");
4451 LTTV_STATE_TRACE_STATE_USE_COUNT
=
4452 g_quark_from_string("trace_state_use_count");
4453 LTTV_STATE_RESOURCE_CPUS
= g_quark_from_string("cpu resource states");
4454 LTTV_STATE_RESOURCE_CPUS
= g_quark_from_string("cpu count");
4455 LTTV_STATE_RESOURCE_IRQS
= g_quark_from_string("irq resource states");
4456 LTTV_STATE_RESOURCE_SOFT_IRQS
= g_quark_from_string("soft irq resource states");
4457 LTTV_STATE_RESOURCE_TRAPS
= g_quark_from_string("trap resource states");
4458 LTTV_STATE_RESOURCE_BLKDEVS
= g_quark_from_string("blkdevs resource states");
4460 LTT_CHANNEL_FD_STATE
= g_quark_from_string("fd_state");
4461 LTT_CHANNEL_GLOBAL_STATE
= g_quark_from_string("global_state");
4462 LTT_CHANNEL_IRQ_STATE
= g_quark_from_string("irq_state");
4463 LTT_CHANNEL_MODULE_STATE
= g_quark_from_string("module_state");
4464 LTT_CHANNEL_NETIF_STATE
= g_quark_from_string("netif_state");
4465 LTT_CHANNEL_SOFTIRQ_STATE
= g_quark_from_string("softirq_state");
4466 LTT_CHANNEL_SWAP_STATE
= g_quark_from_string("swap_state");
4467 LTT_CHANNEL_SYSCALL_STATE
= g_quark_from_string("syscall_state");
4468 LTT_CHANNEL_TASK_STATE
= g_quark_from_string("task_state");
4469 LTT_CHANNEL_VM_STATE
= g_quark_from_string("vm_state");
4470 LTT_CHANNEL_KPROBE_STATE
= g_quark_from_string("kprobe_state");
4471 LTT_CHANNEL_FS
= g_quark_from_string("fs");
4472 LTT_CHANNEL_KERNEL
= g_quark_from_string("kernel");
4473 LTT_CHANNEL_MM
= g_quark_from_string("mm");
4474 LTT_CHANNEL_USERSPACE
= g_quark_from_string("userspace");
4475 LTT_CHANNEL_BLOCK
= g_quark_from_string("block");
4477 LTT_EVENT_SYSCALL_ENTRY
= g_quark_from_string("syscall_entry");
4478 LTT_EVENT_SYSCALL_EXIT
= g_quark_from_string("syscall_exit");
4479 //LTT_EVENT_TRAP_ENTRY = g_quark_from_string("trap_entry");
4480 //LTT_EVENT_TRAP_EXIT = g_quark_from_string("trap_exit");
4481 LTT_EVENT_PAGE_FAULT_ENTRY
= g_quark_from_string("page_fault_entry");
4482 LTT_EVENT_PAGE_FAULT_EXIT
= g_quark_from_string("page_fault_exit");
4483 LTT_EVENT_PAGE_FAULT_NOSEM_ENTRY
= g_quark_from_string("page_fault_nosem_entry");
4484 LTT_EVENT_PAGE_FAULT_NOSEM_EXIT
= g_quark_from_string("page_fault_nosem_exit");
4485 LTT_EVENT_IRQ_ENTRY
= g_quark_from_string("irq_entry");
4486 LTT_EVENT_IRQ_EXIT
= g_quark_from_string("irq_exit");
4487 LTT_EVENT_SOFT_IRQ_RAISE
= g_quark_from_string("softirq_raise");
4488 LTT_EVENT_SOFT_IRQ_ENTRY
= g_quark_from_string("softirq_entry");
4489 LTT_EVENT_SOFT_IRQ_EXIT
= g_quark_from_string("softirq_exit");
4490 LTT_EVENT_SCHED_SCHEDULE
= g_quark_from_string("sched_schedule");
4491 LTT_EVENT_SCHED_TRY_WAKEUP
= g_quark_from_string("sched_try_wakeup");
4492 LTT_EVENT_PROCESS_FORK
= g_quark_from_string("process_fork");
4493 LTT_EVENT_KTHREAD_CREATE
= g_quark_from_string("kthread_create");
4494 LTT_EVENT_PROCESS_EXIT
= g_quark_from_string("process_exit");
4495 LTT_EVENT_PROCESS_FREE
= g_quark_from_string("process_free");
4496 LTT_EVENT_EXEC
= g_quark_from_string("exec");
4497 LTT_EVENT_PROCESS_STATE
= g_quark_from_string("process_state");
4498 LTT_EVENT_STATEDUMP_END
= g_quark_from_string("statedump_end");
4499 LTT_EVENT_FUNCTION_ENTRY
= g_quark_from_string("function_entry");
4500 LTT_EVENT_FUNCTION_EXIT
= g_quark_from_string("function_exit");
4501 LTT_EVENT_THREAD_BRAND
= g_quark_from_string("thread_brand");
4502 LTT_EVENT_REQUEST_ISSUE
= g_quark_from_string("_blk_request_issue");
4503 LTT_EVENT_REQUEST_COMPLETE
= g_quark_from_string("_blk_request_complete");
4504 LTT_EVENT_LIST_INTERRUPT
= g_quark_from_string("interrupt");
4505 LTT_EVENT_SYS_CALL_TABLE
= g_quark_from_string("sys_call_table");
4506 LTT_EVENT_SOFTIRQ_VEC
= g_quark_from_string("softirq_vec");
4507 LTT_EVENT_KPROBE_TABLE
= g_quark_from_string("kprobe_table");
4508 LTT_EVENT_KPROBE
= g_quark_from_string("kprobe");
4509 LTT_EVENT_OPEN
= g_quark_from_string("open");
4510 LTT_EVENT_READ
= g_quark_from_string("read");
4511 LTT_EVENT_POLL_EVENT
= g_quark_from_string("poll_event");
4513 LTT_FIELD_SYSCALL_ID
= g_quark_from_string("syscall_id");
4514 LTT_FIELD_TRAP_ID
= g_quark_from_string("trap_id");
4515 LTT_FIELD_IRQ_ID
= g_quark_from_string("irq_id");
4516 LTT_FIELD_SOFT_IRQ_ID
= g_quark_from_string("softirq_id");
4517 LTT_FIELD_PREV_PID
= g_quark_from_string("prev_pid");
4518 LTT_FIELD_NEXT_PID
= g_quark_from_string("next_pid");
4519 LTT_FIELD_PREV_STATE
= g_quark_from_string("prev_state");
4520 LTT_FIELD_PARENT_PID
= g_quark_from_string("parent_pid");
4521 LTT_FIELD_CHILD_PID
= g_quark_from_string("child_pid");
4522 LTT_FIELD_PID
= g_quark_from_string("pid");
4523 LTT_FIELD_TGID
= g_quark_from_string("tgid");
4524 LTT_FIELD_CHILD_TGID
= g_quark_from_string("child_tgid");
4525 LTT_FIELD_FILENAME
= g_quark_from_string("filename");
4526 LTT_FIELD_NAME
= g_quark_from_string("name");
4527 LTT_FIELD_TYPE
= g_quark_from_string("type");
4528 LTT_FIELD_MODE
= g_quark_from_string("mode");
4529 LTT_FIELD_SUBMODE
= g_quark_from_string("submode");
4530 LTT_FIELD_STATUS
= g_quark_from_string("status");
4531 LTT_FIELD_THIS_FN
= g_quark_from_string("this_fn");
4532 LTT_FIELD_CALL_SITE
= g_quark_from_string("call_site");
4533 LTT_FIELD_MAJOR
= g_quark_from_string("major");
4534 LTT_FIELD_MINOR
= g_quark_from_string("minor");
4535 LTT_FIELD_OPERATION
= g_quark_from_string("direction");
4536 LTT_FIELD_ACTION
= g_quark_from_string("action");
4537 LTT_FIELD_ID
= g_quark_from_string("id");
4538 LTT_FIELD_ADDRESS
= g_quark_from_string("address");
4539 LTT_FIELD_SYMBOL
= g_quark_from_string("symbol");
4540 LTT_FIELD_IP
= g_quark_from_string("ip");
4541 LTT_FIELD_FD
= g_quark_from_string("fd");
4542 LTT_FIELD_STATE
= g_quark_from_string("state");
4543 LTT_FIELD_CPU_ID
= g_quark_from_string("cpu_id");
4545 LTTV_CPU_UNKNOWN
= g_quark_from_string("unknown");
4546 LTTV_CPU_IDLE
= g_quark_from_string("idle");
4547 LTTV_CPU_BUSY
= g_quark_from_string("busy");
4548 LTTV_CPU_IRQ
= g_quark_from_string("irq");
4549 LTTV_CPU_SOFT_IRQ
= g_quark_from_string("softirq");
4550 LTTV_CPU_TRAP
= g_quark_from_string("trap");
4552 LTTV_IRQ_UNKNOWN
= g_quark_from_string("unknown");
4553 LTTV_IRQ_IDLE
= g_quark_from_string("idle");
4554 LTTV_IRQ_BUSY
= g_quark_from_string("busy");
4556 LTTV_BDEV_UNKNOWN
= g_quark_from_string("unknown");
4557 LTTV_BDEV_IDLE
= g_quark_from_string("idle");
4558 LTTV_BDEV_BUSY_READING
= g_quark_from_string("busy_reading");
4559 LTTV_BDEV_BUSY_WRITING
= g_quark_from_string("busy_writing");
4562 static void module_destroy()
4567 LTTV_MODULE("state", "State computation", \
4568 "Update the system state, possibly saving it at intervals", \
4569 module_init
, module_destroy
)