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., 51 Franklin Street, Fifth Floor, 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/traceset-process.h>
31 #include <lttv/trace.h>
35 #include <babeltrace/babeltrace.h>
37 #define PREALLOCATED_EXECUTION_STACK 10
43 LTT_CHANNEL_GLOBAL_STATE
,
44 LTT_CHANNEL_IRQ_STATE
,
45 LTT_CHANNEL_MODULE_STATE
,
46 LTT_CHANNEL_NETIF_STATE
,
47 LTT_CHANNEL_SOFTIRQ_STATE
,
48 LTT_CHANNEL_SWAP_STATE
,
49 LTT_CHANNEL_SYSCALL_STATE
,
50 LTT_CHANNEL_TASK_STATE
,
52 LTT_CHANNEL_KPROBE_STATE
,
56 LTT_CHANNEL_USERSPACE
,
62 LTT_EVENT_SYSCALL_ENTRY
,
63 LTT_EVENT_SYSCALL_EXIT
,
64 LTT_EVENT_PAGE_FAULT_NOSEM_ENTRY
,
65 LTT_EVENT_PAGE_FAULT_NOSEM_EXIT
,
66 LTT_EVENT_PAGE_FAULT_ENTRY
,
67 LTT_EVENT_PAGE_FAULT_EXIT
,
68 //LTT_EVENT_TRAP_ENTRY,
69 //LTT_EVENT_TRAP_EXIT,
72 LTT_EVENT_SOFT_IRQ_RAISE
,
73 LTT_EVENT_SOFT_IRQ_ENTRY
,
74 LTT_EVENT_SOFT_IRQ_EXIT
,
75 LTT_EVENT_SCHED_SCHEDULE
,
76 LTT_EVENT_SCHED_TRY_WAKEUP
,
77 LTT_EVENT_PROCESS_FORK
,
78 LTT_EVENT_KTHREAD_CREATE
,
79 LTT_EVENT_PROCESS_EXIT
,
80 LTT_EVENT_PROCESS_FREE
,
82 LTT_EVENT_PROCESS_STATE
,
83 LTT_EVENT_STATEDUMP_END
,
84 LTT_EVENT_FUNCTION_ENTRY
,
85 LTT_EVENT_FUNCTION_EXIT
,
86 LTT_EVENT_REQUEST_ISSUE
,
87 LTT_EVENT_REQUEST_COMPLETE
,
88 LTT_EVENT_LIST_INTERRUPT
,
89 LTT_EVENT_SYS_CALL_TABLE
,
90 LTT_EVENT_SOFTIRQ_VEC
,
91 LTT_EVENT_KPROBE_TABLE
,
100 LTT_FIELD_SYSCALL_ID
,
103 LTT_FIELD_SOFT_IRQ_ID
,
106 LTT_FIELD_PREV_STATE
,
107 LTT_FIELD_PARENT_PID
,
111 LTT_FIELD_CHILD_TGID
,
133 LTTV_STATE_MODE_UNKNOWN
,
134 LTTV_STATE_USER_MODE
,
135 LTTV_STATE_MAYBE_USER_MODE
,
137 LTTV_STATE_MAYBE_SYSCALL
,
139 LTTV_STATE_MAYBE_TRAP
,
144 LTTV_STATE_SUBMODE_UNKNOWN
,
145 LTTV_STATE_SUBMODE_NONE
;
149 LTTV_STATE_WAIT_FORK
,
158 LTTV_STATE_USER_THREAD
,
159 LTTV_STATE_KERNEL_THREAD
;
177 LTTV_BDEV_BUSY_READING
,
178 LTTV_BDEV_BUSY_WRITING
;
181 LTTV_STATE_TRACEFILES
,
182 LTTV_STATE_PROCESSES
,
184 LTTV_STATE_RUNNING_PROCESS
,
186 LTTV_STATE_SAVED_STATES
,
187 LTTV_STATE_SAVED_STATES_TIME
,
190 LTTV_STATE_NAME_TABLES
,
191 LTTV_STATE_TRACE_STATE_USE_COUNT
,
192 LTTV_STATE_RESOURCE_CPUS
,
193 LTTV_STATE_RESOURCE_CPUS_COUNT
,
194 LTTV_STATE_RESOURCE_IRQS
,
195 LTTV_STATE_RESOURCE_SOFT_IRQS
,
196 LTTV_STATE_RESOURCE_TRAPS
,
197 LTTV_STATE_RESOURCE_BLKDEVS
;
199 static void create_max_time(LttvTraceState
*tcs
);
201 static void get_max_time(LttvTraceState
*tcs
);
203 static void free_max_time(LttvTraceState
*tcs
);
205 static void create_name_tables(LttvTraceState
*tcs
);
207 static void get_name_tables(LttvTraceState
*tcs
);
209 static void free_name_tables(LttvTraceState
*tcs
);
211 static void free_saved_state(LttvTraceState
*tcs
);
213 static void lttv_state_free_process_table(GHashTable
*processes
);
215 static void lttv_trace_states_read_raw(LttvTraceState
*tcs
, FILE *fp
,
216 GPtrArray
*quarktable
);
218 /* Resource function prototypes */
220 static LttvBdevState
*get_hashed_bdevstate(LttvTraceState
*ts
, guint32 devcode
);
221 static LttvBdevState
*bdevstate_new(void);
222 static void bdevstate_free(LttvBdevState
*);
223 static void bdevstate_free_cb(gpointer key
, gpointer value
, gpointer user_data
);
224 static LttvBdevState
*bdevstate_copy(LttvBdevState
*bds
);
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(int nb
, int 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
,
413 self
->trace
->id
,BT_CLOCK_REAL
));
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;
476 /* reset bdev states */
477 g_hash_table_foreach(self
->bdev_states
, bdevstate_free_cb
, NULL
);
478 //g_hash_table_steal_all(self->bdev_states);
479 g_hash_table_foreach_steal(self
->bdev_states
, rettrue
, NULL
);
483 nb_tracefile
= self
->parent
.tracefiles
->len
;
485 for(i
= 0 ; i
< nb_tracefile
; i
++) {
487 LTTV_TRACEFILE_STATE(g_array_index(self
->parent
.tracefiles
,
488 LttvTracefileContext
*, i
));
489 ltt_trace_time_span_get(self
->parent
.t
, &tfcs
->parent
.timestamp
, NULL
);
490 // tfcs->saved_position = 0;
491 tfcs
->process
= lttv_state_create_process(tfcs
, NULL
,0);
492 tfcs
->process
->state
->s
= LTTV_STATE_RUN
;
493 tfcs
->process
->last_cpu
= tfcs
->cpu_name
;
494 tfcs
->process
->last_cpu_index
= ltt_tracefile_num(((LttvTracefileContext
*)tfcs
)->tf
);
499 //static LttTime time_zero = {0,0};
503 #define MAX_STRING_LEN 4096
505 static void state_load_saved_states(LttvTraceState
*tcs
)
508 GPtrArray
*quarktable
;
509 const char *trace_path
;
513 tcs
->has_precomputed_states
= FALSE
;
517 gchar buf
[MAX_STRING_LEN
];
521 trace_path
= g_quark_to_string(ltt_trace_name(tcs
->parent
.t
));
522 strncpy(path
, trace_path
, PATH_MAX
-1);
523 count
= strnlen(trace_path
, PATH_MAX
-1);
524 // quarktable : open, test
525 strncat(path
, "/precomputed/quarktable", PATH_MAX
-count
-1);
526 fp
= fopen(path
, "r");
528 quarktable
= g_ptr_array_sized_new(4096);
530 /* Index 0 is null */
532 if(hdr
== EOF
) return;
533 g_assert(hdr
== HDR_QUARKS
);
537 if(hdr
== EOF
) break;
538 g_assert(hdr
== HDR_QUARK
);
539 g_ptr_array_set_size(quarktable
, q
+1);
542 res
= fread(&buf
[i
], sizeof(gchar
), 1, fp
);
544 if(buf
[i
] == '\0' || feof(fp
)) break;
547 len
= strnlen(buf
, MAX_STRING_LEN
-1);
548 g_ptr_array_index (quarktable
, q
) = g_new(gchar
, len
+1);
549 strncpy(g_ptr_array_index (quarktable
, q
), buf
, len
+1);
555 // saved_states : open, test
556 strncpy(path
, trace_path
, PATH_MAX
-1);
557 count
= strnlen(trace_path
, PATH_MAX
-1);
558 strncat(path
, "/precomputed/states", PATH_MAX
-count
-1);
559 fp
= fopen(path
, "r");
563 if(hdr
!= HDR_TRACE
) goto end
;
565 lttv_trace_states_read_raw(tcs
, fp
, quarktable
);
567 tcs
->has_precomputed_states
= TRUE
;
572 /* Free the quarktable */
573 for(i
=0; i
<quarktable
->len
; i
++) {
574 string
= g_ptr_array_index (quarktable
, i
);
577 g_ptr_array_free(quarktable
, TRUE
);
580 #endif /* BABEL_CLEANUP */
582 void lttv_trace_state_init(LttvTraceState
*trace_state
, LttvTrace
*trace
)
586 LttvAttributeValue v
;
588 trace_state
->trace
= trace
;
590 trace_state
->save_interval
= LTTV_STATE_SAVE_INTERVAL
;
591 lttv_attribute_find(lttv_trace_attribute(trace
), LTTV_STATE_TRACE_STATE_USE_COUNT
,
595 if (*(v
.v_uint
) == 1) {
596 create_name_tables(trace_state
);
597 create_max_time(trace_state
);
599 get_name_tables(trace_state
);
600 get_max_time(trace_state
);
602 nb_cpu
= lttv_trace_get_num_cpu(trace
);
603 nb_irq
= trace_state
->name_tables
->nb_irqs
;
604 trace_state
->processes
= NULL
;
605 trace_state
->running_process
= g_new(LttvProcessState
*, nb_cpu
);
607 /* init cpu resource stuff */
608 trace_state
->cpu_states
= g_new(LttvCPUState
, nb_cpu
);
609 for (j
= 0; j
< nb_cpu
; j
++) {
610 trace_state
->cpu_states
[j
].mode_stack
= g_array_new(FALSE
, FALSE
, sizeof(LttvCPUMode
));
611 trace_state
->cpu_states
[j
].irq_stack
= g_array_new(FALSE
, FALSE
, sizeof(gint
));
612 trace_state
->cpu_states
[j
].softirq_stack
= g_array_new(FALSE
, FALSE
, sizeof(gint
));
613 trace_state
->cpu_states
[j
].trap_stack
= g_array_new(FALSE
, FALSE
, sizeof(gint
));
614 g_assert(trace_state
->cpu_states
[j
].mode_stack
!= NULL
);
617 /* init irq resource stuff */
618 trace_state
->irq_states
= g_new(LttvIRQState
, nb_irq
);
619 for (j
= 0; j
< nb_irq
; j
++) {
620 trace_state
->irq_states
[j
].mode_stack
= g_array_new(FALSE
, FALSE
, sizeof(LttvIRQMode
));
621 g_assert(trace_state
->irq_states
[j
].mode_stack
!= NULL
);
624 /* init soft irq stuff */
625 /* the kernel has a statically fixed max of 32 softirqs */
626 trace_state
->soft_irq_states
= g_new(LttvSoftIRQState
, trace_state
->name_tables
->nb_soft_irqs
);
628 /* init trap stuff */
629 trace_state
->trap_states
= g_new(LttvTrapState
, trace_state
->name_tables
->nb_traps
);
631 /* init bdev resource stuff */
632 trace_state
->bdev_states
= g_hash_table_new(g_int_hash
, g_int_equal
);
634 restore_init_state(trace_state
);
636 /* See if the trace has saved states */
637 //state_load_saved_states(trace_state);
640 void lttv_trace_state_fini(LttvTraceState
*trace_state
)
642 LttvTrace
*trace
= trace_state
->trace
;
643 LttvAttributeValue v
;
645 lttv_attribute_find(lttv_trace_attribute(trace
), LTTV_STATE_TRACE_STATE_USE_COUNT
,
648 g_assert(*(v
.v_uint
) != 0);
651 if (*(v
.v_uint
) == 0) {
652 free_name_tables(trace_state
);
653 free_max_time(trace_state
);
654 free_saved_state(trace_state
);
656 g_free(trace_state
->running_process
);
657 trace_state
->running_process
= NULL
;
658 lttv_state_free_process_table(trace_state
->processes
);
659 trace_state
->processes
= NULL
;
664 /* Write the process state of the trace */
666 static void write_process_state(gpointer key
, gpointer value
,
669 LttvProcessState
*process
;
671 LttvExecutionState
*es
;
673 FILE *fp
= (FILE *)user_data
;
678 process
= (LttvProcessState
*)value
;
679 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\" CPU=\"%u\" FREE_EVENTS=\"%u\">\n",
680 process
, process
->pid
, process
->tgid
, process
->ppid
,
681 g_quark_to_string(process
->type
),
682 process
->creation_time
.tv_sec
,
683 process
->creation_time
.tv_nsec
,
684 process
->insertion_time
.tv_sec
,
685 process
->insertion_time
.tv_nsec
,
686 g_quark_to_string(process
->name
),
687 process
->cpu
, process
->free_events
);
689 for(i
= 0 ; i
< process
->execution_stack
->len
; i
++) {
690 es
= &g_array_index(process
->execution_stack
, LttvExecutionState
, i
);
691 fprintf(fp
, " <ES MODE=\"%s\" SUBMODE=\"%s\" ENTRY_S=%lu ENTRY_NS=%lu",
692 g_quark_to_string(es
->t
), g_quark_to_string(es
->n
),
693 es
->entry
.tv_sec
, es
->entry
.tv_nsec
);
694 fprintf(fp
, " CHANGE_S=%lu CHANGE_NS=%lu STATUS=\"%s\"/>\n",
695 es
->change
.tv_sec
, es
->change
.tv_nsec
, g_quark_to_string(es
->s
));
698 for(i
= 0 ; i
< process
->user_stack
->len
; i
++) {
699 address
= g_array_index(process
->user_stack
, guint64
, i
);
700 fprintf(fp
, " <USER_STACK ADDRESS=\"%" PRIu64
"\"/>\n", address
);
703 fprintf(fp
, " </PROCESS>\n");
707 void lttv_state_write(LttvTraceState
*self
, LttTime t
, FILE *fp
)
709 guint i
, nb_tracefile
, nb_block
, offset
;
712 LttvTracefileState
*tfcs
;
716 LttEventPosition
*ep
;
720 ep
= ltt_event_position_new();
722 fprintf(fp
,"<PROCESS_STATE TIME_S=%lu TIME_NS=%lu>\n", t
.tv_sec
, t
.tv_nsec
);
724 g_hash_table_foreach(self
->processes
, write_process_state
, fp
);
726 nb_cpus
= ltt_trace_get_num_cpu(self
->parent
.t
);
727 for(i
=0;i
<nb_cpus
;i
++) {
728 fprintf(fp
," <CPU NUM=%u RUNNING_PROCESS=%u>\n",
729 i
, self
->running_process
[i
]->pid
);
732 nb_tracefile
= self
->parent
.tracefiles
->len
;
734 for(i
= 0 ; i
< nb_tracefile
; i
++) {
736 LTTV_TRACEFILE_STATE(g_array_index(self
->parent
.tracefiles
,
737 LttvTracefileContext
*, i
));
738 fprintf(fp
, " <TRACEFILE TIMESTAMP_S=%lu TIMESTAMP_NS=%lu",
739 tfcs
->parent
.timestamp
.tv_sec
,
740 tfcs
->parent
.timestamp
.tv_nsec
);
741 LttEvent
*e
= ltt_tracefile_get_event(tfcs
->parent
.tf
);
742 if(e
== NULL
) fprintf(fp
,"/>\n");
744 ltt_event_position(e
, ep
);
745 ltt_event_position_get(ep
, &tf
, &nb_block
, &offset
, &tsc
);
746 fprintf(fp
, " BLOCK=%u OFFSET=%u TSC=%" PRIu64
"/>\n", nb_block
, offset
,
751 fprintf(fp
,"</PROCESS_STATE>\n");
755 static void write_process_state_raw(gpointer key
, gpointer value
,
758 LttvProcessState
*process
;
760 LttvExecutionState
*es
;
762 FILE *fp
= (FILE *)user_data
;
767 process
= (LttvProcessState
*)value
;
768 fputc(HDR_PROCESS
, fp
);
769 //fwrite(&header, sizeof(header), 1, fp);
770 //fprintf(fp, "%s", g_quark_to_string(process->type));
772 fwrite(&process
->type
, sizeof(process
->type
), 1, fp
);
773 //fprintf(fp, "%s", g_quark_to_string(process->name));
775 fwrite(&process
->name
, sizeof(process
->name
), 1, fp
);
777 fwrite(&process
->pid
, sizeof(process
->pid
), 1, fp
);
778 fwrite(&process
->free_events
, sizeof(process
->free_events
), 1, fp
);
779 fwrite(&process
->tgid
, sizeof(process
->tgid
), 1, fp
);
780 fwrite(&process
->ppid
, sizeof(process
->ppid
), 1, fp
);
781 fwrite(&process
->cpu
, sizeof(process
->cpu
), 1, fp
);
782 fwrite(&process
->creation_time
, sizeof(process
->creation_time
), 1, fp
);
783 fwrite(&process
->insertion_time
, sizeof(process
->insertion_time
), 1, fp
);
786 fprintf(fp
," <PROCESS CORE=%p PID=%u TGID=%u PPID=%u TYPE=\"%s\" CTIME_S=%lu CTIME_NS=%lu ITIME_S=%lu ITIME_NS=%lu NAME=\"%s\" CPU=\"%u\" PROCESS_TYPE=%u>\n",
787 process
, process
->pid
, process
->tgid
, process
->ppid
,
788 g_quark_to_string(process
->type
),
789 process
->creation_time
.tv_sec
,
790 process
->creation_time
.tv_nsec
,
791 process
->insertion_time
.tv_sec
,
792 process
->insertion_time
.tv_nsec
,
793 g_quark_to_string(process
->name
),
797 for(i
= 0 ; i
< process
->execution_stack
->len
; i
++) {
798 es
= &g_array_index(process
->execution_stack
, LttvExecutionState
, i
);
801 //fprintf(fp, "%s", g_quark_to_string(es->t));
803 fwrite(&es
->t
, sizeof(es
->t
), 1, fp
);
804 //fprintf(fp, "%s", g_quark_to_string(es->n));
806 fwrite(&es
->n
, sizeof(es
->n
), 1, fp
);
807 //fprintf(fp, "%s", g_quark_to_string(es->s));
809 fwrite(&es
->s
, sizeof(es
->s
), 1, fp
);
810 fwrite(&es
->entry
, sizeof(es
->entry
), 1, fp
);
811 fwrite(&es
->change
, sizeof(es
->change
), 1, fp
);
812 fwrite(&es
->cum_cpu_time
, sizeof(es
->cum_cpu_time
), 1, fp
);
814 fprintf(fp
, " <ES MODE=\"%s\" SUBMODE=\"%s\" ENTRY_S=%lu ENTRY_NS=%lu",
815 g_quark_to_string(es
->t
), g_quark_to_string(es
->n
),
816 es
->entry
.tv_sec
, es
->entry
.tv_nsec
);
817 fprintf(fp
, " CHANGE_S=%lu CHANGE_NS=%lu STATUS=\"%s\"/>\n",
818 es
->change
.tv_sec
, es
->change
.tv_nsec
, g_quark_to_string(es
->s
));
822 for(i
= 0 ; i
< process
->user_stack
->len
; i
++) {
823 address
= g_array_index(process
->user_stack
, guint64
, i
);
824 fputc(HDR_USER_STACK
, fp
);
825 fwrite(&address
, sizeof(address
), 1, fp
);
827 fprintf(fp
, " <USER_STACK ADDRESS=\"%llu\"/>\n", address
);
833 void lttv_state_write_raw(LttvTraceState
*self
, LttTime t
, FILE *fp
)
835 guint i
, nb_tracefile
, nb_block
, offset
;
838 LttvTracefileState
*tfcs
;
842 LttEventPosition
*ep
;
846 ep
= ltt_event_position_new();
848 //fprintf(fp,"<PROCESS_STATE TIME_S=%lu TIME_NS=%lu>\n", t.tv_sec, t.tv_nsec);
849 fputc(HDR_PROCESS_STATE
, fp
);
850 fwrite(&t
, sizeof(t
), 1, fp
);
852 g_hash_table_foreach(self
->processes
, write_process_state_raw
, fp
);
854 nb_cpus
= ltt_trace_get_num_cpu(self
->parent
.t
);
855 for(i
=0;i
<nb_cpus
;i
++) {
857 fwrite(&i
, sizeof(i
), 1, fp
); /* cpu number */
858 fwrite(&self
->running_process
[i
]->pid
,
859 sizeof(self
->running_process
[i
]->pid
), 1, fp
);
860 //fprintf(fp," <CPU NUM=%u RUNNING_PROCESS=%u>\n",
861 // i, self->running_process[i]->pid);
864 nb_tracefile
= self
->parent
.tracefiles
->len
;
866 for(i
= 0 ; i
< nb_tracefile
; i
++) {
868 LTTV_TRACEFILE_STATE(g_array_index(self
->parent
.tracefiles
,
869 LttvTracefileContext
*, i
));
870 // fprintf(fp, " <TRACEFILE TIMESTAMP_S=%lu TIMESTAMP_NS=%lu",
871 // tfcs->parent.timestamp.tv_sec,
872 // tfcs->parent.timestamp.tv_nsec);
873 fputc(HDR_TRACEFILE
, fp
);
874 fwrite(&tfcs
->parent
.timestamp
, sizeof(tfcs
->parent
.timestamp
), 1, fp
);
875 /* Note : if timestamp if LTT_TIME_INFINITE, there will be no
876 * position following : end of trace */
877 LttEvent
*e
= ltt_tracefile_get_event(tfcs
->parent
.tf
);
879 ltt_event_position(e
, ep
);
880 ltt_event_position_get(ep
, &tf
, &nb_block
, &offset
, &tsc
);
881 //fprintf(fp, " BLOCK=%u OFFSET=%u TSC=%llu/>\n", nb_block, offset,
883 fwrite(&nb_block
, sizeof(nb_block
), 1, fp
);
884 fwrite(&offset
, sizeof(offset
), 1, fp
);
885 fwrite(&tsc
, sizeof(tsc
), 1, fp
);
892 /* Read process state from a file */
894 /* Called because a HDR_PROCESS was found */
895 static void read_process_state_raw(LttvTraceState
*self
, FILE *fp
,
896 GPtrArray
*quarktable
)
898 LttvExecutionState
*es
;
899 LttvProcessState
*process
, *parent_process
;
900 LttvProcessState tmp
;
906 res
= fread(&tmp
.type
, sizeof(tmp
.type
), 1, fp
);
907 res
+= fread(&tmp
.name
, sizeof(tmp
.name
), 1, fp
);
908 res
+= fread(&tmp
.pid
, sizeof(tmp
.pid
), 1, fp
);
909 res
+= fread(&tmp
.free_events
, sizeof(tmp
.free_events
), 1, fp
);
910 res
+= fread(&tmp
.tgid
, sizeof(tmp
.tgid
), 1, fp
);
911 res
+= fread(&tmp
.ppid
, sizeof(tmp
.ppid
), 1, fp
);
912 res
+= fread(&tmp
.cpu
, sizeof(tmp
.cpu
), 1, fp
);
913 res
+= fread(&tmp
.creation_time
, sizeof(tmp
.creation_time
), 1, fp
);
914 res
+= fread(&tmp
.insertion_time
, sizeof(tmp
.insertion_time
), 1, fp
);
918 process
= lttv_state_find_process(self
, tmp
.cpu
, tmp
.pid
);
920 /* We must link to the parent */
921 parent_process
= lttv_state_find_process_or_create(self
, ANY_CPU
, tmp
.ppid
,
923 process
= lttv_state_find_process(self
, ANY_CPU
, tmp
.pid
);
924 if(process
== NULL
) {
925 process
= lttv_state_create_process(self
, parent_process
, tmp
.cpu
,
927 g_quark_from_string((gchar
*)g_ptr_array_index(quarktable
, tmp
.name
)),
931 process
->insertion_time
= tmp
.insertion_time
;
932 process
->creation_time
= tmp
.creation_time
;
933 process
->type
= g_quark_from_string(
934 (gchar
*)g_ptr_array_index(quarktable
, tmp
.type
));
935 process
->tgid
= tmp
.tgid
;
936 process
->ppid
= tmp
.ppid
;
938 g_quark_from_string((gchar
*)g_ptr_array_index(quarktable
, tmp
.name
));
939 process
->free_events
= tmp
.free_events
;
942 if(feof(fp
) || ferror(fp
)) goto end_loop
;
944 gint hdr
= fgetc(fp
);
945 if(hdr
== EOF
) goto end_loop
;
949 process
->execution_stack
=
950 g_array_set_size(process
->execution_stack
,
951 process
->execution_stack
->len
+ 1);
952 es
= &g_array_index(process
->execution_stack
, LttvExecutionState
,
953 process
->execution_stack
->len
-1);
956 res
= fread(&es
->t
, sizeof(es
->t
), 1, fp
);
958 es
->t
= g_quark_from_string(
959 (gchar
*)g_ptr_array_index(quarktable
, es
->t
));
960 res
= fread(&es
->n
, sizeof(es
->n
), 1, fp
);
962 es
->n
= g_quark_from_string(
963 (gchar
*)g_ptr_array_index(quarktable
, es
->n
));
964 res
= fread(&es
->s
, sizeof(es
->s
), 1, fp
);
966 es
->s
= g_quark_from_string(
967 (gchar
*)g_ptr_array_index(quarktable
, es
->s
));
968 res
= fread(&es
->entry
, sizeof(es
->entry
), 1, fp
);
969 res
+= fread(&es
->change
, sizeof(es
->change
), 1, fp
);
970 res
+= fread(&es
->cum_cpu_time
, sizeof(es
->cum_cpu_time
), 1, fp
);
975 process
->user_stack
= g_array_set_size(process
->user_stack
,
976 process
->user_stack
->len
+ 1);
977 address
= &g_array_index(process
->user_stack
, guint64
,
978 process
->user_stack
->len
-1);
979 res
= fread(address
, sizeof(address
), 1, fp
);
981 process
->current_function
= *address
;
994 /* Called because a HDR_PROCESS_STATE was found */
995 /* Append a saved state to the trace states */
996 void lttv_state_read_raw(LttvTraceState
*self
, FILE *fp
, GPtrArray
*quarktable
)
998 guint i
, nb_tracefile
, nb_block
, offset
;
1000 LttvTracefileState
*tfcs
;
1002 LttEventPosition
*ep
;
1011 LttvAttribute
*saved_states_tree
, *saved_state_tree
;
1013 LttvAttributeValue value
;
1014 GTree
*pqueue
= self
->parent
.ts_context
->pqueue
;
1015 ep
= ltt_event_position_new();
1017 restore_init_state(self
);
1019 res
= fread(&t
, sizeof(t
), 1, fp
);
1023 if(feof(fp
) || ferror(fp
)) goto end_loop
;
1025 if(hdr
== EOF
) goto end_loop
;
1029 /* Call read_process_state_raw */
1030 read_process_state_raw(self
, fp
, quarktable
);
1038 case HDR_USER_STACK
:
1039 case HDR_PROCESS_STATE
:
1045 g_error("Error while parsing saved state file : unknown data header %d",
1051 nb_cpus
= ltt_trace_get_num_cpu(self
->parent
.t
);
1052 for(i
=0;i
<nb_cpus
;i
++) {
1055 g_assert(hdr
== HDR_CPU
);
1056 res
= fread(&cpu_num
, sizeof(cpu_num
), 1, fp
); /* cpu number */
1058 g_assert(i
== cpu_num
);
1059 res
= fread(&self
->running_process
[i
]->pid
,
1060 sizeof(self
->running_process
[i
]->pid
), 1, fp
);
1064 nb_tracefile
= self
->parent
.tracefiles
->len
;
1066 for(i
= 0 ; i
< nb_tracefile
; i
++) {
1068 LTTV_TRACEFILE_STATE(g_array_index(self
->parent
.tracefiles
,
1069 LttvTracefileContext
*, i
));
1070 // fprintf(fp, " <TRACEFILE TIMESTAMP_S=%lu TIMESTAMP_NS=%lu",
1071 // tfcs->parent.timestamp.tv_sec,
1072 // tfcs->parent.timestamp.tv_nsec);
1073 g_tree_remove(pqueue
, &tfcs
->parent
);
1075 g_assert(hdr
== HDR_TRACEFILE
);
1076 res
= fread(&tfcs
->parent
.timestamp
, sizeof(tfcs
->parent
.timestamp
), 1, fp
);
1078 /* Note : if timestamp if LTT_TIME_INFINITE, there will be no
1079 * position following : end of trace */
1080 if(ltt_time_compare(tfcs
->parent
.timestamp
, ltt_time_infinite
) != 0) {
1081 res
= fread(&nb_block
, sizeof(nb_block
), 1, fp
);
1082 res
+= fread(&offset
, sizeof(offset
), 1, fp
);
1083 res
+= fread(&tsc
, sizeof(tsc
), 1, fp
);
1085 ltt_event_position_set(ep
, tfcs
->parent
.tf
, nb_block
, offset
, tsc
);
1086 gint ret
= ltt_tracefile_seek_position(tfcs
->parent
.tf
, ep
);
1088 g_tree_insert(pqueue
, &tfcs
->parent
, &tfcs
->parent
);
1093 saved_states_tree
= lttv_attribute_find_subdir(self
->parent
.t_a
,
1094 LTTV_STATE_SAVED_STATES
);
1095 saved_state_tree
= g_object_new(LTTV_ATTRIBUTE_TYPE
, NULL
);
1096 value
= lttv_attribute_add(saved_states_tree
,
1097 lttv_attribute_get_number(saved_states_tree
), LTTV_GOBJECT
);
1098 *(value
.v_gobject
) = (GObject
*)saved_state_tree
;
1099 value
= lttv_attribute_add(saved_state_tree
, LTTV_STATE_TIME
, LTTV_TIME
);
1100 *(value
.v_time
) = t
;
1101 lttv_state_save(self
, saved_state_tree
);
1102 g_debug("Saving state at time %lu.%lu", t
.tv_sec
,
1105 *(self
->max_time_state_recomputed_in_seek
) = t
;
1109 /* Called when a HDR_TRACE is found */
1110 void lttv_trace_states_read_raw(LttvTraceState
*tcs
, FILE *fp
,
1111 GPtrArray
*quarktable
)
1116 if(feof(fp
) || ferror(fp
)) goto end_loop
;
1118 if(hdr
== EOF
) goto end_loop
;
1121 case HDR_PROCESS_STATE
:
1122 /* Call read_process_state_raw */
1123 lttv_state_read_raw(tcs
, fp
, quarktable
);
1131 case HDR_USER_STACK
:
1134 g_error("Error while parsing saved state file :"
1135 " unexpected data header %d",
1139 g_error("Error while parsing saved state file : unknown data header %d",
1144 *(tcs
->max_time_state_recomputed_in_seek
) = tcs
->parent
.time_span
.end_time
;
1145 restore_init_state(tcs
);
1146 lttv_process_trace_seek_time(&tcs
->parent
, ltt_time_zero
);
1149 #endif /* BABEL_CLEANUP */
1152 /* Copy each process from an existing hash table to a new one */
1154 static void copy_process_state(gpointer key
, gpointer value
,gpointer user_data
)
1156 LttvProcessState
*process
, *new_process
;
1158 GHashTable
*new_processes
= (GHashTable
*)user_data
;
1162 process
= (LttvProcessState
*)value
;
1163 new_process
= g_new(LttvProcessState
, 1);
1164 *new_process
= *process
;
1165 new_process
->execution_stack
= g_array_sized_new(FALSE
, FALSE
,
1166 sizeof(LttvExecutionState
), PREALLOCATED_EXECUTION_STACK
);
1167 new_process
->execution_stack
=
1168 g_array_set_size(new_process
->execution_stack
,
1169 process
->execution_stack
->len
);
1170 for(i
= 0 ; i
< process
->execution_stack
->len
; i
++) {
1171 g_array_index(new_process
->execution_stack
, LttvExecutionState
, i
) =
1172 g_array_index(process
->execution_stack
, LttvExecutionState
, i
);
1174 new_process
->state
= &g_array_index(new_process
->execution_stack
,
1175 LttvExecutionState
, new_process
->execution_stack
->len
- 1);
1176 #ifdef BABEL_CLEANUP
1177 new_process
->user_stack
= g_array_sized_new(FALSE
, FALSE
,
1178 sizeof(guint64
), 0);
1179 new_process
->user_stack
= g_array_set_size(new_process
->user_stack
,
1180 process
->user_stack
->len
);
1181 for(i
= 0 ; i
< process
->user_stack
->len
; i
++) {
1182 g_array_index(new_process
->user_stack
, guint64
, i
) =
1183 g_array_index(process
->user_stack
, guint64
, i
);
1185 new_process
->current_function
= process
->current_function
;
1186 #endif /* BABEL_CLEANUP */
1188 /* fd hash table stuff */
1194 /* copy every item in the hash table */
1195 new_process
->fds
= g_hash_table_new(g_direct_hash
, g_direct_equal
);
1197 g_hash_table_iter_init(&it
, process
->fds
);
1198 while (g_hash_table_iter_next (&it
, (void *)&key
, (void *)&value
)) {
1199 g_hash_table_insert(new_process
->fds
, key
, value
);
1203 /* When done creating the new process state, insert it in the
1205 g_hash_table_insert(new_processes
, new_process
, new_process
);
1209 static GHashTable
*lttv_state_copy_process_table(GHashTable
*processes
)
1211 GHashTable
*new_processes
= g_hash_table_new(process_hash
, process_equal
);
1213 g_hash_table_foreach(processes
, copy_process_state
, new_processes
);
1214 return new_processes
;
1217 static LttvCPUState
*lttv_state_copy_cpu_states(LttvCPUState
*states
, guint n
)
1220 LttvCPUState
*retval
;
1222 retval
= g_new(LttvCPUState
, n
);
1224 for(i
=0; i
<n
; i
++) {
1225 retval
[i
].irq_stack
= g_array_new(FALSE
, FALSE
, sizeof(gint
));
1226 g_array_set_size(retval
[i
].irq_stack
, states
[i
].irq_stack
->len
);
1227 for(j
=0; j
<states
[i
].irq_stack
->len
; j
++) {
1228 g_array_index(retval
[i
].irq_stack
, gint
, j
) =
1229 g_array_index(states
[i
].irq_stack
, gint
, j
);
1232 retval
[i
].softirq_stack
= g_array_new(FALSE
, FALSE
, sizeof(gint
));
1233 g_array_set_size(retval
[i
].softirq_stack
, states
[i
].softirq_stack
->len
);
1234 for(j
=0; j
<states
[i
].softirq_stack
->len
; j
++) {
1235 g_array_index(retval
[i
].softirq_stack
, gint
, j
) =
1236 g_array_index(states
[i
].softirq_stack
, gint
, j
);
1239 retval
[i
].trap_stack
= g_array_new(FALSE
, FALSE
, sizeof(gint
));
1240 g_array_set_size(retval
[i
].trap_stack
, states
[i
].trap_stack
->len
);
1241 for(j
=0; j
<states
[i
].trap_stack
->len
; j
++) {
1242 g_array_index(retval
[i
].trap_stack
, gint
, j
) =
1243 g_array_index(states
[i
].trap_stack
, gint
, j
);
1246 retval
[i
].mode_stack
= g_array_new(FALSE
, FALSE
, sizeof(LttvCPUMode
));
1247 g_array_set_size(retval
[i
].mode_stack
, states
[i
].mode_stack
->len
);
1248 for(j
=0; j
<states
[i
].mode_stack
->len
; j
++) {
1249 g_array_index(retval
[i
].mode_stack
, GQuark
, j
) =
1250 g_array_index(states
[i
].mode_stack
, GQuark
, j
);
1257 static void lttv_state_free_cpu_states(LttvCPUState
*states
, guint n
)
1261 for(i
=0; i
<n
; i
++) {
1262 g_array_free(states
[i
].mode_stack
, TRUE
);
1263 g_array_free(states
[i
].irq_stack
, TRUE
);
1264 g_array_free(states
[i
].softirq_stack
, TRUE
);
1265 g_array_free(states
[i
].trap_stack
, TRUE
);
1271 static LttvIRQState
*lttv_state_copy_irq_states(LttvIRQState
*states
, guint n
)
1274 LttvIRQState
*retval
;
1276 retval
= g_new(LttvIRQState
, n
);
1278 for(i
=0; i
<n
; i
++) {
1279 retval
[i
].mode_stack
= g_array_new(FALSE
, FALSE
, sizeof(LttvIRQMode
));
1280 g_array_set_size(retval
[i
].mode_stack
, states
[i
].mode_stack
->len
);
1281 for(j
=0; j
<states
[i
].mode_stack
->len
; j
++) {
1282 g_array_index(retval
[i
].mode_stack
, GQuark
, j
) =
1283 g_array_index(states
[i
].mode_stack
, GQuark
, j
);
1290 static void lttv_state_free_irq_states(LttvIRQState
*states
, guint n
)
1294 for(i
=0; i
<n
; i
++) {
1295 g_array_free(states
[i
].mode_stack
, TRUE
);
1301 static LttvSoftIRQState
*
1302 lttv_state_copy_soft_irq_states(LttvSoftIRQState
*states
, guint n
)
1305 LttvSoftIRQState
*retval
;
1307 retval
= g_new(LttvSoftIRQState
, n
);
1309 for(i
=0; i
<n
; i
++) {
1310 retval
[i
].pending
= states
[i
].pending
;
1311 retval
[i
].running
= states
[i
].running
;
1317 static void lttv_state_free_soft_irq_states(LttvSoftIRQState
*states
, guint n
)
1322 static LttvTrapState
*
1323 lttv_state_copy_trap_states(LttvTrapState
*states
, guint n
)
1326 LttvTrapState
*retval
;
1328 retval
= g_new(LttvTrapState
, n
);
1330 for(i
=0; i
<n
; i
++) {
1331 retval
[i
].running
= states
[i
].running
;
1337 static void lttv_state_free_trap_states(LttvTrapState
*states
, guint n
)
1341 #ifdef BABEL_CLEANUP
1342 /* bdevstate stuff */
1344 static LttvBdevState
*get_hashed_bdevstate(LttvTraceState
*ts
, guint32 devcode
)
1346 gint devcode_gint
= devcode
;
1347 gpointer bdev
= g_hash_table_lookup(ts
->bdev_states
, &devcode_gint
);
1349 LttvBdevState
*bdevstate
= g_new(LttvBdevState
, 1);
1350 bdevstate
->mode_stack
= g_array_new(FALSE
, FALSE
, sizeof(GQuark
));
1352 gint
* key
= g_new(gint
, 1);
1354 g_hash_table_insert(ts
->bdev_states
, key
, bdevstate
);
1362 static LttvBdevState
*bdevstate_new(void)
1364 LttvBdevState
*retval
;
1365 retval
= g_new(LttvBdevState
, 1);
1366 retval
->mode_stack
= g_array_new(FALSE
, FALSE
, sizeof(GQuark
));
1371 static void bdevstate_free(LttvBdevState
*bds
)
1373 g_array_free(bds
->mode_stack
, TRUE
);
1377 static void bdevstate_free_cb(gpointer key
, gpointer value
, gpointer user_data
)
1379 LttvBdevState
*bds
= (LttvBdevState
*) value
;
1381 bdevstate_free(bds
);
1384 static LttvBdevState
*bdevstate_copy(LttvBdevState
*bds
)
1386 LttvBdevState
*retval
;
1388 retval
= bdevstate_new();
1389 g_array_insert_vals(retval
->mode_stack
, 0, bds
->mode_stack
->data
,
1390 bds
->mode_stack
->len
);
1395 static void insert_and_copy_bdev_state(gpointer k
, gpointer v
, gpointer u
)
1397 //GHashTable *ht = (GHashTable *)u;
1398 LttvBdevState
*bds
= (LttvBdevState
*)v
;
1399 LttvBdevState
*newbds
;
1401 newbds
= bdevstate_copy(bds
);
1403 g_hash_table_insert(u
, k
, newbds
);
1406 static GHashTable
*lttv_state_copy_blkdev_hashtable(GHashTable
*ht
)
1410 retval
= g_hash_table_new(g_int_hash
, g_int_equal
);
1412 g_hash_table_foreach(ht
, insert_and_copy_bdev_state
, retval
);
1417 /* Free a hashtable and the LttvBdevState structures its values
1420 static void lttv_state_free_blkdev_hashtable(GHashTable
*ht
)
1422 g_hash_table_foreach(ht
, bdevstate_free_cb
, NULL
);
1423 g_hash_table_destroy(ht
);
1426 /* The saved state for each trace contains a member "processes", which
1427 stores a copy of the process table, and a member "tracefiles" with
1428 one entry per tracefile. Each tracefile has a "process" member pointing
1429 to the current process and a "position" member storing the tracefile
1430 position (needed to seek to the current "next" event. */
1432 void lttv_state_save(LttvTraceState
*self
, LttvAttribute
*container
)
1434 guint i
, nb_cpus
, nb_irqs
, nb_soft_irqs
, nb_traps
;
1436 guint
*running_process
;
1438 LttvAttributeValue value
;
1440 value
= lttv_attribute_add(container
, LTTV_STATE_PROCESSES
,
1442 *(value
.v_pointer
) = lttv_state_copy_process_table(self
->processes
);
1444 /* Add the currently running processes array */
1445 nb_cpus
= lttv_trace_get_num_cpu(self
->trace
);
1446 running_process
= g_new(guint
, nb_cpus
);
1447 for(i
=0;i
<nb_cpus
;i
++) {
1448 running_process
[i
] = self
->running_process
[i
]->pid
;
1450 value
= lttv_attribute_add(container
, LTTV_STATE_RUNNING_PROCESS
,
1452 *(value
.v_pointer
) = running_process
;
1454 g_info("State save");
1456 /* Save the current position */
1457 value
= lttv_attribute_add(container
, LTTV_STATE_POSITION
,
1459 *(value
.v_pointer
) = lttv_traceset_create_current_position(lttv_trace_get_traceset(self
->trace
));
1461 #ifdef BABEL_CLEANUP
1462 nb_tracefile
= self
->parent
.tracefiles
->len
;
1463 for(i
= 0 ; i
< nb_tracefile
; i
++) {
1465 LTTV_TRACEFILE_STATE(g_array_index(self
->parent
.tracefiles
,
1466 LttvTracefileContext
*, i
));
1467 tracefile_tree
= g_object_new(LTTV_ATTRIBUTE_TYPE
, NULL
);
1468 value
= lttv_attribute_add(tracefiles_tree
, i
,
1470 *(value
.v_gobject
) = (GObject
*)tracefile_tree
;
1472 value
= lttv_attribute_add(tracefile_tree
, LTTV_STATE_PROCESS
,
1474 *(value
.v_uint
) = tfcs
->process
->pid
;
1476 value
= lttv_attribute_add(tracefile_tree
, LTTV_STATE_EVENT
,
1478 /* Only save the position if the tfs has not infinite time. */
1479 //if(!g_tree_lookup(self->parent.ts_context->pqueue, &tfcs->parent)
1480 // && current_tfcs != tfcs) {
1481 if(ltt_time_compare(tfcs
->parent
.timestamp
, ltt_time_infinite
) == 0) {
1482 *(value
.v_pointer
) = NULL
;
1484 LttEvent
*e
= ltt_tracefile_get_event(tfcs
->parent
.tf
);
1485 ep
= ltt_event_position_new();
1486 ltt_event_position(e
, ep
);
1487 *(value
.v_pointer
) = ep
;
1489 guint nb_block
, offset
;
1492 ltt_event_position_get(ep
, &tf
, &nb_block
, &offset
, &tsc
);
1493 g_info("Block %u offset %u tsc %" PRIu64
" time %lu.%lu", nb_block
,
1494 offset
, tsc
, tfcs
->parent
.timestamp
.tv_sec
,
1495 tfcs
->parent
.timestamp
.tv_nsec
);
1498 #endif /* BABEL_CLEANUP */
1500 /* save the cpu state */
1502 value
= lttv_attribute_add(container
, LTTV_STATE_RESOURCE_CPUS_COUNT
,
1504 *(value
.v_uint
) = nb_cpus
;
1506 value
= lttv_attribute_add(container
, LTTV_STATE_RESOURCE_CPUS
,
1508 *(value
.v_pointer
) = lttv_state_copy_cpu_states(self
->cpu_states
, nb_cpus
);
1511 /* save the irq state */
1512 nb_irqs
= self
->name_tables
->nb_irqs
;
1514 value
= lttv_attribute_add(container
, LTTV_STATE_RESOURCE_IRQS
,
1516 *(value
.v_pointer
) = lttv_state_copy_irq_states(self
->irq_states
, nb_irqs
);
1519 /* save the soft irq state */
1520 nb_soft_irqs
= self
->name_tables
->nb_soft_irqs
;
1522 value
= lttv_attribute_add(container
, LTTV_STATE_RESOURCE_SOFT_IRQS
,
1524 *(value
.v_pointer
) = lttv_state_copy_soft_irq_states(self
->soft_irq_states
, nb_soft_irqs
);
1527 /* save the trap state */
1528 nb_traps
= self
->name_tables
->nb_traps
;
1530 value
= lttv_attribute_add(container
, LTTV_STATE_RESOURCE_TRAPS
,
1532 *(value
.v_pointer
) = lttv_state_copy_trap_states(self
->trap_states
, nb_traps
);
1535 /* save the blkdev states */
1536 value
= lttv_attribute_add(container
, LTTV_STATE_RESOURCE_BLKDEVS
,
1538 *(value
.v_pointer
) = lttv_state_copy_blkdev_hashtable(self
->bdev_states
);
1541 void lttv_state_restore(LttvTraceState
*self
, LttvAttribute
*container
)
1543 guint i
, pid
, nb_cpus
, nb_irqs
, nb_soft_irqs
, nb_traps
;
1544 guint
*running_process
;
1545 LttvAttributeType type
;
1546 LttvAttributeValue value
;
1548 type
= lttv_attribute_get_by_name(container
, LTTV_STATE_PROCESSES
,
1550 g_assert(type
== LTTV_POINTER
);
1551 lttv_state_free_process_table(self
->processes
);
1552 self
->processes
= lttv_state_copy_process_table(*(value
.v_pointer
));
1554 /* Add the currently running processes array */
1555 nb_cpus
= lttv_trace_get_num_cpu(self
->trace
);
1556 type
= lttv_attribute_get_by_name(container
, LTTV_STATE_RUNNING_PROCESS
,
1558 g_assert(type
== LTTV_POINTER
);
1559 running_process
= *(value
.v_pointer
);
1560 for(i
=0;i
<nb_cpus
;i
++) {
1561 pid
= running_process
[i
];
1562 self
->running_process
[i
] = lttv_state_find_process(self
, i
, pid
);
1563 g_assert(self
->running_process
[i
] != NULL
);
1566 //nb_tracefile = self->parent.tracefiles->len;
1568 //g_tree_destroy(tsc->pqueue);
1569 //tsc->pqueue = g_tree_new(compare_tracefile);
1571 /* restore cpu resource states */
1572 type
= lttv_attribute_get_by_name(container
, LTTV_STATE_RESOURCE_CPUS
, &value
);
1573 g_assert(type
== LTTV_POINTER
);
1574 lttv_state_free_cpu_states(self
->cpu_states
, nb_cpus
);
1575 self
->cpu_states
= lttv_state_copy_cpu_states(*(value
.v_pointer
), nb_cpus
);
1577 /* restore irq resource states */
1578 nb_irqs
= self
->name_tables
->nb_irqs
;
1579 type
= lttv_attribute_get_by_name(container
, LTTV_STATE_RESOURCE_IRQS
, &value
);
1580 g_assert(type
== LTTV_POINTER
);
1581 lttv_state_free_irq_states(self
->irq_states
, nb_irqs
);
1582 self
->irq_states
= lttv_state_copy_irq_states(*(value
.v_pointer
), nb_irqs
);
1584 /* restore soft irq resource states */
1585 nb_soft_irqs
= self
->name_tables
->nb_soft_irqs
;
1586 type
= lttv_attribute_get_by_name(container
, LTTV_STATE_RESOURCE_SOFT_IRQS
, &value
);
1587 g_assert(type
== LTTV_POINTER
);
1588 lttv_state_free_soft_irq_states(self
->soft_irq_states
, nb_soft_irqs
);
1589 self
->soft_irq_states
= lttv_state_copy_soft_irq_states(*(value
.v_pointer
), nb_soft_irqs
);
1591 /* restore trap resource states */
1592 nb_traps
= self
->name_tables
->nb_traps
;
1593 type
= lttv_attribute_get_by_name(container
, LTTV_STATE_RESOURCE_TRAPS
, &value
);
1594 g_assert(type
== LTTV_POINTER
);
1595 lttv_state_free_trap_states(self
->trap_states
, nb_traps
);
1596 self
->trap_states
= lttv_state_copy_trap_states(*(value
.v_pointer
), nb_traps
);
1598 /* restore the blkdev states */
1599 type
= lttv_attribute_get_by_name(container
, LTTV_STATE_RESOURCE_BLKDEVS
, &value
);
1600 g_assert(type
== LTTV_POINTER
);
1601 lttv_state_free_blkdev_hashtable(self
->bdev_states
);
1602 self
->bdev_states
= lttv_state_copy_blkdev_hashtable(*(value
.v_pointer
));
1604 #ifdef BABEL_CLEANUP
1605 for(i
= 0 ; i
< nb_tracefile
; i
++) {
1607 LTTV_TRACEFILE_STATE(g_array_index(self
->parent
.tracefiles
,
1608 LttvTracefileContext
*, i
));
1609 type
= lttv_attribute_get(tracefiles_tree
, i
, &name
, &value
, &is_named
);
1610 g_assert(type
== LTTV_GOBJECT
);
1611 tracefile_tree
= *((LttvAttribute
**)(value
.v_gobject
));
1613 type
= lttv_attribute_get_by_name(tracefile_tree
, LTTV_STATE_PROCESS
,
1615 g_assert(type
== LTTV_UINT
);
1616 pid
= *(value
.v_uint
);
1617 tfcs
->process
= lttv_state_find_process_or_create(tfcs
, pid
);
1619 type
= lttv_attribute_get_by_name(tracefile_tree
, LTTV_STATE_EVENT
,
1621 g_assert(type
== LTTV_POINTER
);
1622 //g_assert(*(value.v_pointer) != NULL);
1623 ep
= *(value
.v_pointer
);
1624 g_assert(tfcs
->parent
.t_context
!= NULL
);
1626 tfcs
->cpu_state
= &self
->cpu_states
[tfcs
->cpu
];
1628 LttvTracefileContext
*tfc
= LTTV_TRACEFILE_CONTEXT(tfcs
);
1629 g_tree_remove(tsc
->pqueue
, tfc
);
1632 retval
= ltt_tracefile_seek_position(tfc
->tf
, ep
);
1633 g_assert_cmpint(retval
, ==, 0);
1634 tfc
->timestamp
= ltt_event_time(ltt_tracefile_get_event(tfc
->tf
));
1635 g_assert_cmpint(ltt_time_compare(tfc
->timestamp
, ltt_time_infinite
),
1637 g_tree_insert(tsc
->pqueue
, tfc
, tfc
);
1638 g_info("Restoring state for a tf at time %lu.%lu",
1639 tfc
->timestamp
.tv_sec
, tfc
->timestamp
.tv_nsec
);
1641 tfc
->timestamp
= ltt_time_infinite
;
1644 #endif /* BABEL_CLEANUP */
1648 * Note: the position must be explicitely set on the entire traceset to
1649 * match the trace states.
1651 LttvTracesetPosition
*lttv_trace_state_get_position(LttvAttribute
*container
)
1653 LttvAttributeType type
;
1654 LttvAttributeValue value
;
1656 type
= lttv_attribute_get_by_name(container
, LTTV_STATE_POSITION
, &value
);
1657 g_assert(type
== LTTV_POINTER
);
1658 return *(value
.v_pointer
);
1661 void lttv_state_saved_free(LttvTraceState
*self
, LttvAttribute
*container
)
1663 guint nb_cpus
, nb_irqs
, nb_soft_irqs
;
1664 guint
*running_process
;
1665 LttvAttributeType type
;
1666 LttvAttributeValue value
;
1668 type
= lttv_attribute_get_by_name(container
, LTTV_STATE_PROCESSES
,
1670 g_assert(type
== LTTV_POINTER
);
1671 lttv_state_free_process_table(*(value
.v_pointer
));
1672 *(value
.v_pointer
) = NULL
;
1673 lttv_attribute_remove_by_name(container
, LTTV_STATE_PROCESSES
);
1675 /* Free running processes array */
1676 type
= lttv_attribute_get_by_name(container
, LTTV_STATE_RUNNING_PROCESS
,
1678 g_assert(type
== LTTV_POINTER
);
1679 running_process
= *(value
.v_pointer
);
1680 g_free(running_process
);
1682 /* free cpu resources */
1683 type
= lttv_attribute_get_by_name(container
, LTTV_STATE_RESOURCE_CPUS_COUNT
, &value
);
1684 g_assert(type
== LTTV_UINT
);
1685 nb_cpus
= *value
.v_uint
;
1686 type
= lttv_attribute_get_by_name(container
, LTTV_STATE_RESOURCE_CPUS
, &value
);
1687 g_assert(type
== LTTV_POINTER
);
1688 lttv_state_free_cpu_states(*(value
.v_pointer
), nb_cpus
);
1690 /* free irq resource states */
1691 nb_irqs
= self
->name_tables
->nb_irqs
;
1692 type
= lttv_attribute_get_by_name(container
, LTTV_STATE_RESOURCE_IRQS
, &value
);
1693 g_assert(type
== LTTV_POINTER
);
1694 lttv_state_free_irq_states(*(value
.v_pointer
), nb_irqs
);
1696 /* free softirq resource states */
1697 nb_soft_irqs
= self
->name_tables
->nb_soft_irqs
;
1698 type
= lttv_attribute_get_by_name(container
, LTTV_STATE_RESOURCE_SOFT_IRQS
, &value
);
1699 g_assert(type
== LTTV_POINTER
);
1700 lttv_state_free_soft_irq_states(*(value
.v_pointer
), nb_soft_irqs
);
1702 /* free the blkdev states */
1703 type
= lttv_attribute_get_by_name(container
, LTTV_STATE_RESOURCE_BLKDEVS
, &value
);
1704 g_assert(type
== LTTV_POINTER
);
1705 lttv_state_free_blkdev_hashtable(*(value
.v_pointer
));
1707 /* remove the position */
1708 type
= lttv_attribute_get_by_name(container
, LTTV_STATE_POSITION
, &value
);
1709 g_assert(type
== LTTV_POINTER
);
1710 lttv_traceset_destroy_position(*(value
.v_pointer
));
1712 #ifdef BABEL_CLEANUP
1713 nb_tracefile
= self
->parent
.tracefiles
->len
;
1715 for(i
= 0 ; i
< nb_tracefile
; i
++) {
1717 type
= lttv_attribute_get(tracefiles_tree
, i
, &name
, &value
, &is_named
);
1718 g_assert(type
== LTTV_GOBJECT
);
1719 tracefile_tree
= *((LttvAttribute
**)(value
.v_gobject
));
1721 type
= lttv_attribute_get_by_name(tracefile_tree
, LTTV_STATE_EVENT
,
1723 g_assert(type
== LTTV_POINTER
);
1724 if(*(value
.v_pointer
) != NULL
) g_free(*(value
.v_pointer
));
1726 g_object_unref(G_OBJECT(tracefiles_tree
));
1727 #endif /* BABEL_CLEANUP */
1731 static void free_saved_state(LttvTraceState
*self
)
1734 LttvAttributeType type
;
1735 LttvAttributeValue value
;
1736 LttvAttributeName name
;
1738 LttvAttribute
*saved_states
;
1740 saved_states
= lttv_attribute_find_subdir(lttv_trace_attribute(self
->trace
),
1741 LTTV_STATE_SAVED_STATES
);
1743 nb
= lttv_attribute_get_number(saved_states
);
1744 for(i
= 0 ; i
< nb
; i
++) {
1745 type
= lttv_attribute_get(saved_states
, i
, &name
, &value
, &is_named
);
1746 g_assert(type
== LTTV_GOBJECT
);
1747 lttv_state_saved_free(self
, *((LttvAttribute
**)value
.v_gobject
));
1750 lttv_attribute_remove_by_name(lttv_trace_attribute(self
->trace
),
1751 LTTV_STATE_SAVED_STATES
);
1755 static void create_max_time(LttvTraceState
*trace_state
)
1757 LttvAttributeValue v
;
1759 lttv_attribute_find(lttv_trace_attribute(trace_state
->trace
),
1760 LTTV_STATE_SAVED_STATES_TIME
,
1762 g_assert(*(v
.v_pointer
) == NULL
);
1763 *(v
.v_pointer
) = g_new(LttTime
,1);
1764 *((LttTime
*)*(v
.v_pointer
)) = ltt_time_zero
;
1768 static void get_max_time(LttvTraceState
*trace_state
)
1770 LttvAttributeValue v
;
1772 lttv_attribute_find(lttv_trace_attribute(trace_state
->trace
),
1773 LTTV_STATE_SAVED_STATES_TIME
,
1775 g_assert(*(v
.v_pointer
) != NULL
);
1776 trace_state
->max_time_state_recomputed_in_seek
= (LttTime
*)*(v
.v_pointer
);
1780 static void free_max_time(LttvTraceState
*trace_state
)
1782 LttvAttributeValue v
;
1784 lttv_attribute_find(lttv_trace_attribute(trace_state
->trace
),
1785 LTTV_STATE_SAVED_STATES_TIME
,
1787 g_free(*(v
.v_pointer
));
1788 *(v
.v_pointer
) = NULL
;
1791 static void create_name_tables(LttvTraceState
*tcs
)
1795 GString
*fe_name
= g_string_new("");
1797 LttvNameTables
*name_tables
= g_new(LttvNameTables
, 1);
1799 LttvAttributeValue v
;
1803 lttv_attribute_find(lttv_trace_attribute(tcs
->trace
), LTTV_STATE_NAME_TABLES
,
1805 g_assert(*(v
.v_pointer
) == NULL
);
1806 *(v
.v_pointer
) = name_tables
;
1808 #ifdef BABEL_CLEANUP
1809 hooks
= g_array_sized_new(FALSE
, FALSE
, sizeof(LttvTraceHook
), 1);
1811 if(!lttv_trace_find_hook(tcs
->parent
.t
,
1813 LTT_EVENT_SYSCALL_ENTRY
,
1814 FIELD_ARRAY(LTT_FIELD_SYSCALL_ID
),
1815 NULL
, NULL
, &hooks
)) {
1817 // th = lttv_trace_hook_get_first(&th);
1819 // t = ltt_field_type(lttv_trace_get_hook_field(th, 0));
1820 // nb = ltt_type_element_number(t);
1822 // name_tables->syscall_names = g_new(GQuark, nb);
1823 // name_tables->nb_syscalls = nb;
1825 // for(i = 0 ; i < nb ; i++) {
1826 // name_tables->syscall_names[i] = ltt_enum_string_get(t, i);
1827 // if(!name_tables->syscall_names[i]) {
1828 // GString *string = g_string_new("");
1829 // g_string_printf(string, "syscall %u", i);
1830 // name_tables->syscall_names[i] = g_quark_from_string(string->str);
1831 // g_string_free(string, TRUE);
1834 #endif /* BABEL_CLEANUP */
1836 name_tables
->nb_syscalls
= PREALLOC_NB_SYSCALLS
;
1837 name_tables
->syscall_names
= g_new(GQuark
, name_tables
->nb_syscalls
);
1838 for(i
= 0 ; i
< name_tables
->nb_syscalls
; i
++) {
1839 g_string_printf(fe_name
, "syscall %d", i
);
1840 name_tables
->syscall_names
[i
] = g_quark_from_string(fe_name
->str
);
1842 #ifdef BABEL_CLEANUP
1844 name_tables
->syscall_names
= NULL
;
1845 name_tables
->nb_syscalls
= 0;
1847 lttv_trace_hook_remove_all(&hooks
);
1848 #endif /* BABEL_CLEANUP */
1850 #ifdef BABEL_CLEANUP
1851 if(!lttv_trace_find_hook(tcs
->parent
.t
,
1853 LTT_EVENT_TRAP_ENTRY
,
1854 FIELD_ARRAY(LTT_FIELD_TRAP_ID
),
1855 NULL
, NULL
, &hooks
) ||
1856 !lttv_trace_find_hook(tcs
->parent
.t
,
1858 LTT_EVENT_PAGE_FAULT_ENTRY
,
1859 FIELD_ARRAY(LTT_FIELD_TRAP_ID
),
1860 NULL
, NULL
, &hooks
)) {
1862 // th = lttv_trace_hook_get_first(&th);
1864 // t = ltt_field_type(lttv_trace_get_hook_field(th, 0));
1865 // //nb = ltt_type_element_number(t);
1867 // name_tables->trap_names = g_new(GQuark, nb);
1868 // for(i = 0 ; i < nb ; i++) {
1869 // name_tables->trap_names[i] = g_quark_from_string(
1870 // ltt_enum_string_get(t, i));
1873 #endif /* BABEL_CLEANUP */
1874 name_tables
->nb_traps
= PREALLOC_NB_TRAPS
;
1875 name_tables
->trap_names
= g_new(GQuark
, name_tables
->nb_traps
);
1876 for(i
= 0 ; i
< name_tables
->nb_traps
; i
++) {
1877 g_string_printf(fe_name
, "trap %d", i
);
1878 name_tables
->trap_names
[i
] = g_quark_from_string(fe_name
->str
);
1880 #ifdef BABEL_CLEANUP
1882 name_tables
->trap_names
= NULL
;
1883 name_tables
->nb_traps
= 0;
1885 lttv_trace_hook_remove_all(&hooks
);
1886 #endif /* BABEL_CLEANUP */
1888 #ifdef BABEL_CLEANUP
1889 if(!lttv_trace_find_hook(tcs
->parent
.t
,
1891 LTT_EVENT_IRQ_ENTRY
,
1892 FIELD_ARRAY(LTT_FIELD_IRQ_ID
),
1893 NULL
, NULL
, &hooks
)) {
1896 name_tables->irq_names = g_new(GQuark, nb);
1897 for(i = 0 ; i < nb ; i++) {
1898 name_tables->irq_names[i] = g_quark_from_string(ltt_enum_string_get(t, i));
1901 /* FIXME: LttvIRQState *irq_states should become a g_array */
1903 #endif /* BABEL_CLEANUP */
1904 name_tables
->nb_irqs
= PREALLOC_NB_IRQS
;
1905 name_tables
->irq_names
= g_new(GQuark
, name_tables
->nb_irqs
);
1906 for(i
= 0 ; i
< name_tables
->nb_irqs
; i
++) {
1907 g_string_printf(fe_name
, "irq %d", i
);
1908 name_tables
->irq_names
[i
] = g_quark_from_string(fe_name
->str
);
1910 #ifdef BABEL_CLEANUP
1912 name_tables
->nb_irqs
= 0;
1913 name_tables
->irq_names
= NULL
;
1915 lttv_trace_hook_remove_all(&hooks
);
1916 #endif /* BABEL_CLEANUP */
1918 name_tables->soft_irq_names = g_new(GQuark, nb);
1919 for(i = 0 ; i < nb ; i++) {
1920 name_tables->soft_irq_names[i] = g_quark_from_string(ltt_enum_string_get(t, i));
1924 name_tables
->nb_soft_irqs
= PREALLOC_NB_SOFT_IRQS
;
1925 name_tables
->soft_irq_names
= g_new(GQuark
, name_tables
->nb_soft_irqs
);
1926 for(i
= 0 ; i
< name_tables
->nb_soft_irqs
; i
++) {
1927 g_string_printf(fe_name
, "softirq %d", i
);
1928 name_tables
->soft_irq_names
[i
] = g_quark_from_string(fe_name
->str
);
1930 // g_array_free(hooks, TRUE);
1932 g_string_free(fe_name
, TRUE
);
1934 #if (__WORDSIZE == 32)
1935 name_tables
->kprobe_hash
= g_hash_table_new_full(guint64_hash
, guint64_equal
,
1938 name_tables
->kprobe_hash
= g_hash_table_new(g_direct_hash
, g_direct_equal
);
1943 static void get_name_tables(LttvTraceState
*tcs
)
1945 LttvAttributeValue v
;
1947 lttv_attribute_find(lttv_trace_attribute(tcs
->trace
), LTTV_STATE_NAME_TABLES
,
1949 g_assert(*(v
.v_pointer
) != NULL
);
1950 tcs
->name_tables
= (LttvNameTables
*)*(v
.v_pointer
);
1954 static void free_name_tables(LttvTraceState
*tcs
)
1956 LttvNameTables
*name_tables
;
1958 LttvAttributeValue v
;
1960 lttv_attribute_find(lttv_trace_attribute(tcs
->trace
), LTTV_STATE_NAME_TABLES
,
1962 name_tables
= (LttvNameTables
*)*(v
.v_pointer
);
1963 *(v
.v_pointer
) = NULL
;
1965 // g_free(name_tables->eventtype_names);
1966 if(name_tables
->syscall_names
) g_free(name_tables
->syscall_names
);
1967 if(name_tables
->trap_names
) g_free(name_tables
->trap_names
);
1968 if(name_tables
->irq_names
) g_free(name_tables
->irq_names
);
1969 if(name_tables
->soft_irq_names
) g_free(name_tables
->soft_irq_names
);
1970 g_hash_table_destroy(name_tables
->kprobe_hash
);
1971 g_free(name_tables
);
1974 #ifdef HASH_TABLE_DEBUG
1976 static void test_process(gpointer key
, gpointer value
, gpointer user_data
)
1978 LttvProcessState
*process
= (LttvProcessState
*)value
;
1980 /* Test for process corruption */
1981 guint stack_len
= process
->execution_stack
->len
;
1984 static void hash_table_check(GHashTable
*table
)
1986 g_hash_table_foreach(table
, test_process
, NULL
);
1992 /* clears the stack and sets the state passed as argument */
1993 static void cpu_set_base_mode(LttvCPUState
*cpust
, LttvCPUMode state
)
1995 g_array_set_size(cpust
->mode_stack
, 1);
1996 ((GQuark
*)cpust
->mode_stack
->data
)[0] = state
;
1999 static void cpu_push_mode(LttvCPUState
*cpust
, LttvCPUMode state
)
2001 g_array_set_size(cpust
->mode_stack
, cpust
->mode_stack
->len
+ 1);
2002 ((GQuark
*)cpust
->mode_stack
->data
)[cpust
->mode_stack
->len
- 1] = state
;
2005 static void cpu_pop_mode(LttvCPUState
*cpust
)
2007 if(cpust
->mode_stack
->len
<= 1)
2008 cpu_set_base_mode(cpust
, LTTV_CPU_UNKNOWN
);
2010 g_array_set_size(cpust
->mode_stack
, cpust
->mode_stack
->len
- 1);
2012 #ifdef BABEL_CLEANUP
2013 /* clears the stack and sets the state passed as argument */
2014 static void bdev_set_base_mode(LttvBdevState
*bdevst
, LttvBdevMode state
)
2016 g_array_set_size(bdevst
->mode_stack
, 1);
2017 ((GQuark
*)bdevst
->mode_stack
->data
)[0] = state
;
2020 static void bdev_push_mode(LttvBdevState
*bdevst
, LttvBdevMode state
)
2022 g_array_set_size(bdevst
->mode_stack
, bdevst
->mode_stack
->len
+ 1);
2023 ((GQuark
*)bdevst
->mode_stack
->data
)[bdevst
->mode_stack
->len
- 1] = state
;
2026 static void bdev_pop_mode(LttvBdevState
*bdevst
)
2028 if(bdevst
->mode_stack
->len
<= 1)
2029 bdev_set_base_mode(bdevst
, LTTV_BDEV_UNKNOWN
);
2031 g_array_set_size(bdevst
->mode_stack
, bdevst
->mode_stack
->len
- 1);
2034 static void irq_set_base_mode(LttvIRQState
*irqst
, LttvIRQMode state
)
2036 g_array_set_size(irqst
->mode_stack
, 1);
2037 ((GQuark
*)irqst
->mode_stack
->data
)[0] = state
;
2040 static void irq_push_mode(LttvIRQState
*irqst
, LttvIRQMode state
)
2042 g_array_set_size(irqst
->mode_stack
, irqst
->mode_stack
->len
+ 1);
2043 ((GQuark
*)irqst
->mode_stack
->data
)[irqst
->mode_stack
->len
- 1] = state
;
2046 static void irq_pop_mode(LttvIRQState
*irqst
)
2048 if(irqst
->mode_stack
->len
<= 1)
2049 irq_set_base_mode(irqst
, LTTV_IRQ_UNKNOWN
);
2051 g_array_set_size(irqst
->mode_stack
, irqst
->mode_stack
->len
- 1);
2054 static void push_state(LttvEvent
*event
,
2055 LttvTraceState
*ts
, LttvExecutionMode t
,
2058 LttvExecutionState
*es
;
2061 cpu
= lttv_traceset_get_cpuid_from_event(event
);
2064 #ifdef HASH_TABLE_DEBUG
2065 hash_table_check(ts
->processes
);
2067 LttvProcessState
*process
= ts
->running_process
[cpu
];
2069 guint depth
= process
->execution_stack
->len
;
2071 process
->execution_stack
=
2072 g_array_set_size(process
->execution_stack
, depth
+ 1);
2075 &g_array_index(process
->execution_stack
, LttvExecutionState
, depth
- 1);
2077 es
= &g_array_index(process
->execution_stack
, LttvExecutionState
, depth
);
2080 es
->entry
= es
->change
= lttv_event_get_timestamp(event
);
2081 es
->cum_cpu_time
= ltt_time_zero
;
2082 es
->s
= process
->state
->s
;
2083 process
->state
= es
;
2087 * return 1 when empty, else 0 */
2089 lttv_state_pop_state_cleanup(LttvProcessState
*process
, LttvEvent
*event
)
2091 guint depth
= process
->execution_stack
->len
;
2097 process
->execution_stack
=
2098 g_array_set_size(process
->execution_stack
, depth
- 1);
2099 process
->state
= &g_array_index(process
->execution_stack
, LttvExecutionState
,
2101 process
->state
->change
= lttv_event_get_timestamp(event
);
2106 static void pop_state(LttvEvent
*event
,
2107 LttvTraceState
*ts
, LttvExecutionMode t
)
2109 LttvProcessState
*process
;
2112 cpu
= lttv_traceset_get_cpuid_from_event(event
);
2114 process
= ts
->running_process
[cpu
];
2116 guint depth
= process
->execution_stack
->len
;
2118 if(process
->state
->t
!= t
){
2119 g_info("Different execution mode type: ignore it\n"
2122 g_info("process state has %s when pop_int is %s\n",
2123 g_quark_to_string(process
->state
->t
),
2124 g_quark_to_string(t
));
2125 g_info("{ %u, %u, %s, %s }\n",
2128 g_quark_to_string(process
->name
),
2129 g_quark_to_string(process
->state
->s
));
2134 //TODO ybrosseau readd debug
2135 //g_info("Trying to pop last state on stack (%lu.%09lu): ignore it\n",
2136 // tfs->parent.timestamp.tv_sec, tfs->parent.timestamp.tv_nsec);
2137 g_info("Trying to pop last state on stack: ignore it\n");
2141 process
->execution_stack
=
2142 g_array_set_size(process
->execution_stack
, depth
- 1);
2144 process
->state
= &g_array_index(process
->execution_stack
, LttvExecutionState
,
2146 process
->state
->change
= lttv_event_get_timestamp(event
);
2148 if((process
->state
->t
== LTTV_STATE_MODE_UNKNOWN
) && (t
== LTTV_STATE_SYSCALL
)) {
2149 //Force state at running
2150 process
->state
->t
= LTTV_STATE_USER_MODE
;
2151 process
->state
->s
= LTTV_STATE_RUN
;
2155 struct search_result
{
2156 const LttTime
*time
; /* Requested time */
2157 LttTime
*best
; /* Best result */
2160 /* Return a new and initialized LttvProcessState structure */
2162 LttvProcessState
*lttv_state_create_process(LttvTraceState
*tcs
,
2163 LttvProcessState
*parent
, guint cpu
, guint pid
,
2164 guint tgid
, GQuark name
, const LttTime
*timestamp
)
2166 LttvProcessState
*process
= g_new(LttvProcessState
, 1);
2168 LttvExecutionState
*es
;
2173 process
->tgid
= tgid
;
2175 process
->name
= name
;
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(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
;
2969 #ifdef BABEL_CLEANUP
2970 //NO KTHREAD_CREATE in LTTng 2.0
2971 /* We stamp a newly created process as kernel_thread.
2972 * The thread should not be running yet. */
2973 static gboolean
process_kernel_thread(void *hook_data
, void *call_data
)
2975 LttvTracefileState
*s
= (LttvTracefileState
*)call_data
;
2976 LttEvent
*e
= ltt_tracefile_get_event(s
->parent
.tf
);
2977 LttvTraceHook
*th
= (LttvTraceHook
*)hook_data
;
2979 LttvTraceState
*ts
= (LttvTraceState
*)s
->parent
.t_context
;
2980 LttvProcessState
*process
;
2981 LttvExecutionState
*es
;
2984 pid
= (guint
)ltt_event_get_long_unsigned(e
, lttv_trace_get_hook_field(th
, 0));
2985 //s->parent.target_pid = pid;
2987 process
= lttv_state_find_process_or_create(ts
, ANY_CPU
, pid
,
2989 if (process
->state
->s
!= LTTV_STATE_DEAD
) {
2990 process
->execution_stack
=
2991 g_array_set_size(process
->execution_stack
, 1);
2992 es
= process
->state
=
2993 &g_array_index(process
->execution_stack
, LttvExecutionState
, 0);
2994 es
->t
= LTTV_STATE_SYSCALL
;
2996 process
->type
= LTTV_STATE_KERNEL_THREAD
;
3001 static gboolean
process_exit(void *hook_data
, void *call_data
)
3007 LttvProcessState
*process
; // = ts->running_process[cpu];
3009 event
= (LttvEvent
*) call_data
;
3010 if (strcmp(lttv_traceset_get_name_from_event(event
),
3011 "sched_process_exit") != 0)
3013 cpu
= lttv_traceset_get_cpuid_from_event(event
);
3015 process
= ts
->running_process
[cpu
];
3017 pid
= lttv_event_get_long(event
, "tid");
3018 //s->parent.target_pid = pid;
3020 // FIXME : Add this test in the "known state" section
3021 // g_assert(process->pid == pid);
3023 process
= lttv_state_find_process(ts
, ANY_CPU
, pid
);
3024 if(likely(process
!= NULL
)) {
3025 process
->state
->s
= LTTV_STATE_EXIT
;
3030 static gboolean
process_free(void *hook_data
, void *call_data
)
3036 LttvProcessState
*process
;
3038 event
= (LttvEvent
*) call_data
;
3039 if (strcmp(lttv_traceset_get_name_from_event(event
),
3040 "sched_process_free") != 0)
3042 cpu
= lttv_traceset_get_cpuid_from_event(event
);
3044 process
= ts
->running_process
[cpu
];
3046 /* PID of the process to release */
3047 release_pid
= lttv_event_get_long(event
, "_tid");
3048 //s->parent.target_pid = release_pid;
3050 g_assert(release_pid
!= 0);
3052 process
= lttv_state_find_process(ts
, ANY_CPU
, release_pid
);
3053 if(likely(process
!= NULL
))
3054 exit_process(event
, process
);
3058 if(likely(process
!= NULL
)) {
3059 /* release_task is happening at kernel level : we can now safely release
3060 * the data structure of the process */
3061 //This test is fun, though, as it may happen that
3062 //at time t : CPU 0 : process_free
3063 //at time t+150ns : CPU 1 : schedule out
3064 //Clearly due to time imprecision, we disable it. (Mathieu)
3065 //If this weird case happen, we have no choice but to put the
3066 //Currently running process on the cpu to 0.
3067 //I re-enable it following time precision fixes. (Mathieu)
3068 //Well, in the case where an process is freed by a process on another CPU
3069 //and still scheduled, it happens that this is the schedchange that will
3070 //drop the last reference count. Do not free it here!
3071 guint num_cpus
= ltt_trace_get_num_cpu(ts
->parent
.t
);
3073 for(i
=0; i
< num_cpus
; i
++) {
3074 //g_assert(process != ts->running_process[i]);
3075 if(process
== ts
->running_process
[i
]) {
3076 //ts->running_process[i] = lttv_state_find_process(ts, i, 0);
3080 if(i
== num_cpus
) /* process is not scheduled */
3081 exit_process(s
, process
);
3089 static gboolean
process_exec(void *hook_data
, void *call_data
)
3095 LttvProcessState
*process
;
3097 event
= (LttvEvent
*) call_data
;
3098 if (strcmp(lttv_traceset_get_name_from_event(event
),
3101 cpu
= lttv_traceset_get_cpuid_from_event(event
);
3103 process
= ts
->running_process
[cpu
];
3105 #if 0//how to use a sequence that must be transformed in a string
3106 /* PID of the process to release */
3107 guint64 name_len
= ltt_event_field_element_number(e
,
3108 lttv_trace_get_hook_field(th
, 0));
3109 //name = ltt_event_get_string(e, lttv_trace_get_hook_field(th, 0));
3110 LttField
*child
= ltt_event_field_element_select(e
,
3111 lttv_trace_get_hook_field(th
, 0), 0);
3113 (gchar
*)(ltt_event_data(e
)+ltt_event_field_offset(e
, child
));
3114 gchar
*null_term_name
= g_new(gchar
, name_len
+1);
3115 memcpy(null_term_name
, name_begin
, name_len
);
3116 null_term_name
[name_len
] = '\0';
3117 process
->name
= g_quark_from_string(null_term_name
);
3120 process
->name
= g_quark_from_string(lttv_event_get_string(event
,
3122 //g_free(null_term_name);
3126 // TODO We only have sys_open, without the FD
3127 // manage to do somehting better
3128 static gboolean
fs_open(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
;
3134 struct marker_field
*f
;
3138 LttvProcessState
*process
= ts
->running_process
[cpu
];
3140 f
= lttv_trace_get_hook_field(th
, 0);
3141 fd
= ltt_event_get_int(e
, f
);
3143 f
= lttv_trace_get_hook_field(th
, 1);
3144 filename
= ltt_event_get_string(e
, f
);
3146 g_hash_table_insert(process
->fds
, (gpointer
)(long)fd
,
3147 (gpointer
)(unsigned long)g_quark_from_string(filename
));
3152 static void print_stack(LttvProcessState
*process
)
3154 LttvExecutionState
*es
;
3157 g_debug("Execution stack for process %u %s:\n",
3158 process
->pid
, g_quark_to_string(process
->name
));
3160 for (i
= 0; i
< process
->execution_stack
->len
; i
++) {
3161 es
= &g_array_index(process
->execution_stack
,
3162 LttvExecutionState
, i
);
3163 g_debug("Depth %d mode %s submode %s status %s\n",
3164 i
, g_quark_to_string(es
->t
),
3165 g_quark_to_string(es
->n
),
3166 g_quark_to_string(es
->s
));
3171 static void fix_process(gpointer key
, gpointer value
, gpointer user_data
)
3173 LttvProcessState
*process
;
3174 LttvExecutionState
*es
;
3175 process
= (LttvProcessState
*)value
;
3176 LttTime
*timestamp
= (LttTime
*)user_data
;
3178 print_stack(process
);
3180 if(process
->type
== LTTV_STATE_KERNEL_THREAD
) {
3181 es
= &g_array_index(process
->execution_stack
, LttvExecutionState
, 0);
3182 if(es
->t
== LTTV_STATE_MAYBE_SYSCALL
) {
3183 es
->t
= LTTV_STATE_SYSCALL
;
3184 es
->n
= LTTV_STATE_SUBMODE_NONE
;
3185 es
->entry
= *timestamp
;
3186 es
->change
= *timestamp
;
3187 es
->cum_cpu_time
= ltt_time_zero
;
3188 if(es
->s
== LTTV_STATE_UNNAMED
)
3189 es
->s
= LTTV_STATE_WAIT
;
3192 es
= &g_array_index(process
->execution_stack
, LttvExecutionState
, 0);
3193 if(es
->t
== LTTV_STATE_MAYBE_USER_MODE
) {
3194 es
->t
= LTTV_STATE_USER_MODE
;
3195 es
->n
= LTTV_STATE_SUBMODE_NONE
;
3196 es
->entry
= *timestamp
;
3197 //g_assert(timestamp->tv_sec != 0);
3198 es
->change
= *timestamp
;
3199 es
->cum_cpu_time
= ltt_time_zero
;
3200 if(es
->s
== LTTV_STATE_UNNAMED
)
3201 es
->s
= LTTV_STATE_RUN
;
3203 if(process
->execution_stack
->len
== 1) {
3204 /* Still in bottom unknown mode, means we either:
3205 * - never did a system call
3206 * - are scheduled out from user mode.
3207 * May be either in user mode, syscall mode, running or waiting.*/
3208 /* CHECK : we may be tagging syscall mode when being user mode
3209 * (should be fixed now) */
3210 if (es
->s
== LTTV_STATE_WAIT_CPU
) {
3211 /* nothing to do: scheduled out from userspace */
3213 process
->execution_stack
=
3214 g_array_set_size(process
->execution_stack
, 2);
3215 es
= process
->state
= &g_array_index(process
->execution_stack
,
3216 LttvExecutionState
, 1);
3217 es
->t
= LTTV_STATE_SYSCALL
;
3218 es
->n
= LTTV_STATE_SUBMODE_NONE
;
3219 es
->entry
= *timestamp
;
3220 //g_assert(timestamp->tv_sec != 0);
3221 es
->change
= *timestamp
;
3222 es
->cum_cpu_time
= ltt_time_zero
;
3223 if(es
->s
== LTTV_STATE_WAIT_FORK
)
3224 es
->s
= LTTV_STATE_WAIT
;
3231 static gboolean
statedump_end(void *hook_data
, void *call_data
)
3236 //LttEvent *e = ltt_tracefile_get_event(s->parent.tf);
3237 //LttvTraceHook *th = (LttvTraceHook *)hook_data;
3238 event
= (LttvEvent
*) call_data
;
3239 if (strcmp(lttv_traceset_get_name_from_event(event
),
3240 "lttng_statedump_end") != 0)
3244 timestamp
= lttv_event_get_timestamp(event
);
3246 /* For all processes */
3247 /* if kernel thread, if stack[0] is unknown, set to syscall mode, wait */
3248 /* else, if stack[0] is unknown, set to user mode, running */
3250 g_hash_table_foreach(ts
->processes
, fix_process
, ×tamp
);
3255 static gboolean
enum_process_state(void *hook_data
, void *call_data
)
3265 LttvProcessState
*parent_process
;
3266 LttvProcessState
*process
;
3269 LttvExecutionState
*es
;
3272 event
= (LttvEvent
*) call_data
;
3273 if (strcmp(lttv_traceset_get_name_from_event(event
),
3274 "lttng_statedump_process_state") != 0)
3276 cpu
= lttv_traceset_get_cpuid_from_event(event
);
3278 process
= ts
->running_process
[cpu
];
3279 timestamp
= lttv_event_get_timestamp(event
);
3282 pid
= lttv_event_get_long(event
, "tid");
3283 //s->parent.target_pid = pid;
3286 parent_pid
= lttv_event_get_long(event
, "ppid");
3289 command
= lttv_event_get_string(event
, "name");
3293 type
= lttv_event_get_long(event
, "type");
3295 //FIXME: type is rarely used, enum must match possible types.
3297 /* Skip mode 4th param */
3299 /* Skip submode 5th param */
3301 /* Skip status 6th param */
3303 tgid
= lttv_event_get_long(event
, "pid");
3306 nb_cpus
= lttv_trace_get_num_cpu(ts
->trace
);
3307 for(i
=0; i
<nb_cpus
; i
++) {
3308 process
= lttv_state_find_process(ts
, i
, pid
);
3309 g_assert(process
!= NULL
);
3311 process
->ppid
= parent_pid
;
3312 process
->tgid
= tgid
;
3313 process
->name
= g_quark_from_string(command
);
3314 es
= &g_array_index(process
->execution_stack
, LttvExecutionState
, 0);
3315 process
->type
= LTTV_STATE_KERNEL_THREAD
;
3319 /* The process might exist if a process was forked while performing the
3321 process
= lttv_state_find_process(ts
, ANY_CPU
, pid
);
3322 if(process
== NULL
) {
3323 parent_process
= lttv_state_find_process(ts
, ANY_CPU
, parent_pid
);
3324 process
= lttv_state_create_process(ts
, parent_process
, cpu
,
3325 pid
, tgid
, g_quark_from_string(command
),
3328 /* Keep the stack bottom : a running user mode */
3329 /* Disabled because of inconsistencies in the current statedump states. */
3330 //if(type == LTTV_STATE_KERNEL_THREAD) {
3332 /* Only keep the bottom
3333 * FIXME Kernel thread : can be in syscall or interrupt or trap. */
3334 /* Will cause expected trap when in fact being syscall (even after end of
3336 * Will cause expected interrupt when being syscall. (only before end of
3337 * statedump event) */
3338 // This will cause a "popping last state on stack, ignoring it."
3339 process
->execution_stack
= g_array_set_size(process
->execution_stack
, 1);
3340 es
= process
->state
= &g_array_index(process
->execution_stack
,
3341 LttvExecutionState
, 0);
3342 process
->type
= LTTV_STATE_KERNEL_THREAD
;
3343 es
->t
= LTTV_STATE_MAYBE_SYSCALL
;
3344 es
->s
= LTTV_STATE_UNNAMED
;
3345 es
->n
= LTTV_STATE_SUBMODE_UNKNOWN
;
3349 /* User space process :
3350 * bottom : user mode
3351 * either currently running or scheduled out.
3352 * can be scheduled out because interrupted in (user mode or in syscall)
3353 * or because of an explicit call to the scheduler in syscall. Note that
3354 * the scheduler call comes after the irq_exit, so never in interrupt
3356 // temp workaround : set size to 1 : only have user mode bottom of stack.
3357 // will cause g_info message of expected syscall mode when in fact being
3358 // in user mode. Can also cause expected trap when in fact being user
3359 // mode in the event of a page fault reenabling interrupts in the handler.
3360 // Expected syscall and trap can also happen after the end of statedump
3361 // This will cause a "popping last state on stack, ignoring it."
3362 process
->execution_stack
= g_array_set_size(process
->execution_stack
, 1);
3363 es
= process
->state
= &g_array_index(process
->execution_stack
,
3364 LttvExecutionState
, 0);
3365 es
->t
= LTTV_STATE_MAYBE_USER_MODE
;
3366 es
->s
= LTTV_STATE_UNNAMED
;
3367 es
->n
= LTTV_STATE_SUBMODE_UNKNOWN
;
3374 es
= process
->state
= &g_array_index(process
->execution_stack
,
3375 LttvExecutionState
, 1);
3376 es
->t
= LTTV_STATE_MODE_UNKNOWN
;
3377 es
->s
= LTTV_STATE_UNNAMED
;
3378 es
->n
= LTTV_STATE_SUBMODE_UNKNOWN
;
3382 /* The process has already been created :
3383 * Probably was forked while dumping the process state or
3384 * was simply scheduled in prior to get the state dump event.
3386 process
->ppid
= parent_pid
;
3387 process
->tgid
= tgid
;
3388 process
->name
= g_quark_from_string(command
);
3389 process
->type
= type
;
3390 es
= &g_array_index(process
->execution_stack
, LttvExecutionState
, 0);
3392 if(es
->t
== LTTV_STATE_MODE_UNKNOWN
) {
3393 if(type
== LTTV_STATE_KERNEL_THREAD
)
3394 es
->t
= LTTV_STATE_SYSCALL
;
3396 es
->t
= LTTV_STATE_USER_MODE
;
3399 /* Don't mess around with the stack, it will eventually become
3400 * ok after the end of state dump. */
3409 gint
lttv_state_hook_add_event_hooks(void *hook_data
, void *call_data
)
3411 LttvTraceset
*traceset
= (LttvTraceset
*)(call_data
);
3413 lttv_state_add_event_hooks(traceset
);
3418 void lttv_state_add_event_hooks(LttvTraceset
*traceset
)
3420 LttvHooks
*event_hook
;
3422 //Use traceset hooks
3423 event_hook
= lttv_traceset_get_hooks(traceset
);
3424 g_assert(event_hook
);
3426 lttv_hooks_add(event_hook
,syscall_entry
, NULL
, LTTV_PRIO_STATE
);
3427 lttv_hooks_add(event_hook
,syscall_exit
, NULL
, LTTV_PRIO_STATE
);
3428 lttv_hooks_add(event_hook
,irq_entry
, NULL
, LTTV_PRIO_STATE
);
3429 lttv_hooks_add(event_hook
,irq_exit
, NULL
, LTTV_PRIO_STATE
);
3430 lttv_hooks_add(event_hook
,soft_irq_raise
, NULL
, LTTV_PRIO_STATE
);
3431 lttv_hooks_add(event_hook
,soft_irq_entry
, NULL
, LTTV_PRIO_STATE
);
3432 lttv_hooks_add(event_hook
,soft_irq_exit
, NULL
, LTTV_PRIO_STATE
);
3433 lttv_hooks_add(event_hook
,schedchange
, NULL
, LTTV_PRIO_STATE
);
3434 lttv_hooks_add(event_hook
,sched_try_wakeup
, NULL
, LTTV_PRIO_STATE
);
3435 lttv_hooks_add(event_hook
,process_exit
, NULL
, LTTV_PRIO_STATE
);
3436 lttv_hooks_add(event_hook
,process_free
, NULL
, LTTV_PRIO_STATE
);
3437 lttv_hooks_add(event_hook
,process_fork
, NULL
, LTTV_PRIO_STATE
);
3438 lttv_hooks_add(event_hook
,process_exec
, NULL
, LTTV_PRIO_STATE
);
3439 lttv_hooks_add(event_hook
,enum_process_state
, NULL
, LTTV_PRIO_STATE
);
3440 lttv_hooks_add(event_hook
,statedump_end
, NULL
, LTTV_PRIO_STATE
);
3441 lttv_hooks_add(event_hook
,enum_interrupt
, NULL
, LTTV_PRIO_STATE
);
3445 gint
lttv_state_hook_remove_event_hooks(void *hook_data
, void *call_data
)
3448 LttvTraceset
*traceset
= (LttvTraceset
*)(call_data
);
3450 lttv_state_remove_event_hooks(traceset
);
3455 void lttv_state_remove_event_hooks(LttvTraceset
*traceset
)
3458 LttvHooks
*event_hook
;
3460 event_hook
= lttv_traceset_get_hooks(traceset
);
3462 g_assert(event_hook
);
3465 lttv_hooks_remove(event_hook
,syscall_entry
);
3466 lttv_hooks_remove(event_hook
,syscall_exit
);
3467 lttv_hooks_remove(event_hook
,irq_entry
);
3468 lttv_hooks_remove(event_hook
,irq_exit
);
3469 lttv_hooks_remove(event_hook
,soft_irq_raise
);
3470 lttv_hooks_remove(event_hook
,soft_irq_entry
);
3471 lttv_hooks_remove(event_hook
,soft_irq_exit
);
3472 lttv_hooks_remove(event_hook
,schedchange
);
3473 lttv_hooks_remove(event_hook
,sched_try_wakeup
);
3474 lttv_hooks_remove(event_hook
,process_exit
);
3475 lttv_hooks_remove(event_hook
,process_free
);
3476 lttv_hooks_remove(event_hook
,process_exec
);
3477 lttv_hooks_remove(event_hook
,enum_process_state
);
3478 lttv_hooks_remove(event_hook
,statedump_end
);
3479 lttv_hooks_remove(event_hook
,enum_interrupt
);
3483 static gboolean
state_save_event_hook(void *hook_data
, void *call_data
)
3485 guint
*event_count
= (guint
*)hook_data
;
3487 /* Only save at LTTV_STATE_SAVE_INTERVAL */
3488 if(likely((*event_count
)++ < LTTV_STATE_SAVE_INTERVAL
))
3493 LttvEvent
*event
= (LttvEvent
*)call_data
;
3495 LttvTraceset
*traceset
= lttv_trace_get_traceset(event
->state
->trace
);
3497 LttvAttribute
*saved_states_tree
, *saved_state_tree
;
3499 LttvAttributeValue value
;
3500 LttTime currentTime
;
3502 currentTime
= lttv_event_get_timestamp(event
);
3503 int nb_trace
= lttv_traceset_number(traceset
);
3504 for(i
= 0 ; i
< nb_trace
; i
++) {
3506 LttvTrace
*trace
= lttv_traceset_get(traceset
, i
);
3507 LttvTraceState
*tstate
= trace
->state
;
3508 saved_states_tree
= lttv_attribute_find_subdir(trace
->a
,
3509 LTTV_STATE_SAVED_STATES
);
3511 saved_state_tree
= g_object_new(LTTV_ATTRIBUTE_TYPE
, NULL
);
3512 value
= lttv_attribute_add(saved_states_tree
,
3513 lttv_attribute_get_number(saved_states_tree
), LTTV_GOBJECT
);
3514 *(value
.v_gobject
) = (GObject
*)saved_state_tree
;
3517 value
= lttv_attribute_add(saved_state_tree
, LTTV_STATE_TIME
, LTTV_TIME
);
3518 *(value
.v_time
) = currentTime
;
3520 lttv_state_save(tstate
, saved_state_tree
);
3521 g_debug("Saving state at time %lu.%lu", currentTime
.tv_sec
,
3522 currentTime
.tv_nsec
);
3524 *(tstate
->max_time_state_recomputed_in_seek
) = currentTime
;
3529 static gboolean
state_save_after_trace_hook(void *hook_data
, void *call_data
)
3531 #warning "Would we move max_time to traceset"
3532 LttvTrace
*trace
= (LttvTrace
*)(call_data
);
3533 LttvTraceState
*tcs
= trace
->state
;
3534 TimeInterval time_span
= lttv_traceset_get_time_span_real(lttv_trace_get_traceset(trace
));
3536 *(tcs
->max_time_state_recomputed_in_seek
) = time_span
.end_time
;
3540 #ifdef BABEL_CLEANUP
3541 guint
lttv_state_current_cpu(LttvTracefileState
*tfs
)
3546 #endif //BABEL_CLEANUP
3549 static gboolean
block_start(void *hook_data
, void *call_data
)
3551 LttvTracefileState
*self
= (LttvTracefileState
*)call_data
;
3553 LttvTracefileState
*tfcs
;
3555 LttvTraceState
*tcs
= (LttvTraceState
*)(self
->parent
.t_context
);
3557 LttEventPosition
*ep
;
3559 guint i
, nb_block
, nb_event
, nb_tracefile
;
3563 LttvAttribute
*saved_states_tree
, *saved_state_tree
;
3565 LttvAttributeValue value
;
3567 ep
= ltt_event_position_new();
3569 nb_tracefile
= tcs
->parent
.tracefiles
->len
;
3571 /* Count the number of events added since the last block end in any
3574 for(i
= 0 ; i
< nb_tracefile
; i
++) {
3576 LTTV_TRACEFILE_STATE(&g_array_index(tcs
->parent
.tracefiles
,
3577 LttvTracefileContext
, i
));
3578 ltt_event_position(tfcs
->parent
.e
, ep
);
3579 ltt_event_position_get(ep
, &nb_block
, &nb_event
, &tf
);
3580 tcs
->nb_event
+= nb_event
- tfcs
->saved_position
;
3581 tfcs
->saved_position
= nb_event
;
3585 if(tcs
->nb_event
>= tcs
->save_interval
) {
3586 saved_states_tree
= lttv_attribute_find_subdir(tcs
->parent
.t_a
,
3587 LTTV_STATE_SAVED_STATES
);
3588 saved_state_tree
= g_object_new(LTTV_ATTRIBUTE_TYPE
, NULL
);
3589 value
= lttv_attribute_add(saved_states_tree
,
3590 lttv_attribute_get_number(saved_states_tree
), LTTV_GOBJECT
);
3591 *(value
.v_gobject
) = (GObject
*)saved_state_tree
;
3592 value
= lttv_attribute_add(saved_state_tree
, LTTV_STATE_TIME
, LTTV_TIME
);
3593 *(value
.v_time
) = self
->parent
.timestamp
;
3594 lttv_state_save(tcs
, saved_state_tree
);
3596 g_debug("Saving state at time %lu.%lu", self
->parent
.timestamp
.tv_sec
,
3597 self
->parent
.timestamp
.tv_nsec
);
3599 *(tcs
->max_time_state_recomputed_in_seek
) = self
->parent
.timestamp
;
3605 static gboolean
block_end(void *hook_data
, void *call_data
)
3607 LttvTracefileState
*self
= (LttvTracefileState
*)call_data
;
3609 LttvTraceState
*tcs
= (LttvTraceState
*)(self
->parent
.t_context
);
3613 LttEventPosition
*ep
;
3615 guint nb_block
, nb_event
;
3617 ep
= ltt_event_position_new();
3618 ltt_event_position(self
->parent
.e
, ep
);
3619 ltt_event_position_get(ep
, &nb_block
, &nb_event
, &tf
);
3620 tcs
->nb_event
+= nb_event
- self
->saved_position
+ 1;
3621 self
->saved_position
= 0;
3622 *(tcs
->max_time_state_recomputed_in_seek
) = self
->parent
.timestamp
;
3629 void lttv_state_save_add_event_hooks(LttvTracesetState
*self
)
3631 LttvTraceset
*traceset
= self
->parent
.ts
;
3633 guint i
, j
, nb_trace
, nb_tracefile
;
3637 LttvTracefileState
*tfs
;
3639 LttvTraceHook hook_start
, hook_end
;
3641 nb_trace
= lttv_traceset_number(traceset
);
3642 for(i
= 0 ; i
< nb_trace
; i
++) {
3643 ts
= (LttvTraceState
*)self
->parent
.traces
[i
];
3645 lttv_trace_find_hook(ts
->parent
.t
, "core","block_start",NULL
,
3646 NULL
, NULL
, block_start
, &hook_start
);
3647 lttv_trace_find_hook(ts
->parent
.t
, "core","block_end",NULL
,
3648 NULL
, NULL
, block_end
, &hook_end
);
3650 nb_tracefile
= ts
->parent
.tracefiles
->len
;
3652 for(j
= 0 ; j
< nb_tracefile
; j
++) {
3654 LTTV_TRACEFILE_STATE(&g_array_index(ts
->parent
.tracefiles
,
3655 LttvTracefileContext
, j
));
3656 lttv_hooks_add(lttv_hooks_by_id_find(tfs
->parent
.event_by_id
,
3657 hook_start
.id
), hook_start
.h
, NULL
, LTTV_PRIO_STATE
);
3658 lttv_hooks_add(lttv_hooks_by_id_find(tfs
->parent
.event_by_id
,
3659 hook_end
.id
), hook_end
.h
, NULL
, LTTV_PRIO_STATE
);
3665 void lttv_state_save_add_event_hooks(LttvTraceset
*traceset
)
3668 if(!traceset
->has_precomputed_states
) {
3669 guint
*event_count
= g_new(guint
, 1);
3672 lttv_hooks_add(traceset
->event_hooks
,
3673 state_save_event_hook
,
3677 lttv_process_traceset_begin(traceset
,
3683 gint
lttv_state_save_hook_add_event_hooks(void *hook_data
, void *call_data
)
3685 LttvTraceset
*ts
= (LttvTraceset
*)(call_data
);
3687 lttv_state_save_add_event_hooks(ts
);
3693 void lttv_state_save_remove_event_hooks(LttvTraceset
*traceset
)
3696 LttvHooks
*after_trace
= lttv_hooks_new();
3697 guint
*event_count
= NULL
;
3699 lttv_hooks_add(after_trace
,
3700 state_save_after_trace_hook
,
3705 lttv_process_traceset_end(traceset
,
3706 NULL
, after_trace
, NULL
);
3708 lttv_hooks_destroy(after_trace
);
3710 //nb_trace = lttv_traceset_number(traceset);
3712 event_count
= lttv_hooks_remove(traceset
->event_hooks
,
3713 state_save_event_hook
);
3715 if(event_count
) g_free(event_count
);
3719 gint
lttv_state_save_hook_remove_event_hooks(void *hook_data
, void *call_data
)
3721 LttvTraceset
*ts
= (LttvTraceset
*)(call_data
);
3723 lttv_state_save_remove_event_hooks(ts
);
3729 void lttv_state_traceset_seek_time(LttvTraceset
*traceset
, LttTime t
)
3731 lttv_state_traceset_seek_time_closest(traceset
,
3733 lttv_process_traceset_middle(traceset
, t
, G_MAXUINT
,
3737 void lttv_state_traceset_seek_position(LttvTraceset
*traceset
, LttvTracesetPosition
*position
)
3739 LttTime t
= lttv_traceset_position_get_time(position
);
3741 lttv_state_traceset_seek_time_closest(traceset
,
3743 lttv_process_traceset_middle(traceset
,
3749 void lttv_state_traceset_seek_time_closest(LttvTraceset
*traceset
, LttTime t
)
3753 int min_pos
, mid_pos
, max_pos
;
3755 guint resto_start
= 0;
3758 LttvAttributeValue value
;
3760 LttvAttributeType type
;
3762 LttvAttributeName name
;
3766 LttvAttribute
*saved_states_tree
, *saved_state_tree
, *closest_tree
= NULL
;
3768 LttTime closest_tree_time
, restored_time
;
3769 guint first_restored_time
= 1;
3771 //g_tree_destroy(self->parent.pqueue);
3772 //self->parent.pqueue = g_tree_new(compare_tracefile);
3774 g_debug("Entering seek_time_closest for time %lu.%lu", t
.tv_sec
, t
.tv_nsec
);
3776 nb_trace
= lttv_traceset_number(traceset
);
3777 for(i
= 0 ; i
< nb_trace
; i
++) {
3779 LttvTrace
*trace
= lttv_traceset_get(traceset
, i
);
3780 LttvTraceState
*tstate
= trace
->state
;
3782 if(ltt_time_compare(t
, *(tstate
->max_time_state_recomputed_in_seek
)) < 0) {
3783 saved_states_tree
= lttv_attribute_find_subdir(trace
->a
,
3784 LTTV_STATE_SAVED_STATES
);
3787 if(saved_states_tree
) {
3788 max_pos
= lttv_attribute_get_number(saved_states_tree
) - 1;
3789 mid_pos
= max_pos
/ 2;
3790 while(min_pos
< max_pos
) {
3791 type
= lttv_attribute_get(saved_states_tree
, mid_pos
,
3792 &name
, &value
, &is_named
);
3793 g_assert(type
== LTTV_GOBJECT
);
3794 saved_state_tree
= *((LttvAttribute
**)(value
.v_gobject
));
3795 type
= lttv_attribute_get_by_name(saved_state_tree
,
3796 LTTV_STATE_TIME
, &value
);
3797 g_assert(type
== LTTV_TIME
);
3798 if(ltt_time_compare(*(value
.v_time
), t
) < 0) {
3800 closest_tree
= saved_state_tree
;
3801 closest_tree_time
= *(value
.v_time
);
3803 else max_pos
= mid_pos
- 1;
3805 mid_pos
= (min_pos
+ max_pos
+ 1) / 2;
3809 /* restore the closest earlier saved state */
3811 if(first_restored_time
|| (ltt_time_compare(restored_time
, closest_tree_time
) == 0)) {
3812 first_restored_time
= 0;
3813 lttv_state_restore(tstate
, closest_tree
);
3815 restored_time
= closest_tree_time
;
3817 g_debug("State: restored time mismatch between traces");
3824 /* There is no saved state, yet we want to have it. Restart at T0 */
3830 /* We want to seek quickly without restoring/updating the state */
3837 if(resto_start
|| resto_at
) {
3838 // Restore init state and seek so
3839 for(i
= 0 ; i
< nb_trace
; i
++) {
3841 LttvTrace
*trace
= lttv_traceset_get(traceset
, i
);
3842 LttvTraceState
*tstate
= trace
->state
;
3844 restore_init_state(tstate
);
3847 // If t > max saved state
3849 lttv_process_traceset_seek_time(traceset
, t
);
3850 } else if (resto_start
) {
3851 // If no saved state
3852 lttv_process_traceset_seek_time(traceset
, ltt_time_zero
);
3856 g_info("NOT Calling restore");
3859 // Seek at checkpoint
3860 lttv_process_traceset_seek_time(traceset
, restored_time
);
3868 #ifdef BABEL_CLEANUP
3869 static void traceset_state_instance_init (GTypeInstance
*instance
, gpointer g_class
)
3874 static void traceset_state_finalize (LttvTracesetState
*self
)
3876 G_OBJECT_CLASS(g_type_class_peek(LTTV_TRACESET_CONTEXT_TYPE
))->
3877 finalize(G_OBJECT(self
));
3881 static void traceset_state_class_init (LttvTracesetContextClass
*klass
)
3883 GObjectClass
*gobject_class
= G_OBJECT_CLASS(klass
);
3885 gobject_class
->finalize
= (void (*)(GObject
*self
)) traceset_state_finalize
;
3886 klass
->init
= (void (*)(LttvTracesetContext
*self
, LttvTraceset
*ts
))init
;
3887 klass
->fini
= (void (*)(LttvTracesetContext
*self
))fini
;
3888 klass
->new_traceset_context
= new_traceset_context
;
3889 klass
->new_trace_context
= new_trace_context
;
3890 klass
->new_tracefile_context
= new_tracefile_context
;
3894 GType
lttv_traceset_state_get_type(void)
3896 static GType type
= 0;
3898 static const GTypeInfo info
= {
3899 sizeof (LttvTracesetStateClass
),
3900 NULL
, /* base_init */
3901 NULL
, /* base_finalize */
3902 (GClassInitFunc
) traceset_state_class_init
, /* class_init */
3903 NULL
, /* class_finalize */
3904 NULL
, /* class_data */
3905 sizeof (LttvTracesetState
),
3906 0, /* n_preallocs */
3907 (GInstanceInitFunc
) traceset_state_instance_init
, /* instance_init */
3908 NULL
/* value handling */
3911 type
= g_type_register_static (LTTV_TRACESET_CONTEXT_TYPE
, "LttvTracesetStateType",
3919 static void trace_state_instance_init (GTypeInstance
*instance
, gpointer g_class
)
3924 static void trace_state_finalize (LttvTraceState
*self
)
3926 G_OBJECT_CLASS(g_type_class_peek(LTTV_TRACE_CONTEXT_TYPE
))->
3927 finalize(G_OBJECT(self
));
3931 static void trace_state_class_init (LttvTraceStateClass
*klass
)
3933 GObjectClass
*gobject_class
= G_OBJECT_CLASS(klass
);
3935 gobject_class
->finalize
= (void (*)(GObject
*self
)) trace_state_finalize
;
3936 klass
->state_save
= state_save
;
3937 klass
->state_restore
= state_restore
;
3938 klass
->state_saved_free
= state_saved_free
;
3942 GType
lttv_trace_state_get_type(void)
3944 static GType type
= 0;
3946 static const GTypeInfo info
= {
3947 sizeof (LttvTraceStateClass
),
3948 NULL
, /* base_init */
3949 NULL
, /* base_finalize */
3950 (GClassInitFunc
) trace_state_class_init
, /* class_init */
3951 NULL
, /* class_finalize */
3952 NULL
, /* class_data */
3953 sizeof (LttvTraceState
),
3954 0, /* n_preallocs */
3955 (GInstanceInitFunc
) trace_state_instance_init
, /* instance_init */
3956 NULL
/* value handling */
3959 type
= g_type_register_static (LTTV_TRACE_CONTEXT_TYPE
,
3960 "LttvTraceStateType", &info
, 0);
3966 static void tracefile_state_instance_init (GTypeInstance
*instance
,
3972 static void tracefile_state_finalize (LttvTracefileState
*self
)
3974 G_OBJECT_CLASS(g_type_class_peek(LTTV_TRACEFILE_CONTEXT_TYPE
))->
3975 finalize(G_OBJECT(self
));
3979 static void tracefile_state_class_init (LttvTracefileStateClass
*klass
)
3981 GObjectClass
*gobject_class
= G_OBJECT_CLASS(klass
);
3983 gobject_class
->finalize
= (void (*)(GObject
*self
)) tracefile_state_finalize
;
3987 GType
lttv_tracefile_state_get_type(void)
3989 static GType type
= 0;
3991 static const GTypeInfo info
= {
3992 sizeof (LttvTracefileStateClass
),
3993 NULL
, /* base_init */
3994 NULL
, /* base_finalize */
3995 (GClassInitFunc
) tracefile_state_class_init
, /* class_init */
3996 NULL
, /* class_finalize */
3997 NULL
, /* class_data */
3998 sizeof (LttvTracefileState
),
3999 0, /* n_preallocs */
4000 (GInstanceInitFunc
) tracefile_state_instance_init
, /* instance_init */
4001 NULL
/* value handling */
4004 type
= g_type_register_static (LTTV_TRACEFILE_CONTEXT_TYPE
,
4005 "LttvTracefileStateType", &info
, 0);
4011 static void module_init(void)
4013 LTTV_STATE_UNNAMED
= g_quark_from_string("");
4014 LTTV_STATE_MODE_UNKNOWN
= g_quark_from_string("MODE_UNKNOWN");
4015 LTTV_STATE_USER_MODE
= g_quark_from_string("USER_MODE");
4016 LTTV_STATE_MAYBE_USER_MODE
= g_quark_from_string("MAYBE_USER_MODE");
4017 LTTV_STATE_SYSCALL
= g_quark_from_string("SYSCALL");
4018 LTTV_STATE_MAYBE_SYSCALL
= g_quark_from_string("MAYBE_SYSCALL");
4019 LTTV_STATE_TRAP
= g_quark_from_string("TRAP");
4020 LTTV_STATE_MAYBE_TRAP
= g_quark_from_string("MAYBE_TRAP");
4021 LTTV_STATE_IRQ
= g_quark_from_string("IRQ");
4022 LTTV_STATE_SOFT_IRQ
= g_quark_from_string("SOFTIRQ");
4023 LTTV_STATE_SUBMODE_UNKNOWN
= g_quark_from_string("UNKNOWN");
4024 LTTV_STATE_SUBMODE_NONE
= g_quark_from_string("NONE");
4025 LTTV_STATE_WAIT_FORK
= g_quark_from_string("WAIT_FORK");
4026 LTTV_STATE_WAIT_CPU
= g_quark_from_string("WAIT_CPU");
4027 LTTV_STATE_EXIT
= g_quark_from_string("EXIT");
4028 LTTV_STATE_ZOMBIE
= g_quark_from_string("ZOMBIE");
4029 LTTV_STATE_WAIT
= g_quark_from_string("WAIT");
4030 LTTV_STATE_RUN
= g_quark_from_string("RUN");
4031 LTTV_STATE_DEAD
= g_quark_from_string("DEAD");
4032 LTTV_STATE_USER_THREAD
= g_quark_from_string("USER_THREAD");
4033 LTTV_STATE_KERNEL_THREAD
= g_quark_from_string("KERNEL_THREAD");
4034 LTTV_STATE_TRACEFILES
= g_quark_from_string("tracefiles");
4035 LTTV_STATE_PROCESSES
= g_quark_from_string("processes");
4036 LTTV_STATE_PROCESS
= g_quark_from_string("process");
4037 LTTV_STATE_RUNNING_PROCESS
= g_quark_from_string("running_process");
4038 LTTV_STATE_POSITION
= g_quark_from_string("position");
4039 LTTV_STATE_SAVED_STATES
= g_quark_from_string("saved states");
4040 LTTV_STATE_SAVED_STATES_TIME
= g_quark_from_string("saved states time");
4041 LTTV_STATE_TIME
= g_quark_from_string("time");
4042 LTTV_STATE_HOOKS
= g_quark_from_string("saved state hooks");
4043 LTTV_STATE_NAME_TABLES
= g_quark_from_string("name tables");
4044 LTTV_STATE_TRACE_STATE_USE_COUNT
=
4045 g_quark_from_string("trace_state_use_count");
4046 LTTV_STATE_RESOURCE_CPUS
= g_quark_from_string("cpu resource states");
4047 LTTV_STATE_RESOURCE_CPUS
= g_quark_from_string("cpu count");
4048 LTTV_STATE_RESOURCE_IRQS
= g_quark_from_string("irq resource states");
4049 LTTV_STATE_RESOURCE_SOFT_IRQS
= g_quark_from_string("soft irq resource states");
4050 LTTV_STATE_RESOURCE_TRAPS
= g_quark_from_string("trap resource states");
4051 LTTV_STATE_RESOURCE_BLKDEVS
= g_quark_from_string("blkdevs resource states");
4053 LTT_CHANNEL_FD_STATE
= g_quark_from_string("fd_state");
4054 LTT_CHANNEL_GLOBAL_STATE
= g_quark_from_string("global_state");
4055 LTT_CHANNEL_IRQ_STATE
= g_quark_from_string("irq_state");
4056 LTT_CHANNEL_MODULE_STATE
= g_quark_from_string("module_state");
4057 LTT_CHANNEL_NETIF_STATE
= g_quark_from_string("netif_state");
4058 LTT_CHANNEL_SOFTIRQ_STATE
= g_quark_from_string("softirq_state");
4059 LTT_CHANNEL_SWAP_STATE
= g_quark_from_string("swap_state");
4060 LTT_CHANNEL_SYSCALL_STATE
= g_quark_from_string("syscall_state");
4061 LTT_CHANNEL_TASK_STATE
= g_quark_from_string("task_state");
4062 LTT_CHANNEL_VM_STATE
= g_quark_from_string("vm_state");
4063 LTT_CHANNEL_KPROBE_STATE
= g_quark_from_string("kprobe_state");
4064 LTT_CHANNEL_FS
= g_quark_from_string("fs");
4065 LTT_CHANNEL_KERNEL
= g_quark_from_string("kernel");
4066 LTT_CHANNEL_MM
= g_quark_from_string("mm");
4067 LTT_CHANNEL_USERSPACE
= g_quark_from_string("userspace");
4068 LTT_CHANNEL_BLOCK
= g_quark_from_string("block");
4070 LTT_EVENT_SYSCALL_ENTRY
= g_quark_from_string("syscall_entry");
4071 LTT_EVENT_SYSCALL_EXIT
= g_quark_from_string("syscall_exit");
4072 //LTT_EVENT_TRAP_ENTRY = g_quark_from_string("trap_entry");
4073 //LTT_EVENT_TRAP_EXIT = g_quark_from_string("trap_exit");
4074 LTT_EVENT_PAGE_FAULT_ENTRY
= g_quark_from_string("page_fault_entry");
4075 LTT_EVENT_PAGE_FAULT_EXIT
= g_quark_from_string("page_fault_exit");
4076 LTT_EVENT_PAGE_FAULT_NOSEM_ENTRY
= g_quark_from_string("page_fault_nosem_entry");
4077 LTT_EVENT_PAGE_FAULT_NOSEM_EXIT
= g_quark_from_string("page_fault_nosem_exit");
4078 LTT_EVENT_IRQ_ENTRY
= g_quark_from_string("irq_entry");
4079 LTT_EVENT_IRQ_EXIT
= g_quark_from_string("irq_exit");
4080 LTT_EVENT_SOFT_IRQ_RAISE
= g_quark_from_string("softirq_raise");
4081 LTT_EVENT_SOFT_IRQ_ENTRY
= g_quark_from_string("softirq_entry");
4082 LTT_EVENT_SOFT_IRQ_EXIT
= g_quark_from_string("softirq_exit");
4083 LTT_EVENT_SCHED_SCHEDULE
= g_quark_from_string("sched_schedule");
4084 LTT_EVENT_SCHED_TRY_WAKEUP
= g_quark_from_string("sched_try_wakeup");
4085 LTT_EVENT_PROCESS_FORK
= g_quark_from_string("process_fork");
4086 LTT_EVENT_KTHREAD_CREATE
= g_quark_from_string("kthread_create");
4087 LTT_EVENT_PROCESS_EXIT
= g_quark_from_string("process_exit");
4088 LTT_EVENT_PROCESS_FREE
= g_quark_from_string("process_free");
4089 LTT_EVENT_EXEC
= g_quark_from_string("exec");
4090 LTT_EVENT_PROCESS_STATE
= g_quark_from_string("process_state");
4091 LTT_EVENT_STATEDUMP_END
= g_quark_from_string("statedump_end");
4092 LTT_EVENT_FUNCTION_ENTRY
= g_quark_from_string("function_entry");
4093 LTT_EVENT_FUNCTION_EXIT
= g_quark_from_string("function_exit");
4094 LTT_EVENT_REQUEST_ISSUE
= g_quark_from_string("_blk_request_issue");
4095 LTT_EVENT_REQUEST_COMPLETE
= g_quark_from_string("_blk_request_complete");
4096 LTT_EVENT_LIST_INTERRUPT
= g_quark_from_string("interrupt");
4097 LTT_EVENT_SYS_CALL_TABLE
= g_quark_from_string("sys_call_table");
4098 LTT_EVENT_SOFTIRQ_VEC
= g_quark_from_string("softirq_vec");
4099 LTT_EVENT_KPROBE_TABLE
= g_quark_from_string("kprobe_table");
4100 LTT_EVENT_KPROBE
= g_quark_from_string("kprobe");
4101 LTT_EVENT_OPEN
= g_quark_from_string("open");
4102 LTT_EVENT_READ
= g_quark_from_string("read");
4103 LTT_EVENT_POLL_EVENT
= g_quark_from_string("poll_event");
4105 LTT_FIELD_SYSCALL_ID
= g_quark_from_string("syscall_id");
4106 LTT_FIELD_TRAP_ID
= g_quark_from_string("trap_id");
4107 LTT_FIELD_IRQ_ID
= g_quark_from_string("irq_id");
4108 LTT_FIELD_SOFT_IRQ_ID
= g_quark_from_string("softirq_id");
4109 LTT_FIELD_PREV_PID
= g_quark_from_string("prev_pid");
4110 LTT_FIELD_NEXT_PID
= g_quark_from_string("next_pid");
4111 LTT_FIELD_PREV_STATE
= g_quark_from_string("prev_state");
4112 LTT_FIELD_PARENT_PID
= g_quark_from_string("parent_pid");
4113 LTT_FIELD_CHILD_PID
= g_quark_from_string("child_pid");
4114 LTT_FIELD_PID
= g_quark_from_string("pid");
4115 LTT_FIELD_TGID
= g_quark_from_string("tgid");
4116 LTT_FIELD_CHILD_TGID
= g_quark_from_string("child_tgid");
4117 LTT_FIELD_FILENAME
= g_quark_from_string("filename");
4118 LTT_FIELD_NAME
= g_quark_from_string("name");
4119 LTT_FIELD_TYPE
= g_quark_from_string("type");
4120 LTT_FIELD_MODE
= g_quark_from_string("mode");
4121 LTT_FIELD_SUBMODE
= g_quark_from_string("submode");
4122 LTT_FIELD_STATUS
= g_quark_from_string("status");
4123 LTT_FIELD_THIS_FN
= g_quark_from_string("this_fn");
4124 LTT_FIELD_CALL_SITE
= g_quark_from_string("call_site");
4125 LTT_FIELD_MAJOR
= g_quark_from_string("major");
4126 LTT_FIELD_MINOR
= g_quark_from_string("minor");
4127 LTT_FIELD_OPERATION
= g_quark_from_string("direction");
4128 LTT_FIELD_ACTION
= g_quark_from_string("action");
4129 LTT_FIELD_ID
= g_quark_from_string("id");
4130 LTT_FIELD_ADDRESS
= g_quark_from_string("address");
4131 LTT_FIELD_SYMBOL
= g_quark_from_string("symbol");
4132 LTT_FIELD_IP
= g_quark_from_string("ip");
4133 LTT_FIELD_FD
= g_quark_from_string("fd");
4134 LTT_FIELD_STATE
= g_quark_from_string("state");
4135 LTT_FIELD_CPU_ID
= g_quark_from_string("cpu_id");
4137 LTTV_CPU_UNKNOWN
= g_quark_from_string("unknown");
4138 LTTV_CPU_IDLE
= g_quark_from_string("idle");
4139 LTTV_CPU_BUSY
= g_quark_from_string("busy");
4140 LTTV_CPU_IRQ
= g_quark_from_string("irq");
4141 LTTV_CPU_SOFT_IRQ
= g_quark_from_string("softirq");
4142 LTTV_CPU_TRAP
= g_quark_from_string("trap");
4144 LTTV_IRQ_UNKNOWN
= g_quark_from_string("unknown");
4145 LTTV_IRQ_IDLE
= g_quark_from_string("idle");
4146 LTTV_IRQ_BUSY
= g_quark_from_string("busy");
4148 LTTV_BDEV_UNKNOWN
= g_quark_from_string("unknown");
4149 LTTV_BDEV_IDLE
= g_quark_from_string("idle");
4150 LTTV_BDEV_BUSY_READING
= g_quark_from_string("busy_reading");
4151 LTTV_BDEV_BUSY_WRITING
= g_quark_from_string("busy_writing");
4154 static void module_destroy()
4159 LTTV_MODULE("state", "State computation", \
4160 "Update the system state, possibly saving it at intervals", \
4161 module_init
, module_destroy
)