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>
30 #include <lttv/trace.h>
35 #define PREALLOCATED_EXECUTION_STACK 10
41 LTT_CHANNEL_GLOBAL_STATE
,
42 LTT_CHANNEL_IRQ_STATE
,
43 LTT_CHANNEL_MODULE_STATE
,
44 LTT_CHANNEL_NETIF_STATE
,
45 LTT_CHANNEL_SOFTIRQ_STATE
,
46 LTT_CHANNEL_SWAP_STATE
,
47 LTT_CHANNEL_SYSCALL_STATE
,
48 LTT_CHANNEL_TASK_STATE
,
50 LTT_CHANNEL_KPROBE_STATE
,
54 LTT_CHANNEL_USERSPACE
,
60 LTT_EVENT_SYSCALL_ENTRY
,
61 LTT_EVENT_SYSCALL_EXIT
,
62 LTT_EVENT_PAGE_FAULT_NOSEM_ENTRY
,
63 LTT_EVENT_PAGE_FAULT_NOSEM_EXIT
,
64 LTT_EVENT_PAGE_FAULT_ENTRY
,
65 LTT_EVENT_PAGE_FAULT_EXIT
,
66 //LTT_EVENT_TRAP_ENTRY,
67 //LTT_EVENT_TRAP_EXIT,
70 LTT_EVENT_SOFT_IRQ_RAISE
,
71 LTT_EVENT_SOFT_IRQ_ENTRY
,
72 LTT_EVENT_SOFT_IRQ_EXIT
,
73 LTT_EVENT_SCHED_SCHEDULE
,
74 LTT_EVENT_SCHED_TRY_WAKEUP
,
75 LTT_EVENT_PROCESS_FORK
,
76 LTT_EVENT_KTHREAD_CREATE
,
77 LTT_EVENT_PROCESS_EXIT
,
78 LTT_EVENT_PROCESS_FREE
,
80 LTT_EVENT_PROCESS_STATE
,
81 LTT_EVENT_STATEDUMP_END
,
82 LTT_EVENT_FUNCTION_ENTRY
,
83 LTT_EVENT_FUNCTION_EXIT
,
84 LTT_EVENT_THREAD_BRAND
,
85 LTT_EVENT_REQUEST_ISSUE
,
86 LTT_EVENT_REQUEST_COMPLETE
,
87 LTT_EVENT_LIST_INTERRUPT
,
88 LTT_EVENT_SYS_CALL_TABLE
,
89 LTT_EVENT_SOFTIRQ_VEC
,
90 LTT_EVENT_KPROBE_TABLE
,
102 LTT_FIELD_SOFT_IRQ_ID
,
105 LTT_FIELD_PREV_STATE
,
106 LTT_FIELD_PARENT_PID
,
110 LTT_FIELD_CHILD_TGID
,
132 LTTV_STATE_MODE_UNKNOWN
,
133 LTTV_STATE_USER_MODE
,
134 LTTV_STATE_MAYBE_USER_MODE
,
136 LTTV_STATE_MAYBE_SYSCALL
,
138 LTTV_STATE_MAYBE_TRAP
,
143 LTTV_STATE_SUBMODE_UNKNOWN
,
144 LTTV_STATE_SUBMODE_NONE
;
148 LTTV_STATE_WAIT_FORK
,
157 LTTV_STATE_UNBRANDED
;
160 LTTV_STATE_USER_THREAD
,
161 LTTV_STATE_KERNEL_THREAD
;
179 LTTV_BDEV_BUSY_READING
,
180 LTTV_BDEV_BUSY_WRITING
;
183 LTTV_STATE_TRACEFILES
,
184 LTTV_STATE_PROCESSES
,
186 LTTV_STATE_RUNNING_PROCESS
,
188 LTTV_STATE_SAVED_STATES
,
189 LTTV_STATE_SAVED_STATES_TIME
,
192 LTTV_STATE_NAME_TABLES
,
193 LTTV_STATE_TRACE_STATE_USE_COUNT
,
194 LTTV_STATE_RESOURCE_CPUS
,
195 LTTV_STATE_RESOURCE_CPUS_COUNT
,
196 LTTV_STATE_RESOURCE_IRQS
,
197 LTTV_STATE_RESOURCE_SOFT_IRQS
,
198 LTTV_STATE_RESOURCE_TRAPS
,
199 LTTV_STATE_RESOURCE_BLKDEVS
;
201 static void create_max_time(LttvTraceState
*tcs
);
203 static void get_max_time(LttvTraceState
*tcs
);
205 static void free_max_time(LttvTraceState
*tcs
);
207 static void create_name_tables(LttvTraceState
*tcs
);
209 static void get_name_tables(LttvTraceState
*tcs
);
211 static void free_name_tables(LttvTraceState
*tcs
);
213 static void free_saved_state(LttvTraceState
*tcs
);
215 static void lttv_state_free_process_table(GHashTable
*processes
);
217 static void lttv_trace_states_read_raw(LttvTraceState
*tcs
, FILE *fp
,
218 GPtrArray
*quarktable
);
220 /* Resource function prototypes */
221 static LttvBdevState
*get_hashed_bdevstate(LttvTraceState
*ts
, guint32 devcode
);
222 static LttvBdevState
*bdevstate_new(void);
223 static void bdevstate_free(LttvBdevState
*);
224 static void bdevstate_free_cb(gpointer key
, gpointer value
, gpointer user_data
);
225 static LttvBdevState
*bdevstate_copy(LttvBdevState
*bds
);
226 void lttv_state_add_event_hooks(LttvTraceset
*traceset
);
228 #if (__WORDSIZE == 32)
229 guint
guint64_hash(gconstpointer key
)
231 guint64 ukey
= *(const guint64
*)key
;
233 return (guint
)ukey
^ (guint
)(ukey
>> 32);
236 gboolean
guint64_equal(gconstpointer a
, gconstpointer b
)
238 guint64 ua
= *(const guint64
*)a
;
239 guint64 ub
= *(const guint64
*)b
;
245 guint
process_hash(gconstpointer key
)
247 guint pid
= ((const LttvProcessState
*)key
)->pid
;
248 return (pid
>>8 ^ pid
>>4 ^ pid
>>2 ^ pid
) ;
252 /* If the hash table hash function is well distributed,
253 * the process_equal should compare different pid */
254 gboolean
process_equal(gconstpointer a
, gconstpointer b
)
256 const LttvProcessState
*process_a
, *process_b
;
259 process_a
= (const LttvProcessState
*)a
;
260 process_b
= (const LttvProcessState
*)b
;
262 if(likely(process_a
->pid
!= process_b
->pid
)) ret
= FALSE
;
263 else if(likely(process_a
->pid
== 0 &&
264 process_a
->cpu
!= process_b
->cpu
)) ret
= FALSE
;
269 gboolean
rettrue(gpointer key
, gpointer value
, gpointer user_data
)
274 static guint
check_expand(nb
, id
)
279 return max(id
+ 1, nb
* 2);
282 static void expand_name_table(LttvTraceState
*ts
, GQuark
**table
,
283 guint nb
, guint new_nb
)
285 /* Expand an incomplete table */
286 GQuark
*old_table
= *table
;
287 *table
= g_new(GQuark
, new_nb
);
288 memcpy(*table
, old_table
, nb
* sizeof(GQuark
));
292 static void fill_name_table(LttvTraceState
*ts
, GQuark
*table
, guint nb
,
293 guint new_nb
, const char *def_string
)
296 GString
*fe_name
= g_string_new("");
297 for(i
= nb
; i
< new_nb
; i
++) {
298 g_string_printf(fe_name
, "%s %d", def_string
, i
);
299 table
[i
] = g_quark_from_string(fe_name
->str
);
301 g_string_free(fe_name
, TRUE
);
304 static void expand_kprobe_table(LttvTraceState
*ts
, guint64 ip
, char *symbol
)
306 LttvNameTables
*nt
= ts
->name_tables
;
307 #if (__WORDSIZE == 32)
308 guint64
*ip_ptr
= g_new(guint64
, 1);
309 g_hash_table_insert(nt
->kprobe_hash
, ip_ptr
,
310 (gpointer
)(glong
)g_quark_from_string(symbol
));
312 g_hash_table_insert(nt
->kprobe_hash
, (gpointer
)ip
,
313 (gpointer
)(glong
)g_quark_from_string(symbol
));
317 static void expand_trap_table(LttvTraceState
*ts
, int id
)
319 LttvNameTables
*nt
= ts
->name_tables
;
320 LttvTrapState
*old_table
;
323 new_nb
= check_expand(nt
->nb_traps
, id
);
324 if(likely(new_nb
== nt
->nb_traps
))
327 expand_name_table(ts
, &nt
->trap_names
, nt
->nb_traps
, new_nb
);
328 fill_name_table(ts
, nt
->trap_names
, nt
->nb_traps
, new_nb
, "trap");
330 old_table
= ts
->trap_states
;
331 ts
->trap_states
= g_new(LttvTrapState
, new_nb
);
332 memcpy(ts
->trap_states
, old_table
, nt
->nb_traps
* sizeof(LttvTrapState
));
334 for(i
= nt
->nb_traps
; i
< new_nb
; i
++)
335 ts
->trap_states
[i
].running
= 0;
337 /* Update the table size */
338 nt
->nb_traps
= new_nb
;
341 static void expand_irq_table(LttvTraceState
*ts
, int id
)
343 LttvNameTables
*nt
= ts
->name_tables
;
344 LttvIRQState
*old_table
;
347 new_nb
= check_expand(nt
->nb_irqs
, id
);
348 if(likely(new_nb
== nt
->nb_irqs
))
351 expand_name_table(ts
, &nt
->irq_names
, nt
->nb_irqs
, new_nb
);
352 fill_name_table(ts
, nt
->irq_names
, nt
->nb_irqs
, new_nb
, "irq");
354 old_table
= ts
->irq_states
;
355 ts
->irq_states
= g_new(LttvIRQState
, new_nb
);
356 memcpy(ts
->irq_states
, old_table
, nt
->nb_irqs
* sizeof(LttvIRQState
));
358 for(i
= nt
->nb_irqs
; i
< new_nb
; i
++)
359 ts
->irq_states
[i
].mode_stack
=
360 g_array_new(FALSE
, FALSE
, sizeof(LttvIRQMode
));
362 /* Update the table size */
363 nt
->nb_irqs
= new_nb
;
366 static void expand_soft_irq_table(LttvTraceState
*ts
, int id
)
368 LttvNameTables
*nt
= ts
->name_tables
;
369 LttvSoftIRQState
*old_table
;
372 new_nb
= check_expand(nt
->nb_soft_irqs
, id
);
373 if(likely(new_nb
== nt
->nb_soft_irqs
))
376 expand_name_table(ts
, &nt
->soft_irq_names
, nt
->nb_soft_irqs
, new_nb
);
377 fill_name_table(ts
, nt
->soft_irq_names
, nt
->nb_soft_irqs
, new_nb
, "softirq");
379 old_table
= ts
->soft_irq_states
;
380 ts
->soft_irq_states
= g_new(LttvSoftIRQState
, new_nb
);
381 memcpy(ts
->soft_irq_states
, old_table
,
382 nt
->nb_soft_irqs
* sizeof(LttvSoftIRQState
));
384 for(i
= nt
->nb_soft_irqs
; i
< new_nb
; i
++)
385 ts
->soft_irq_states
[i
].running
= 0;
387 /* Update the table size */
388 nt
->nb_soft_irqs
= new_nb
;
391 static void restore_init_state(LttvTraceState
*self
)
393 guint i
, nb_cpus
, nb_irqs
, nb_soft_irqs
, nb_traps
;
395 //LttvTracefileState *tfcs;
399 /* Free the process tables */
400 if(self
->processes
!= NULL
) lttv_state_free_process_table(self
->processes
);
401 self
->processes
= g_hash_table_new(process_hash
, process_equal
);
404 /* Seek time to beginning */
405 // Mathieu : fix : don't seek traceset here : causes inconsistency in seek
406 // closest. It's the tracecontext job to seek the trace to the beginning
407 // anyway : the init state might be used at the middle of the trace as well...
408 //g_tree_destroy(self->parent.ts_context->pqueue);
409 //self->parent.ts_context->pqueue = g_tree_new(compare_tracefile);
411 start_time
= ltt_time_from_uint64(
412 bt_trace_handle_get_timestamp_begin(self
->trace
->traceset
->context
,
416 //lttv_process_trace_seek_time(&self->parent, ltt_time_zero);
418 nb_cpus
= lttv_trace_get_num_cpu(self
->trace
);
419 nb_irqs
= self
->name_tables
->nb_irqs
;
420 nb_soft_irqs
= self
->name_tables
->nb_soft_irqs
;
421 nb_traps
= self
->name_tables
->nb_traps
;
423 /* Put the per cpu running_process to beginning state : process 0. */
424 for(i
=0; i
< nb_cpus
; i
++) {
425 LttvExecutionState
*es
;
426 self
->running_process
[i
] = lttv_state_create_process(self
, NULL
, i
, 0, 0,
427 LTTV_STATE_UNNAMED
, &start_time
);
428 /* We are not sure is it's a kernel thread or normal thread, put the
429 * bottom stack state to unknown */
430 self
->running_process
[i
]->execution_stack
=
431 g_array_set_size(self
->running_process
[i
]->execution_stack
, 1);
432 es
= self
->running_process
[i
]->state
=
433 &g_array_index(self
->running_process
[i
]->execution_stack
,
434 LttvExecutionState
, 0);
435 es
->t
= LTTV_STATE_MODE_UNKNOWN
;
436 es
->s
= LTTV_STATE_UNNAMED
;
438 //self->running_process[i]->state->s = LTTV_STATE_RUN;
439 self
->running_process
[i
]->cpu
= i
;
441 /* reset cpu states */
442 if(self
->cpu_states
[i
].mode_stack
->len
> 0) {
443 g_array_remove_range(self
->cpu_states
[i
].mode_stack
, 0,
444 self
->cpu_states
[i
].mode_stack
->len
);
445 if(self
->cpu_states
[i
].irq_stack
->len
)
446 g_array_remove_range(self
->cpu_states
[i
].irq_stack
, 0,
447 self
->cpu_states
[i
].irq_stack
->len
);
448 if(self
->cpu_states
[i
].softirq_stack
->len
)
449 g_array_remove_range(self
->cpu_states
[i
].softirq_stack
, 0,
450 self
->cpu_states
[i
].softirq_stack
->len
);
451 if(self
->cpu_states
[i
].trap_stack
->len
)
452 g_array_remove_range(self
->cpu_states
[i
].trap_stack
, 0,
453 self
->cpu_states
[i
].trap_stack
->len
);
457 /* reset irq states */
458 for(i
=0; i
<nb_irqs
; i
++) {
459 if(self
->irq_states
[i
].mode_stack
->len
> 0)
460 g_array_remove_range(self
->irq_states
[i
].mode_stack
, 0,
461 self
->irq_states
[i
].mode_stack
->len
);
464 /* reset softirq states */
465 for(i
=0; i
<nb_soft_irqs
; i
++) {
466 self
->soft_irq_states
[i
].pending
= 0;
467 self
->soft_irq_states
[i
].running
= 0;
470 /* reset trap states */
471 for(i
=0; i
<nb_traps
; i
++) {
472 self
->trap_states
[i
].running
= 0;
475 /* reset bdev states */
476 g_hash_table_foreach(self
->bdev_states
, bdevstate_free_cb
, NULL
);
477 //g_hash_table_steal_all(self->bdev_states);
478 g_hash_table_foreach_steal(self
->bdev_states
, rettrue
, NULL
);
481 nb_tracefile
= self
->parent
.tracefiles
->len
;
483 for(i
= 0 ; i
< nb_tracefile
; i
++) {
485 LTTV_TRACEFILE_STATE(g_array_index(self
->parent
.tracefiles
,
486 LttvTracefileContext
*, i
));
487 ltt_trace_time_span_get(self
->parent
.t
, &tfcs
->parent
.timestamp
, NULL
);
488 // tfcs->saved_position = 0;
489 tfcs
->process
= lttv_state_create_process(tfcs
, NULL
,0);
490 tfcs
->process
->state
->s
= LTTV_STATE_RUN
;
491 tfcs
->process
->last_cpu
= tfcs
->cpu_name
;
492 tfcs
->process
->last_cpu_index
= ltt_tracefile_num(((LttvTracefileContext
*)tfcs
)->tf
);
497 //static LttTime time_zero = {0,0};
501 #define MAX_STRING_LEN 4096
503 static void state_load_saved_states(LttvTraceState
*tcs
)
506 GPtrArray
*quarktable
;
507 const char *trace_path
;
511 tcs
->has_precomputed_states
= FALSE
;
515 gchar buf
[MAX_STRING_LEN
];
519 trace_path
= g_quark_to_string(ltt_trace_name(tcs
->parent
.t
));
520 strncpy(path
, trace_path
, PATH_MAX
-1);
521 count
= strnlen(trace_path
, PATH_MAX
-1);
522 // quarktable : open, test
523 strncat(path
, "/precomputed/quarktable", PATH_MAX
-count
-1);
524 fp
= fopen(path
, "r");
526 quarktable
= g_ptr_array_sized_new(4096);
528 /* Index 0 is null */
530 if(hdr
== EOF
) return;
531 g_assert(hdr
== HDR_QUARKS
);
535 if(hdr
== EOF
) break;
536 g_assert(hdr
== HDR_QUARK
);
537 g_ptr_array_set_size(quarktable
, q
+1);
540 res
= fread(&buf
[i
], sizeof(gchar
), 1, fp
);
542 if(buf
[i
] == '\0' || feof(fp
)) break;
545 len
= strnlen(buf
, MAX_STRING_LEN
-1);
546 g_ptr_array_index (quarktable
, q
) = g_new(gchar
, len
+1);
547 strncpy(g_ptr_array_index (quarktable
, q
), buf
, len
+1);
553 // saved_states : open, test
554 strncpy(path
, trace_path
, PATH_MAX
-1);
555 count
= strnlen(trace_path
, PATH_MAX
-1);
556 strncat(path
, "/precomputed/states", PATH_MAX
-count
-1);
557 fp
= fopen(path
, "r");
561 if(hdr
!= HDR_TRACE
) goto end
;
563 lttv_trace_states_read_raw(tcs
, fp
, quarktable
);
565 tcs
->has_precomputed_states
= TRUE
;
570 /* Free the quarktable */
571 for(i
=0; i
<quarktable
->len
; i
++) {
572 string
= g_ptr_array_index (quarktable
, i
);
575 g_ptr_array_free(quarktable
, TRUE
);
578 #endif /* BABEL_CLEANUP */
580 void lttv_trace_state_init(LttvTraceState
*trace_state
, LttvTrace
*trace
)
584 LttvAttributeValue v
;
586 trace_state
->trace
= trace
;
588 trace_state
->save_interval
= LTTV_STATE_SAVE_INTERVAL
;
589 lttv_attribute_find(lttv_trace_attribute(trace
), LTTV_STATE_TRACE_STATE_USE_COUNT
,
593 if (*(v
.v_uint
) == 1) {
594 create_name_tables(trace_state
);
595 create_max_time(trace_state
);
597 get_name_tables(trace_state
);
598 get_max_time(trace_state
);
600 nb_cpu
= lttv_trace_get_num_cpu(trace
);
601 nb_irq
= trace_state
->name_tables
->nb_irqs
;
602 trace_state
->processes
= NULL
;
603 trace_state
->running_process
= g_new(LttvProcessState
*, nb_cpu
);
605 /* init cpu resource stuff */
606 trace_state
->cpu_states
= g_new(LttvCPUState
, nb_cpu
);
607 for (j
= 0; j
< nb_cpu
; j
++) {
608 trace_state
->cpu_states
[j
].mode_stack
= g_array_new(FALSE
, FALSE
, sizeof(LttvCPUMode
));
609 trace_state
->cpu_states
[j
].irq_stack
= g_array_new(FALSE
, FALSE
, sizeof(gint
));
610 trace_state
->cpu_states
[j
].softirq_stack
= g_array_new(FALSE
, FALSE
, sizeof(gint
));
611 trace_state
->cpu_states
[j
].trap_stack
= g_array_new(FALSE
, FALSE
, sizeof(gint
));
612 g_assert(trace_state
->cpu_states
[j
].mode_stack
!= NULL
);
615 /* init irq resource stuff */
616 trace_state
->irq_states
= g_new(LttvIRQState
, nb_irq
);
617 for (j
= 0; j
< nb_irq
; j
++) {
618 trace_state
->irq_states
[j
].mode_stack
= g_array_new(FALSE
, FALSE
, sizeof(LttvIRQMode
));
619 g_assert(trace_state
->irq_states
[j
].mode_stack
!= NULL
);
622 /* init soft irq stuff */
623 /* the kernel has a statically fixed max of 32 softirqs */
624 trace_state
->soft_irq_states
= g_new(LttvSoftIRQState
, trace_state
->name_tables
->nb_soft_irqs
);
626 /* init trap stuff */
627 trace_state
->trap_states
= g_new(LttvTrapState
, trace_state
->name_tables
->nb_traps
);
629 /* init bdev resource stuff */
630 trace_state
->bdev_states
= g_hash_table_new(g_int_hash
, g_int_equal
);
632 restore_init_state(trace_state
);
634 /* See if the trace has saved states */
635 //state_load_saved_states(trace_state);
638 void lttv_trace_state_fini(LttvTraceState
*trace_state
)
640 LttvTrace
*trace
= trace_state
->trace
;
641 LttvAttributeValue v
;
643 lttv_attribute_find(lttv_trace_attribute(trace
), LTTV_STATE_TRACE_STATE_USE_COUNT
,
646 g_assert(*(v
.v_uint
) != 0);
649 if (*(v
.v_uint
) == 0) {
650 free_name_tables(trace_state
);
651 free_max_time(trace_state
);
652 free_saved_state(trace_state
);
654 g_free(trace_state
->running_process
);
655 trace_state
->running_process
= NULL
;
656 lttv_state_free_process_table(trace_state
->processes
);
657 trace_state
->processes
= NULL
;
662 /* Write the process state of the trace */
664 static void write_process_state(gpointer key
, gpointer value
,
667 LttvProcessState
*process
;
669 LttvExecutionState
*es
;
671 FILE *fp
= (FILE *)user_data
;
676 process
= (LttvProcessState
*)value
;
677 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",
678 process
, process
->pid
, process
->tgid
, process
->ppid
,
679 g_quark_to_string(process
->type
),
680 process
->creation_time
.tv_sec
,
681 process
->creation_time
.tv_nsec
,
682 process
->insertion_time
.tv_sec
,
683 process
->insertion_time
.tv_nsec
,
684 g_quark_to_string(process
->name
),
685 g_quark_to_string(process
->brand
),
686 process
->cpu
, process
->free_events
);
688 for(i
= 0 ; i
< process
->execution_stack
->len
; i
++) {
689 es
= &g_array_index(process
->execution_stack
, LttvExecutionState
, i
);
690 fprintf(fp
, " <ES MODE=\"%s\" SUBMODE=\"%s\" ENTRY_S=%lu ENTRY_NS=%lu",
691 g_quark_to_string(es
->t
), g_quark_to_string(es
->n
),
692 es
->entry
.tv_sec
, es
->entry
.tv_nsec
);
693 fprintf(fp
, " CHANGE_S=%lu CHANGE_NS=%lu STATUS=\"%s\"/>\n",
694 es
->change
.tv_sec
, es
->change
.tv_nsec
, g_quark_to_string(es
->s
));
697 for(i
= 0 ; i
< process
->user_stack
->len
; i
++) {
698 address
= g_array_index(process
->user_stack
, guint64
, i
);
699 fprintf(fp
, " <USER_STACK ADDRESS=\"%" PRIu64
"\"/>\n", address
);
702 fprintf(fp
, " </PROCESS>\n");
706 void lttv_state_write(LttvTraceState
*self
, LttTime t
, FILE *fp
)
708 guint i
, nb_tracefile
, nb_block
, offset
;
711 LttvTracefileState
*tfcs
;
715 LttEventPosition
*ep
;
719 ep
= ltt_event_position_new();
721 fprintf(fp
,"<PROCESS_STATE TIME_S=%lu TIME_NS=%lu>\n", t
.tv_sec
, t
.tv_nsec
);
723 g_hash_table_foreach(self
->processes
, write_process_state
, fp
);
725 nb_cpus
= ltt_trace_get_num_cpu(self
->parent
.t
);
726 for(i
=0;i
<nb_cpus
;i
++) {
727 fprintf(fp
," <CPU NUM=%u RUNNING_PROCESS=%u>\n",
728 i
, self
->running_process
[i
]->pid
);
731 nb_tracefile
= self
->parent
.tracefiles
->len
;
733 for(i
= 0 ; i
< nb_tracefile
; i
++) {
735 LTTV_TRACEFILE_STATE(g_array_index(self
->parent
.tracefiles
,
736 LttvTracefileContext
*, i
));
737 fprintf(fp
, " <TRACEFILE TIMESTAMP_S=%lu TIMESTAMP_NS=%lu",
738 tfcs
->parent
.timestamp
.tv_sec
,
739 tfcs
->parent
.timestamp
.tv_nsec
);
740 LttEvent
*e
= ltt_tracefile_get_event(tfcs
->parent
.tf
);
741 if(e
== NULL
) fprintf(fp
,"/>\n");
743 ltt_event_position(e
, ep
);
744 ltt_event_position_get(ep
, &tf
, &nb_block
, &offset
, &tsc
);
745 fprintf(fp
, " BLOCK=%u OFFSET=%u TSC=%" PRIu64
"/>\n", nb_block
, offset
,
750 fprintf(fp
,"</PROCESS_STATE>\n");
754 static void write_process_state_raw(gpointer key
, gpointer value
,
757 LttvProcessState
*process
;
759 LttvExecutionState
*es
;
761 FILE *fp
= (FILE *)user_data
;
766 process
= (LttvProcessState
*)value
;
767 fputc(HDR_PROCESS
, fp
);
768 //fwrite(&header, sizeof(header), 1, fp);
769 //fprintf(fp, "%s", g_quark_to_string(process->type));
771 fwrite(&process
->type
, sizeof(process
->type
), 1, fp
);
772 //fprintf(fp, "%s", g_quark_to_string(process->name));
774 fwrite(&process
->name
, sizeof(process
->name
), 1, fp
);
775 //fprintf(fp, "%s", g_quark_to_string(process->brand));
777 fwrite(&process
->brand
, sizeof(process
->brand
), 1, fp
);
778 fwrite(&process
->pid
, sizeof(process
->pid
), 1, fp
);
779 fwrite(&process
->free_events
, sizeof(process
->free_events
), 1, fp
);
780 fwrite(&process
->tgid
, sizeof(process
->tgid
), 1, fp
);
781 fwrite(&process
->ppid
, sizeof(process
->ppid
), 1, fp
);
782 fwrite(&process
->cpu
, sizeof(process
->cpu
), 1, fp
);
783 fwrite(&process
->creation_time
, sizeof(process
->creation_time
), 1, fp
);
784 fwrite(&process
->insertion_time
, sizeof(process
->insertion_time
), 1, fp
);
787 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",
788 process
, process
->pid
, process
->tgid
, process
->ppid
,
789 g_quark_to_string(process
->type
),
790 process
->creation_time
.tv_sec
,
791 process
->creation_time
.tv_nsec
,
792 process
->insertion_time
.tv_sec
,
793 process
->insertion_time
.tv_nsec
,
794 g_quark_to_string(process
->name
),
795 g_quark_to_string(process
->brand
),
799 for(i
= 0 ; i
< process
->execution_stack
->len
; i
++) {
800 es
= &g_array_index(process
->execution_stack
, LttvExecutionState
, i
);
803 //fprintf(fp, "%s", g_quark_to_string(es->t));
805 fwrite(&es
->t
, sizeof(es
->t
), 1, fp
);
806 //fprintf(fp, "%s", g_quark_to_string(es->n));
808 fwrite(&es
->n
, sizeof(es
->n
), 1, fp
);
809 //fprintf(fp, "%s", g_quark_to_string(es->s));
811 fwrite(&es
->s
, sizeof(es
->s
), 1, fp
);
812 fwrite(&es
->entry
, sizeof(es
->entry
), 1, fp
);
813 fwrite(&es
->change
, sizeof(es
->change
), 1, fp
);
814 fwrite(&es
->cum_cpu_time
, sizeof(es
->cum_cpu_time
), 1, fp
);
816 fprintf(fp
, " <ES MODE=\"%s\" SUBMODE=\"%s\" ENTRY_S=%lu ENTRY_NS=%lu",
817 g_quark_to_string(es
->t
), g_quark_to_string(es
->n
),
818 es
->entry
.tv_sec
, es
->entry
.tv_nsec
);
819 fprintf(fp
, " CHANGE_S=%lu CHANGE_NS=%lu STATUS=\"%s\"/>\n",
820 es
->change
.tv_sec
, es
->change
.tv_nsec
, g_quark_to_string(es
->s
));
824 for(i
= 0 ; i
< process
->user_stack
->len
; i
++) {
825 address
= g_array_index(process
->user_stack
, guint64
, i
);
826 fputc(HDR_USER_STACK
, fp
);
827 fwrite(&address
, sizeof(address
), 1, fp
);
829 fprintf(fp
, " <USER_STACK ADDRESS=\"%llu\"/>\n", address
);
835 void lttv_state_write_raw(LttvTraceState
*self
, LttTime t
, FILE *fp
)
837 guint i
, nb_tracefile
, nb_block
, offset
;
840 LttvTracefileState
*tfcs
;
844 LttEventPosition
*ep
;
848 ep
= ltt_event_position_new();
850 //fprintf(fp,"<PROCESS_STATE TIME_S=%lu TIME_NS=%lu>\n", t.tv_sec, t.tv_nsec);
851 fputc(HDR_PROCESS_STATE
, fp
);
852 fwrite(&t
, sizeof(t
), 1, fp
);
854 g_hash_table_foreach(self
->processes
, write_process_state_raw
, fp
);
856 nb_cpus
= ltt_trace_get_num_cpu(self
->parent
.t
);
857 for(i
=0;i
<nb_cpus
;i
++) {
859 fwrite(&i
, sizeof(i
), 1, fp
); /* cpu number */
860 fwrite(&self
->running_process
[i
]->pid
,
861 sizeof(self
->running_process
[i
]->pid
), 1, fp
);
862 //fprintf(fp," <CPU NUM=%u RUNNING_PROCESS=%u>\n",
863 // i, self->running_process[i]->pid);
866 nb_tracefile
= self
->parent
.tracefiles
->len
;
868 for(i
= 0 ; i
< nb_tracefile
; i
++) {
870 LTTV_TRACEFILE_STATE(g_array_index(self
->parent
.tracefiles
,
871 LttvTracefileContext
*, i
));
872 // fprintf(fp, " <TRACEFILE TIMESTAMP_S=%lu TIMESTAMP_NS=%lu",
873 // tfcs->parent.timestamp.tv_sec,
874 // tfcs->parent.timestamp.tv_nsec);
875 fputc(HDR_TRACEFILE
, fp
);
876 fwrite(&tfcs
->parent
.timestamp
, sizeof(tfcs
->parent
.timestamp
), 1, fp
);
877 /* Note : if timestamp if LTT_TIME_INFINITE, there will be no
878 * position following : end of trace */
879 LttEvent
*e
= ltt_tracefile_get_event(tfcs
->parent
.tf
);
881 ltt_event_position(e
, ep
);
882 ltt_event_position_get(ep
, &tf
, &nb_block
, &offset
, &tsc
);
883 //fprintf(fp, " BLOCK=%u OFFSET=%u TSC=%llu/>\n", nb_block, offset,
885 fwrite(&nb_block
, sizeof(nb_block
), 1, fp
);
886 fwrite(&offset
, sizeof(offset
), 1, fp
);
887 fwrite(&tsc
, sizeof(tsc
), 1, fp
);
894 /* Read process state from a file */
896 /* Called because a HDR_PROCESS was found */
897 static void read_process_state_raw(LttvTraceState
*self
, FILE *fp
,
898 GPtrArray
*quarktable
)
900 LttvExecutionState
*es
;
901 LttvProcessState
*process
, *parent_process
;
902 LttvProcessState tmp
;
908 res
= fread(&tmp
.type
, sizeof(tmp
.type
), 1, fp
);
909 res
+= fread(&tmp
.name
, sizeof(tmp
.name
), 1, fp
);
910 res
+= fread(&tmp
.brand
, sizeof(tmp
.brand
), 1, fp
);
911 res
+= fread(&tmp
.pid
, sizeof(tmp
.pid
), 1, fp
);
912 res
+= fread(&tmp
.free_events
, sizeof(tmp
.free_events
), 1, fp
);
913 res
+= fread(&tmp
.tgid
, sizeof(tmp
.tgid
), 1, fp
);
914 res
+= fread(&tmp
.ppid
, sizeof(tmp
.ppid
), 1, fp
);
915 res
+= fread(&tmp
.cpu
, sizeof(tmp
.cpu
), 1, fp
);
916 res
+= fread(&tmp
.creation_time
, sizeof(tmp
.creation_time
), 1, fp
);
917 res
+= fread(&tmp
.insertion_time
, sizeof(tmp
.insertion_time
), 1, fp
);
921 process
= lttv_state_find_process(self
, tmp
.cpu
, tmp
.pid
);
923 /* We must link to the parent */
924 parent_process
= lttv_state_find_process_or_create(self
, ANY_CPU
, tmp
.ppid
,
926 process
= lttv_state_find_process(self
, ANY_CPU
, tmp
.pid
);
927 if(process
== NULL
) {
928 process
= lttv_state_create_process(self
, parent_process
, tmp
.cpu
,
930 g_quark_from_string((gchar
*)g_ptr_array_index(quarktable
, tmp
.name
)),
934 process
->insertion_time
= tmp
.insertion_time
;
935 process
->creation_time
= tmp
.creation_time
;
936 process
->type
= g_quark_from_string(
937 (gchar
*)g_ptr_array_index(quarktable
, tmp
.type
));
938 process
->tgid
= tmp
.tgid
;
939 process
->ppid
= tmp
.ppid
;
940 process
->brand
= g_quark_from_string(
941 (gchar
*)g_ptr_array_index(quarktable
, tmp
.brand
));
943 g_quark_from_string((gchar
*)g_ptr_array_index(quarktable
, tmp
.name
));
944 process
->free_events
= tmp
.free_events
;
947 if(feof(fp
) || ferror(fp
)) goto end_loop
;
949 gint hdr
= fgetc(fp
);
950 if(hdr
== EOF
) goto end_loop
;
954 process
->execution_stack
=
955 g_array_set_size(process
->execution_stack
,
956 process
->execution_stack
->len
+ 1);
957 es
= &g_array_index(process
->execution_stack
, LttvExecutionState
,
958 process
->execution_stack
->len
-1);
961 res
= fread(&es
->t
, sizeof(es
->t
), 1, fp
);
963 es
->t
= g_quark_from_string(
964 (gchar
*)g_ptr_array_index(quarktable
, es
->t
));
965 res
= fread(&es
->n
, sizeof(es
->n
), 1, fp
);
967 es
->n
= g_quark_from_string(
968 (gchar
*)g_ptr_array_index(quarktable
, es
->n
));
969 res
= fread(&es
->s
, sizeof(es
->s
), 1, fp
);
971 es
->s
= g_quark_from_string(
972 (gchar
*)g_ptr_array_index(quarktable
, es
->s
));
973 res
= fread(&es
->entry
, sizeof(es
->entry
), 1, fp
);
974 res
+= fread(&es
->change
, sizeof(es
->change
), 1, fp
);
975 res
+= fread(&es
->cum_cpu_time
, sizeof(es
->cum_cpu_time
), 1, fp
);
980 process
->user_stack
= g_array_set_size(process
->user_stack
,
981 process
->user_stack
->len
+ 1);
982 address
= &g_array_index(process
->user_stack
, guint64
,
983 process
->user_stack
->len
-1);
984 res
= fread(address
, sizeof(address
), 1, fp
);
986 process
->current_function
= *address
;
999 /* Called because a HDR_PROCESS_STATE was found */
1000 /* Append a saved state to the trace states */
1001 void lttv_state_read_raw(LttvTraceState
*self
, FILE *fp
, GPtrArray
*quarktable
)
1003 guint i
, nb_tracefile
, nb_block
, offset
;
1005 LttvTracefileState
*tfcs
;
1007 LttEventPosition
*ep
;
1016 LttvAttribute
*saved_states_tree
, *saved_state_tree
;
1018 LttvAttributeValue value
;
1019 GTree
*pqueue
= self
->parent
.ts_context
->pqueue
;
1020 ep
= ltt_event_position_new();
1022 restore_init_state(self
);
1024 res
= fread(&t
, sizeof(t
), 1, fp
);
1028 if(feof(fp
) || ferror(fp
)) goto end_loop
;
1030 if(hdr
== EOF
) goto end_loop
;
1034 /* Call read_process_state_raw */
1035 read_process_state_raw(self
, fp
, quarktable
);
1043 case HDR_USER_STACK
:
1044 case HDR_PROCESS_STATE
:
1050 g_error("Error while parsing saved state file : unknown data header %d",
1056 nb_cpus
= ltt_trace_get_num_cpu(self
->parent
.t
);
1057 for(i
=0;i
<nb_cpus
;i
++) {
1060 g_assert(hdr
== HDR_CPU
);
1061 res
= fread(&cpu_num
, sizeof(cpu_num
), 1, fp
); /* cpu number */
1063 g_assert(i
== cpu_num
);
1064 res
= fread(&self
->running_process
[i
]->pid
,
1065 sizeof(self
->running_process
[i
]->pid
), 1, fp
);
1069 nb_tracefile
= self
->parent
.tracefiles
->len
;
1071 for(i
= 0 ; i
< nb_tracefile
; i
++) {
1073 LTTV_TRACEFILE_STATE(g_array_index(self
->parent
.tracefiles
,
1074 LttvTracefileContext
*, i
));
1075 // fprintf(fp, " <TRACEFILE TIMESTAMP_S=%lu TIMESTAMP_NS=%lu",
1076 // tfcs->parent.timestamp.tv_sec,
1077 // tfcs->parent.timestamp.tv_nsec);
1078 g_tree_remove(pqueue
, &tfcs
->parent
);
1080 g_assert(hdr
== HDR_TRACEFILE
);
1081 res
= fread(&tfcs
->parent
.timestamp
, sizeof(tfcs
->parent
.timestamp
), 1, fp
);
1083 /* Note : if timestamp if LTT_TIME_INFINITE, there will be no
1084 * position following : end of trace */
1085 if(ltt_time_compare(tfcs
->parent
.timestamp
, ltt_time_infinite
) != 0) {
1086 res
= fread(&nb_block
, sizeof(nb_block
), 1, fp
);
1087 res
+= fread(&offset
, sizeof(offset
), 1, fp
);
1088 res
+= fread(&tsc
, sizeof(tsc
), 1, fp
);
1090 ltt_event_position_set(ep
, tfcs
->parent
.tf
, nb_block
, offset
, tsc
);
1091 gint ret
= ltt_tracefile_seek_position(tfcs
->parent
.tf
, ep
);
1093 g_tree_insert(pqueue
, &tfcs
->parent
, &tfcs
->parent
);
1098 saved_states_tree
= lttv_attribute_find_subdir(self
->parent
.t_a
,
1099 LTTV_STATE_SAVED_STATES
);
1100 saved_state_tree
= g_object_new(LTTV_ATTRIBUTE_TYPE
, NULL
);
1101 value
= lttv_attribute_add(saved_states_tree
,
1102 lttv_attribute_get_number(saved_states_tree
), LTTV_GOBJECT
);
1103 *(value
.v_gobject
) = (GObject
*)saved_state_tree
;
1104 value
= lttv_attribute_add(saved_state_tree
, LTTV_STATE_TIME
, LTTV_TIME
);
1105 *(value
.v_time
) = t
;
1106 lttv_state_save(self
, saved_state_tree
);
1107 g_debug("Saving state at time %lu.%lu", t
.tv_sec
,
1110 *(self
->max_time_state_recomputed_in_seek
) = t
;
1114 /* Called when a HDR_TRACE is found */
1115 void lttv_trace_states_read_raw(LttvTraceState
*tcs
, FILE *fp
,
1116 GPtrArray
*quarktable
)
1121 if(feof(fp
) || ferror(fp
)) goto end_loop
;
1123 if(hdr
== EOF
) goto end_loop
;
1126 case HDR_PROCESS_STATE
:
1127 /* Call read_process_state_raw */
1128 lttv_state_read_raw(tcs
, fp
, quarktable
);
1136 case HDR_USER_STACK
:
1139 g_error("Error while parsing saved state file :"
1140 " unexpected data header %d",
1144 g_error("Error while parsing saved state file : unknown data header %d",
1149 *(tcs
->max_time_state_recomputed_in_seek
) = tcs
->parent
.time_span
.end_time
;
1150 restore_init_state(tcs
);
1151 lttv_process_trace_seek_time(&tcs
->parent
, ltt_time_zero
);
1154 #endif /* BABEL_CLEANUP */
1157 /* Copy each process from an existing hash table to a new one */
1159 static void copy_process_state(gpointer key
, gpointer value
,gpointer user_data
)
1161 LttvProcessState
*process
, *new_process
;
1163 GHashTable
*new_processes
= (GHashTable
*)user_data
;
1167 process
= (LttvProcessState
*)value
;
1168 new_process
= g_new(LttvProcessState
, 1);
1169 *new_process
= *process
;
1170 new_process
->execution_stack
= g_array_sized_new(FALSE
, FALSE
,
1171 sizeof(LttvExecutionState
), PREALLOCATED_EXECUTION_STACK
);
1172 new_process
->execution_stack
=
1173 g_array_set_size(new_process
->execution_stack
,
1174 process
->execution_stack
->len
);
1175 for(i
= 0 ; i
< process
->execution_stack
->len
; i
++) {
1176 g_array_index(new_process
->execution_stack
, LttvExecutionState
, i
) =
1177 g_array_index(process
->execution_stack
, LttvExecutionState
, i
);
1179 new_process
->state
= &g_array_index(new_process
->execution_stack
,
1180 LttvExecutionState
, new_process
->execution_stack
->len
- 1);
1181 #ifdef BABEL_CLEANUP
1182 new_process
->user_stack
= g_array_sized_new(FALSE
, FALSE
,
1183 sizeof(guint64
), 0);
1184 new_process
->user_stack
= g_array_set_size(new_process
->user_stack
,
1185 process
->user_stack
->len
);
1186 for(i
= 0 ; i
< process
->user_stack
->len
; i
++) {
1187 g_array_index(new_process
->user_stack
, guint64
, i
) =
1188 g_array_index(process
->user_stack
, guint64
, i
);
1190 new_process
->current_function
= process
->current_function
;
1191 #endif /* BABEL_CLEANUP */
1193 /* fd hash table stuff */
1199 /* copy every item in the hash table */
1200 new_process
->fds
= g_hash_table_new(g_direct_hash
, g_direct_equal
);
1202 g_hash_table_iter_init(&it
, process
->fds
);
1203 while (g_hash_table_iter_next (&it
, (void *)&key
, (void *)&value
)) {
1204 g_hash_table_insert(new_process
->fds
, key
, value
);
1208 /* When done creating the new process state, insert it in the
1210 g_hash_table_insert(new_processes
, new_process
, new_process
);
1214 static GHashTable
*lttv_state_copy_process_table(GHashTable
*processes
)
1216 GHashTable
*new_processes
= g_hash_table_new(process_hash
, process_equal
);
1218 g_hash_table_foreach(processes
, copy_process_state
, new_processes
);
1219 return new_processes
;
1222 static LttvCPUState
*lttv_state_copy_cpu_states(LttvCPUState
*states
, guint n
)
1225 LttvCPUState
*retval
;
1227 retval
= g_new(LttvCPUState
, n
);
1229 for(i
=0; i
<n
; i
++) {
1230 retval
[i
].irq_stack
= g_array_new(FALSE
, FALSE
, sizeof(gint
));
1231 g_array_set_size(retval
[i
].irq_stack
, states
[i
].irq_stack
->len
);
1232 for(j
=0; j
<states
[i
].irq_stack
->len
; j
++) {
1233 g_array_index(retval
[i
].irq_stack
, gint
, j
) =
1234 g_array_index(states
[i
].irq_stack
, gint
, j
);
1237 retval
[i
].softirq_stack
= g_array_new(FALSE
, FALSE
, sizeof(gint
));
1238 g_array_set_size(retval
[i
].softirq_stack
, states
[i
].softirq_stack
->len
);
1239 for(j
=0; j
<states
[i
].softirq_stack
->len
; j
++) {
1240 g_array_index(retval
[i
].softirq_stack
, gint
, j
) =
1241 g_array_index(states
[i
].softirq_stack
, gint
, j
);
1244 retval
[i
].trap_stack
= g_array_new(FALSE
, FALSE
, sizeof(gint
));
1245 g_array_set_size(retval
[i
].trap_stack
, states
[i
].trap_stack
->len
);
1246 for(j
=0; j
<states
[i
].trap_stack
->len
; j
++) {
1247 g_array_index(retval
[i
].trap_stack
, gint
, j
) =
1248 g_array_index(states
[i
].trap_stack
, gint
, j
);
1251 retval
[i
].mode_stack
= g_array_new(FALSE
, FALSE
, sizeof(LttvCPUMode
));
1252 g_array_set_size(retval
[i
].mode_stack
, states
[i
].mode_stack
->len
);
1253 for(j
=0; j
<states
[i
].mode_stack
->len
; j
++) {
1254 g_array_index(retval
[i
].mode_stack
, GQuark
, j
) =
1255 g_array_index(states
[i
].mode_stack
, GQuark
, j
);
1262 static void lttv_state_free_cpu_states(LttvCPUState
*states
, guint n
)
1266 for(i
=0; i
<n
; i
++) {
1267 g_array_free(states
[i
].mode_stack
, TRUE
);
1268 g_array_free(states
[i
].irq_stack
, TRUE
);
1269 g_array_free(states
[i
].softirq_stack
, TRUE
);
1270 g_array_free(states
[i
].trap_stack
, TRUE
);
1276 static LttvIRQState
*lttv_state_copy_irq_states(LttvIRQState
*states
, guint n
)
1279 LttvIRQState
*retval
;
1281 retval
= g_new(LttvIRQState
, n
);
1283 for(i
=0; i
<n
; i
++) {
1284 retval
[i
].mode_stack
= g_array_new(FALSE
, FALSE
, sizeof(LttvIRQMode
));
1285 g_array_set_size(retval
[i
].mode_stack
, states
[i
].mode_stack
->len
);
1286 for(j
=0; j
<states
[i
].mode_stack
->len
; j
++) {
1287 g_array_index(retval
[i
].mode_stack
, GQuark
, j
) =
1288 g_array_index(states
[i
].mode_stack
, GQuark
, j
);
1295 static void lttv_state_free_irq_states(LttvIRQState
*states
, guint n
)
1299 for(i
=0; i
<n
; i
++) {
1300 g_array_free(states
[i
].mode_stack
, TRUE
);
1306 static LttvSoftIRQState
*
1307 lttv_state_copy_soft_irq_states(LttvSoftIRQState
*states
, guint n
)
1310 LttvSoftIRQState
*retval
;
1312 retval
= g_new(LttvSoftIRQState
, n
);
1314 for(i
=0; i
<n
; i
++) {
1315 retval
[i
].pending
= states
[i
].pending
;
1316 retval
[i
].running
= states
[i
].running
;
1322 static void lttv_state_free_soft_irq_states(LttvSoftIRQState
*states
, guint n
)
1327 static LttvTrapState
*
1328 lttv_state_copy_trap_states(LttvTrapState
*states
, guint n
)
1331 LttvTrapState
*retval
;
1333 retval
= g_new(LttvTrapState
, n
);
1335 for(i
=0; i
<n
; i
++) {
1336 retval
[i
].running
= states
[i
].running
;
1342 static void lttv_state_free_trap_states(LttvTrapState
*states
, guint n
)
1347 /* bdevstate stuff */
1349 static LttvBdevState
*get_hashed_bdevstate(LttvTraceState
*ts
, guint32 devcode
)
1351 gint devcode_gint
= devcode
;
1352 gpointer bdev
= g_hash_table_lookup(ts
->bdev_states
, &devcode_gint
);
1354 LttvBdevState
*bdevstate
= g_new(LttvBdevState
, 1);
1355 bdevstate
->mode_stack
= g_array_new(FALSE
, FALSE
, sizeof(GQuark
));
1357 gint
* key
= g_new(gint
, 1);
1359 g_hash_table_insert(ts
->bdev_states
, key
, bdevstate
);
1367 static LttvBdevState
*bdevstate_new(void)
1369 LttvBdevState
*retval
;
1370 retval
= g_new(LttvBdevState
, 1);
1371 retval
->mode_stack
= g_array_new(FALSE
, FALSE
, sizeof(GQuark
));
1376 static void bdevstate_free(LttvBdevState
*bds
)
1378 g_array_free(bds
->mode_stack
, TRUE
);
1382 static void bdevstate_free_cb(gpointer key
, gpointer value
, gpointer user_data
)
1384 LttvBdevState
*bds
= (LttvBdevState
*) value
;
1386 bdevstate_free(bds
);
1389 static LttvBdevState
*bdevstate_copy(LttvBdevState
*bds
)
1391 LttvBdevState
*retval
;
1393 retval
= bdevstate_new();
1394 g_array_insert_vals(retval
->mode_stack
, 0, bds
->mode_stack
->data
,
1395 bds
->mode_stack
->len
);
1400 static void insert_and_copy_bdev_state(gpointer k
, gpointer v
, gpointer u
)
1402 //GHashTable *ht = (GHashTable *)u;
1403 LttvBdevState
*bds
= (LttvBdevState
*)v
;
1404 LttvBdevState
*newbds
;
1406 newbds
= bdevstate_copy(bds
);
1408 g_hash_table_insert(u
, k
, newbds
);
1411 static GHashTable
*lttv_state_copy_blkdev_hashtable(GHashTable
*ht
)
1415 retval
= g_hash_table_new(g_int_hash
, g_int_equal
);
1417 g_hash_table_foreach(ht
, insert_and_copy_bdev_state
, retval
);
1422 /* Free a hashtable and the LttvBdevState structures its values
1425 static void lttv_state_free_blkdev_hashtable(GHashTable
*ht
)
1427 g_hash_table_foreach(ht
, bdevstate_free_cb
, NULL
);
1428 g_hash_table_destroy(ht
);
1431 /* The saved state for each trace contains a member "processes", which
1432 stores a copy of the process table, and a member "tracefiles" with
1433 one entry per tracefile. Each tracefile has a "process" member pointing
1434 to the current process and a "position" member storing the tracefile
1435 position (needed to seek to the current "next" event. */
1437 void lttv_state_save(LttvTraceState
*self
, LttvAttribute
*container
)
1439 guint i
, nb_cpus
, nb_irqs
, nb_soft_irqs
, nb_traps
;
1441 guint
*running_process
;
1443 LttvAttributeValue value
;
1445 value
= lttv_attribute_add(container
, LTTV_STATE_PROCESSES
,
1447 *(value
.v_pointer
) = lttv_state_copy_process_table(self
->processes
);
1449 /* Add the currently running processes array */
1450 nb_cpus
= lttv_trace_get_num_cpu(self
->trace
);
1451 running_process
= g_new(guint
, nb_cpus
);
1452 for(i
=0;i
<nb_cpus
;i
++) {
1453 running_process
[i
] = self
->running_process
[i
]->pid
;
1455 value
= lttv_attribute_add(container
, LTTV_STATE_RUNNING_PROCESS
,
1457 *(value
.v_pointer
) = running_process
;
1459 g_info("State save");
1461 /* Save the current position */
1462 value
= lttv_attribute_add(container
, LTTV_STATE_POSITION
,
1464 *(value
.v_pointer
) = lttv_traceset_create_current_position(lttv_trace_get_traceset(self
->trace
));
1466 #ifdef BABEL_CLEANUP
1467 nb_tracefile
= self
->parent
.tracefiles
->len
;
1468 for(i
= 0 ; i
< nb_tracefile
; i
++) {
1470 LTTV_TRACEFILE_STATE(g_array_index(self
->parent
.tracefiles
,
1471 LttvTracefileContext
*, i
));
1472 tracefile_tree
= g_object_new(LTTV_ATTRIBUTE_TYPE
, NULL
);
1473 value
= lttv_attribute_add(tracefiles_tree
, i
,
1475 *(value
.v_gobject
) = (GObject
*)tracefile_tree
;
1477 value
= lttv_attribute_add(tracefile_tree
, LTTV_STATE_PROCESS
,
1479 *(value
.v_uint
) = tfcs
->process
->pid
;
1481 value
= lttv_attribute_add(tracefile_tree
, LTTV_STATE_EVENT
,
1483 /* Only save the position if the tfs has not infinite time. */
1484 //if(!g_tree_lookup(self->parent.ts_context->pqueue, &tfcs->parent)
1485 // && current_tfcs != tfcs) {
1486 if(ltt_time_compare(tfcs
->parent
.timestamp
, ltt_time_infinite
) == 0) {
1487 *(value
.v_pointer
) = NULL
;
1489 LttEvent
*e
= ltt_tracefile_get_event(tfcs
->parent
.tf
);
1490 ep
= ltt_event_position_new();
1491 ltt_event_position(e
, ep
);
1492 *(value
.v_pointer
) = ep
;
1494 guint nb_block
, offset
;
1497 ltt_event_position_get(ep
, &tf
, &nb_block
, &offset
, &tsc
);
1498 g_info("Block %u offset %u tsc %" PRIu64
" time %lu.%lu", nb_block
,
1499 offset
, tsc
, tfcs
->parent
.timestamp
.tv_sec
,
1500 tfcs
->parent
.timestamp
.tv_nsec
);
1503 #endif /* BABEL_CLEANUP */
1505 /* save the cpu state */
1507 value
= lttv_attribute_add(container
, LTTV_STATE_RESOURCE_CPUS_COUNT
,
1509 *(value
.v_uint
) = nb_cpus
;
1511 value
= lttv_attribute_add(container
, LTTV_STATE_RESOURCE_CPUS
,
1513 *(value
.v_pointer
) = lttv_state_copy_cpu_states(self
->cpu_states
, nb_cpus
);
1516 /* save the irq state */
1517 nb_irqs
= self
->name_tables
->nb_irqs
;
1519 value
= lttv_attribute_add(container
, LTTV_STATE_RESOURCE_IRQS
,
1521 *(value
.v_pointer
) = lttv_state_copy_irq_states(self
->irq_states
, nb_irqs
);
1524 /* save the soft irq state */
1525 nb_soft_irqs
= self
->name_tables
->nb_soft_irqs
;
1527 value
= lttv_attribute_add(container
, LTTV_STATE_RESOURCE_SOFT_IRQS
,
1529 *(value
.v_pointer
) = lttv_state_copy_soft_irq_states(self
->soft_irq_states
, nb_soft_irqs
);
1532 /* save the trap state */
1533 nb_traps
= self
->name_tables
->nb_traps
;
1535 value
= lttv_attribute_add(container
, LTTV_STATE_RESOURCE_TRAPS
,
1537 *(value
.v_pointer
) = lttv_state_copy_trap_states(self
->trap_states
, nb_traps
);
1540 /* save the blkdev states */
1541 value
= lttv_attribute_add(container
, LTTV_STATE_RESOURCE_BLKDEVS
,
1543 *(value
.v_pointer
) = lttv_state_copy_blkdev_hashtable(self
->bdev_states
);
1546 void lttv_state_restore(LttvTraceState
*self
, LttvAttribute
*container
)
1548 guint i
, pid
, nb_cpus
, nb_irqs
, nb_soft_irqs
, nb_traps
;
1549 guint
*running_process
;
1550 LttvAttributeType type
;
1551 LttvAttributeValue value
;
1553 type
= lttv_attribute_get_by_name(container
, LTTV_STATE_PROCESSES
,
1555 g_assert(type
== LTTV_POINTER
);
1556 lttv_state_free_process_table(self
->processes
);
1557 self
->processes
= lttv_state_copy_process_table(*(value
.v_pointer
));
1559 /* Add the currently running processes array */
1560 nb_cpus
= lttv_trace_get_num_cpu(self
->trace
);
1561 type
= lttv_attribute_get_by_name(container
, LTTV_STATE_RUNNING_PROCESS
,
1563 g_assert(type
== LTTV_POINTER
);
1564 running_process
= *(value
.v_pointer
);
1565 for(i
=0;i
<nb_cpus
;i
++) {
1566 pid
= running_process
[i
];
1567 self
->running_process
[i
] = lttv_state_find_process(self
, i
, pid
);
1568 g_assert(self
->running_process
[i
] != NULL
);
1571 //nb_tracefile = self->parent.tracefiles->len;
1573 //g_tree_destroy(tsc->pqueue);
1574 //tsc->pqueue = g_tree_new(compare_tracefile);
1576 /* restore cpu resource states */
1577 type
= lttv_attribute_get_by_name(container
, LTTV_STATE_RESOURCE_CPUS
, &value
);
1578 g_assert(type
== LTTV_POINTER
);
1579 lttv_state_free_cpu_states(self
->cpu_states
, nb_cpus
);
1580 self
->cpu_states
= lttv_state_copy_cpu_states(*(value
.v_pointer
), nb_cpus
);
1582 /* restore irq resource states */
1583 nb_irqs
= self
->name_tables
->nb_irqs
;
1584 type
= lttv_attribute_get_by_name(container
, LTTV_STATE_RESOURCE_IRQS
, &value
);
1585 g_assert(type
== LTTV_POINTER
);
1586 lttv_state_free_irq_states(self
->irq_states
, nb_irqs
);
1587 self
->irq_states
= lttv_state_copy_irq_states(*(value
.v_pointer
), nb_irqs
);
1589 /* restore soft irq resource states */
1590 nb_soft_irqs
= self
->name_tables
->nb_soft_irqs
;
1591 type
= lttv_attribute_get_by_name(container
, LTTV_STATE_RESOURCE_SOFT_IRQS
, &value
);
1592 g_assert(type
== LTTV_POINTER
);
1593 lttv_state_free_soft_irq_states(self
->soft_irq_states
, nb_soft_irqs
);
1594 self
->soft_irq_states
= lttv_state_copy_soft_irq_states(*(value
.v_pointer
), nb_soft_irqs
);
1596 /* restore trap resource states */
1597 nb_traps
= self
->name_tables
->nb_traps
;
1598 type
= lttv_attribute_get_by_name(container
, LTTV_STATE_RESOURCE_TRAPS
, &value
);
1599 g_assert(type
== LTTV_POINTER
);
1600 lttv_state_free_trap_states(self
->trap_states
, nb_traps
);
1601 self
->trap_states
= lttv_state_copy_trap_states(*(value
.v_pointer
), nb_traps
);
1603 /* restore the blkdev states */
1604 type
= lttv_attribute_get_by_name(container
, LTTV_STATE_RESOURCE_BLKDEVS
, &value
);
1605 g_assert(type
== LTTV_POINTER
);
1606 lttv_state_free_blkdev_hashtable(self
->bdev_states
);
1607 self
->bdev_states
= lttv_state_copy_blkdev_hashtable(*(value
.v_pointer
));
1609 #ifdef BABEL_CLEANUP
1610 for(i
= 0 ; i
< nb_tracefile
; i
++) {
1612 LTTV_TRACEFILE_STATE(g_array_index(self
->parent
.tracefiles
,
1613 LttvTracefileContext
*, i
));
1614 type
= lttv_attribute_get(tracefiles_tree
, i
, &name
, &value
, &is_named
);
1615 g_assert(type
== LTTV_GOBJECT
);
1616 tracefile_tree
= *((LttvAttribute
**)(value
.v_gobject
));
1618 type
= lttv_attribute_get_by_name(tracefile_tree
, LTTV_STATE_PROCESS
,
1620 g_assert(type
== LTTV_UINT
);
1621 pid
= *(value
.v_uint
);
1622 tfcs
->process
= lttv_state_find_process_or_create(tfcs
, pid
);
1624 type
= lttv_attribute_get_by_name(tracefile_tree
, LTTV_STATE_EVENT
,
1626 g_assert(type
== LTTV_POINTER
);
1627 //g_assert(*(value.v_pointer) != NULL);
1628 ep
= *(value
.v_pointer
);
1629 g_assert(tfcs
->parent
.t_context
!= NULL
);
1631 tfcs
->cpu_state
= &self
->cpu_states
[tfcs
->cpu
];
1633 LttvTracefileContext
*tfc
= LTTV_TRACEFILE_CONTEXT(tfcs
);
1634 g_tree_remove(tsc
->pqueue
, tfc
);
1637 retval
= ltt_tracefile_seek_position(tfc
->tf
, ep
);
1638 g_assert_cmpint(retval
, ==, 0);
1639 tfc
->timestamp
= ltt_event_time(ltt_tracefile_get_event(tfc
->tf
));
1640 g_assert_cmpint(ltt_time_compare(tfc
->timestamp
, ltt_time_infinite
),
1642 g_tree_insert(tsc
->pqueue
, tfc
, tfc
);
1643 g_info("Restoring state for a tf at time %lu.%lu",
1644 tfc
->timestamp
.tv_sec
, tfc
->timestamp
.tv_nsec
);
1646 tfc
->timestamp
= ltt_time_infinite
;
1649 #endif /* BABEL_CLEANUP */
1653 * Note: the position must be explicitely set on the entire traceset to
1654 * match the trace states.
1656 LttvTracesetPosition
*lttv_trace_state_get_position(LttvAttribute
*container
)
1658 LttvAttributeType type
;
1659 LttvAttributeValue value
;
1661 type
= lttv_attribute_get_by_name(container
, LTTV_STATE_POSITION
, &value
);
1662 g_assert(type
== LTTV_POINTER
);
1663 return *(value
.v_pointer
);
1666 void lttv_state_saved_free(LttvTraceState
*self
, LttvAttribute
*container
)
1668 guint nb_cpus
, nb_irqs
, nb_soft_irqs
;
1669 guint
*running_process
;
1670 LttvAttributeType type
;
1671 LttvAttributeValue value
;
1673 type
= lttv_attribute_get_by_name(container
, LTTV_STATE_PROCESSES
,
1675 g_assert(type
== LTTV_POINTER
);
1676 lttv_state_free_process_table(*(value
.v_pointer
));
1677 *(value
.v_pointer
) = NULL
;
1678 lttv_attribute_remove_by_name(container
, LTTV_STATE_PROCESSES
);
1680 /* Free running processes array */
1681 type
= lttv_attribute_get_by_name(container
, LTTV_STATE_RUNNING_PROCESS
,
1683 g_assert(type
== LTTV_POINTER
);
1684 running_process
= *(value
.v_pointer
);
1685 g_free(running_process
);
1687 /* free cpu resources */
1688 type
= lttv_attribute_get_by_name(container
, LTTV_STATE_RESOURCE_CPUS_COUNT
, &value
);
1689 g_assert(type
== LTTV_UINT
);
1690 nb_cpus
= *value
.v_uint
;
1691 type
= lttv_attribute_get_by_name(container
, LTTV_STATE_RESOURCE_CPUS
, &value
);
1692 g_assert(type
== LTTV_POINTER
);
1693 lttv_state_free_cpu_states(*(value
.v_pointer
), nb_cpus
);
1695 /* free irq resource states */
1696 nb_irqs
= self
->name_tables
->nb_irqs
;
1697 type
= lttv_attribute_get_by_name(container
, LTTV_STATE_RESOURCE_IRQS
, &value
);
1698 g_assert(type
== LTTV_POINTER
);
1699 lttv_state_free_irq_states(*(value
.v_pointer
), nb_irqs
);
1701 /* free softirq resource states */
1702 nb_soft_irqs
= self
->name_tables
->nb_soft_irqs
;
1703 type
= lttv_attribute_get_by_name(container
, LTTV_STATE_RESOURCE_SOFT_IRQS
, &value
);
1704 g_assert(type
== LTTV_POINTER
);
1705 lttv_state_free_soft_irq_states(*(value
.v_pointer
), nb_soft_irqs
);
1707 /* free the blkdev states */
1708 type
= lttv_attribute_get_by_name(container
, LTTV_STATE_RESOURCE_BLKDEVS
, &value
);
1709 g_assert(type
== LTTV_POINTER
);
1710 lttv_state_free_blkdev_hashtable(*(value
.v_pointer
));
1712 /* remove the position */
1713 type
= lttv_attribute_get_by_name(container
, LTTV_STATE_POSITION
, &value
);
1714 g_assert(type
== LTTV_POINTER
);
1715 lttv_traceset_destroy_position(*(value
.v_pointer
));
1717 #ifdef BABEL_CLEANUP
1718 nb_tracefile
= self
->parent
.tracefiles
->len
;
1720 for(i
= 0 ; i
< nb_tracefile
; i
++) {
1722 type
= lttv_attribute_get(tracefiles_tree
, i
, &name
, &value
, &is_named
);
1723 g_assert(type
== LTTV_GOBJECT
);
1724 tracefile_tree
= *((LttvAttribute
**)(value
.v_gobject
));
1726 type
= lttv_attribute_get_by_name(tracefile_tree
, LTTV_STATE_EVENT
,
1728 g_assert(type
== LTTV_POINTER
);
1729 if(*(value
.v_pointer
) != NULL
) g_free(*(value
.v_pointer
));
1731 g_object_unref(G_OBJECT(tracefiles_tree
));
1732 #endif /* BABEL_CLEANUP */
1736 static void free_saved_state(LttvTraceState
*self
)
1739 LttvAttributeType type
;
1740 LttvAttributeValue value
;
1741 LttvAttributeName name
;
1743 LttvAttribute
*saved_states
;
1745 saved_states
= lttv_attribute_find_subdir(lttv_trace_attribute(self
->trace
),
1746 LTTV_STATE_SAVED_STATES
);
1748 nb
= lttv_attribute_get_number(saved_states
);
1749 for(i
= 0 ; i
< nb
; i
++) {
1750 type
= lttv_attribute_get(saved_states
, i
, &name
, &value
, &is_named
);
1751 g_assert(type
== LTTV_GOBJECT
);
1752 lttv_state_saved_free(self
, *((LttvAttribute
**)value
.v_gobject
));
1755 lttv_attribute_remove_by_name(lttv_trace_attribute(self
->trace
),
1756 LTTV_STATE_SAVED_STATES
);
1760 static void create_max_time(LttvTraceState
*trace_state
)
1762 LttvAttributeValue v
;
1764 lttv_attribute_find(lttv_trace_attribute(trace_state
->trace
),
1765 LTTV_STATE_SAVED_STATES_TIME
,
1767 g_assert(*(v
.v_pointer
) == NULL
);
1768 *(v
.v_pointer
) = g_new(LttTime
,1);
1769 *((LttTime
*)*(v
.v_pointer
)) = ltt_time_zero
;
1773 static void get_max_time(LttvTraceState
*trace_state
)
1775 LttvAttributeValue v
;
1777 lttv_attribute_find(lttv_trace_attribute(trace_state
->trace
),
1778 LTTV_STATE_SAVED_STATES_TIME
,
1780 g_assert(*(v
.v_pointer
) != NULL
);
1781 trace_state
->max_time_state_recomputed_in_seek
= (LttTime
*)*(v
.v_pointer
);
1785 static void free_max_time(LttvTraceState
*trace_state
)
1787 LttvAttributeValue v
;
1789 lttv_attribute_find(lttv_trace_attribute(trace_state
->trace
),
1790 LTTV_STATE_SAVED_STATES_TIME
,
1792 g_free(*(v
.v_pointer
));
1793 *(v
.v_pointer
) = NULL
;
1796 static void create_name_tables(LttvTraceState
*tcs
)
1800 GString
*fe_name
= g_string_new("");
1802 LttvNameTables
*name_tables
= g_new(LttvNameTables
, 1);
1804 LttvAttributeValue v
;
1808 lttv_attribute_find(lttv_trace_attribute(tcs
->trace
), LTTV_STATE_NAME_TABLES
,
1810 g_assert(*(v
.v_pointer
) == NULL
);
1811 *(v
.v_pointer
) = name_tables
;
1813 #ifdef BABEL_CLEANUP
1814 hooks
= g_array_sized_new(FALSE
, FALSE
, sizeof(LttvTraceHook
), 1);
1816 if(!lttv_trace_find_hook(tcs
->parent
.t
,
1818 LTT_EVENT_SYSCALL_ENTRY
,
1819 FIELD_ARRAY(LTT_FIELD_SYSCALL_ID
),
1820 NULL
, NULL
, &hooks
)) {
1822 // th = lttv_trace_hook_get_first(&th);
1824 // t = ltt_field_type(lttv_trace_get_hook_field(th, 0));
1825 // nb = ltt_type_element_number(t);
1827 // name_tables->syscall_names = g_new(GQuark, nb);
1828 // name_tables->nb_syscalls = nb;
1830 // for(i = 0 ; i < nb ; i++) {
1831 // name_tables->syscall_names[i] = ltt_enum_string_get(t, i);
1832 // if(!name_tables->syscall_names[i]) {
1833 // GString *string = g_string_new("");
1834 // g_string_printf(string, "syscall %u", i);
1835 // name_tables->syscall_names[i] = g_quark_from_string(string->str);
1836 // g_string_free(string, TRUE);
1839 #endif /* BABEL_CLEANUP */
1841 name_tables
->nb_syscalls
= PREALLOC_NB_SYSCALLS
;
1842 name_tables
->syscall_names
= g_new(GQuark
, name_tables
->nb_syscalls
);
1843 for(i
= 0 ; i
< name_tables
->nb_syscalls
; i
++) {
1844 g_string_printf(fe_name
, "syscall %d", i
);
1845 name_tables
->syscall_names
[i
] = g_quark_from_string(fe_name
->str
);
1847 #ifdef BABEL_CLEANUP
1849 name_tables
->syscall_names
= NULL
;
1850 name_tables
->nb_syscalls
= 0;
1852 lttv_trace_hook_remove_all(&hooks
);
1853 #endif /* BABEL_CLEANUP */
1855 #ifdef BABEL_CLEANUP
1856 if(!lttv_trace_find_hook(tcs
->parent
.t
,
1858 LTT_EVENT_TRAP_ENTRY
,
1859 FIELD_ARRAY(LTT_FIELD_TRAP_ID
),
1860 NULL
, NULL
, &hooks
) ||
1861 !lttv_trace_find_hook(tcs
->parent
.t
,
1863 LTT_EVENT_PAGE_FAULT_ENTRY
,
1864 FIELD_ARRAY(LTT_FIELD_TRAP_ID
),
1865 NULL
, NULL
, &hooks
)) {
1867 // th = lttv_trace_hook_get_first(&th);
1869 // t = ltt_field_type(lttv_trace_get_hook_field(th, 0));
1870 // //nb = ltt_type_element_number(t);
1872 // name_tables->trap_names = g_new(GQuark, nb);
1873 // for(i = 0 ; i < nb ; i++) {
1874 // name_tables->trap_names[i] = g_quark_from_string(
1875 // ltt_enum_string_get(t, i));
1878 #endif /* BABEL_CLEANUP */
1879 name_tables
->nb_traps
= PREALLOC_NB_TRAPS
;
1880 name_tables
->trap_names
= g_new(GQuark
, name_tables
->nb_traps
);
1881 for(i
= 0 ; i
< name_tables
->nb_traps
; i
++) {
1882 g_string_printf(fe_name
, "trap %d", i
);
1883 name_tables
->trap_names
[i
] = g_quark_from_string(fe_name
->str
);
1885 #ifdef BABEL_CLEANUP
1887 name_tables
->trap_names
= NULL
;
1888 name_tables
->nb_traps
= 0;
1890 lttv_trace_hook_remove_all(&hooks
);
1891 #endif /* BABEL_CLEANUP */
1893 #ifdef BABEL_CLEANUP
1894 if(!lttv_trace_find_hook(tcs
->parent
.t
,
1896 LTT_EVENT_IRQ_ENTRY
,
1897 FIELD_ARRAY(LTT_FIELD_IRQ_ID
),
1898 NULL
, NULL
, &hooks
)) {
1901 name_tables->irq_names = g_new(GQuark, nb);
1902 for(i = 0 ; i < nb ; i++) {
1903 name_tables->irq_names[i] = g_quark_from_string(ltt_enum_string_get(t, i));
1906 /* FIXME: LttvIRQState *irq_states should become a g_array */
1908 #endif /* BABEL_CLEANUP */
1909 name_tables
->nb_irqs
= PREALLOC_NB_IRQS
;
1910 name_tables
->irq_names
= g_new(GQuark
, name_tables
->nb_irqs
);
1911 for(i
= 0 ; i
< name_tables
->nb_irqs
; i
++) {
1912 g_string_printf(fe_name
, "irq %d", i
);
1913 name_tables
->irq_names
[i
] = g_quark_from_string(fe_name
->str
);
1915 #ifdef BABEL_CLEANUP
1917 name_tables
->nb_irqs
= 0;
1918 name_tables
->irq_names
= NULL
;
1920 lttv_trace_hook_remove_all(&hooks
);
1921 #endif /* BABEL_CLEANUP */
1923 name_tables->soft_irq_names = g_new(GQuark, nb);
1924 for(i = 0 ; i < nb ; i++) {
1925 name_tables->soft_irq_names[i] = g_quark_from_string(ltt_enum_string_get(t, i));
1929 name_tables
->nb_soft_irqs
= PREALLOC_NB_SOFT_IRQS
;
1930 name_tables
->soft_irq_names
= g_new(GQuark
, name_tables
->nb_soft_irqs
);
1931 for(i
= 0 ; i
< name_tables
->nb_soft_irqs
; i
++) {
1932 g_string_printf(fe_name
, "softirq %d", i
);
1933 name_tables
->soft_irq_names
[i
] = g_quark_from_string(fe_name
->str
);
1935 // g_array_free(hooks, TRUE);
1937 g_string_free(fe_name
, TRUE
);
1939 #if (__WORDSIZE == 32)
1940 name_tables
->kprobe_hash
= g_hash_table_new_full(guint64_hash
, guint64_equal
,
1943 name_tables
->kprobe_hash
= g_hash_table_new(g_direct_hash
, g_direct_equal
);
1948 static void get_name_tables(LttvTraceState
*tcs
)
1950 LttvAttributeValue v
;
1952 lttv_attribute_find(lttv_trace_attribute(tcs
->trace
), LTTV_STATE_NAME_TABLES
,
1954 g_assert(*(v
.v_pointer
) != NULL
);
1955 tcs
->name_tables
= (LttvNameTables
*)*(v
.v_pointer
);
1959 static void free_name_tables(LttvTraceState
*tcs
)
1961 LttvNameTables
*name_tables
;
1963 LttvAttributeValue v
;
1965 lttv_attribute_find(lttv_trace_attribute(tcs
->trace
), LTTV_STATE_NAME_TABLES
,
1967 name_tables
= (LttvNameTables
*)*(v
.v_pointer
);
1968 *(v
.v_pointer
) = NULL
;
1970 // g_free(name_tables->eventtype_names);
1971 if(name_tables
->syscall_names
) g_free(name_tables
->syscall_names
);
1972 if(name_tables
->trap_names
) g_free(name_tables
->trap_names
);
1973 if(name_tables
->irq_names
) g_free(name_tables
->irq_names
);
1974 if(name_tables
->soft_irq_names
) g_free(name_tables
->soft_irq_names
);
1975 g_hash_table_destroy(name_tables
->kprobe_hash
);
1976 g_free(name_tables
);
1979 #ifdef HASH_TABLE_DEBUG
1981 static void test_process(gpointer key
, gpointer value
, gpointer user_data
)
1983 LttvProcessState
*process
= (LttvProcessState
*)value
;
1985 /* Test for process corruption */
1986 guint stack_len
= process
->execution_stack
->len
;
1989 static void hash_table_check(GHashTable
*table
)
1991 g_hash_table_foreach(table
, test_process
, NULL
);
1997 /* clears the stack and sets the state passed as argument */
1998 static void cpu_set_base_mode(LttvCPUState
*cpust
, LttvCPUMode state
)
2000 g_array_set_size(cpust
->mode_stack
, 1);
2001 ((GQuark
*)cpust
->mode_stack
->data
)[0] = state
;
2004 static void cpu_push_mode(LttvCPUState
*cpust
, LttvCPUMode state
)
2006 g_array_set_size(cpust
->mode_stack
, cpust
->mode_stack
->len
+ 1);
2007 ((GQuark
*)cpust
->mode_stack
->data
)[cpust
->mode_stack
->len
- 1] = state
;
2010 static void cpu_pop_mode(LttvCPUState
*cpust
)
2012 if(cpust
->mode_stack
->len
<= 1)
2013 cpu_set_base_mode(cpust
, LTTV_CPU_UNKNOWN
);
2015 g_array_set_size(cpust
->mode_stack
, cpust
->mode_stack
->len
- 1);
2018 /* clears the stack and sets the state passed as argument */
2019 static void bdev_set_base_mode(LttvBdevState
*bdevst
, LttvBdevMode state
)
2021 g_array_set_size(bdevst
->mode_stack
, 1);
2022 ((GQuark
*)bdevst
->mode_stack
->data
)[0] = state
;
2025 static void bdev_push_mode(LttvBdevState
*bdevst
, LttvBdevMode state
)
2027 g_array_set_size(bdevst
->mode_stack
, bdevst
->mode_stack
->len
+ 1);
2028 ((GQuark
*)bdevst
->mode_stack
->data
)[bdevst
->mode_stack
->len
- 1] = state
;
2031 static void bdev_pop_mode(LttvBdevState
*bdevst
)
2033 if(bdevst
->mode_stack
->len
<= 1)
2034 bdev_set_base_mode(bdevst
, LTTV_BDEV_UNKNOWN
);
2036 g_array_set_size(bdevst
->mode_stack
, bdevst
->mode_stack
->len
- 1);
2039 static void irq_set_base_mode(LttvIRQState
*irqst
, LttvIRQMode state
)
2041 g_array_set_size(irqst
->mode_stack
, 1);
2042 ((GQuark
*)irqst
->mode_stack
->data
)[0] = state
;
2045 static void irq_push_mode(LttvIRQState
*irqst
, LttvIRQMode state
)
2047 g_array_set_size(irqst
->mode_stack
, irqst
->mode_stack
->len
+ 1);
2048 ((GQuark
*)irqst
->mode_stack
->data
)[irqst
->mode_stack
->len
- 1] = state
;
2051 static void irq_pop_mode(LttvIRQState
*irqst
)
2053 if(irqst
->mode_stack
->len
<= 1)
2054 irq_set_base_mode(irqst
, LTTV_IRQ_UNKNOWN
);
2056 g_array_set_size(irqst
->mode_stack
, irqst
->mode_stack
->len
- 1);
2059 static void push_state(LttvEvent
*event
,
2060 LttvTraceState
*ts
, LttvExecutionMode t
,
2063 LttvExecutionState
*es
;
2066 cpu
= lttv_traceset_get_cpuid_from_event(event
);
2069 #ifdef HASH_TABLE_DEBUG
2070 hash_table_check(ts
->processes
);
2072 LttvProcessState
*process
= ts
->running_process
[cpu
];
2074 guint depth
= process
->execution_stack
->len
;
2076 process
->execution_stack
=
2077 g_array_set_size(process
->execution_stack
, depth
+ 1);
2080 &g_array_index(process
->execution_stack
, LttvExecutionState
, depth
- 1);
2082 es
= &g_array_index(process
->execution_stack
, LttvExecutionState
, depth
);
2085 es
->entry
= es
->change
= lttv_event_get_timestamp(event
);
2086 es
->cum_cpu_time
= ltt_time_zero
;
2087 es
->s
= process
->state
->s
;
2088 process
->state
= es
;
2092 * return 1 when empty, else 0 */
2094 lttv_state_pop_state_cleanup(LttvProcessState
*process
, LttvEvent
*event
)
2096 guint depth
= process
->execution_stack
->len
;
2102 process
->execution_stack
=
2103 g_array_set_size(process
->execution_stack
, depth
- 1);
2104 process
->state
= &g_array_index(process
->execution_stack
, LttvExecutionState
,
2106 process
->state
->change
= lttv_event_get_timestamp(event
);
2111 static void pop_state(LttvEvent
*event
,
2112 LttvTraceState
*ts
, LttvExecutionMode t
)
2114 LttvProcessState
*process
;
2117 cpu
= lttv_traceset_get_cpuid_from_event(event
);
2119 process
= ts
->running_process
[cpu
];
2121 guint depth
= process
->execution_stack
->len
;
2123 if(process
->state
->t
!= t
){
2124 g_info("Different execution mode type: ignore it\n"
2127 g_info("process state has %s when pop_int is %s\n",
2128 g_quark_to_string(process
->state
->t
),
2129 g_quark_to_string(t
));
2130 g_info("{ %u, %u, %s, %s, %s }\n",
2133 g_quark_to_string(process
->name
),
2134 g_quark_to_string(process
->brand
),
2135 g_quark_to_string(process
->state
->s
));
2140 //TODO ybrosseau readd debug
2141 //g_info("Trying to pop last state on stack (%lu.%09lu): ignore it\n",
2142 // tfs->parent.timestamp.tv_sec, tfs->parent.timestamp.tv_nsec);
2143 g_info("Trying to pop last state on stack: ignore it\n");
2147 process
->execution_stack
=
2148 g_array_set_size(process
->execution_stack
, depth
- 1);
2149 process
->state
= &g_array_index(process
->execution_stack
, LttvExecutionState
,
2151 process
->state
->change
= lttv_event_get_timestamp(event
);
2154 struct search_result
{
2155 const LttTime
*time
; /* Requested time */
2156 LttTime
*best
; /* Best result */
2159 /* Return a new and initialized LttvProcessState structure */
2161 LttvProcessState
*lttv_state_create_process(LttvTraceState
*tcs
,
2162 LttvProcessState
*parent
, guint cpu
, guint pid
,
2163 guint tgid
, GQuark name
, const LttTime
*timestamp
)
2165 LttvProcessState
*process
= g_new(LttvProcessState
, 1);
2167 LttvExecutionState
*es
;
2172 process
->tgid
= tgid
;
2174 process
->name
= name
;
2175 process
->brand
= LTTV_STATE_UNBRANDED
;
2176 //process->last_cpu = tfs->cpu_name;
2177 //process->last_cpu_index = ltt_tracefile_num(((LttvTracefileContext*)tfs)->tf);
2178 process
->type
= LTTV_STATE_USER_THREAD
;
2180 g_info("Process %u, core %p", process
->pid
, process
);
2181 g_hash_table_insert(tcs
->processes
, process
, process
);
2184 process
->ppid
= parent
->pid
;
2185 process
->creation_time
= *timestamp
;
2188 /* No parent. This process exists but we are missing all information about
2189 its creation. The birth time is set to zero but we remember the time of
2194 process
->creation_time
= ltt_time_zero
;
2197 process
->insertion_time
= *timestamp
;
2198 sprintf(buffer
,"%d-%lu.%lu",pid
, process
->creation_time
.tv_sec
,
2199 process
->creation_time
.tv_nsec
);
2200 process
->pid_time
= g_quark_from_string(buffer
);
2202 process
->free_events
= 0;
2203 //process->last_cpu = tfs->cpu_name;
2204 //process->last_cpu_index = ltt_tracefile_num(((LttvTracefileContext*)tfs)->tf);
2205 process
->execution_stack
= g_array_sized_new(FALSE
, FALSE
,
2206 sizeof(LttvExecutionState
), PREALLOCATED_EXECUTION_STACK
);
2207 process
->execution_stack
= g_array_set_size(process
->execution_stack
, 2);
2208 es
= process
->state
= &g_array_index(process
->execution_stack
,
2209 LttvExecutionState
, 0);
2210 es
->t
= LTTV_STATE_USER_MODE
;
2211 es
->n
= LTTV_STATE_SUBMODE_NONE
;
2212 es
->entry
= *timestamp
;
2213 //g_assert(timestamp->tv_sec != 0);
2214 es
->change
= *timestamp
;
2215 es
->cum_cpu_time
= ltt_time_zero
;
2216 es
->s
= LTTV_STATE_RUN
;
2218 es
= process
->state
= &g_array_index(process
->execution_stack
,
2219 LttvExecutionState
, 1);
2220 es
->t
= LTTV_STATE_SYSCALL
;
2221 es
->n
= LTTV_STATE_SUBMODE_NONE
;
2222 es
->entry
= *timestamp
;
2223 //g_assert(timestamp->tv_sec != 0);
2224 es
->change
= *timestamp
;
2225 es
->cum_cpu_time
= ltt_time_zero
;
2226 es
->s
= LTTV_STATE_WAIT_FORK
;
2228 /* Allocate an empty function call stack. If it's empty, use 0x0. */
2229 #ifdef BABEL_CLEANUP
2230 //process->user_stack = g_array_sized_new(FALSE, FALSE,
2231 // sizeof(guint64), 0);
2233 process
->fds
= g_hash_table_new(g_direct_hash
, g_direct_equal
);
2239 lttv_state_find_process(LttvTraceState
*ts
, guint cpu
, guint pid
)
2241 LttvProcessState key
;
2242 LttvProcessState
*process
;
2246 process
= g_hash_table_lookup(ts
->processes
, &key
);
2250 LttvProcessState
*lttv_state_find_process_or_create(LttvTraceState
*ts
,
2251 guint cpu
, guint pid
, const LttTime
*timestamp
)
2253 LttvProcessState
*process
= lttv_state_find_process(ts
, cpu
, pid
);
2254 LttvExecutionState
*es
;
2256 /* Put ltt_time_zero creation time for unexisting processes */
2257 if(unlikely(process
== NULL
)) {
2258 process
= lttv_state_create_process(ts
,
2259 NULL
, cpu
, pid
, 0, LTTV_STATE_UNNAMED
, timestamp
);
2260 /* We are not sure is it's a kernel thread or normal thread, put the
2261 * bottom stack state to unknown */
2262 process
->execution_stack
=
2263 g_array_set_size(process
->execution_stack
, 1);
2264 process
->state
= es
=
2265 &g_array_index(process
->execution_stack
, LttvExecutionState
, 0);
2266 es
->t
= LTTV_STATE_MODE_UNKNOWN
;
2267 es
->s
= LTTV_STATE_UNNAMED
;
2272 /* FIXME : this function should be called when we receive an event telling that
2273 * release_task has been called in the kernel. In happens generally when
2274 * the parent waits for its child termination, but may also happens in special
2275 * cases in the child's exit : when the parent ignores its children SIGCCHLD or
2276 * has the flag SA_NOCLDWAIT. It can also happen when the child is part
2277 * of a killed thread group, but isn't the leader.
2279 static int exit_process(LttvEvent
*event
, LttvProcessState
*process
)
2281 LttvTraceState
*ts
= event
->state
;
2282 LttvProcessState key
;
2284 /* Wait for both schedule with exit dead and process free to happen.
2285 * They can happen in any order. */
2286 if (++(process
->free_events
) < 2)
2289 key
.pid
= process
->pid
;
2290 key
.cpu
= process
->cpu
;
2291 g_hash_table_remove(ts
->processes
, &key
);
2292 g_array_free(process
->execution_stack
, TRUE
);
2294 /* the following also clears the content */
2295 g_hash_table_destroy(process
->fds
);
2302 static void free_process_state(gpointer key
, gpointer value
,gpointer user_data
)
2304 g_array_free(((LttvProcessState
*)value
)->execution_stack
, TRUE
);
2306 /* the following also clears the content */
2307 g_hash_table_destroy(((LttvProcessState
*)value
)->fds
);
2313 static void lttv_state_free_process_table(GHashTable
*processes
)
2315 g_hash_table_foreach(processes
, free_process_state
, NULL
);
2316 g_hash_table_destroy(processes
);
2320 static gboolean
syscall_entry(void *hook_data
, void *call_data
)
2325 LttvProcessState
*process
;
2326 LttvExecutionSubmode submode
;
2327 char syscall_name
[200];
2329 event
= (LttvEvent
*) call_data
;
2330 if (strncmp(lttv_traceset_get_name_from_event(event
),
2331 "sys_", sizeof("sys_") - 1) != 0)
2334 strncpy(syscall_name
,lttv_traceset_get_name_from_event(event
)+4,200);
2336 cpu
= lttv_traceset_get_cpuid_from_event(event
);
2338 process
= ts
->running_process
[cpu
];
2340 submode
= g_quark_from_string(syscall_name
);
2341 /* There can be no system call from PID 0 : unknown state */
2342 if(process
->pid
!= 0)
2343 push_state(event
, ts
, LTTV_STATE_SYSCALL
, submode
);
2348 static gboolean
syscall_exit(void *hook_data
, void *call_data
)
2353 LttvProcessState
*process
;
2356 event
= (LttvEvent
*) call_data
;
2357 if (strcmp(lttv_traceset_get_name_from_event(event
),
2358 "exit_syscall") != 0)
2361 cpu
= lttv_traceset_get_cpuid_from_event(event
);
2363 process
= ts
->running_process
[cpu
];
2365 /* There can be no system call from PID 0 : unknown state */
2366 if (process
->pid
!= 0)
2367 pop_state(event
, ts
, LTTV_STATE_SYSCALL
);
2371 #ifdef BABEL_CLEANUP
2372 static gboolean
trap_entry(void *hook_data
, void *call_data
)
2374 LttvTracefileState
*s
= (LttvTracefileState
*)call_data
;
2375 LttvTraceState
*ts
= (LttvTraceState
*)s
->parent
.t_context
;
2376 LttEvent
*e
= ltt_tracefile_get_event(s
->parent
.tf
);
2377 LttvTraceHook
*th
= (LttvTraceHook
*)hook_data
;
2378 struct marker_field
*f
= lttv_trace_get_hook_field(th
, 0);
2379 LttvNameTables
*nt
= ((LttvTraceState
*)(s
->parent
.t_context
))->name_tables
;
2381 LttvExecutionSubmode submode
;
2383 guint64 trap
= ltt_event_get_long_unsigned(e
, f
);
2385 expand_trap_table(ts
, trap
);
2387 submode
= nt
->trap_names
[trap
];
2389 push_state(s
, LTTV_STATE_TRAP
, submode
);
2391 /* update cpu status */
2392 cpu_push_mode(s
->cpu_state
, LTTV_CPU_TRAP
);
2394 /* update trap status */
2395 g_array_append_val(s
->cpu_state
->trap_stack
, trap
);
2396 ts
->trap_states
[trap
].running
++;
2401 static gboolean
trap_exit(void *hook_data
, void *call_data
)
2403 LttvTracefileState
*s
= (LttvTracefileState
*)call_data
;
2404 LttvTraceState
*ts
= (LttvTraceState
*)s
->parent
.t_context
;
2406 pop_state(s
, LTTV_STATE_TRAP
);
2408 /* update cpu status */
2409 cpu_pop_mode(s
->cpu_state
);
2411 /* update trap status */
2412 if (s
->cpu_state
->trap_stack
->len
> 0) {
2413 gint last
= g_array_index(s
->cpu_state
->trap_stack
, gint
,
2414 s
->cpu_state
->trap_stack
->len
-1);
2415 if(ts
->trap_states
[last
].running
)
2416 ts
->trap_states
[last
].running
--;
2417 g_array_remove_index(s
->cpu_state
->trap_stack
,
2418 s
->cpu_state
->trap_stack
->len
-1);
2422 #endif /* BABEL_CLEANUP */
2424 static gboolean
irq_entry(void *hook_data
, void *call_data
)
2430 LttvExecutionSubmode submode
;
2434 event
= (LttvEvent
*) call_data
;
2435 if (strcmp(lttv_traceset_get_name_from_event(event
),
2436 "irq_handler_entry") != 0)
2439 cpu
= lttv_traceset_get_cpuid_from_event(event
);
2442 nt
= ts
->name_tables
;
2443 irq
= lttv_event_get_long(event
, "irq");
2445 expand_irq_table(ts
, irq
);
2447 submode
= nt
->irq_names
[irq
];
2449 /* Do something with the info about being in user or system mode when int? */
2450 push_state(event
, ts
, LTTV_STATE_IRQ
, submode
);
2452 /* update cpu status */
2453 cpu_push_mode(&(ts
->cpu_states
[cpu
]), LTTV_CPU_IRQ
);
2455 /* update irq status */
2456 g_array_append_val(ts
->cpu_states
[cpu
].irq_stack
, irq
);
2457 irq_push_mode(&ts
->irq_states
[irq
], LTTV_IRQ_BUSY
);
2462 static gboolean
soft_irq_exit(void *hook_data
, void *call_data
)
2468 LttvCPUState
*cpu_state
;
2470 event
= (LttvEvent
*) call_data
;
2471 if (strcmp(lttv_traceset_get_name_from_event(event
),
2472 "softirq_exit") != 0)
2475 cpu
= lttv_traceset_get_cpuid_from_event(event
);
2478 cpu_state
= &(ts
->cpu_states
[cpu
]);
2479 pop_state(event
, ts
, LTTV_STATE_SOFT_IRQ
);
2481 /* update cpu status */
2482 cpu_pop_mode(cpu_state
);
2484 /* update softirq status */
2485 if (cpu_state
->softirq_stack
->len
> 0) {
2486 gint last
= g_array_index(cpu_state
->softirq_stack
, gint
, cpu_state
->softirq_stack
->len
-1);
2487 if(ts
->soft_irq_states
[last
].running
)
2488 ts
->soft_irq_states
[last
].running
--;
2489 g_array_remove_index(cpu_state
->softirq_stack
, cpu_state
->softirq_stack
->len
-1);
2494 static gboolean
irq_exit(void *hook_data
, void *call_data
)
2500 LttvCPUState
*cpu_state
;
2502 event
= (LttvEvent
*) call_data
;
2503 if (strcmp(lttv_traceset_get_name_from_event(event
),
2504 "irq_handler_exit") != 0)
2507 cpu
= lttv_traceset_get_cpuid_from_event(event
);
2509 cpu_state
= &(ts
->cpu_states
[cpu
]);
2511 pop_state(event
, ts
, LTTV_STATE_IRQ
);
2513 /* update cpu status */
2514 cpu_pop_mode(cpu_state
);
2516 /* update irq status */
2517 if (cpu_state
->irq_stack
->len
> 0) {
2518 gint last
= g_array_index(cpu_state
->irq_stack
, gint
, cpu_state
->irq_stack
->len
-1);
2519 g_array_remove_index(cpu_state
->irq_stack
, cpu_state
->irq_stack
->len
-1);
2520 irq_pop_mode(&ts
->irq_states
[last
]);
2526 static gboolean
soft_irq_raise(void *hook_data
, void *call_data
)
2534 event
= (LttvEvent
*) call_data
;
2535 if (strcmp(lttv_traceset_get_name_from_event(event
),
2536 "softirq_raise") != 0)
2539 //cpu = lttv_traceset_get_cpuid_from_event(event);
2541 softirq
= lttv_event_get_long_unsigned(event
, "vec");
2543 expand_soft_irq_table(ts
, softirq
);
2545 /* update softirq status */
2546 /* a soft irq raises are not cumulative */
2547 ts
->soft_irq_states
[softirq
].pending
=1;
2552 static gboolean
soft_irq_entry(void *hook_data
, void *call_data
)
2557 LttvExecutionSubmode submode
;
2561 event
= (LttvEvent
*) call_data
;
2562 if (strcmp(lttv_traceset_get_name_from_event(event
),
2563 "softirq_entry") != 0)
2566 cpu
= lttv_traceset_get_cpuid_from_event(event
);
2572 softirq
= lttv_event_get_long_unsigned(event
, "vec");
2573 expand_soft_irq_table(ts
, softirq
);
2574 nt
= ts
->name_tables
;
2575 submode
= nt
->soft_irq_names
[softirq
];
2577 /* Do something with the info about being in user or system mode when int? */
2578 push_state(event
, ts
, LTTV_STATE_SOFT_IRQ
, submode
);
2580 /* update cpu status */
2581 cpu_push_mode(&(ts
->cpu_states
[cpu
]), LTTV_CPU_SOFT_IRQ
);
2583 /* update softirq status */
2584 g_array_append_val(ts
->cpu_states
[cpu
].softirq_stack
, softirq
);
2585 if (ts
->soft_irq_states
[softirq
].pending
)
2586 ts
->soft_irq_states
[softirq
].pending
--;
2587 ts
->soft_irq_states
[softirq
].running
++;
2592 static gboolean
enum_interrupt(void *hook_data
, void *call_data
)
2602 event
= (LttvEvent
*) call_data
;
2603 if (strcmp(lttv_traceset_get_name_from_event(event
),
2604 "lttng_statedump_interrupt") != 0)
2608 nt
= ts
->name_tables
;
2609 irq
= lttv_event_get_long_unsigned(event
, "irq");
2610 action
= g_quark_from_string(lttv_event_get_string(event
,
2612 expand_irq_table(ts
, irq
);
2613 nt
->irq_names
[irq
] = action
;
2618 #ifdef BABEL_CLEANUP
2619 static gboolean
bdev_request_issue(void *hook_data
, void *call_data
)
2630 event
= (LttvEvent
*) call_data
;
2631 if (strcmp(lttv_traceset_get_name_from_event(event
),
2632 "block_rq_issue") != 0)
2636 major
= lttv_event_get_long_unsigned(event
,);
2638 minor
= lttv_event_get_long_unsigned(event
,);
2640 oper
= lttv_event_get_long_unsigned(event
,);
2642 devcode
= MKDEV(major
,minor
);
2644 /* have we seen this block device before? */
2645 bdev
= get_hashed_bdevstate(ts
, devcode
);
2647 bdev_push_mode(bdev
, LTTV_BDEV_BUSY_READING
);
2649 bdev_push_mode(bdev
, LTTV_BDEV_BUSY_WRITING
);
2654 static gboolean
bdev_request_complete(void *hook_data
, void *call_data
)
2656 LttvTracefileState
*s
= (LttvTracefileState
*)call_data
;
2657 LttvTraceState
*ts
= (LttvTraceState
*)s
->parent
.t_context
;
2658 LttEvent
*e
= ltt_tracefile_get_event(s
->parent
.tf
);
2659 LttvTraceHook
*th
= (LttvTraceHook
*)hook_data
;
2661 guint major
= ltt_event_get_long_unsigned(e
,
2662 lttv_trace_get_hook_field(th
, 0));
2663 guint minor
= ltt_event_get_long_unsigned(e
,
2664 lttv_trace_get_hook_field(th
, 1));
2665 //guint oper = ltt_event_get_long_unsigned(e,
2666 // lttv_trace_get_hook_field(th, 2));
2667 guint32 devcode
= MKDEV(major
,minor
);
2669 /* have we seen this block device before? */
2670 gpointer bdev
= get_hashed_bdevstate(ts
, devcode
);
2672 /* update block device */
2673 bdev_pop_mode(bdev
);
2678 #ifdef BABEL_CLEANUP
2679 // We dont have the syscall table in LTTng 2.0
2680 static gboolean
dump_syscall(void *hook_data
, void *call_data
)
2682 LttvTracefileState
*s
= (LttvTracefileState
*)call_data
;
2683 LttvTraceState
*ts
= (LttvTraceState
*)s
->parent
.t_context
;
2684 LttvNameTables
*nt
= ts
->name_tables
;
2685 LttEvent
*e
= ltt_tracefile_get_event(s
->parent
.tf
);
2686 LttvTraceHook
*th
= (LttvTraceHook
*)hook_data
;
2690 id
= ltt_event_get_unsigned(e
, lttv_trace_get_hook_field(th
, 0));
2691 symbol
= ltt_event_get_string(e
, lttv_trace_get_hook_field(th
, 2));
2693 expand_syscall_table(ts
, id
);
2694 nt
->syscall_names
[id
] = g_quark_from_string(symbol
);
2699 static gboolean
dump_kprobe(void *hook_data
, void *call_data
)
2701 LttvTracefileState
*s
= (LttvTracefileState
*)call_data
;
2702 LttvTraceState
*ts
= (LttvTraceState
*)s
->parent
.t_context
;
2703 LttEvent
*e
= ltt_tracefile_get_event(s
->parent
.tf
);
2704 LttvTraceHook
*th
= (LttvTraceHook
*)hook_data
;
2708 ip
= ltt_event_get_long_unsigned(e
, lttv_trace_get_hook_field(th
, 0));
2709 symbol
= ltt_event_get_string(e
, lttv_trace_get_hook_field(th
, 1));
2711 expand_kprobe_table(ts
, ip
, symbol
);
2716 #ifdef BABEL_CLEANUP
2717 static gboolean
dump_softirq(void *hook_data
, void *call_data
)
2720 LttvTracefileState
*s
= (LttvTracefileState
*)call_data
;
2721 LttvTraceState
*ts
= (LttvTraceState
*)s
->parent
.t_context
;
2722 LttvNameTables
*nt
= ts
->name_tables
;
2723 LttEvent
*e
= ltt_tracefile_get_event(s
->parent
.tf
);
2724 LttvTraceHook
*th
= (LttvTraceHook
*)hook_data
;
2728 id
= ltt_event_get_unsigned(e
, lttv_trace_get_hook_field(th
, 0));
2729 symbol
= ltt_event_get_string(e
, lttv_trace_get_hook_field(th
, 2));
2731 expand_soft_irq_table(ts
, id
);
2732 nt
->soft_irq_names
[id
] = g_quark_from_string(symbol
);
2738 static gboolean
sched_try_wakeup(void *hook_data
, void *call_data
)
2742 LttvProcessState
*process
;
2747 event
= (LttvEvent
*) call_data
;
2748 if (strcmp(lttv_traceset_get_name_from_event(event
),
2749 "sched_wakeup") != 0)
2754 woken_pid
= lttv_event_get_long(event
, "tid");
2755 woken_cpu
= lttv_event_get_long(event
, "target_cpu");
2757 timestamp
= lttv_event_get_timestamp(event
);
2758 process
= lttv_state_find_process_or_create(
2760 woken_cpu
, woken_pid
,
2763 if (process
->state
->s
== LTTV_STATE_WAIT
|| process
->state
->s
== LTTV_STATE_WAIT_FORK
)
2765 process
->state
->s
= LTTV_STATE_WAIT_CPU
;
2766 process
->state
->change
= timestamp
;
2769 g_debug("Wakeup: process %d on CPU %u\n", woken_pid
, woken_cpu
);
2774 static gboolean
schedchange(void *hook_data
, void *call_data
)
2779 LttvProcessState
*process
;
2782 //LttvProcessState *old_process = ts->running_process[cpu];
2784 guint pid_in
, pid_out
;
2786 //TODO ybrosseau 2012-07-13: manage this 20 in a constact or dynamically
2789 event
= (LttvEvent
*) call_data
;
2790 if (strcmp(lttv_traceset_get_name_from_event(event
),
2791 "sched_switch") != 0)
2794 cpu
= lttv_traceset_get_cpuid_from_event(event
);
2796 process
= ts
->running_process
[cpu
];
2797 pid_out
= lttv_event_get_long(event
, "prev_tid");
2798 pid_in
= lttv_event_get_long(event
, "next_tid");
2799 state_out
= lttv_event_get_long(event
, "prev_state");
2801 strncpy(next_comm
, lttv_event_get_string(event
, "next_comm"), 20);
2802 next_comm
[20-1] = '\0';
2804 timestamp
= lttv_event_get_timestamp(event
);
2806 if(likely(process
!= NULL
)) {
2808 /* We could not know but it was not the idle process executing.
2809 This should only happen at the beginning, before the first schedule
2810 event, and when the initial information (current process for each CPU)
2811 is missing. It is not obvious how we could, after the fact, compensate
2812 the wrongly attributed statistics. */
2814 //This test only makes sense once the state is known and if there is no
2815 //missing events. We need to silently ignore schedchange coming after a
2816 //process_free, or it causes glitches. (FIXME)
2817 //if(unlikely(process->pid != pid_out)) {
2818 // g_assert(process->pid == 0);
2820 if(process
->pid
== 0
2821 && process
->state
->t
== LTTV_STATE_MODE_UNKNOWN
) {
2824 * Scheduling out of pid 0 at beginning of the trace.
2825 * We are typically in system call mode at this point although
2826 * (FIXME) we might be in a trap handler.
2828 g_assert(process
->execution_stack
->len
== 1);
2829 process
->state
->t
= LTTV_STATE_SYSCALL
;
2830 process
->state
->s
= LTTV_STATE_WAIT
;
2831 process
->state
->change
= timestamp
;
2832 process
->state
->entry
= timestamp
;
2835 if(unlikely(process
->state
->s
== LTTV_STATE_EXIT
)) {
2836 process
->state
->s
= LTTV_STATE_ZOMBIE
;
2837 process
->state
->change
= timestamp
;
2839 if(unlikely(state_out
== 0)) process
->state
->s
= LTTV_STATE_WAIT_CPU
;
2840 else process
->state
->s
= LTTV_STATE_WAIT
;
2841 process
->state
->change
= timestamp
;
2844 if(state_out
== 32 || state_out
== 64) { /* EXIT_DEAD || TASK_DEAD */
2845 /* see sched.h for states */
2846 if (!exit_process(event
, process
)) {
2847 process
->state
->s
= LTTV_STATE_DEAD
;
2848 process
->state
->change
= timestamp
;
2853 process
= ts
->running_process
[cpu
] = lttv_state_find_process_or_create(
2857 process
->state
->s
= LTTV_STATE_RUN
;
2859 // process->last_cpu_index = ltt_tracefile_num(((LttvTracefileContext*)s)->tf);
2860 process
->state
->change
= timestamp
;
2861 process
->name
= g_quark_from_string(next_comm
);
2863 /* update cpu status */
2865 /* going to idle task */
2866 cpu_set_base_mode(&(ts
->cpu_states
[cpu
]), LTTV_CPU_IDLE
);
2868 /* scheduling a real task.
2869 * we must be careful here:
2870 * if we just schedule()'ed to a process that is
2871 * in a trap, we must put the cpu in trap mode
2873 cpu_set_base_mode(&(ts
->cpu_states
[cpu
]), LTTV_CPU_BUSY
);
2874 if(process
->state
->t
== LTTV_STATE_TRAP
)
2875 cpu_push_mode(&(ts
->cpu_states
[cpu
]), LTTV_CPU_TRAP
);
2881 static gboolean
process_fork(void *hook_data
, void *call_data
)
2885 LttvProcessState
*process
;
2886 LttvProcessState
*child_process
;
2887 guint child_pid
; /* In the Linux Kernel, there is one PID per thread. */
2888 guint child_tgid
; /* tgid in the Linux kernel is the "real" POSIX PID. */
2889 //LttvProcessState *zombie_process;
2893 event
= (LttvEvent
*) call_data
;
2894 if (strcmp(lttv_traceset_get_name_from_event(event
),
2895 "sched_process_fork") != 0)
2897 cpu
= lttv_traceset_get_cpuid_from_event(event
);
2899 process
= ts
->running_process
[cpu
];
2900 timestamp
= lttv_event_get_timestamp(event
);
2902 /* Skip Parent PID param */
2905 child_pid
= lttv_event_get_long_unsigned(event
, "child_tid");
2906 //ts->target_pid = child_pid;
2912 /* Mathieu : it seems like the process might have been scheduled in before the
2913 * fork, and, in a rare case, might be the current process. This might happen
2914 * in a SMP case where we don't have enough precision on the clocks.
2916 * Test reenabled after precision fixes on time. (Mathieu) */
2918 zombie_process
= lttv_state_find_process(ts
, ANY_CPU
, child_pid
);
2920 if(unlikely(zombie_process
!= NULL
)) {
2921 /* Reutilisation of PID. Only now we are sure that the old PID
2922 * has been released. FIXME : should know when release_task happens instead.
2924 guint num_cpus
= ltt_trace_get_num_cpu(ts
->parent
.t
);
2926 for(i
=0; i
< num_cpus
; i
++) {
2927 g_assert(zombie_process
!= ts
->running_process
[i
]);
2930 exit_process(s
, zombie_process
);
2933 g_assert(process
->pid
!= child_pid
);
2934 // FIXME : Add this test in the "known state" section
2935 // g_assert(process->pid == parent_pid);
2936 child_process
= lttv_state_find_process(ts
, ANY_CPU
, child_pid
);
2937 if(child_process
== NULL
) {
2938 child_process
= lttv_state_create_process(ts
, process
, cpu
,
2939 child_pid
, child_tgid
,
2940 LTTV_STATE_UNNAMED
, ×tamp
);
2942 /* The process has already been created : due to time imprecision between
2943 * multiple CPUs : it has been scheduled in before creation. Note that we
2944 * shouldn't have this kind of imprecision.
2946 * Simply put a correct parent.
2948 g_error("Process %u has been created at [%lu.%09lu] "
2949 "and inserted at [%lu.%09lu] before \n"
2950 "fork on cpu %u[%lu.%09lu].\n"
2951 "Probably an unsynchronized TSC problem on the traced machine.",
2953 child_process
->creation_time
.tv_sec
,
2954 child_process
->creation_time
.tv_nsec
,
2955 child_process
->insertion_time
.tv_sec
,
2956 child_process
->insertion_time
.tv_nsec
,
2957 cpu
, timestamp
.tv_sec
, timestamp
.tv_nsec
);
2958 //g_assert(0); /* This is a problematic case : the process has been created
2959 // before the fork event */
2960 child_process
->ppid
= process
->pid
;
2961 child_process
->tgid
= child_tgid
;
2963 g_assert(child_process
->name
== LTTV_STATE_UNNAMED
);
2964 child_process
->name
= process
->name
;
2965 child_process
->brand
= process
->brand
;
2970 #ifdef BABEL_CLEANUP
2971 //NO KTHREAD_CREATE in LTTng 2.0
2972 /* We stamp a newly created process as kernel_thread.
2973 * The thread should not be running yet. */
2974 static gboolean
process_kernel_thread(void *hook_data
, void *call_data
)
2976 LttvTracefileState
*s
= (LttvTracefileState
*)call_data
;
2977 LttEvent
*e
= ltt_tracefile_get_event(s
->parent
.tf
);
2978 LttvTraceHook
*th
= (LttvTraceHook
*)hook_data
;
2980 LttvTraceState
*ts
= (LttvTraceState
*)s
->parent
.t_context
;
2981 LttvProcessState
*process
;
2982 LttvExecutionState
*es
;
2985 pid
= (guint
)ltt_event_get_long_unsigned(e
, lttv_trace_get_hook_field(th
, 0));
2986 //s->parent.target_pid = pid;
2988 process
= lttv_state_find_process_or_create(ts
, ANY_CPU
, pid
,
2990 if (process
->state
->s
!= LTTV_STATE_DEAD
) {
2991 process
->execution_stack
=
2992 g_array_set_size(process
->execution_stack
, 1);
2993 es
= process
->state
=
2994 &g_array_index(process
->execution_stack
, LttvExecutionState
, 0);
2995 es
->t
= LTTV_STATE_SYSCALL
;
2997 process
->type
= LTTV_STATE_KERNEL_THREAD
;
3002 static gboolean
process_exit(void *hook_data
, void *call_data
)
3008 LttvProcessState
*process
; // = ts->running_process[cpu];
3010 event
= (LttvEvent
*) call_data
;
3011 if (strcmp(lttv_traceset_get_name_from_event(event
),
3012 "sched_process_exit") != 0)
3014 cpu
= lttv_traceset_get_cpuid_from_event(event
);
3016 process
= ts
->running_process
[cpu
];
3018 pid
= lttv_event_get_long(event
, "tid");
3019 //s->parent.target_pid = pid;
3021 // FIXME : Add this test in the "known state" section
3022 // g_assert(process->pid == pid);
3024 process
= lttv_state_find_process(ts
, ANY_CPU
, pid
);
3025 if(likely(process
!= NULL
)) {
3026 process
->state
->s
= LTTV_STATE_EXIT
;
3031 static gboolean
process_free(void *hook_data
, void *call_data
)
3037 LttvProcessState
*process
;
3039 event
= (LttvEvent
*) call_data
;
3040 if (strcmp(lttv_traceset_get_name_from_event(event
),
3041 "sched_process_free") != 0)
3043 cpu
= lttv_traceset_get_cpuid_from_event(event
);
3045 process
= ts
->running_process
[cpu
];
3047 /* PID of the process to release */
3048 release_pid
= lttv_event_get_long(event
, "_tid");
3049 //s->parent.target_pid = release_pid;
3051 g_assert(release_pid
!= 0);
3053 process
= lttv_state_find_process(ts
, ANY_CPU
, release_pid
);
3054 if(likely(process
!= NULL
))
3055 exit_process(event
, process
);
3059 if(likely(process
!= NULL
)) {
3060 /* release_task is happening at kernel level : we can now safely release
3061 * the data structure of the process */
3062 //This test is fun, though, as it may happen that
3063 //at time t : CPU 0 : process_free
3064 //at time t+150ns : CPU 1 : schedule out
3065 //Clearly due to time imprecision, we disable it. (Mathieu)
3066 //If this weird case happen, we have no choice but to put the
3067 //Currently running process on the cpu to 0.
3068 //I re-enable it following time precision fixes. (Mathieu)
3069 //Well, in the case where an process is freed by a process on another CPU
3070 //and still scheduled, it happens that this is the schedchange that will
3071 //drop the last reference count. Do not free it here!
3072 guint num_cpus
= ltt_trace_get_num_cpu(ts
->parent
.t
);
3074 for(i
=0; i
< num_cpus
; i
++) {
3075 //g_assert(process != ts->running_process[i]);
3076 if(process
== ts
->running_process
[i
]) {
3077 //ts->running_process[i] = lttv_state_find_process(ts, i, 0);
3081 if(i
== num_cpus
) /* process is not scheduled */
3082 exit_process(s
, process
);
3090 static gboolean
process_exec(void *hook_data
, void *call_data
)
3096 LttvProcessState
*process
;
3098 event
= (LttvEvent
*) call_data
;
3099 if (strcmp(lttv_traceset_get_name_from_event(event
),
3102 cpu
= lttv_traceset_get_cpuid_from_event(event
);
3104 process
= ts
->running_process
[cpu
];
3106 #if 0//how to use a sequence that must be transformed in a string
3107 /* PID of the process to release */
3108 guint64 name_len
= ltt_event_field_element_number(e
,
3109 lttv_trace_get_hook_field(th
, 0));
3110 //name = ltt_event_get_string(e, lttv_trace_get_hook_field(th, 0));
3111 LttField
*child
= ltt_event_field_element_select(e
,
3112 lttv_trace_get_hook_field(th
, 0), 0);
3114 (gchar
*)(ltt_event_data(e
)+ltt_event_field_offset(e
, child
));
3115 gchar
*null_term_name
= g_new(gchar
, name_len
+1);
3116 memcpy(null_term_name
, name_begin
, name_len
);
3117 null_term_name
[name_len
] = '\0';
3118 process
->name
= g_quark_from_string(null_term_name
);
3121 process
->name
= g_quark_from_string(lttv_event_get_string(event
,
3123 process
->brand
= LTTV_STATE_UNBRANDED
;
3124 //g_free(null_term_name);
3127 #ifdef BABEL_CLEANUP
3128 static gboolean
thread_brand(void *hook_data
, void *call_data
)
3130 LttvTracefileState
*s
= (LttvTracefileState
*)call_data
;
3131 LttvTraceState
*ts
= (LttvTraceState
*)s
->parent
.t_context
;
3132 LttEvent
*e
= ltt_tracefile_get_event(s
->parent
.tf
);
3133 LttvTraceHook
*th
= (LttvTraceHook
*)hook_data
;
3136 LttvProcessState
*process
= ts
->running_process
[cpu
];
3138 name
= ltt_event_get_string(e
, lttv_trace_get_hook_field(th
, 0));
3139 process
->brand
= g_quark_from_string(name
);
3145 // TODO We only have sys_open, without the FD
3146 // manage to do somehting better
3147 static gboolean
fs_open(void *hook_data
, void *call_data
)
3149 LttvTracefileState
*s
= (LttvTracefileState
*)call_data
;
3150 LttvTraceState
*ts
= (LttvTraceState
*)s
->parent
.t_context
;
3151 LttEvent
*e
= ltt_tracefile_get_event(s
->parent
.tf
);
3152 LttvTraceHook
*th
= (LttvTraceHook
*)hook_data
;
3153 struct marker_field
*f
;
3157 LttvProcessState
*process
= ts
->running_process
[cpu
];
3159 f
= lttv_trace_get_hook_field(th
, 0);
3160 fd
= ltt_event_get_int(e
, f
);
3162 f
= lttv_trace_get_hook_field(th
, 1);
3163 filename
= ltt_event_get_string(e
, f
);
3165 g_hash_table_insert(process
->fds
, (gpointer
)(long)fd
,
3166 (gpointer
)(unsigned long)g_quark_from_string(filename
));
3171 static void print_stack(LttvProcessState
*process
)
3173 LttvExecutionState
*es
;
3176 g_debug("Execution stack for process %u %s:\n",
3177 process
->pid
, g_quark_to_string(process
->name
));
3179 for (i
= 0; i
< process
->execution_stack
->len
; i
++) {
3180 es
= &g_array_index(process
->execution_stack
,
3181 LttvExecutionState
, i
);
3182 g_debug("Depth %d mode %s submode %s status %s\n",
3183 i
, g_quark_to_string(es
->t
),
3184 g_quark_to_string(es
->n
),
3185 g_quark_to_string(es
->s
));
3190 static void fix_process(gpointer key
, gpointer value
, gpointer user_data
)
3192 LttvProcessState
*process
;
3193 LttvExecutionState
*es
;
3194 process
= (LttvProcessState
*)value
;
3195 LttTime
*timestamp
= (LttTime
*)user_data
;
3197 print_stack(process
);
3199 if(process
->type
== LTTV_STATE_KERNEL_THREAD
) {
3200 es
= &g_array_index(process
->execution_stack
, LttvExecutionState
, 0);
3201 if(es
->t
== LTTV_STATE_MAYBE_SYSCALL
) {
3202 es
->t
= LTTV_STATE_SYSCALL
;
3203 es
->n
= LTTV_STATE_SUBMODE_NONE
;
3204 es
->entry
= *timestamp
;
3205 es
->change
= *timestamp
;
3206 es
->cum_cpu_time
= ltt_time_zero
;
3207 if(es
->s
== LTTV_STATE_UNNAMED
)
3208 es
->s
= LTTV_STATE_WAIT
;
3211 es
= &g_array_index(process
->execution_stack
, LttvExecutionState
, 0);
3212 if(es
->t
== LTTV_STATE_MAYBE_USER_MODE
) {
3213 es
->t
= LTTV_STATE_USER_MODE
;
3214 es
->n
= LTTV_STATE_SUBMODE_NONE
;
3215 es
->entry
= *timestamp
;
3216 //g_assert(timestamp->tv_sec != 0);
3217 es
->change
= *timestamp
;
3218 es
->cum_cpu_time
= ltt_time_zero
;
3219 if(es
->s
== LTTV_STATE_UNNAMED
)
3220 es
->s
= LTTV_STATE_RUN
;
3222 if(process
->execution_stack
->len
== 1) {
3223 /* Still in bottom unknown mode, means we either:
3224 * - never did a system call
3225 * - are scheduled out from user mode.
3226 * May be either in user mode, syscall mode, running or waiting.*/
3227 /* CHECK : we may be tagging syscall mode when being user mode
3228 * (should be fixed now) */
3229 if (es
->s
== LTTV_STATE_WAIT_CPU
) {
3230 /* nothing to do: scheduled out from userspace */
3232 process
->execution_stack
=
3233 g_array_set_size(process
->execution_stack
, 2);
3234 es
= process
->state
= &g_array_index(process
->execution_stack
,
3235 LttvExecutionState
, 1);
3236 es
->t
= LTTV_STATE_SYSCALL
;
3237 es
->n
= LTTV_STATE_SUBMODE_NONE
;
3238 es
->entry
= *timestamp
;
3239 //g_assert(timestamp->tv_sec != 0);
3240 es
->change
= *timestamp
;
3241 es
->cum_cpu_time
= ltt_time_zero
;
3242 if(es
->s
== LTTV_STATE_WAIT_FORK
)
3243 es
->s
= LTTV_STATE_WAIT
;
3250 static gboolean
statedump_end(void *hook_data
, void *call_data
)
3255 //LttEvent *e = ltt_tracefile_get_event(s->parent.tf);
3256 //LttvTraceHook *th = (LttvTraceHook *)hook_data;
3257 event
= (LttvEvent
*) call_data
;
3258 if (strcmp(lttv_traceset_get_name_from_event(event
),
3259 "lttng_statedump_end") != 0)
3263 timestamp
= lttv_event_get_timestamp(event
);
3265 /* For all processes */
3266 /* if kernel thread, if stack[0] is unknown, set to syscall mode, wait */
3267 /* else, if stack[0] is unknown, set to user mode, running */
3269 g_hash_table_foreach(ts
->processes
, fix_process
, ×tamp
);
3274 static gboolean
enum_process_state(void *hook_data
, void *call_data
)
3284 LttvProcessState
*parent_process
;
3285 LttvProcessState
*process
;
3288 LttvExecutionState
*es
;
3291 event
= (LttvEvent
*) call_data
;
3292 if (strcmp(lttv_traceset_get_name_from_event(event
),
3293 "lttng_statedump_process_state") != 0)
3295 cpu
= lttv_traceset_get_cpuid_from_event(event
);
3297 process
= ts
->running_process
[cpu
];
3298 timestamp
= lttv_event_get_timestamp(event
);
3301 pid
= lttv_event_get_long(event
, "tid");
3302 //s->parent.target_pid = pid;
3305 parent_pid
= lttv_event_get_long(event
, "ppid");
3308 command
= lttv_event_get_string(event
, "name");
3312 type
= lttv_event_get_long(event
, "type");
3314 //FIXME: type is rarely used, enum must match possible types.
3316 /* Skip mode 4th param */
3318 /* Skip submode 5th param */
3320 /* Skip status 6th param */
3322 tgid
= lttv_event_get_long(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
)