1 /* This file is part of the Linux Trace Toolkit viewer
2 * Copyright (C) 2003-2004 Michel Dagenais
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License Version 2 as
6 * published by the Free Software Foundation;
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
13 * You should have received a copy of the GNU General Public License
14 * along with this program; if not, write to the Free Software
15 * Foundation, Inc., 59 Temple Place - Suite 330, Boston,
25 #include <lttv/lttv.h>
26 #include <lttv/module.h>
27 #include <lttv/state.h>
28 #include <lttv/compiler.h>
29 #include <lttv/traceset.h>
34 #define PREALLOCATED_EXECUTION_STACK 10
40 LTT_CHANNEL_GLOBAL_STATE
,
41 LTT_CHANNEL_IRQ_STATE
,
42 LTT_CHANNEL_MODULE_STATE
,
43 LTT_CHANNEL_NETIF_STATE
,
44 LTT_CHANNEL_SOFTIRQ_STATE
,
45 LTT_CHANNEL_SWAP_STATE
,
46 LTT_CHANNEL_SYSCALL_STATE
,
47 LTT_CHANNEL_TASK_STATE
,
49 LTT_CHANNEL_KPROBE_STATE
,
53 LTT_CHANNEL_USERSPACE
,
59 LTT_EVENT_SYSCALL_ENTRY
,
60 LTT_EVENT_SYSCALL_EXIT
,
61 LTT_EVENT_PAGE_FAULT_NOSEM_ENTRY
,
62 LTT_EVENT_PAGE_FAULT_NOSEM_EXIT
,
63 LTT_EVENT_PAGE_FAULT_ENTRY
,
64 LTT_EVENT_PAGE_FAULT_EXIT
,
65 //LTT_EVENT_TRAP_ENTRY,
66 //LTT_EVENT_TRAP_EXIT,
69 LTT_EVENT_SOFT_IRQ_RAISE
,
70 LTT_EVENT_SOFT_IRQ_ENTRY
,
71 LTT_EVENT_SOFT_IRQ_EXIT
,
72 LTT_EVENT_SCHED_SCHEDULE
,
73 LTT_EVENT_SCHED_TRY_WAKEUP
,
74 LTT_EVENT_PROCESS_FORK
,
75 LTT_EVENT_KTHREAD_CREATE
,
76 LTT_EVENT_PROCESS_EXIT
,
77 LTT_EVENT_PROCESS_FREE
,
79 LTT_EVENT_PROCESS_STATE
,
80 LTT_EVENT_STATEDUMP_END
,
81 LTT_EVENT_FUNCTION_ENTRY
,
82 LTT_EVENT_FUNCTION_EXIT
,
83 LTT_EVENT_THREAD_BRAND
,
84 LTT_EVENT_REQUEST_ISSUE
,
85 LTT_EVENT_REQUEST_COMPLETE
,
86 LTT_EVENT_LIST_INTERRUPT
,
87 LTT_EVENT_SYS_CALL_TABLE
,
88 LTT_EVENT_SOFTIRQ_VEC
,
89 LTT_EVENT_KPROBE_TABLE
,
101 LTT_FIELD_SOFT_IRQ_ID
,
104 LTT_FIELD_PREV_STATE
,
105 LTT_FIELD_PARENT_PID
,
109 LTT_FIELD_CHILD_TGID
,
131 LTTV_STATE_MODE_UNKNOWN
,
132 LTTV_STATE_USER_MODE
,
133 LTTV_STATE_MAYBE_USER_MODE
,
135 LTTV_STATE_MAYBE_SYSCALL
,
137 LTTV_STATE_MAYBE_TRAP
,
142 LTTV_STATE_SUBMODE_UNKNOWN
,
143 LTTV_STATE_SUBMODE_NONE
;
147 LTTV_STATE_WAIT_FORK
,
156 LTTV_STATE_UNBRANDED
;
159 LTTV_STATE_USER_THREAD
,
160 LTTV_STATE_KERNEL_THREAD
;
178 LTTV_BDEV_BUSY_READING
,
179 LTTV_BDEV_BUSY_WRITING
;
182 LTTV_STATE_TRACEFILES
,
183 LTTV_STATE_PROCESSES
,
185 LTTV_STATE_RUNNING_PROCESS
,
187 LTTV_STATE_SAVED_STATES
,
188 LTTV_STATE_SAVED_STATES_TIME
,
191 LTTV_STATE_NAME_TABLES
,
192 LTTV_STATE_TRACE_STATE_USE_COUNT
,
193 LTTV_STATE_RESOURCE_CPUS
,
194 LTTV_STATE_RESOURCE_CPUS_COUNT
,
195 LTTV_STATE_RESOURCE_IRQS
,
196 LTTV_STATE_RESOURCE_SOFT_IRQS
,
197 LTTV_STATE_RESOURCE_TRAPS
,
198 LTTV_STATE_RESOURCE_BLKDEVS
;
200 static void create_max_time(LttvTraceState
*tcs
);
202 static void get_max_time(LttvTraceState
*tcs
);
204 static void free_max_time(LttvTraceState
*tcs
);
206 static void create_name_tables(LttvTraceState
*tcs
);
208 static void get_name_tables(LttvTraceState
*tcs
);
210 static void free_name_tables(LttvTraceState
*tcs
);
212 static void free_saved_state(LttvTraceState
*tcs
);
214 static void lttv_state_free_process_table(GHashTable
*processes
);
216 static void lttv_trace_states_read_raw(LttvTraceState
*tcs
, FILE *fp
,
217 GPtrArray
*quarktable
);
219 /* Resource function prototypes */
220 static LttvBdevState
*get_hashed_bdevstate(LttvTraceState
*ts
, guint32 devcode
);
221 static LttvBdevState
*bdevstate_new(void);
222 static void bdevstate_free(LttvBdevState
*);
223 static void bdevstate_free_cb(gpointer key
, gpointer value
, gpointer user_data
);
224 static LttvBdevState
*bdevstate_copy(LttvBdevState
*bds
);
225 void lttv_state_add_event_hooks(LttvTraceset
*traceset
);
227 #if (__WORDSIZE == 32)
228 guint
guint64_hash(gconstpointer key
)
230 guint64 ukey
= *(const guint64
*)key
;
232 return (guint
)ukey
^ (guint
)(ukey
>> 32);
235 gboolean
guint64_equal(gconstpointer a
, gconstpointer b
)
237 guint64 ua
= *(const guint64
*)a
;
238 guint64 ub
= *(const guint64
*)b
;
244 guint
process_hash(gconstpointer key
)
246 guint pid
= ((const LttvProcessState
*)key
)->pid
;
247 return (pid
>>8 ^ pid
>>4 ^ pid
>>2 ^ pid
) ;
251 /* If the hash table hash function is well distributed,
252 * the process_equal should compare different pid */
253 gboolean
process_equal(gconstpointer a
, gconstpointer b
)
255 const LttvProcessState
*process_a
, *process_b
;
258 process_a
= (const LttvProcessState
*)a
;
259 process_b
= (const LttvProcessState
*)b
;
261 if(likely(process_a
->pid
!= process_b
->pid
)) ret
= FALSE
;
262 else if(likely(process_a
->pid
== 0 &&
263 process_a
->cpu
!= process_b
->cpu
)) ret
= FALSE
;
268 gboolean
rettrue(gpointer key
, gpointer value
, gpointer user_data
)
273 static guint
check_expand(nb
, id
)
278 return max(id
+ 1, nb
* 2);
281 static void expand_name_table(LttvTraceState
*ts
, GQuark
**table
,
282 guint nb
, guint new_nb
)
284 /* Expand an incomplete table */
285 GQuark
*old_table
= *table
;
286 *table
= g_new(GQuark
, new_nb
);
287 memcpy(*table
, old_table
, nb
* sizeof(GQuark
));
291 static void fill_name_table(LttvTraceState
*ts
, GQuark
*table
, guint nb
,
292 guint new_nb
, const char *def_string
)
295 GString
*fe_name
= g_string_new("");
296 for(i
= nb
; i
< new_nb
; i
++) {
297 g_string_printf(fe_name
, "%s %d", def_string
, i
);
298 table
[i
] = g_quark_from_string(fe_name
->str
);
300 g_string_free(fe_name
, TRUE
);
303 static void expand_kprobe_table(LttvTraceState
*ts
, guint64 ip
, char *symbol
)
305 LttvNameTables
*nt
= ts
->name_tables
;
306 #if (__WORDSIZE == 32)
307 guint64
*ip_ptr
= g_new(guint64
, 1);
308 g_hash_table_insert(nt
->kprobe_hash
, ip_ptr
,
309 (gpointer
)(glong
)g_quark_from_string(symbol
));
311 g_hash_table_insert(nt
->kprobe_hash
, (gpointer
)ip
,
312 (gpointer
)(glong
)g_quark_from_string(symbol
));
316 static void expand_trap_table(LttvTraceState
*ts
, int id
)
318 LttvNameTables
*nt
= ts
->name_tables
;
319 LttvTrapState
*old_table
;
322 new_nb
= check_expand(nt
->nb_traps
, id
);
323 if(likely(new_nb
== nt
->nb_traps
))
326 expand_name_table(ts
, &nt
->trap_names
, nt
->nb_traps
, new_nb
);
327 fill_name_table(ts
, nt
->trap_names
, nt
->nb_traps
, new_nb
, "trap");
329 old_table
= ts
->trap_states
;
330 ts
->trap_states
= g_new(LttvTrapState
, new_nb
);
331 memcpy(ts
->trap_states
, old_table
, nt
->nb_traps
* sizeof(LttvTrapState
));
333 for(i
= nt
->nb_traps
; i
< new_nb
; i
++)
334 ts
->trap_states
[i
].running
= 0;
336 /* Update the table size */
337 nt
->nb_traps
= new_nb
;
340 static void expand_irq_table(LttvTraceState
*ts
, int id
)
342 LttvNameTables
*nt
= ts
->name_tables
;
343 LttvIRQState
*old_table
;
346 new_nb
= check_expand(nt
->nb_irqs
, id
);
347 if(likely(new_nb
== nt
->nb_irqs
))
350 expand_name_table(ts
, &nt
->irq_names
, nt
->nb_irqs
, new_nb
);
351 fill_name_table(ts
, nt
->irq_names
, nt
->nb_irqs
, new_nb
, "irq");
353 old_table
= ts
->irq_states
;
354 ts
->irq_states
= g_new(LttvIRQState
, new_nb
);
355 memcpy(ts
->irq_states
, old_table
, nt
->nb_irqs
* sizeof(LttvIRQState
));
357 for(i
= nt
->nb_irqs
; i
< new_nb
; i
++)
358 ts
->irq_states
[i
].mode_stack
=
359 g_array_new(FALSE
, FALSE
, sizeof(LttvIRQMode
));
361 /* Update the table size */
362 nt
->nb_irqs
= new_nb
;
365 static void expand_soft_irq_table(LttvTraceState
*ts
, int id
)
367 LttvNameTables
*nt
= ts
->name_tables
;
368 LttvSoftIRQState
*old_table
;
371 new_nb
= check_expand(nt
->nb_soft_irqs
, id
);
372 if(likely(new_nb
== nt
->nb_soft_irqs
))
375 expand_name_table(ts
, &nt
->soft_irq_names
, nt
->nb_soft_irqs
, new_nb
);
376 fill_name_table(ts
, nt
->soft_irq_names
, nt
->nb_soft_irqs
, new_nb
, "softirq");
378 old_table
= ts
->soft_irq_states
;
379 ts
->soft_irq_states
= g_new(LttvSoftIRQState
, new_nb
);
380 memcpy(ts
->soft_irq_states
, old_table
,
381 nt
->nb_soft_irqs
* sizeof(LttvSoftIRQState
));
383 for(i
= nt
->nb_soft_irqs
; i
< new_nb
; i
++)
384 ts
->soft_irq_states
[i
].running
= 0;
386 /* Update the table size */
387 nt
->nb_soft_irqs
= new_nb
;
390 static void restore_init_state(LttvTraceState
*self
)
392 guint i
, nb_cpus
, nb_irqs
, nb_soft_irqs
, nb_traps
;
394 //LttvTracefileState *tfcs;
396 //LttTime start_time, end_time;
398 /* Free the process tables */
399 if(self
->processes
!= NULL
) lttv_state_free_process_table(self
->processes
);
400 self
->processes
= g_hash_table_new(process_hash
, process_equal
);
403 /* Seek time to beginning */
404 // Mathieu : fix : don't seek traceset here : causes inconsistency in seek
405 // closest. It's the tracecontext job to seek the trace to the beginning
406 // anyway : the init state might be used at the middle of the trace as well...
407 //g_tree_destroy(self->parent.ts_context->pqueue);
408 //self->parent.ts_context->pqueue = g_tree_new(compare_tracefile);
410 //TODO use babeltrace one.
411 //ltt_trace_time_span_get(self->parent.t, &start_time, &end_time);
413 //lttv_process_trace_seek_time(&self->parent, ltt_time_zero);
415 nb_cpus
= lttv_trace_get_num_cpu(self
->trace
);
416 nb_irqs
= self
->name_tables
->nb_irqs
;
417 nb_soft_irqs
= self
->name_tables
->nb_soft_irqs
;
418 nb_traps
= self
->name_tables
->nb_traps
;
420 /* Put the per cpu running_process to beginning state : process 0. */
421 for(i
=0; i
< nb_cpus
; i
++) {
422 LttvExecutionState
*es
;
423 self
->running_process
[i
] = lttv_state_create_process(self
, NULL
, i
, 0, 0,
424 //TODO use &start_time...
425 LTTV_STATE_UNNAMED
, <t_time_zero
);
426 /* We are not sure is it's a kernel thread or normal thread, put the
427 * bottom stack state to unknown */
428 self
->running_process
[i
]->execution_stack
=
429 g_array_set_size(self
->running_process
[i
]->execution_stack
, 1);
430 es
= self
->running_process
[i
]->state
=
431 &g_array_index(self
->running_process
[i
]->execution_stack
,
432 LttvExecutionState
, 0);
433 es
->t
= LTTV_STATE_MODE_UNKNOWN
;
434 es
->s
= LTTV_STATE_UNNAMED
;
436 //self->running_process[i]->state->s = LTTV_STATE_RUN;
437 self
->running_process
[i
]->cpu
= i
;
439 /* reset cpu states */
440 if(self
->cpu_states
[i
].mode_stack
->len
> 0) {
441 g_array_remove_range(self
->cpu_states
[i
].mode_stack
, 0,
442 self
->cpu_states
[i
].mode_stack
->len
);
443 if(self
->cpu_states
[i
].irq_stack
->len
)
444 g_array_remove_range(self
->cpu_states
[i
].irq_stack
, 0,
445 self
->cpu_states
[i
].irq_stack
->len
);
446 if(self
->cpu_states
[i
].softirq_stack
->len
)
447 g_array_remove_range(self
->cpu_states
[i
].softirq_stack
, 0,
448 self
->cpu_states
[i
].softirq_stack
->len
);
449 if(self
->cpu_states
[i
].trap_stack
->len
)
450 g_array_remove_range(self
->cpu_states
[i
].trap_stack
, 0,
451 self
->cpu_states
[i
].trap_stack
->len
);
455 /* reset irq states */
456 for(i
=0; i
<nb_irqs
; i
++) {
457 if(self
->irq_states
[i
].mode_stack
->len
> 0)
458 g_array_remove_range(self
->irq_states
[i
].mode_stack
, 0,
459 self
->irq_states
[i
].mode_stack
->len
);
462 /* reset softirq states */
463 for(i
=0; i
<nb_soft_irqs
; i
++) {
464 self
->soft_irq_states
[i
].pending
= 0;
465 self
->soft_irq_states
[i
].running
= 0;
468 /* reset trap states */
469 for(i
=0; i
<nb_traps
; i
++) {
470 self
->trap_states
[i
].running
= 0;
473 /* reset bdev states */
474 g_hash_table_foreach(self
->bdev_states
, bdevstate_free_cb
, NULL
);
475 //g_hash_table_steal_all(self->bdev_states);
476 g_hash_table_foreach_steal(self
->bdev_states
, rettrue
, NULL
);
479 nb_tracefile
= self
->parent
.tracefiles
->len
;
481 for(i
= 0 ; i
< nb_tracefile
; i
++) {
483 LTTV_TRACEFILE_STATE(g_array_index(self
->parent
.tracefiles
,
484 LttvTracefileContext
*, i
));
485 ltt_trace_time_span_get(self
->parent
.t
, &tfcs
->parent
.timestamp
, NULL
);
486 // tfcs->saved_position = 0;
487 tfcs
->process
= lttv_state_create_process(tfcs
, NULL
,0);
488 tfcs
->process
->state
->s
= LTTV_STATE_RUN
;
489 tfcs
->process
->last_cpu
= tfcs
->cpu_name
;
490 tfcs
->process
->last_cpu_index
= ltt_tracefile_num(((LttvTracefileContext
*)tfcs
)->tf
);
495 //static LttTime time_zero = {0,0};
499 #define MAX_STRING_LEN 4096
501 static void state_load_saved_states(LttvTraceState
*tcs
)
504 GPtrArray
*quarktable
;
505 const char *trace_path
;
509 tcs
->has_precomputed_states
= FALSE
;
513 gchar buf
[MAX_STRING_LEN
];
517 trace_path
= g_quark_to_string(ltt_trace_name(tcs
->parent
.t
));
518 strncpy(path
, trace_path
, PATH_MAX
-1);
519 count
= strnlen(trace_path
, PATH_MAX
-1);
520 // quarktable : open, test
521 strncat(path
, "/precomputed/quarktable", PATH_MAX
-count
-1);
522 fp
= fopen(path
, "r");
524 quarktable
= g_ptr_array_sized_new(4096);
526 /* Index 0 is null */
528 if(hdr
== EOF
) return;
529 g_assert(hdr
== HDR_QUARKS
);
533 if(hdr
== EOF
) break;
534 g_assert(hdr
== HDR_QUARK
);
535 g_ptr_array_set_size(quarktable
, q
+1);
538 res
= fread(&buf
[i
], sizeof(gchar
), 1, fp
);
540 if(buf
[i
] == '\0' || feof(fp
)) break;
543 len
= strnlen(buf
, MAX_STRING_LEN
-1);
544 g_ptr_array_index (quarktable
, q
) = g_new(gchar
, len
+1);
545 strncpy(g_ptr_array_index (quarktable
, q
), buf
, len
+1);
551 // saved_states : open, test
552 strncpy(path
, trace_path
, PATH_MAX
-1);
553 count
= strnlen(trace_path
, PATH_MAX
-1);
554 strncat(path
, "/precomputed/states", PATH_MAX
-count
-1);
555 fp
= fopen(path
, "r");
559 if(hdr
!= HDR_TRACE
) goto end
;
561 lttv_trace_states_read_raw(tcs
, fp
, quarktable
);
563 tcs
->has_precomputed_states
= TRUE
;
568 /* Free the quarktable */
569 for(i
=0; i
<quarktable
->len
; i
++) {
570 string
= g_ptr_array_index (quarktable
, i
);
573 g_ptr_array_free(quarktable
, TRUE
);
576 #endif /* BABEL_CLEANUP */
578 void lttv_trace_state_init(LttvTraceState
*trace_state
, LttvTrace
*trace
)
582 LttvAttributeValue v
;
584 trace_state
->trace
= trace
;
586 trace_state
->save_interval
= LTTV_STATE_SAVE_INTERVAL
;
587 lttv_attribute_find(lttv_trace_attribute(trace
), LTTV_STATE_TRACE_STATE_USE_COUNT
,
591 if (*(v
.v_uint
) == 1) {
592 create_name_tables(trace_state
);
593 create_max_time(trace_state
);
595 get_name_tables(trace_state
);
596 get_max_time(trace_state
);
598 nb_cpu
= lttv_trace_get_num_cpu(trace
);
599 nb_irq
= trace_state
->name_tables
->nb_irqs
;
600 trace_state
->processes
= NULL
;
601 trace_state
->running_process
= g_new(LttvProcessState
*, nb_cpu
);
603 /* init cpu resource stuff */
604 trace_state
->cpu_states
= g_new(LttvCPUState
, nb_cpu
);
605 for (j
= 0; j
< nb_cpu
; j
++) {
606 trace_state
->cpu_states
[j
].mode_stack
= g_array_new(FALSE
, FALSE
, sizeof(LttvCPUMode
));
607 trace_state
->cpu_states
[j
].irq_stack
= g_array_new(FALSE
, FALSE
, sizeof(gint
));
608 trace_state
->cpu_states
[j
].softirq_stack
= g_array_new(FALSE
, FALSE
, sizeof(gint
));
609 trace_state
->cpu_states
[j
].trap_stack
= g_array_new(FALSE
, FALSE
, sizeof(gint
));
610 g_assert(trace_state
->cpu_states
[j
].mode_stack
!= NULL
);
613 /* init irq resource stuff */
614 trace_state
->irq_states
= g_new(LttvIRQState
, nb_irq
);
615 for (j
= 0; j
< nb_irq
; j
++) {
616 trace_state
->irq_states
[j
].mode_stack
= g_array_new(FALSE
, FALSE
, sizeof(LttvIRQMode
));
617 g_assert(trace_state
->irq_states
[j
].mode_stack
!= NULL
);
620 /* init soft irq stuff */
621 /* the kernel has a statically fixed max of 32 softirqs */
622 trace_state
->soft_irq_states
= g_new(LttvSoftIRQState
, trace_state
->name_tables
->nb_soft_irqs
);
624 /* init trap stuff */
625 trace_state
->trap_states
= g_new(LttvTrapState
, trace_state
->name_tables
->nb_traps
);
627 /* init bdev resource stuff */
628 trace_state
->bdev_states
= g_hash_table_new(g_int_hash
, g_int_equal
);
630 restore_init_state(trace_state
);
632 /* See if the trace has saved states */
633 //state_load_saved_states(trace_state);
636 void lttv_trace_state_fini(LttvTraceState
*trace_state
)
638 LttvTrace
*trace
= trace_state
->trace
;
639 LttvAttributeValue v
;
641 lttv_attribute_find(lttv_trace_attribute(trace
), LTTV_STATE_TRACE_STATE_USE_COUNT
,
644 g_assert(*(v
.v_uint
) != 0);
647 if (*(v
.v_uint
) == 0) {
648 free_name_tables(trace_state
);
649 free_max_time(trace_state
);
650 free_saved_state(trace_state
);
652 g_free(trace_state
->running_process
);
653 trace_state
->running_process
= NULL
;
654 lttv_state_free_process_table(trace_state
->processes
);
655 trace_state
->processes
= NULL
;
660 /* Write the process state of the trace */
662 static void write_process_state(gpointer key
, gpointer value
,
665 LttvProcessState
*process
;
667 LttvExecutionState
*es
;
669 FILE *fp
= (FILE *)user_data
;
674 process
= (LttvProcessState
*)value
;
675 fprintf(fp
," <PROCESS CORE=%p PID=%u TGID=%u PPID=%u TYPE=\"%s\" CTIME_S=%lu CTIME_NS=%lu ITIME_S=%lu ITIME_NS=%lu NAME=\"%s\" BRAND=\"%s\" CPU=\"%u\" FREE_EVENTS=\"%u\">\n",
676 process
, process
->pid
, process
->tgid
, process
->ppid
,
677 g_quark_to_string(process
->type
),
678 process
->creation_time
.tv_sec
,
679 process
->creation_time
.tv_nsec
,
680 process
->insertion_time
.tv_sec
,
681 process
->insertion_time
.tv_nsec
,
682 g_quark_to_string(process
->name
),
683 g_quark_to_string(process
->brand
),
684 process
->cpu
, process
->free_events
);
686 for(i
= 0 ; i
< process
->execution_stack
->len
; i
++) {
687 es
= &g_array_index(process
->execution_stack
, LttvExecutionState
, i
);
688 fprintf(fp
, " <ES MODE=\"%s\" SUBMODE=\"%s\" ENTRY_S=%lu ENTRY_NS=%lu",
689 g_quark_to_string(es
->t
), g_quark_to_string(es
->n
),
690 es
->entry
.tv_sec
, es
->entry
.tv_nsec
);
691 fprintf(fp
, " CHANGE_S=%lu CHANGE_NS=%lu STATUS=\"%s\"/>\n",
692 es
->change
.tv_sec
, es
->change
.tv_nsec
, g_quark_to_string(es
->s
));
695 for(i
= 0 ; i
< process
->user_stack
->len
; i
++) {
696 address
= g_array_index(process
->user_stack
, guint64
, i
);
697 fprintf(fp
, " <USER_STACK ADDRESS=\"%" PRIu64
"\"/>\n", address
);
700 fprintf(fp
, " </PROCESS>\n");
704 void lttv_state_write(LttvTraceState
*self
, LttTime t
, FILE *fp
)
706 guint i
, nb_tracefile
, nb_block
, offset
;
709 LttvTracefileState
*tfcs
;
713 LttEventPosition
*ep
;
717 ep
= ltt_event_position_new();
719 fprintf(fp
,"<PROCESS_STATE TIME_S=%lu TIME_NS=%lu>\n", t
.tv_sec
, t
.tv_nsec
);
721 g_hash_table_foreach(self
->processes
, write_process_state
, fp
);
723 nb_cpus
= ltt_trace_get_num_cpu(self
->parent
.t
);
724 for(i
=0;i
<nb_cpus
;i
++) {
725 fprintf(fp
," <CPU NUM=%u RUNNING_PROCESS=%u>\n",
726 i
, self
->running_process
[i
]->pid
);
729 nb_tracefile
= self
->parent
.tracefiles
->len
;
731 for(i
= 0 ; i
< nb_tracefile
; i
++) {
733 LTTV_TRACEFILE_STATE(g_array_index(self
->parent
.tracefiles
,
734 LttvTracefileContext
*, i
));
735 fprintf(fp
, " <TRACEFILE TIMESTAMP_S=%lu TIMESTAMP_NS=%lu",
736 tfcs
->parent
.timestamp
.tv_sec
,
737 tfcs
->parent
.timestamp
.tv_nsec
);
738 LttEvent
*e
= ltt_tracefile_get_event(tfcs
->parent
.tf
);
739 if(e
== NULL
) fprintf(fp
,"/>\n");
741 ltt_event_position(e
, ep
);
742 ltt_event_position_get(ep
, &tf
, &nb_block
, &offset
, &tsc
);
743 fprintf(fp
, " BLOCK=%u OFFSET=%u TSC=%" PRIu64
"/>\n", nb_block
, offset
,
748 fprintf(fp
,"</PROCESS_STATE>\n");
752 static void write_process_state_raw(gpointer key
, gpointer value
,
755 LttvProcessState
*process
;
757 LttvExecutionState
*es
;
759 FILE *fp
= (FILE *)user_data
;
764 process
= (LttvProcessState
*)value
;
765 fputc(HDR_PROCESS
, fp
);
766 //fwrite(&header, sizeof(header), 1, fp);
767 //fprintf(fp, "%s", g_quark_to_string(process->type));
769 fwrite(&process
->type
, sizeof(process
->type
), 1, fp
);
770 //fprintf(fp, "%s", g_quark_to_string(process->name));
772 fwrite(&process
->name
, sizeof(process
->name
), 1, fp
);
773 //fprintf(fp, "%s", g_quark_to_string(process->brand));
775 fwrite(&process
->brand
, sizeof(process
->brand
), 1, fp
);
776 fwrite(&process
->pid
, sizeof(process
->pid
), 1, fp
);
777 fwrite(&process
->free_events
, sizeof(process
->free_events
), 1, fp
);
778 fwrite(&process
->tgid
, sizeof(process
->tgid
), 1, fp
);
779 fwrite(&process
->ppid
, sizeof(process
->ppid
), 1, fp
);
780 fwrite(&process
->cpu
, sizeof(process
->cpu
), 1, fp
);
781 fwrite(&process
->creation_time
, sizeof(process
->creation_time
), 1, fp
);
782 fwrite(&process
->insertion_time
, sizeof(process
->insertion_time
), 1, fp
);
785 fprintf(fp
," <PROCESS CORE=%p PID=%u TGID=%u PPID=%u TYPE=\"%s\" CTIME_S=%lu CTIME_NS=%lu ITIME_S=%lu ITIME_NS=%lu NAME=\"%s\" BRAND=\"%s\" CPU=\"%u\" PROCESS_TYPE=%u>\n",
786 process
, process
->pid
, process
->tgid
, process
->ppid
,
787 g_quark_to_string(process
->type
),
788 process
->creation_time
.tv_sec
,
789 process
->creation_time
.tv_nsec
,
790 process
->insertion_time
.tv_sec
,
791 process
->insertion_time
.tv_nsec
,
792 g_quark_to_string(process
->name
),
793 g_quark_to_string(process
->brand
),
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
.brand
, sizeof(tmp
.brand
), 1, fp
);
909 res
+= fread(&tmp
.pid
, sizeof(tmp
.pid
), 1, fp
);
910 res
+= fread(&tmp
.free_events
, sizeof(tmp
.free_events
), 1, fp
);
911 res
+= fread(&tmp
.tgid
, sizeof(tmp
.tgid
), 1, fp
);
912 res
+= fread(&tmp
.ppid
, sizeof(tmp
.ppid
), 1, fp
);
913 res
+= fread(&tmp
.cpu
, sizeof(tmp
.cpu
), 1, fp
);
914 res
+= fread(&tmp
.creation_time
, sizeof(tmp
.creation_time
), 1, fp
);
915 res
+= fread(&tmp
.insertion_time
, sizeof(tmp
.insertion_time
), 1, fp
);
919 process
= lttv_state_find_process(self
, tmp
.cpu
, tmp
.pid
);
921 /* We must link to the parent */
922 parent_process
= lttv_state_find_process_or_create(self
, ANY_CPU
, tmp
.ppid
,
924 process
= lttv_state_find_process(self
, ANY_CPU
, tmp
.pid
);
925 if(process
== NULL
) {
926 process
= lttv_state_create_process(self
, parent_process
, tmp
.cpu
,
928 g_quark_from_string((gchar
*)g_ptr_array_index(quarktable
, tmp
.name
)),
932 process
->insertion_time
= tmp
.insertion_time
;
933 process
->creation_time
= tmp
.creation_time
;
934 process
->type
= g_quark_from_string(
935 (gchar
*)g_ptr_array_index(quarktable
, tmp
.type
));
936 process
->tgid
= tmp
.tgid
;
937 process
->ppid
= tmp
.ppid
;
938 process
->brand
= g_quark_from_string(
939 (gchar
*)g_ptr_array_index(quarktable
, tmp
.brand
));
941 g_quark_from_string((gchar
*)g_ptr_array_index(quarktable
, tmp
.name
));
942 process
->free_events
= tmp
.free_events
;
945 if(feof(fp
) || ferror(fp
)) goto end_loop
;
947 gint hdr
= fgetc(fp
);
948 if(hdr
== EOF
) goto end_loop
;
952 process
->execution_stack
=
953 g_array_set_size(process
->execution_stack
,
954 process
->execution_stack
->len
+ 1);
955 es
= &g_array_index(process
->execution_stack
, LttvExecutionState
,
956 process
->execution_stack
->len
-1);
959 res
= fread(&es
->t
, sizeof(es
->t
), 1, fp
);
961 es
->t
= g_quark_from_string(
962 (gchar
*)g_ptr_array_index(quarktable
, es
->t
));
963 res
= fread(&es
->n
, sizeof(es
->n
), 1, fp
);
965 es
->n
= g_quark_from_string(
966 (gchar
*)g_ptr_array_index(quarktable
, es
->n
));
967 res
= fread(&es
->s
, sizeof(es
->s
), 1, fp
);
969 es
->s
= g_quark_from_string(
970 (gchar
*)g_ptr_array_index(quarktable
, es
->s
));
971 res
= fread(&es
->entry
, sizeof(es
->entry
), 1, fp
);
972 res
+= fread(&es
->change
, sizeof(es
->change
), 1, fp
);
973 res
+= fread(&es
->cum_cpu_time
, sizeof(es
->cum_cpu_time
), 1, fp
);
978 process
->user_stack
= g_array_set_size(process
->user_stack
,
979 process
->user_stack
->len
+ 1);
980 address
= &g_array_index(process
->user_stack
, guint64
,
981 process
->user_stack
->len
-1);
982 res
= fread(address
, sizeof(address
), 1, fp
);
984 process
->current_function
= *address
;
997 /* Called because a HDR_PROCESS_STATE was found */
998 /* Append a saved state to the trace states */
999 void lttv_state_read_raw(LttvTraceState
*self
, FILE *fp
, GPtrArray
*quarktable
)
1001 guint i
, nb_tracefile
, nb_block
, offset
;
1003 LttvTracefileState
*tfcs
;
1005 LttEventPosition
*ep
;
1014 LttvAttribute
*saved_states_tree
, *saved_state_tree
;
1016 LttvAttributeValue value
;
1017 GTree
*pqueue
= self
->parent
.ts_context
->pqueue
;
1018 ep
= ltt_event_position_new();
1020 restore_init_state(self
);
1022 res
= fread(&t
, sizeof(t
), 1, fp
);
1026 if(feof(fp
) || ferror(fp
)) goto end_loop
;
1028 if(hdr
== EOF
) goto end_loop
;
1032 /* Call read_process_state_raw */
1033 read_process_state_raw(self
, fp
, quarktable
);
1041 case HDR_USER_STACK
:
1042 case HDR_PROCESS_STATE
:
1048 g_error("Error while parsing saved state file : unknown data header %d",
1054 nb_cpus
= ltt_trace_get_num_cpu(self
->parent
.t
);
1055 for(i
=0;i
<nb_cpus
;i
++) {
1058 g_assert(hdr
== HDR_CPU
);
1059 res
= fread(&cpu_num
, sizeof(cpu_num
), 1, fp
); /* cpu number */
1061 g_assert(i
== cpu_num
);
1062 res
= fread(&self
->running_process
[i
]->pid
,
1063 sizeof(self
->running_process
[i
]->pid
), 1, fp
);
1067 nb_tracefile
= self
->parent
.tracefiles
->len
;
1069 for(i
= 0 ; i
< nb_tracefile
; i
++) {
1071 LTTV_TRACEFILE_STATE(g_array_index(self
->parent
.tracefiles
,
1072 LttvTracefileContext
*, i
));
1073 // fprintf(fp, " <TRACEFILE TIMESTAMP_S=%lu TIMESTAMP_NS=%lu",
1074 // tfcs->parent.timestamp.tv_sec,
1075 // tfcs->parent.timestamp.tv_nsec);
1076 g_tree_remove(pqueue
, &tfcs
->parent
);
1078 g_assert(hdr
== HDR_TRACEFILE
);
1079 res
= fread(&tfcs
->parent
.timestamp
, sizeof(tfcs
->parent
.timestamp
), 1, fp
);
1081 /* Note : if timestamp if LTT_TIME_INFINITE, there will be no
1082 * position following : end of trace */
1083 if(ltt_time_compare(tfcs
->parent
.timestamp
, ltt_time_infinite
) != 0) {
1084 res
= fread(&nb_block
, sizeof(nb_block
), 1, fp
);
1085 res
+= fread(&offset
, sizeof(offset
), 1, fp
);
1086 res
+= fread(&tsc
, sizeof(tsc
), 1, fp
);
1088 ltt_event_position_set(ep
, tfcs
->parent
.tf
, nb_block
, offset
, tsc
);
1089 gint ret
= ltt_tracefile_seek_position(tfcs
->parent
.tf
, ep
);
1091 g_tree_insert(pqueue
, &tfcs
->parent
, &tfcs
->parent
);
1096 saved_states_tree
= lttv_attribute_find_subdir(self
->parent
.t_a
,
1097 LTTV_STATE_SAVED_STATES
);
1098 saved_state_tree
= g_object_new(LTTV_ATTRIBUTE_TYPE
, NULL
);
1099 value
= lttv_attribute_add(saved_states_tree
,
1100 lttv_attribute_get_number(saved_states_tree
), LTTV_GOBJECT
);
1101 *(value
.v_gobject
) = (GObject
*)saved_state_tree
;
1102 value
= lttv_attribute_add(saved_state_tree
, LTTV_STATE_TIME
, LTTV_TIME
);
1103 *(value
.v_time
) = t
;
1104 lttv_state_save(self
, saved_state_tree
);
1105 g_debug("Saving state at time %lu.%lu", t
.tv_sec
,
1108 *(self
->max_time_state_recomputed_in_seek
) = t
;
1112 /* Called when a HDR_TRACE is found */
1113 void lttv_trace_states_read_raw(LttvTraceState
*tcs
, FILE *fp
,
1114 GPtrArray
*quarktable
)
1119 if(feof(fp
) || ferror(fp
)) goto end_loop
;
1121 if(hdr
== EOF
) goto end_loop
;
1124 case HDR_PROCESS_STATE
:
1125 /* Call read_process_state_raw */
1126 lttv_state_read_raw(tcs
, fp
, quarktable
);
1134 case HDR_USER_STACK
:
1137 g_error("Error while parsing saved state file :"
1138 " unexpected data header %d",
1142 g_error("Error while parsing saved state file : unknown data header %d",
1147 *(tcs
->max_time_state_recomputed_in_seek
) = tcs
->parent
.time_span
.end_time
;
1148 restore_init_state(tcs
);
1149 lttv_process_trace_seek_time(&tcs
->parent
, ltt_time_zero
);
1152 #endif /* BABEL_CLEANUP */
1155 /* Copy each process from an existing hash table to a new one */
1157 static void copy_process_state(gpointer key
, gpointer value
,gpointer user_data
)
1159 LttvProcessState
*process
, *new_process
;
1161 GHashTable
*new_processes
= (GHashTable
*)user_data
;
1165 process
= (LttvProcessState
*)value
;
1166 new_process
= g_new(LttvProcessState
, 1);
1167 *new_process
= *process
;
1168 new_process
->execution_stack
= g_array_sized_new(FALSE
, FALSE
,
1169 sizeof(LttvExecutionState
), PREALLOCATED_EXECUTION_STACK
);
1170 new_process
->execution_stack
=
1171 g_array_set_size(new_process
->execution_stack
,
1172 process
->execution_stack
->len
);
1173 for(i
= 0 ; i
< process
->execution_stack
->len
; i
++) {
1174 g_array_index(new_process
->execution_stack
, LttvExecutionState
, i
) =
1175 g_array_index(process
->execution_stack
, LttvExecutionState
, i
);
1177 new_process
->state
= &g_array_index(new_process
->execution_stack
,
1178 LttvExecutionState
, new_process
->execution_stack
->len
- 1);
1179 #ifdef BABEL_CLEANUP
1180 new_process
->user_stack
= g_array_sized_new(FALSE
, FALSE
,
1181 sizeof(guint64
), 0);
1182 new_process
->user_stack
= g_array_set_size(new_process
->user_stack
,
1183 process
->user_stack
->len
);
1184 for(i
= 0 ; i
< process
->user_stack
->len
; i
++) {
1185 g_array_index(new_process
->user_stack
, guint64
, i
) =
1186 g_array_index(process
->user_stack
, guint64
, i
);
1188 new_process
->current_function
= process
->current_function
;
1189 #endif /* BABEL_CLEANUP */
1191 /* fd hash table stuff */
1197 /* copy every item in the hash table */
1198 new_process
->fds
= g_hash_table_new(g_direct_hash
, g_direct_equal
);
1200 g_hash_table_iter_init(&it
, process
->fds
);
1201 while (g_hash_table_iter_next (&it
, (void *)&key
, (void *)&value
)) {
1202 g_hash_table_insert(new_process
->fds
, key
, value
);
1206 /* When done creating the new process state, insert it in the
1208 g_hash_table_insert(new_processes
, new_process
, new_process
);
1212 static GHashTable
*lttv_state_copy_process_table(GHashTable
*processes
)
1214 GHashTable
*new_processes
= g_hash_table_new(process_hash
, process_equal
);
1216 g_hash_table_foreach(processes
, copy_process_state
, new_processes
);
1217 return new_processes
;
1220 static LttvCPUState
*lttv_state_copy_cpu_states(LttvCPUState
*states
, guint n
)
1223 LttvCPUState
*retval
;
1225 retval
= g_new(LttvCPUState
, n
);
1227 for(i
=0; i
<n
; i
++) {
1228 retval
[i
].irq_stack
= g_array_new(FALSE
, FALSE
, sizeof(gint
));
1229 g_array_set_size(retval
[i
].irq_stack
, states
[i
].irq_stack
->len
);
1230 for(j
=0; j
<states
[i
].irq_stack
->len
; j
++) {
1231 g_array_index(retval
[i
].irq_stack
, gint
, j
) =
1232 g_array_index(states
[i
].irq_stack
, gint
, j
);
1235 retval
[i
].softirq_stack
= g_array_new(FALSE
, FALSE
, sizeof(gint
));
1236 g_array_set_size(retval
[i
].softirq_stack
, states
[i
].softirq_stack
->len
);
1237 for(j
=0; j
<states
[i
].softirq_stack
->len
; j
++) {
1238 g_array_index(retval
[i
].softirq_stack
, gint
, j
) =
1239 g_array_index(states
[i
].softirq_stack
, gint
, j
);
1242 retval
[i
].trap_stack
= g_array_new(FALSE
, FALSE
, sizeof(gint
));
1243 g_array_set_size(retval
[i
].trap_stack
, states
[i
].trap_stack
->len
);
1244 for(j
=0; j
<states
[i
].trap_stack
->len
; j
++) {
1245 g_array_index(retval
[i
].trap_stack
, gint
, j
) =
1246 g_array_index(states
[i
].trap_stack
, gint
, j
);
1249 retval
[i
].mode_stack
= g_array_new(FALSE
, FALSE
, sizeof(LttvCPUMode
));
1250 g_array_set_size(retval
[i
].mode_stack
, states
[i
].mode_stack
->len
);
1251 for(j
=0; j
<states
[i
].mode_stack
->len
; j
++) {
1252 g_array_index(retval
[i
].mode_stack
, GQuark
, j
) =
1253 g_array_index(states
[i
].mode_stack
, GQuark
, j
);
1260 static void lttv_state_free_cpu_states(LttvCPUState
*states
, guint n
)
1264 for(i
=0; i
<n
; i
++) {
1265 g_array_free(states
[i
].mode_stack
, TRUE
);
1266 g_array_free(states
[i
].irq_stack
, TRUE
);
1267 g_array_free(states
[i
].softirq_stack
, TRUE
);
1268 g_array_free(states
[i
].trap_stack
, TRUE
);
1274 static LttvIRQState
*lttv_state_copy_irq_states(LttvIRQState
*states
, guint n
)
1277 LttvIRQState
*retval
;
1279 retval
= g_new(LttvIRQState
, n
);
1281 for(i
=0; i
<n
; i
++) {
1282 retval
[i
].mode_stack
= g_array_new(FALSE
, FALSE
, sizeof(LttvIRQMode
));
1283 g_array_set_size(retval
[i
].mode_stack
, states
[i
].mode_stack
->len
);
1284 for(j
=0; j
<states
[i
].mode_stack
->len
; j
++) {
1285 g_array_index(retval
[i
].mode_stack
, GQuark
, j
) =
1286 g_array_index(states
[i
].mode_stack
, GQuark
, j
);
1293 static void lttv_state_free_irq_states(LttvIRQState
*states
, guint n
)
1297 for(i
=0; i
<n
; i
++) {
1298 g_array_free(states
[i
].mode_stack
, TRUE
);
1304 static LttvSoftIRQState
*
1305 lttv_state_copy_soft_irq_states(LttvSoftIRQState
*states
, guint n
)
1308 LttvSoftIRQState
*retval
;
1310 retval
= g_new(LttvSoftIRQState
, n
);
1312 for(i
=0; i
<n
; i
++) {
1313 retval
[i
].pending
= states
[i
].pending
;
1314 retval
[i
].running
= states
[i
].running
;
1320 static void lttv_state_free_soft_irq_states(LttvSoftIRQState
*states
, guint n
)
1325 static LttvTrapState
*
1326 lttv_state_copy_trap_states(LttvTrapState
*states
, guint n
)
1329 LttvTrapState
*retval
;
1331 retval
= g_new(LttvTrapState
, n
);
1333 for(i
=0; i
<n
; i
++) {
1334 retval
[i
].running
= states
[i
].running
;
1340 static void lttv_state_free_trap_states(LttvTrapState
*states
, guint n
)
1345 /* bdevstate stuff */
1347 static LttvBdevState
*get_hashed_bdevstate(LttvTraceState
*ts
, guint32 devcode
)
1349 gint devcode_gint
= devcode
;
1350 gpointer bdev
= g_hash_table_lookup(ts
->bdev_states
, &devcode_gint
);
1352 LttvBdevState
*bdevstate
= g_new(LttvBdevState
, 1);
1353 bdevstate
->mode_stack
= g_array_new(FALSE
, FALSE
, sizeof(GQuark
));
1355 gint
* key
= g_new(gint
, 1);
1357 g_hash_table_insert(ts
->bdev_states
, key
, bdevstate
);
1365 static LttvBdevState
*bdevstate_new(void)
1367 LttvBdevState
*retval
;
1368 retval
= g_new(LttvBdevState
, 1);
1369 retval
->mode_stack
= g_array_new(FALSE
, FALSE
, sizeof(GQuark
));
1374 static void bdevstate_free(LttvBdevState
*bds
)
1376 g_array_free(bds
->mode_stack
, TRUE
);
1380 static void bdevstate_free_cb(gpointer key
, gpointer value
, gpointer user_data
)
1382 LttvBdevState
*bds
= (LttvBdevState
*) value
;
1384 bdevstate_free(bds
);
1387 static LttvBdevState
*bdevstate_copy(LttvBdevState
*bds
)
1389 LttvBdevState
*retval
;
1391 retval
= bdevstate_new();
1392 g_array_insert_vals(retval
->mode_stack
, 0, bds
->mode_stack
->data
,
1393 bds
->mode_stack
->len
);
1398 static void insert_and_copy_bdev_state(gpointer k
, gpointer v
, gpointer u
)
1400 //GHashTable *ht = (GHashTable *)u;
1401 LttvBdevState
*bds
= (LttvBdevState
*)v
;
1402 LttvBdevState
*newbds
;
1404 newbds
= bdevstate_copy(bds
);
1406 g_hash_table_insert(u
, k
, newbds
);
1409 static GHashTable
*lttv_state_copy_blkdev_hashtable(GHashTable
*ht
)
1413 retval
= g_hash_table_new(g_int_hash
, g_int_equal
);
1415 g_hash_table_foreach(ht
, insert_and_copy_bdev_state
, retval
);
1420 /* Free a hashtable and the LttvBdevState structures its values
1423 static void lttv_state_free_blkdev_hashtable(GHashTable
*ht
)
1425 g_hash_table_foreach(ht
, bdevstate_free_cb
, NULL
);
1426 g_hash_table_destroy(ht
);
1429 /* The saved state for each trace contains a member "processes", which
1430 stores a copy of the process table, and a member "tracefiles" with
1431 one entry per tracefile. Each tracefile has a "process" member pointing
1432 to the current process and a "position" member storing the tracefile
1433 position (needed to seek to the current "next" event. */
1435 void lttv_state_save(LttvTraceState
*self
, LttvAttribute
*container
)
1437 guint i
, nb_cpus
, nb_irqs
, nb_soft_irqs
, nb_traps
;
1439 guint
*running_process
;
1441 LttvAttributeValue value
;
1443 value
= lttv_attribute_add(container
, LTTV_STATE_PROCESSES
,
1445 *(value
.v_pointer
) = lttv_state_copy_process_table(self
->processes
);
1447 /* Add the currently running processes array */
1448 nb_cpus
= lttv_trace_get_num_cpu(self
->trace
);
1449 running_process
= g_new(guint
, nb_cpus
);
1450 for(i
=0;i
<nb_cpus
;i
++) {
1451 running_process
[i
] = self
->running_process
[i
]->pid
;
1453 value
= lttv_attribute_add(container
, LTTV_STATE_RUNNING_PROCESS
,
1455 *(value
.v_pointer
) = running_process
;
1457 g_info("State save");
1459 /* Save the current position */
1460 value
= lttv_attribute_add(container
, LTTV_STATE_POSITION
,
1462 *(value
.v_pointer
) = lttv_traceset_create_position(lttv_trace_get_traceset(self
->trace
));
1464 #ifdef BABEL_CLEANUP
1465 nb_tracefile
= self
->parent
.tracefiles
->len
;
1466 for(i
= 0 ; i
< nb_tracefile
; i
++) {
1468 LTTV_TRACEFILE_STATE(g_array_index(self
->parent
.tracefiles
,
1469 LttvTracefileContext
*, i
));
1470 tracefile_tree
= g_object_new(LTTV_ATTRIBUTE_TYPE
, NULL
);
1471 value
= lttv_attribute_add(tracefiles_tree
, i
,
1473 *(value
.v_gobject
) = (GObject
*)tracefile_tree
;
1475 value
= lttv_attribute_add(tracefile_tree
, LTTV_STATE_PROCESS
,
1477 *(value
.v_uint
) = tfcs
->process
->pid
;
1479 value
= lttv_attribute_add(tracefile_tree
, LTTV_STATE_EVENT
,
1481 /* Only save the position if the tfs has not infinite time. */
1482 //if(!g_tree_lookup(self->parent.ts_context->pqueue, &tfcs->parent)
1483 // && current_tfcs != tfcs) {
1484 if(ltt_time_compare(tfcs
->parent
.timestamp
, ltt_time_infinite
) == 0) {
1485 *(value
.v_pointer
) = NULL
;
1487 LttEvent
*e
= ltt_tracefile_get_event(tfcs
->parent
.tf
);
1488 ep
= ltt_event_position_new();
1489 ltt_event_position(e
, ep
);
1490 *(value
.v_pointer
) = ep
;
1492 guint nb_block
, offset
;
1495 ltt_event_position_get(ep
, &tf
, &nb_block
, &offset
, &tsc
);
1496 g_info("Block %u offset %u tsc %" PRIu64
" time %lu.%lu", nb_block
,
1497 offset
, tsc
, tfcs
->parent
.timestamp
.tv_sec
,
1498 tfcs
->parent
.timestamp
.tv_nsec
);
1501 #endif /* BABEL_CLEANUP */
1503 /* save the cpu state */
1505 value
= lttv_attribute_add(container
, LTTV_STATE_RESOURCE_CPUS_COUNT
,
1507 *(value
.v_uint
) = nb_cpus
;
1509 value
= lttv_attribute_add(container
, LTTV_STATE_RESOURCE_CPUS
,
1511 *(value
.v_pointer
) = lttv_state_copy_cpu_states(self
->cpu_states
, nb_cpus
);
1514 /* save the irq state */
1515 nb_irqs
= self
->name_tables
->nb_irqs
;
1517 value
= lttv_attribute_add(container
, LTTV_STATE_RESOURCE_IRQS
,
1519 *(value
.v_pointer
) = lttv_state_copy_irq_states(self
->irq_states
, nb_irqs
);
1522 /* save the soft irq state */
1523 nb_soft_irqs
= self
->name_tables
->nb_soft_irqs
;
1525 value
= lttv_attribute_add(container
, LTTV_STATE_RESOURCE_SOFT_IRQS
,
1527 *(value
.v_pointer
) = lttv_state_copy_soft_irq_states(self
->soft_irq_states
, nb_soft_irqs
);
1530 /* save the trap state */
1531 nb_traps
= self
->name_tables
->nb_traps
;
1533 value
= lttv_attribute_add(container
, LTTV_STATE_RESOURCE_TRAPS
,
1535 *(value
.v_pointer
) = lttv_state_copy_trap_states(self
->trap_states
, nb_traps
);
1538 /* save the blkdev states */
1539 value
= lttv_attribute_add(container
, LTTV_STATE_RESOURCE_BLKDEVS
,
1541 *(value
.v_pointer
) = lttv_state_copy_blkdev_hashtable(self
->bdev_states
);
1544 void lttv_state_restore(LttvTraceState
*self
, LttvAttribute
*container
)
1546 guint i
, pid
, nb_cpus
, nb_irqs
, nb_soft_irqs
, nb_traps
;
1547 guint
*running_process
;
1548 LttvAttributeType type
;
1549 LttvAttributeValue value
;
1551 type
= lttv_attribute_get_by_name(container
, LTTV_STATE_PROCESSES
,
1553 g_assert(type
== LTTV_POINTER
);
1554 lttv_state_free_process_table(self
->processes
);
1555 self
->processes
= lttv_state_copy_process_table(*(value
.v_pointer
));
1557 /* Add the currently running processes array */
1558 nb_cpus
= lttv_trace_get_num_cpu(self
->trace
);
1559 type
= lttv_attribute_get_by_name(container
, LTTV_STATE_RUNNING_PROCESS
,
1561 g_assert(type
== LTTV_POINTER
);
1562 running_process
= *(value
.v_pointer
);
1563 for(i
=0;i
<nb_cpus
;i
++) {
1564 pid
= running_process
[i
];
1565 self
->running_process
[i
] = lttv_state_find_process(self
, i
, pid
);
1566 g_assert(self
->running_process
[i
] != NULL
);
1569 //nb_tracefile = self->parent.tracefiles->len;
1571 //g_tree_destroy(tsc->pqueue);
1572 //tsc->pqueue = g_tree_new(compare_tracefile);
1574 /* restore cpu resource states */
1575 type
= lttv_attribute_get_by_name(container
, LTTV_STATE_RESOURCE_CPUS
, &value
);
1576 g_assert(type
== LTTV_POINTER
);
1577 lttv_state_free_cpu_states(self
->cpu_states
, nb_cpus
);
1578 self
->cpu_states
= lttv_state_copy_cpu_states(*(value
.v_pointer
), nb_cpus
);
1580 /* restore irq resource states */
1581 nb_irqs
= self
->name_tables
->nb_irqs
;
1582 type
= lttv_attribute_get_by_name(container
, LTTV_STATE_RESOURCE_IRQS
, &value
);
1583 g_assert(type
== LTTV_POINTER
);
1584 lttv_state_free_irq_states(self
->irq_states
, nb_irqs
);
1585 self
->irq_states
= lttv_state_copy_irq_states(*(value
.v_pointer
), nb_irqs
);
1587 /* restore soft irq resource states */
1588 nb_soft_irqs
= self
->name_tables
->nb_soft_irqs
;
1589 type
= lttv_attribute_get_by_name(container
, LTTV_STATE_RESOURCE_SOFT_IRQS
, &value
);
1590 g_assert(type
== LTTV_POINTER
);
1591 lttv_state_free_soft_irq_states(self
->soft_irq_states
, nb_soft_irqs
);
1592 self
->soft_irq_states
= lttv_state_copy_soft_irq_states(*(value
.v_pointer
), nb_soft_irqs
);
1594 /* restore trap resource states */
1595 nb_traps
= self
->name_tables
->nb_traps
;
1596 type
= lttv_attribute_get_by_name(container
, LTTV_STATE_RESOURCE_TRAPS
, &value
);
1597 g_assert(type
== LTTV_POINTER
);
1598 lttv_state_free_trap_states(self
->trap_states
, nb_traps
);
1599 self
->trap_states
= lttv_state_copy_trap_states(*(value
.v_pointer
), nb_traps
);
1601 /* restore the blkdev states */
1602 type
= lttv_attribute_get_by_name(container
, LTTV_STATE_RESOURCE_BLKDEVS
, &value
);
1603 g_assert(type
== LTTV_POINTER
);
1604 lttv_state_free_blkdev_hashtable(self
->bdev_states
);
1605 self
->bdev_states
= lttv_state_copy_blkdev_hashtable(*(value
.v_pointer
));
1607 #ifdef BABEL_CLEANUP
1608 for(i
= 0 ; i
< nb_tracefile
; i
++) {
1610 LTTV_TRACEFILE_STATE(g_array_index(self
->parent
.tracefiles
,
1611 LttvTracefileContext
*, i
));
1612 type
= lttv_attribute_get(tracefiles_tree
, i
, &name
, &value
, &is_named
);
1613 g_assert(type
== LTTV_GOBJECT
);
1614 tracefile_tree
= *((LttvAttribute
**)(value
.v_gobject
));
1616 type
= lttv_attribute_get_by_name(tracefile_tree
, LTTV_STATE_PROCESS
,
1618 g_assert(type
== LTTV_UINT
);
1619 pid
= *(value
.v_uint
);
1620 tfcs
->process
= lttv_state_find_process_or_create(tfcs
, pid
);
1622 type
= lttv_attribute_get_by_name(tracefile_tree
, LTTV_STATE_EVENT
,
1624 g_assert(type
== LTTV_POINTER
);
1625 //g_assert(*(value.v_pointer) != NULL);
1626 ep
= *(value
.v_pointer
);
1627 g_assert(tfcs
->parent
.t_context
!= NULL
);
1629 tfcs
->cpu_state
= &self
->cpu_states
[tfcs
->cpu
];
1631 LttvTracefileContext
*tfc
= LTTV_TRACEFILE_CONTEXT(tfcs
);
1632 g_tree_remove(tsc
->pqueue
, tfc
);
1635 retval
= ltt_tracefile_seek_position(tfc
->tf
, ep
);
1636 g_assert_cmpint(retval
, ==, 0);
1637 tfc
->timestamp
= ltt_event_time(ltt_tracefile_get_event(tfc
->tf
));
1638 g_assert_cmpint(ltt_time_compare(tfc
->timestamp
, ltt_time_infinite
),
1640 g_tree_insert(tsc
->pqueue
, tfc
, tfc
);
1641 g_info("Restoring state for a tf at time %lu.%lu",
1642 tfc
->timestamp
.tv_sec
, tfc
->timestamp
.tv_nsec
);
1644 tfc
->timestamp
= ltt_time_infinite
;
1647 #endif /* BABEL_CLEANUP */
1651 * Note: the position must be explicitely set on the entire traceset to
1652 * match the trace states.
1654 LttvTracesetPosition
*lttv_trace_state_get_position(LttvAttribute
*container
)
1656 LttvAttributeType type
;
1657 LttvAttributeValue value
;
1659 type
= lttv_attribute_get_by_name(container
, LTTV_STATE_POSITION
, &value
);
1660 g_assert(type
== LTTV_POINTER
);
1661 return *(value
.v_pointer
);
1664 void lttv_state_saved_free(LttvTraceState
*self
, LttvAttribute
*container
)
1666 guint nb_cpus
, nb_irqs
, nb_soft_irqs
;
1667 guint
*running_process
;
1668 LttvAttributeType type
;
1669 LttvAttributeValue value
;
1671 type
= lttv_attribute_get_by_name(container
, LTTV_STATE_PROCESSES
,
1673 g_assert(type
== LTTV_POINTER
);
1674 lttv_state_free_process_table(*(value
.v_pointer
));
1675 *(value
.v_pointer
) = NULL
;
1676 lttv_attribute_remove_by_name(container
, LTTV_STATE_PROCESSES
);
1678 /* Free running processes array */
1679 type
= lttv_attribute_get_by_name(container
, LTTV_STATE_RUNNING_PROCESS
,
1681 g_assert(type
== LTTV_POINTER
);
1682 running_process
= *(value
.v_pointer
);
1683 g_free(running_process
);
1685 /* free cpu resource states */
1686 type
= lttv_attribute_get_by_name(container
, LTTV_STATE_RESOURCE_CPUS_COUNT
, &value
);
1687 g_assert(type
== LTTV_UINT
);
1688 nb_cpus
= *value
.v_uint
;
1689 type
= lttv_attribute_get_by_name(container
, LTTV_STATE_RESOURCE_CPUS
, &value
);
1690 g_assert(type
== LTTV_POINTER
);
1691 lttv_state_free_cpu_states(*(value
.v_pointer
), nb_cpus
);
1693 /* free irq resource states */
1694 nb_irqs
= self
->name_tables
->nb_irqs
;
1695 type
= lttv_attribute_get_by_name(container
, LTTV_STATE_RESOURCE_IRQS
, &value
);
1696 g_assert(type
== LTTV_POINTER
);
1697 lttv_state_free_irq_states(*(value
.v_pointer
), nb_irqs
);
1699 /* free softirq resource states */
1700 nb_soft_irqs
= self
->name_tables
->nb_soft_irqs
;
1701 type
= lttv_attribute_get_by_name(container
, LTTV_STATE_RESOURCE_SOFT_IRQS
, &value
);
1702 g_assert(type
== LTTV_POINTER
);
1703 lttv_state_free_soft_irq_states(*(value
.v_pointer
), nb_soft_irqs
);
1705 /* free the blkdev states */
1706 type
= lttv_attribute_get_by_name(container
, LTTV_STATE_RESOURCE_BLKDEVS
, &value
);
1707 g_assert(type
== LTTV_POINTER
);
1708 lttv_state_free_blkdev_hashtable(*(value
.v_pointer
));
1710 /* remove the position */
1711 type
= lttv_attribute_get_by_name(container
, LTTV_STATE_POSITION
, &value
);
1712 g_assert(type
== LTTV_POINTER
);
1713 lttv_traceset_destroy_position(*(value
.v_pointer
));
1715 #ifdef BABEL_CLEANUP
1716 nb_tracefile
= self
->parent
.tracefiles
->len
;
1718 for(i
= 0 ; i
< nb_tracefile
; i
++) {
1720 type
= lttv_attribute_get(tracefiles_tree
, i
, &name
, &value
, &is_named
);
1721 g_assert(type
== LTTV_GOBJECT
);
1722 tracefile_tree
= *((LttvAttribute
**)(value
.v_gobject
));
1724 type
= lttv_attribute_get_by_name(tracefile_tree
, LTTV_STATE_EVENT
,
1726 g_assert(type
== LTTV_POINTER
);
1727 if(*(value
.v_pointer
) != NULL
) g_free(*(value
.v_pointer
));
1729 g_object_unref(G_OBJECT(tracefiles_tree
));
1730 #endif /* BABEL_CLEANUP */
1734 static void free_saved_state(LttvTraceState
*self
)
1737 LttvAttributeType type
;
1738 LttvAttributeValue value
;
1739 LttvAttributeName name
;
1741 LttvAttribute
*saved_states
;
1743 saved_states
= lttv_attribute_find_subdir(lttv_trace_attribute(self
->trace
),
1744 LTTV_STATE_SAVED_STATES
);
1746 nb
= lttv_attribute_get_number(saved_states
);
1747 for(i
= 0 ; i
< nb
; i
++) {
1748 type
= lttv_attribute_get(saved_states
, i
, &name
, &value
, &is_named
);
1749 g_assert(type
== LTTV_GOBJECT
);
1750 lttv_state_saved_free(self
, *((LttvAttribute
**)value
.v_gobject
));
1753 lttv_attribute_remove_by_name(lttv_trace_attribute(self
->trace
),
1754 LTTV_STATE_SAVED_STATES
);
1758 static void create_max_time(LttvTraceState
*trace_state
)
1760 LttvAttributeValue v
;
1762 lttv_attribute_find(lttv_trace_attribute(trace_state
->trace
),
1763 LTTV_STATE_SAVED_STATES_TIME
,
1765 g_assert(*(v
.v_pointer
) == NULL
);
1766 *(v
.v_pointer
) = g_new(LttTime
,1);
1767 *((LttTime
*)*(v
.v_pointer
)) = ltt_time_zero
;
1771 static void get_max_time(LttvTraceState
*trace_state
)
1773 LttvAttributeValue v
;
1775 lttv_attribute_find(lttv_trace_attribute(trace_state
->trace
),
1776 LTTV_STATE_SAVED_STATES_TIME
,
1778 g_assert(*(v
.v_pointer
) != NULL
);
1779 trace_state
->max_time_state_recomputed_in_seek
= (LttTime
*)*(v
.v_pointer
);
1783 static void free_max_time(LttvTraceState
*trace_state
)
1785 LttvAttributeValue v
;
1787 lttv_attribute_find(lttv_trace_attribute(trace_state
->trace
),
1788 LTTV_STATE_SAVED_STATES_TIME
,
1790 g_free(*(v
.v_pointer
));
1791 *(v
.v_pointer
) = NULL
;
1794 static void create_name_tables(LttvTraceState
*tcs
)
1798 GString
*fe_name
= g_string_new("");
1800 LttvNameTables
*name_tables
= g_new(LttvNameTables
, 1);
1802 LttvAttributeValue v
;
1806 lttv_attribute_find(lttv_trace_attribute(tcs
->trace
), LTTV_STATE_NAME_TABLES
,
1808 g_assert(*(v
.v_pointer
) == NULL
);
1809 *(v
.v_pointer
) = name_tables
;
1811 #ifdef BABEL_CLEANUP
1812 hooks
= g_array_sized_new(FALSE
, FALSE
, sizeof(LttvTraceHook
), 1);
1814 if(!lttv_trace_find_hook(tcs
->parent
.t
,
1816 LTT_EVENT_SYSCALL_ENTRY
,
1817 FIELD_ARRAY(LTT_FIELD_SYSCALL_ID
),
1818 NULL
, NULL
, &hooks
)) {
1820 // th = lttv_trace_hook_get_first(&th);
1822 // t = ltt_field_type(lttv_trace_get_hook_field(th, 0));
1823 // nb = ltt_type_element_number(t);
1825 // name_tables->syscall_names = g_new(GQuark, nb);
1826 // name_tables->nb_syscalls = nb;
1828 // for(i = 0 ; i < nb ; i++) {
1829 // name_tables->syscall_names[i] = ltt_enum_string_get(t, i);
1830 // if(!name_tables->syscall_names[i]) {
1831 // GString *string = g_string_new("");
1832 // g_string_printf(string, "syscall %u", i);
1833 // name_tables->syscall_names[i] = g_quark_from_string(string->str);
1834 // g_string_free(string, TRUE);
1837 #endif /* BABEL_CLEANUP */
1839 name_tables
->nb_syscalls
= PREALLOC_NB_SYSCALLS
;
1840 name_tables
->syscall_names
= g_new(GQuark
, name_tables
->nb_syscalls
);
1841 for(i
= 0 ; i
< name_tables
->nb_syscalls
; i
++) {
1842 g_string_printf(fe_name
, "syscall %d", i
);
1843 name_tables
->syscall_names
[i
] = g_quark_from_string(fe_name
->str
);
1845 #ifdef BABEL_CLEANUP
1847 name_tables
->syscall_names
= NULL
;
1848 name_tables
->nb_syscalls
= 0;
1850 lttv_trace_hook_remove_all(&hooks
);
1851 #endif /* BABEL_CLEANUP */
1853 #ifdef BABEL_CLEANUP
1854 if(!lttv_trace_find_hook(tcs
->parent
.t
,
1856 LTT_EVENT_TRAP_ENTRY
,
1857 FIELD_ARRAY(LTT_FIELD_TRAP_ID
),
1858 NULL
, NULL
, &hooks
) ||
1859 !lttv_trace_find_hook(tcs
->parent
.t
,
1861 LTT_EVENT_PAGE_FAULT_ENTRY
,
1862 FIELD_ARRAY(LTT_FIELD_TRAP_ID
),
1863 NULL
, NULL
, &hooks
)) {
1865 // th = lttv_trace_hook_get_first(&th);
1867 // t = ltt_field_type(lttv_trace_get_hook_field(th, 0));
1868 // //nb = ltt_type_element_number(t);
1870 // name_tables->trap_names = g_new(GQuark, nb);
1871 // for(i = 0 ; i < nb ; i++) {
1872 // name_tables->trap_names[i] = g_quark_from_string(
1873 // ltt_enum_string_get(t, i));
1876 #endif /* BABEL_CLEANUP */
1877 name_tables
->nb_traps
= PREALLOC_NB_TRAPS
;
1878 name_tables
->trap_names
= g_new(GQuark
, name_tables
->nb_traps
);
1879 for(i
= 0 ; i
< name_tables
->nb_traps
; i
++) {
1880 g_string_printf(fe_name
, "trap %d", i
);
1881 name_tables
->trap_names
[i
] = g_quark_from_string(fe_name
->str
);
1883 #ifdef BABEL_CLEANUP
1885 name_tables
->trap_names
= NULL
;
1886 name_tables
->nb_traps
= 0;
1888 lttv_trace_hook_remove_all(&hooks
);
1889 #endif /* BABEL_CLEANUP */
1891 #ifdef BABEL_CLEANUP
1892 if(!lttv_trace_find_hook(tcs
->parent
.t
,
1894 LTT_EVENT_IRQ_ENTRY
,
1895 FIELD_ARRAY(LTT_FIELD_IRQ_ID
),
1896 NULL
, NULL
, &hooks
)) {
1899 name_tables->irq_names = g_new(GQuark, nb);
1900 for(i = 0 ; i < nb ; i++) {
1901 name_tables->irq_names[i] = g_quark_from_string(ltt_enum_string_get(t, i));
1904 /* FIXME: LttvIRQState *irq_states should become a g_array */
1906 #endif /* BABEL_CLEANUP */
1907 name_tables
->nb_irqs
= PREALLOC_NB_IRQS
;
1908 name_tables
->irq_names
= g_new(GQuark
, name_tables
->nb_irqs
);
1909 for(i
= 0 ; i
< name_tables
->nb_irqs
; i
++) {
1910 g_string_printf(fe_name
, "irq %d", i
);
1911 name_tables
->irq_names
[i
] = g_quark_from_string(fe_name
->str
);
1913 #ifdef BABEL_CLEANUP
1915 name_tables
->nb_irqs
= 0;
1916 name_tables
->irq_names
= NULL
;
1918 lttv_trace_hook_remove_all(&hooks
);
1919 #endif /* BABEL_CLEANUP */
1921 name_tables->soft_irq_names = g_new(GQuark, nb);
1922 for(i = 0 ; i < nb ; i++) {
1923 name_tables->soft_irq_names[i] = g_quark_from_string(ltt_enum_string_get(t, i));
1927 name_tables
->nb_soft_irqs
= PREALLOC_NB_SOFT_IRQS
;
1928 name_tables
->soft_irq_names
= g_new(GQuark
, name_tables
->nb_soft_irqs
);
1929 for(i
= 0 ; i
< name_tables
->nb_soft_irqs
; i
++) {
1930 g_string_printf(fe_name
, "softirq %d", i
);
1931 name_tables
->soft_irq_names
[i
] = g_quark_from_string(fe_name
->str
);
1933 // g_array_free(hooks, TRUE);
1935 g_string_free(fe_name
, TRUE
);
1937 #if (__WORDSIZE == 32)
1938 name_tables
->kprobe_hash
= g_hash_table_new_full(guint64_hash
, guint64_equal
,
1941 name_tables
->kprobe_hash
= g_hash_table_new(g_direct_hash
, g_direct_equal
);
1946 static void get_name_tables(LttvTraceState
*tcs
)
1948 LttvAttributeValue v
;
1950 lttv_attribute_find(lttv_trace_attribute(tcs
->trace
), LTTV_STATE_NAME_TABLES
,
1952 g_assert(*(v
.v_pointer
) != NULL
);
1953 tcs
->name_tables
= (LttvNameTables
*)*(v
.v_pointer
);
1957 static void free_name_tables(LttvTraceState
*tcs
)
1959 LttvNameTables
*name_tables
;
1961 LttvAttributeValue v
;
1963 lttv_attribute_find(lttv_trace_attribute(tcs
->trace
), LTTV_STATE_NAME_TABLES
,
1965 name_tables
= (LttvNameTables
*)*(v
.v_pointer
);
1966 *(v
.v_pointer
) = NULL
;
1968 // g_free(name_tables->eventtype_names);
1969 if(name_tables
->syscall_names
) g_free(name_tables
->syscall_names
);
1970 if(name_tables
->trap_names
) g_free(name_tables
->trap_names
);
1971 if(name_tables
->irq_names
) g_free(name_tables
->irq_names
);
1972 if(name_tables
->soft_irq_names
) g_free(name_tables
->soft_irq_names
);
1973 g_hash_table_destroy(name_tables
->kprobe_hash
);
1974 g_free(name_tables
);
1977 #ifdef HASH_TABLE_DEBUG
1979 static void test_process(gpointer key
, gpointer value
, gpointer user_data
)
1981 LttvProcessState
*process
= (LttvProcessState
*)value
;
1983 /* Test for process corruption */
1984 guint stack_len
= process
->execution_stack
->len
;
1987 static void hash_table_check(GHashTable
*table
)
1989 g_hash_table_foreach(table
, test_process
, NULL
);
1995 /* clears the stack and sets the state passed as argument */
1996 static void cpu_set_base_mode(LttvCPUState
*cpust
, LttvCPUMode state
)
1998 g_array_set_size(cpust
->mode_stack
, 1);
1999 ((GQuark
*)cpust
->mode_stack
->data
)[0] = state
;
2002 static void cpu_push_mode(LttvCPUState
*cpust
, LttvCPUMode state
)
2004 g_array_set_size(cpust
->mode_stack
, cpust
->mode_stack
->len
+ 1);
2005 ((GQuark
*)cpust
->mode_stack
->data
)[cpust
->mode_stack
->len
- 1] = state
;
2008 static void cpu_pop_mode(LttvCPUState
*cpust
)
2010 if(cpust
->mode_stack
->len
<= 1)
2011 cpu_set_base_mode(cpust
, LTTV_CPU_UNKNOWN
);
2013 g_array_set_size(cpust
->mode_stack
, cpust
->mode_stack
->len
- 1);
2016 /* clears the stack and sets the state passed as argument */
2017 static void bdev_set_base_mode(LttvBdevState
*bdevst
, LttvBdevMode state
)
2019 g_array_set_size(bdevst
->mode_stack
, 1);
2020 ((GQuark
*)bdevst
->mode_stack
->data
)[0] = state
;
2023 static void bdev_push_mode(LttvBdevState
*bdevst
, LttvBdevMode state
)
2025 g_array_set_size(bdevst
->mode_stack
, bdevst
->mode_stack
->len
+ 1);
2026 ((GQuark
*)bdevst
->mode_stack
->data
)[bdevst
->mode_stack
->len
- 1] = state
;
2029 static void bdev_pop_mode(LttvBdevState
*bdevst
)
2031 if(bdevst
->mode_stack
->len
<= 1)
2032 bdev_set_base_mode(bdevst
, LTTV_BDEV_UNKNOWN
);
2034 g_array_set_size(bdevst
->mode_stack
, bdevst
->mode_stack
->len
- 1);
2037 static void irq_set_base_mode(LttvIRQState
*irqst
, LttvIRQMode state
)
2039 g_array_set_size(irqst
->mode_stack
, 1);
2040 ((GQuark
*)irqst
->mode_stack
->data
)[0] = state
;
2043 static void irq_push_mode(LttvIRQState
*irqst
, LttvIRQMode state
)
2045 g_array_set_size(irqst
->mode_stack
, irqst
->mode_stack
->len
+ 1);
2046 ((GQuark
*)irqst
->mode_stack
->data
)[irqst
->mode_stack
->len
- 1] = state
;
2049 static void irq_pop_mode(LttvIRQState
*irqst
)
2051 if(irqst
->mode_stack
->len
<= 1)
2052 irq_set_base_mode(irqst
, LTTV_IRQ_UNKNOWN
);
2054 g_array_set_size(irqst
->mode_stack
, irqst
->mode_stack
->len
- 1);
2057 static void push_state(LttvEvent
*event
,
2058 LttvTraceState
*ts
, LttvExecutionMode t
,
2061 LttvExecutionState
*es
;
2064 cpu
= lttv_traceset_get_cpuid_from_event(event
);
2067 #ifdef HASH_TABLE_DEBUG
2068 hash_table_check(ts
->processes
);
2070 LttvProcessState
*process
= ts
->running_process
[cpu
];
2072 guint depth
= process
->execution_stack
->len
;
2074 process
->execution_stack
=
2075 g_array_set_size(process
->execution_stack
, depth
+ 1);
2078 &g_array_index(process
->execution_stack
, LttvExecutionState
, depth
- 1);
2080 es
= &g_array_index(process
->execution_stack
, LttvExecutionState
, depth
);
2083 es
->entry
= es
->change
= lttv_event_get_timestamp(event
);
2084 es
->cum_cpu_time
= ltt_time_zero
;
2085 es
->s
= process
->state
->s
;
2086 process
->state
= es
;
2090 * return 1 when empty, else 0 */
2092 lttv_state_pop_state_cleanup(LttvProcessState
*process
, LttvEvent
*event
)
2094 guint depth
= process
->execution_stack
->len
;
2100 process
->execution_stack
=
2101 g_array_set_size(process
->execution_stack
, depth
- 1);
2102 process
->state
= &g_array_index(process
->execution_stack
, LttvExecutionState
,
2104 process
->state
->change
= lttv_event_get_timestamp(event
);
2109 static void pop_state(LttvEvent
*event
,
2110 LttvTraceState
*ts
, LttvExecutionMode t
)
2112 LttvProcessState
*process
;
2115 cpu
= lttv_traceset_get_cpuid_from_event(event
);
2117 process
= ts
->running_process
[cpu
];
2119 guint depth
= process
->execution_stack
->len
;
2121 if(process
->state
->t
!= t
){
2122 g_info("Different execution mode type: ignore it\n"
2125 g_info("process state has %s when pop_int is %s\n",
2126 g_quark_to_string(process
->state
->t
),
2127 g_quark_to_string(t
));
2128 g_info("{ %u, %u, %s, %s, %s }\n",
2131 g_quark_to_string(process
->name
),
2132 g_quark_to_string(process
->brand
),
2133 g_quark_to_string(process
->state
->s
));
2138 //TODO ybrosseau readd debug
2139 //g_info("Trying to pop last state on stack (%lu.%09lu): ignore it\n",
2140 // tfs->parent.timestamp.tv_sec, tfs->parent.timestamp.tv_nsec);
2141 g_info("Trying to pop last state on stack: ignore it\n");
2145 process
->execution_stack
=
2146 g_array_set_size(process
->execution_stack
, depth
- 1);
2147 process
->state
= &g_array_index(process
->execution_stack
, LttvExecutionState
,
2149 process
->state
->change
= lttv_event_get_timestamp(event
);
2152 struct search_result
{
2153 const LttTime
*time
; /* Requested time */
2154 LttTime
*best
; /* Best result */
2157 /* Return a new and initialized LttvProcessState structure */
2159 LttvProcessState
*lttv_state_create_process(LttvTraceState
*tcs
,
2160 LttvProcessState
*parent
, guint cpu
, guint pid
,
2161 guint tgid
, GQuark name
, const LttTime
*timestamp
)
2163 LttvProcessState
*process
= g_new(LttvProcessState
, 1);
2165 LttvExecutionState
*es
;
2170 process
->tgid
= tgid
;
2172 process
->name
= name
;
2173 process
->brand
= LTTV_STATE_UNBRANDED
;
2174 //process->last_cpu = tfs->cpu_name;
2175 //process->last_cpu_index = ltt_tracefile_num(((LttvTracefileContext*)tfs)->tf);
2176 process
->type
= LTTV_STATE_USER_THREAD
;
2178 g_info("Process %u, core %p", process
->pid
, process
);
2179 g_hash_table_insert(tcs
->processes
, process
, process
);
2182 process
->ppid
= parent
->pid
;
2183 process
->creation_time
= *timestamp
;
2186 /* No parent. This process exists but we are missing all information about
2187 its creation. The birth time is set to zero but we remember the time of
2192 process
->creation_time
= ltt_time_zero
;
2195 process
->insertion_time
= *timestamp
;
2196 sprintf(buffer
,"%d-%lu.%lu",pid
, process
->creation_time
.tv_sec
,
2197 process
->creation_time
.tv_nsec
);
2198 process
->pid_time
= g_quark_from_string(buffer
);
2200 process
->free_events
= 0;
2201 //process->last_cpu = tfs->cpu_name;
2202 //process->last_cpu_index = ltt_tracefile_num(((LttvTracefileContext*)tfs)->tf);
2203 process
->execution_stack
= g_array_sized_new(FALSE
, FALSE
,
2204 sizeof(LttvExecutionState
), PREALLOCATED_EXECUTION_STACK
);
2205 process
->execution_stack
= g_array_set_size(process
->execution_stack
, 2);
2206 es
= process
->state
= &g_array_index(process
->execution_stack
,
2207 LttvExecutionState
, 0);
2208 es
->t
= LTTV_STATE_USER_MODE
;
2209 es
->n
= LTTV_STATE_SUBMODE_NONE
;
2210 es
->entry
= *timestamp
;
2211 //g_assert(timestamp->tv_sec != 0);
2212 es
->change
= *timestamp
;
2213 es
->cum_cpu_time
= ltt_time_zero
;
2214 es
->s
= LTTV_STATE_RUN
;
2216 es
= process
->state
= &g_array_index(process
->execution_stack
,
2217 LttvExecutionState
, 1);
2218 es
->t
= LTTV_STATE_SYSCALL
;
2219 es
->n
= LTTV_STATE_SUBMODE_NONE
;
2220 es
->entry
= *timestamp
;
2221 //g_assert(timestamp->tv_sec != 0);
2222 es
->change
= *timestamp
;
2223 es
->cum_cpu_time
= ltt_time_zero
;
2224 es
->s
= LTTV_STATE_WAIT_FORK
;
2226 /* Allocate an empty function call stack. If it's empty, use 0x0. */
2227 #ifdef BABEL_CLEANUP
2228 //process->user_stack = g_array_sized_new(FALSE, FALSE,
2229 // sizeof(guint64), 0);
2231 process
->fds
= g_hash_table_new(g_direct_hash
, g_direct_equal
);
2237 lttv_state_find_process(LttvTraceState
*ts
, guint cpu
, guint pid
)
2239 LttvProcessState key
;
2240 LttvProcessState
*process
;
2244 process
= g_hash_table_lookup(ts
->processes
, &key
);
2248 LttvProcessState
*lttv_state_find_process_or_create(LttvTraceState
*ts
,
2249 guint cpu
, guint pid
, const LttTime
*timestamp
)
2251 LttvProcessState
*process
= lttv_state_find_process(ts
, cpu
, pid
);
2252 LttvExecutionState
*es
;
2254 /* Put ltt_time_zero creation time for unexisting processes */
2255 if(unlikely(process
== NULL
)) {
2256 process
= lttv_state_create_process(ts
,
2257 NULL
, cpu
, pid
, 0, LTTV_STATE_UNNAMED
, timestamp
);
2258 /* We are not sure is it's a kernel thread or normal thread, put the
2259 * bottom stack state to unknown */
2260 process
->execution_stack
=
2261 g_array_set_size(process
->execution_stack
, 1);
2262 process
->state
= es
=
2263 &g_array_index(process
->execution_stack
, LttvExecutionState
, 0);
2264 es
->t
= LTTV_STATE_MODE_UNKNOWN
;
2265 es
->s
= LTTV_STATE_UNNAMED
;
2270 /* FIXME : this function should be called when we receive an event telling that
2271 * release_task has been called in the kernel. In happens generally when
2272 * the parent waits for its child termination, but may also happens in special
2273 * cases in the child's exit : when the parent ignores its children SIGCCHLD or
2274 * has the flag SA_NOCLDWAIT. It can also happen when the child is part
2275 * of a killed thread group, but isn't the leader.
2277 static int exit_process(LttvEvent
*event
, LttvProcessState
*process
)
2279 LttvTraceState
*ts
= event
->state
;
2280 LttvProcessState key
;
2282 /* Wait for both schedule with exit dead and process free to happen.
2283 * They can happen in any order. */
2284 if (++(process
->free_events
) < 2)
2287 key
.pid
= process
->pid
;
2288 key
.cpu
= process
->cpu
;
2289 g_hash_table_remove(ts
->processes
, &key
);
2290 g_array_free(process
->execution_stack
, TRUE
);
2292 /* the following also clears the content */
2293 g_hash_table_destroy(process
->fds
);
2300 static void free_process_state(gpointer key
, gpointer value
,gpointer user_data
)
2302 g_array_free(((LttvProcessState
*)value
)->execution_stack
, TRUE
);
2304 /* the following also clears the content */
2305 g_hash_table_destroy(((LttvProcessState
*)value
)->fds
);
2311 static void lttv_state_free_process_table(GHashTable
*processes
)
2313 g_hash_table_foreach(processes
, free_process_state
, NULL
);
2314 g_hash_table_destroy(processes
);
2318 static gboolean
syscall_entry(void *hook_data
, void *call_data
)
2323 LttvProcessState
*process
;
2324 LttvExecutionSubmode submode
;
2325 char syscall_name
[200];
2327 event
= (LttvEvent
*) call_data
;
2328 if (strncmp(lttv_traceset_get_name_from_event(event
),
2329 "sys_", sizeof("sys_") - 1) != 0)
2332 strncpy(syscall_name
,lttv_traceset_get_name_from_event(event
)+4,200);
2334 cpu
= lttv_traceset_get_cpuid_from_event(event
);
2336 process
= ts
->running_process
[cpu
];
2338 submode
= g_quark_from_string(syscall_name
);
2339 /* There can be no system call from PID 0 : unknown state */
2340 if(process
->pid
!= 0)
2341 push_state(event
, ts
, LTTV_STATE_SYSCALL
, submode
);
2346 static gboolean
syscall_exit(void *hook_data
, void *call_data
)
2351 LttvProcessState
*process
;
2354 event
= (LttvEvent
*) call_data
;
2355 if (strcmp(lttv_traceset_get_name_from_event(event
),
2356 "exit_syscall") != 0)
2359 cpu
= lttv_traceset_get_cpuid_from_event(event
);
2361 process
= ts
->running_process
[cpu
];
2363 /* There can be no system call from PID 0 : unknown state */
2364 if (process
->pid
!= 0)
2365 pop_state(event
, ts
, LTTV_STATE_SYSCALL
);
2369 #ifdef BABEL_CLEANUP
2370 static gboolean
trap_entry(void *hook_data
, void *call_data
)
2372 LttvTracefileState
*s
= (LttvTracefileState
*)call_data
;
2373 LttvTraceState
*ts
= (LttvTraceState
*)s
->parent
.t_context
;
2374 LttEvent
*e
= ltt_tracefile_get_event(s
->parent
.tf
);
2375 LttvTraceHook
*th
= (LttvTraceHook
*)hook_data
;
2376 struct marker_field
*f
= lttv_trace_get_hook_field(th
, 0);
2377 LttvNameTables
*nt
= ((LttvTraceState
*)(s
->parent
.t_context
))->name_tables
;
2379 LttvExecutionSubmode submode
;
2381 guint64 trap
= ltt_event_get_long_unsigned(e
, f
);
2383 expand_trap_table(ts
, trap
);
2385 submode
= nt
->trap_names
[trap
];
2387 push_state(s
, LTTV_STATE_TRAP
, submode
);
2389 /* update cpu status */
2390 cpu_push_mode(s
->cpu_state
, LTTV_CPU_TRAP
);
2392 /* update trap status */
2393 g_array_append_val(s
->cpu_state
->trap_stack
, trap
);
2394 ts
->trap_states
[trap
].running
++;
2399 static gboolean
trap_exit(void *hook_data
, void *call_data
)
2401 LttvTracefileState
*s
= (LttvTracefileState
*)call_data
;
2402 LttvTraceState
*ts
= (LttvTraceState
*)s
->parent
.t_context
;
2404 pop_state(s
, LTTV_STATE_TRAP
);
2406 /* update cpu status */
2407 cpu_pop_mode(s
->cpu_state
);
2409 /* update trap status */
2410 if (s
->cpu_state
->trap_stack
->len
> 0) {
2411 gint last
= g_array_index(s
->cpu_state
->trap_stack
, gint
,
2412 s
->cpu_state
->trap_stack
->len
-1);
2413 if(ts
->trap_states
[last
].running
)
2414 ts
->trap_states
[last
].running
--;
2415 g_array_remove_index(s
->cpu_state
->trap_stack
,
2416 s
->cpu_state
->trap_stack
->len
-1);
2420 #endif /* BABEL_CLEANUP */
2422 static gboolean
irq_entry(void *hook_data
, void *call_data
)
2428 LttvExecutionSubmode submode
;
2432 event
= (LttvEvent
*) call_data
;
2433 if (strcmp(lttv_traceset_get_name_from_event(event
),
2434 "irq_handler_entry") != 0)
2437 cpu
= lttv_traceset_get_cpuid_from_event(event
);
2440 nt
= ts
->name_tables
;
2441 irq
= lttv_event_get_long_unsigned(event
, "irq");
2443 expand_irq_table(ts
, irq
);
2445 submode
= nt
->irq_names
[irq
];
2447 /* Do something with the info about being in user or system mode when int? */
2448 push_state(event
, ts
, LTTV_STATE_IRQ
, submode
);
2450 /* update cpu status */
2451 cpu_push_mode(&(ts
->cpu_states
[cpu
]), LTTV_CPU_IRQ
);
2453 /* update irq status */
2454 g_array_append_val(ts
->cpu_states
[cpu
].irq_stack
, irq
);
2455 irq_push_mode(&ts
->irq_states
[irq
], LTTV_IRQ_BUSY
);
2460 static gboolean
soft_irq_exit(void *hook_data
, void *call_data
)
2466 LttvCPUState
*cpu_state
;
2468 event
= (LttvEvent
*) call_data
;
2469 if (strcmp(lttv_traceset_get_name_from_event(event
),
2470 "softirq_exit") != 0)
2473 cpu
= lttv_traceset_get_cpuid_from_event(event
);
2476 cpu_state
= &(ts
->cpu_states
[cpu
]);
2477 pop_state(event
, ts
, LTTV_STATE_SOFT_IRQ
);
2479 /* update cpu status */
2480 cpu_pop_mode(cpu_state
);
2482 /* update softirq status */
2483 if (cpu_state
->softirq_stack
->len
> 0) {
2484 gint last
= g_array_index(cpu_state
->softirq_stack
, gint
, cpu_state
->softirq_stack
->len
-1);
2485 if(ts
->soft_irq_states
[last
].running
)
2486 ts
->soft_irq_states
[last
].running
--;
2487 g_array_remove_index(cpu_state
->softirq_stack
, cpu_state
->softirq_stack
->len
-1);
2492 static gboolean
irq_exit(void *hook_data
, void *call_data
)
2498 LttvCPUState
*cpu_state
;
2500 event
= (LttvEvent
*) call_data
;
2501 if (strcmp(lttv_traceset_get_name_from_event(event
),
2502 "irq_handler_exit") != 0)
2505 cpu
= lttv_traceset_get_cpuid_from_event(event
);
2507 cpu_state
= &(ts
->cpu_states
[cpu
]);
2509 pop_state(event
, ts
, LTTV_STATE_IRQ
);
2511 /* update cpu status */
2512 cpu_pop_mode(cpu_state
);
2514 /* update irq status */
2515 if (cpu_state
->irq_stack
->len
> 0) {
2516 gint last
= g_array_index(cpu_state
->irq_stack
, gint
, cpu_state
->irq_stack
->len
-1);
2517 g_array_remove_index(cpu_state
->irq_stack
, cpu_state
->irq_stack
->len
-1);
2518 irq_pop_mode(&ts
->irq_states
[last
]);
2524 static gboolean
soft_irq_raise(void *hook_data
, void *call_data
)
2532 event
= (LttvEvent
*) call_data
;
2533 if (strcmp(lttv_traceset_get_name_from_event(event
),
2534 "softirq_raise") != 0)
2537 //cpu = lttv_traceset_get_cpuid_from_event(event);
2539 softirq
= lttv_event_get_long_unsigned(event
, "vec");
2541 expand_soft_irq_table(ts
, softirq
);
2543 /* update softirq status */
2544 /* a soft irq raises are not cumulative */
2545 ts
->soft_irq_states
[softirq
].pending
=1;
2550 static gboolean
soft_irq_entry(void *hook_data
, void *call_data
)
2555 LttvExecutionSubmode submode
;
2559 event
= (LttvEvent
*) call_data
;
2560 if (strcmp(lttv_traceset_get_name_from_event(event
),
2561 "softirq_exit") != 0)
2564 cpu
= lttv_traceset_get_cpuid_from_event(event
);
2570 softirq
= lttv_event_get_long_unsigned(event
, "vec");
2571 expand_soft_irq_table(ts
, softirq
);
2572 nt
= ts
->name_tables
;
2573 submode
= nt
->soft_irq_names
[softirq
];
2575 /* Do something with the info about being in user or system mode when int? */
2576 push_state(event
, ts
, LTTV_STATE_SOFT_IRQ
, submode
);
2578 /* update cpu status */
2579 cpu_push_mode(&(ts
->cpu_states
[cpu
]), LTTV_CPU_SOFT_IRQ
);
2581 /* update softirq status */
2582 g_array_append_val(ts
->cpu_states
[cpu
].softirq_stack
, softirq
);
2583 if (ts
->soft_irq_states
[softirq
].pending
)
2584 ts
->soft_irq_states
[softirq
].pending
--;
2585 ts
->soft_irq_states
[softirq
].running
++;
2590 static gboolean
enum_interrupt(void *hook_data
, void *call_data
)
2600 event
= (LttvEvent
*) call_data
;
2601 if (strcmp(lttv_traceset_get_name_from_event(event
),
2602 "lttng_statedump_interrupt") != 0)
2606 nt
= ts
->name_tables
;
2607 irq
= lttv_event_get_long_unsigned(event
, "irq");
2608 action
= g_quark_from_string(lttv_event_get_string(event
,
2610 expand_irq_table(ts
, irq
);
2611 nt
->irq_names
[irq
] = action
;
2616 #ifdef BABEL_CLEANUP
2617 static gboolean
bdev_request_issue(void *hook_data
, void *call_data
)
2628 event
= (LttvEvent
*) call_data
;
2629 if (strcmp(lttv_traceset_get_name_from_event(event
),
2630 "block_rq_issue") != 0)
2634 major
= lttv_event_get_long_unsigned(event
,);
2636 minor
= lttv_event_get_long_unsigned(event
,);
2638 oper
= lttv_event_get_long_unsigned(event
,);
2640 devcode
= MKDEV(major
,minor
);
2642 /* have we seen this block device before? */
2643 bdev
= get_hashed_bdevstate(ts
, devcode
);
2645 bdev_push_mode(bdev
, LTTV_BDEV_BUSY_READING
);
2647 bdev_push_mode(bdev
, LTTV_BDEV_BUSY_WRITING
);
2652 static gboolean
bdev_request_complete(void *hook_data
, void *call_data
)
2654 LttvTracefileState
*s
= (LttvTracefileState
*)call_data
;
2655 LttvTraceState
*ts
= (LttvTraceState
*)s
->parent
.t_context
;
2656 LttEvent
*e
= ltt_tracefile_get_event(s
->parent
.tf
);
2657 LttvTraceHook
*th
= (LttvTraceHook
*)hook_data
;
2659 guint major
= ltt_event_get_long_unsigned(e
,
2660 lttv_trace_get_hook_field(th
, 0));
2661 guint minor
= ltt_event_get_long_unsigned(e
,
2662 lttv_trace_get_hook_field(th
, 1));
2663 //guint oper = ltt_event_get_long_unsigned(e,
2664 // lttv_trace_get_hook_field(th, 2));
2665 guint32 devcode
= MKDEV(major
,minor
);
2667 /* have we seen this block device before? */
2668 gpointer bdev
= get_hashed_bdevstate(ts
, devcode
);
2670 /* update block device */
2671 bdev_pop_mode(bdev
);
2676 #ifdef BABEL_CLEANUP
2677 // We dont have the syscall table in LTTng 2.0
2678 static gboolean
dump_syscall(void *hook_data
, void *call_data
)
2680 LttvTracefileState
*s
= (LttvTracefileState
*)call_data
;
2681 LttvTraceState
*ts
= (LttvTraceState
*)s
->parent
.t_context
;
2682 LttvNameTables
*nt
= ts
->name_tables
;
2683 LttEvent
*e
= ltt_tracefile_get_event(s
->parent
.tf
);
2684 LttvTraceHook
*th
= (LttvTraceHook
*)hook_data
;
2688 id
= ltt_event_get_unsigned(e
, lttv_trace_get_hook_field(th
, 0));
2689 symbol
= ltt_event_get_string(e
, lttv_trace_get_hook_field(th
, 2));
2691 expand_syscall_table(ts
, id
);
2692 nt
->syscall_names
[id
] = g_quark_from_string(symbol
);
2697 static gboolean
dump_kprobe(void *hook_data
, void *call_data
)
2699 LttvTracefileState
*s
= (LttvTracefileState
*)call_data
;
2700 LttvTraceState
*ts
= (LttvTraceState
*)s
->parent
.t_context
;
2701 LttEvent
*e
= ltt_tracefile_get_event(s
->parent
.tf
);
2702 LttvTraceHook
*th
= (LttvTraceHook
*)hook_data
;
2706 ip
= ltt_event_get_long_unsigned(e
, lttv_trace_get_hook_field(th
, 0));
2707 symbol
= ltt_event_get_string(e
, lttv_trace_get_hook_field(th
, 1));
2709 expand_kprobe_table(ts
, ip
, symbol
);
2714 #ifdef BABEL_CLEANUP
2715 static gboolean
dump_softirq(void *hook_data
, void *call_data
)
2718 LttvTracefileState
*s
= (LttvTracefileState
*)call_data
;
2719 LttvTraceState
*ts
= (LttvTraceState
*)s
->parent
.t_context
;
2720 LttvNameTables
*nt
= ts
->name_tables
;
2721 LttEvent
*e
= ltt_tracefile_get_event(s
->parent
.tf
);
2722 LttvTraceHook
*th
= (LttvTraceHook
*)hook_data
;
2726 id
= ltt_event_get_unsigned(e
, lttv_trace_get_hook_field(th
, 0));
2727 symbol
= ltt_event_get_string(e
, lttv_trace_get_hook_field(th
, 2));
2729 expand_soft_irq_table(ts
, id
);
2730 nt
->soft_irq_names
[id
] = g_quark_from_string(symbol
);
2736 static gboolean
sched_try_wakeup(void *hook_data
, void *call_data
)
2740 LttvProcessState
*process
;
2745 event
= (LttvEvent
*) call_data
;
2746 if (strcmp(lttv_traceset_get_name_from_event(event
),
2747 "sched_wakeup") != 0)
2752 woken_pid
= lttv_event_get_long(event
, "tid");
2753 woken_cpu
= lttv_event_get_long_unsigned(event
, "target_cpu");
2755 timestamp
= lttv_event_get_timestamp(event
);
2756 process
= lttv_state_find_process_or_create(
2758 woken_cpu
, woken_pid
,
2761 if (process
->state
->s
== LTTV_STATE_WAIT
|| process
->state
->s
== LTTV_STATE_WAIT_FORK
)
2763 process
->state
->s
= LTTV_STATE_WAIT_CPU
;
2764 process
->state
->change
= timestamp
;
2767 g_debug("Wakeup: process %d on CPU %u\n", woken_pid
, woken_cpu
);
2772 static gboolean
schedchange(void *hook_data
, void *call_data
)
2777 LttvProcessState
*process
;
2780 //LttvProcessState *old_process = ts->running_process[cpu];
2782 guint pid_in
, pid_out
;
2785 event
= (LttvEvent
*) call_data
;
2786 if (strcmp(lttv_traceset_get_name_from_event(event
),
2787 "sched_switch") != 0)
2790 cpu
= lttv_traceset_get_cpuid_from_event(event
);
2792 process
= ts
->running_process
[cpu
];
2793 pid_out
= lttv_event_get_long_unsigned(event
, "prev_tid");
2794 pid_in
= lttv_event_get_long_unsigned(event
, "next_tid");
2795 state_out
= lttv_event_get_long(event
, "prev_state");
2797 timestamp
= lttv_event_get_timestamp(event
);
2799 if(likely(process
!= NULL
)) {
2801 /* We could not know but it was not the idle process executing.
2802 This should only happen at the beginning, before the first schedule
2803 event, and when the initial information (current process for each CPU)
2804 is missing. It is not obvious how we could, after the fact, compensate
2805 the wrongly attributed statistics. */
2807 //This test only makes sense once the state is known and if there is no
2808 //missing events. We need to silently ignore schedchange coming after a
2809 //process_free, or it causes glitches. (FIXME)
2810 //if(unlikely(process->pid != pid_out)) {
2811 // g_assert(process->pid == 0);
2813 if(process
->pid
== 0
2814 && process
->state
->t
== LTTV_STATE_MODE_UNKNOWN
) {
2817 * Scheduling out of pid 0 at beginning of the trace.
2818 * We are typically in system call mode at this point although
2819 * (FIXME) we might be in a trap handler.
2821 g_assert(process
->execution_stack
->len
== 1);
2822 process
->state
->t
= LTTV_STATE_SYSCALL
;
2823 process
->state
->s
= LTTV_STATE_WAIT
;
2824 process
->state
->change
= timestamp
;
2825 process
->state
->entry
= timestamp
;
2828 if(unlikely(process
->state
->s
== LTTV_STATE_EXIT
)) {
2829 process
->state
->s
= LTTV_STATE_ZOMBIE
;
2830 process
->state
->change
= timestamp
;
2832 if(unlikely(state_out
== 0)) process
->state
->s
= LTTV_STATE_WAIT_CPU
;
2833 else process
->state
->s
= LTTV_STATE_WAIT
;
2834 process
->state
->change
= timestamp
;
2837 if(state_out
== 32 || state_out
== 64) { /* EXIT_DEAD || TASK_DEAD */
2838 /* see sched.h for states */
2839 if (!exit_process(event
, process
)) {
2840 process
->state
->s
= LTTV_STATE_DEAD
;
2841 process
->state
->change
= timestamp
;
2846 process
= ts
->running_process
[cpu
] = lttv_state_find_process_or_create(
2850 process
->state
->s
= LTTV_STATE_RUN
;
2852 // process->last_cpu_index = ltt_tracefile_num(((LttvTracefileContext*)s)->tf);
2853 process
->state
->change
= timestamp
;
2855 /* update cpu status */
2857 /* going to idle task */
2858 cpu_set_base_mode(&(ts
->cpu_states
[cpu
]), LTTV_CPU_IDLE
);
2860 /* scheduling a real task.
2861 * we must be careful here:
2862 * if we just schedule()'ed to a process that is
2863 * in a trap, we must put the cpu in trap mode
2865 cpu_set_base_mode(&(ts
->cpu_states
[cpu
]), LTTV_CPU_BUSY
);
2866 if(process
->state
->t
== LTTV_STATE_TRAP
)
2867 cpu_push_mode(&(ts
->cpu_states
[cpu
]), LTTV_CPU_TRAP
);
2873 static gboolean
process_fork(void *hook_data
, void *call_data
)
2877 LttvProcessState
*process
;
2878 LttvProcessState
*child_process
;
2879 guint child_pid
; /* In the Linux Kernel, there is one PID per thread. */
2880 guint child_tgid
; /* tgid in the Linux kernel is the "real" POSIX PID. */
2881 //LttvProcessState *zombie_process;
2885 event
= (LttvEvent
*) call_data
;
2886 if (strcmp(lttv_traceset_get_name_from_event(event
),
2887 "sched_process_fork") != 0)
2889 cpu
= lttv_traceset_get_cpuid_from_event(event
);
2891 process
= ts
->running_process
[cpu
];
2892 timestamp
= lttv_event_get_timestamp(event
);
2894 /* Skip Parent PID param */
2897 child_pid
= lttv_event_get_long_unsigned(event
, "child_tid");
2898 //ts->target_pid = child_pid;
2904 /* Mathieu : it seems like the process might have been scheduled in before the
2905 * fork, and, in a rare case, might be the current process. This might happen
2906 * in a SMP case where we don't have enough precision on the clocks.
2908 * Test reenabled after precision fixes on time. (Mathieu) */
2910 zombie_process
= lttv_state_find_process(ts
, ANY_CPU
, child_pid
);
2912 if(unlikely(zombie_process
!= NULL
)) {
2913 /* Reutilisation of PID. Only now we are sure that the old PID
2914 * has been released. FIXME : should know when release_task happens instead.
2916 guint num_cpus
= ltt_trace_get_num_cpu(ts
->parent
.t
);
2918 for(i
=0; i
< num_cpus
; i
++) {
2919 g_assert(zombie_process
!= ts
->running_process
[i
]);
2922 exit_process(s
, zombie_process
);
2925 g_assert(process
->pid
!= child_pid
);
2926 // FIXME : Add this test in the "known state" section
2927 // g_assert(process->pid == parent_pid);
2928 child_process
= lttv_state_find_process(ts
, ANY_CPU
, child_pid
);
2929 if(child_process
== NULL
) {
2930 child_process
= lttv_state_create_process(ts
, process
, cpu
,
2931 child_pid
, child_tgid
,
2932 LTTV_STATE_UNNAMED
, ×tamp
);
2934 /* The process has already been created : due to time imprecision between
2935 * multiple CPUs : it has been scheduled in before creation. Note that we
2936 * shouldn't have this kind of imprecision.
2938 * Simply put a correct parent.
2940 g_error("Process %u has been created at [%lu.%09lu] "
2941 "and inserted at [%lu.%09lu] before \n"
2942 "fork on cpu %u[%lu.%09lu].\n"
2943 "Probably an unsynchronized TSC problem on the traced machine.",
2945 child_process
->creation_time
.tv_sec
,
2946 child_process
->creation_time
.tv_nsec
,
2947 child_process
->insertion_time
.tv_sec
,
2948 child_process
->insertion_time
.tv_nsec
,
2949 cpu
, timestamp
.tv_sec
, timestamp
.tv_nsec
);
2950 //g_assert(0); /* This is a problematic case : the process has been created
2951 // before the fork event */
2952 child_process
->ppid
= process
->pid
;
2953 child_process
->tgid
= child_tgid
;
2955 g_assert(child_process
->name
== LTTV_STATE_UNNAMED
);
2956 child_process
->name
= process
->name
;
2957 child_process
->brand
= process
->brand
;
2962 #ifdef BABEL_CLEANUP
2963 //NO KTHREAD_CREATE in LTTng 2.0
2964 /* We stamp a newly created process as kernel_thread.
2965 * The thread should not be running yet. */
2966 static gboolean
process_kernel_thread(void *hook_data
, void *call_data
)
2968 LttvTracefileState
*s
= (LttvTracefileState
*)call_data
;
2969 LttEvent
*e
= ltt_tracefile_get_event(s
->parent
.tf
);
2970 LttvTraceHook
*th
= (LttvTraceHook
*)hook_data
;
2972 LttvTraceState
*ts
= (LttvTraceState
*)s
->parent
.t_context
;
2973 LttvProcessState
*process
;
2974 LttvExecutionState
*es
;
2977 pid
= (guint
)ltt_event_get_long_unsigned(e
, lttv_trace_get_hook_field(th
, 0));
2978 //s->parent.target_pid = pid;
2980 process
= lttv_state_find_process_or_create(ts
, ANY_CPU
, pid
,
2982 if (process
->state
->s
!= LTTV_STATE_DEAD
) {
2983 process
->execution_stack
=
2984 g_array_set_size(process
->execution_stack
, 1);
2985 es
= process
->state
=
2986 &g_array_index(process
->execution_stack
, LttvExecutionState
, 0);
2987 es
->t
= LTTV_STATE_SYSCALL
;
2989 process
->type
= LTTV_STATE_KERNEL_THREAD
;
2994 static gboolean
process_exit(void *hook_data
, void *call_data
)
3000 LttvProcessState
*process
; // = ts->running_process[cpu];
3002 event
= (LttvEvent
*) call_data
;
3003 if (strcmp(lttv_traceset_get_name_from_event(event
),
3004 "sched_process_exit") != 0)
3006 cpu
= lttv_traceset_get_cpuid_from_event(event
);
3008 process
= ts
->running_process
[cpu
];
3010 pid
= lttv_event_get_long_unsigned(event
, "tid");
3011 //s->parent.target_pid = pid;
3013 // FIXME : Add this test in the "known state" section
3014 // g_assert(process->pid == pid);
3016 process
= lttv_state_find_process(ts
, ANY_CPU
, pid
);
3017 if(likely(process
!= NULL
)) {
3018 process
->state
->s
= LTTV_STATE_EXIT
;
3023 static gboolean
process_free(void *hook_data
, void *call_data
)
3029 LttvProcessState
*process
;
3031 event
= (LttvEvent
*) call_data
;
3032 if (strcmp(lttv_traceset_get_name_from_event(event
),
3033 "sched_process_free") != 0)
3035 cpu
= lttv_traceset_get_cpuid_from_event(event
);
3037 process
= ts
->running_process
[cpu
];
3039 /* PID of the process to release */
3040 release_pid
= lttv_event_get_long_unsigned(event
, "_tid");
3041 //s->parent.target_pid = release_pid;
3043 g_assert(release_pid
!= 0);
3045 process
= lttv_state_find_process(ts
, ANY_CPU
, release_pid
);
3046 if(likely(process
!= NULL
))
3047 exit_process(event
, process
);
3051 if(likely(process
!= NULL
)) {
3052 /* release_task is happening at kernel level : we can now safely release
3053 * the data structure of the process */
3054 //This test is fun, though, as it may happen that
3055 //at time t : CPU 0 : process_free
3056 //at time t+150ns : CPU 1 : schedule out
3057 //Clearly due to time imprecision, we disable it. (Mathieu)
3058 //If this weird case happen, we have no choice but to put the
3059 //Currently running process on the cpu to 0.
3060 //I re-enable it following time precision fixes. (Mathieu)
3061 //Well, in the case where an process is freed by a process on another CPU
3062 //and still scheduled, it happens that this is the schedchange that will
3063 //drop the last reference count. Do not free it here!
3064 guint num_cpus
= ltt_trace_get_num_cpu(ts
->parent
.t
);
3066 for(i
=0; i
< num_cpus
; i
++) {
3067 //g_assert(process != ts->running_process[i]);
3068 if(process
== ts
->running_process
[i
]) {
3069 //ts->running_process[i] = lttv_state_find_process(ts, i, 0);
3073 if(i
== num_cpus
) /* process is not scheduled */
3074 exit_process(s
, process
);
3082 static gboolean
process_exec(void *hook_data
, void *call_data
)
3088 LttvProcessState
*process
;
3090 event
= (LttvEvent
*) call_data
;
3091 if (strcmp(lttv_traceset_get_name_from_event(event
),
3094 cpu
= lttv_traceset_get_cpuid_from_event(event
);
3096 process
= ts
->running_process
[cpu
];
3098 #if 0//how to use a sequence that must be transformed in a string
3099 /* PID of the process to release */
3100 guint64 name_len
= ltt_event_field_element_number(e
,
3101 lttv_trace_get_hook_field(th
, 0));
3102 //name = ltt_event_get_string(e, lttv_trace_get_hook_field(th, 0));
3103 LttField
*child
= ltt_event_field_element_select(e
,
3104 lttv_trace_get_hook_field(th
, 0), 0);
3106 (gchar
*)(ltt_event_data(e
)+ltt_event_field_offset(e
, child
));
3107 gchar
*null_term_name
= g_new(gchar
, name_len
+1);
3108 memcpy(null_term_name
, name_begin
, name_len
);
3109 null_term_name
[name_len
] = '\0';
3110 process
->name
= g_quark_from_string(null_term_name
);
3113 process
->name
= g_quark_from_string(lttv_event_get_string(event
,
3115 process
->brand
= LTTV_STATE_UNBRANDED
;
3116 //g_free(null_term_name);
3119 #ifdef BABEL_CLEANUP
3120 static gboolean
thread_brand(void *hook_data
, void *call_data
)
3122 LttvTracefileState
*s
= (LttvTracefileState
*)call_data
;
3123 LttvTraceState
*ts
= (LttvTraceState
*)s
->parent
.t_context
;
3124 LttEvent
*e
= ltt_tracefile_get_event(s
->parent
.tf
);
3125 LttvTraceHook
*th
= (LttvTraceHook
*)hook_data
;
3128 LttvProcessState
*process
= ts
->running_process
[cpu
];
3130 name
= ltt_event_get_string(e
, lttv_trace_get_hook_field(th
, 0));
3131 process
->brand
= g_quark_from_string(name
);
3137 // TODO We only have sys_open, without the FD
3138 // manage to do somehting better
3139 static gboolean
fs_open(void *hook_data
, void *call_data
)
3141 LttvTracefileState
*s
= (LttvTracefileState
*)call_data
;
3142 LttvTraceState
*ts
= (LttvTraceState
*)s
->parent
.t_context
;
3143 LttEvent
*e
= ltt_tracefile_get_event(s
->parent
.tf
);
3144 LttvTraceHook
*th
= (LttvTraceHook
*)hook_data
;
3145 struct marker_field
*f
;
3149 LttvProcessState
*process
= ts
->running_process
[cpu
];
3151 f
= lttv_trace_get_hook_field(th
, 0);
3152 fd
= ltt_event_get_int(e
, f
);
3154 f
= lttv_trace_get_hook_field(th
, 1);
3155 filename
= ltt_event_get_string(e
, f
);
3157 g_hash_table_insert(process
->fds
, (gpointer
)(long)fd
,
3158 (gpointer
)(unsigned long)g_quark_from_string(filename
));
3163 static void print_stack(LttvProcessState
*process
)
3165 LttvExecutionState
*es
;
3168 g_debug("Execution stack for process %u %s:\n",
3169 process
->pid
, g_quark_to_string(process
->name
));
3171 for (i
= 0; i
< process
->execution_stack
->len
; i
++) {
3172 es
= &g_array_index(process
->execution_stack
,
3173 LttvExecutionState
, i
);
3174 g_debug("Depth %d mode %s submode %s status %s\n",
3175 i
, g_quark_to_string(es
->t
),
3176 g_quark_to_string(es
->n
),
3177 g_quark_to_string(es
->s
));
3182 static void fix_process(gpointer key
, gpointer value
, gpointer user_data
)
3184 LttvProcessState
*process
;
3185 LttvExecutionState
*es
;
3186 process
= (LttvProcessState
*)value
;
3187 LttTime
*timestamp
= (LttTime
*)user_data
;
3189 print_stack(process
);
3191 if(process
->type
== LTTV_STATE_KERNEL_THREAD
) {
3192 es
= &g_array_index(process
->execution_stack
, LttvExecutionState
, 0);
3193 if(es
->t
== LTTV_STATE_MAYBE_SYSCALL
) {
3194 es
->t
= LTTV_STATE_SYSCALL
;
3195 es
->n
= LTTV_STATE_SUBMODE_NONE
;
3196 es
->entry
= *timestamp
;
3197 es
->change
= *timestamp
;
3198 es
->cum_cpu_time
= ltt_time_zero
;
3199 if(es
->s
== LTTV_STATE_UNNAMED
)
3200 es
->s
= LTTV_STATE_WAIT
;
3203 es
= &g_array_index(process
->execution_stack
, LttvExecutionState
, 0);
3204 if(es
->t
== LTTV_STATE_MAYBE_USER_MODE
) {
3205 es
->t
= LTTV_STATE_USER_MODE
;
3206 es
->n
= LTTV_STATE_SUBMODE_NONE
;
3207 es
->entry
= *timestamp
;
3208 //g_assert(timestamp->tv_sec != 0);
3209 es
->change
= *timestamp
;
3210 es
->cum_cpu_time
= ltt_time_zero
;
3211 if(es
->s
== LTTV_STATE_UNNAMED
)
3212 es
->s
= LTTV_STATE_RUN
;
3214 if(process
->execution_stack
->len
== 1) {
3215 /* Still in bottom unknown mode, means we either:
3216 * - never did a system call
3217 * - are scheduled out from user mode.
3218 * May be either in user mode, syscall mode, running or waiting.*/
3219 /* CHECK : we may be tagging syscall mode when being user mode
3220 * (should be fixed now) */
3221 if (es
->s
== LTTV_STATE_WAIT_CPU
) {
3222 /* nothing to do: scheduled out from userspace */
3224 process
->execution_stack
=
3225 g_array_set_size(process
->execution_stack
, 2);
3226 es
= process
->state
= &g_array_index(process
->execution_stack
,
3227 LttvExecutionState
, 1);
3228 es
->t
= LTTV_STATE_SYSCALL
;
3229 es
->n
= LTTV_STATE_SUBMODE_NONE
;
3230 es
->entry
= *timestamp
;
3231 //g_assert(timestamp->tv_sec != 0);
3232 es
->change
= *timestamp
;
3233 es
->cum_cpu_time
= ltt_time_zero
;
3234 if(es
->s
== LTTV_STATE_WAIT_FORK
)
3235 es
->s
= LTTV_STATE_WAIT
;
3242 static gboolean
statedump_end(void *hook_data
, void *call_data
)
3247 //LttEvent *e = ltt_tracefile_get_event(s->parent.tf);
3248 //LttvTraceHook *th = (LttvTraceHook *)hook_data;
3249 event
= (LttvEvent
*) call_data
;
3250 if (strcmp(lttv_traceset_get_name_from_event(event
),
3251 "lttng_statedump_end") != 0)
3255 timestamp
= lttv_event_get_timestamp(event
);
3257 /* For all processes */
3258 /* if kernel thread, if stack[0] is unknown, set to syscall mode, wait */
3259 /* else, if stack[0] is unknown, set to user mode, running */
3261 g_hash_table_foreach(ts
->processes
, fix_process
, ×tamp
);
3266 static gboolean
enum_process_state(void *hook_data
, void *call_data
)
3276 LttvProcessState
*parent_process
;
3277 LttvProcessState
*process
;
3280 LttvExecutionState
*es
;
3283 event
= (LttvEvent
*) call_data
;
3284 if (strcmp(lttv_traceset_get_name_from_event(event
),
3285 "lttng_statedump_process_state") != 0)
3287 cpu
= lttv_traceset_get_cpuid_from_event(event
);
3289 process
= ts
->running_process
[cpu
];
3290 timestamp
= lttv_event_get_timestamp(event
);
3293 pid
= lttv_event_get_long_unsigned(event
, "tid");
3294 //s->parent.target_pid = pid;
3297 parent_pid
= lttv_event_get_long_unsigned(event
, "ppid");
3300 command
= lttv_event_get_string(event
, "name");
3304 type
= lttv_event_get_long_unsigned(event
, "type");
3306 //FIXME: type is rarely used, enum must match possible types.
3308 /* Skip mode 4th param */
3310 /* Skip submode 5th param */
3312 /* Skip status 6th param */
3315 tgid
= lttv_event_get_long_unsigned(event
, "pid");
3318 nb_cpus
= lttv_trace_get_num_cpu(ts
->trace
);
3319 for(i
=0; i
<nb_cpus
; i
++) {
3320 process
= lttv_state_find_process(ts
, i
, pid
);
3321 g_assert(process
!= NULL
);
3323 process
->ppid
= parent_pid
;
3324 process
->tgid
= tgid
;
3325 process
->name
= g_quark_from_string(command
);
3326 es
= &g_array_index(process
->execution_stack
, LttvExecutionState
, 0);
3327 process
->type
= LTTV_STATE_KERNEL_THREAD
;
3331 /* The process might exist if a process was forked while performing the
3333 process
= lttv_state_find_process(ts
, ANY_CPU
, pid
);
3334 if(process
== NULL
) {
3335 parent_process
= lttv_state_find_process(ts
, ANY_CPU
, parent_pid
);
3336 process
= lttv_state_create_process(ts
, parent_process
, cpu
,
3337 pid
, tgid
, g_quark_from_string(command
),
3340 /* Keep the stack bottom : a running user mode */
3341 /* Disabled because of inconsistencies in the current statedump states. */
3342 //if(type == LTTV_STATE_KERNEL_THREAD) {
3344 /* Only keep the bottom
3345 * FIXME Kernel thread : can be in syscall or interrupt or trap. */
3346 /* Will cause expected trap when in fact being syscall (even after end of
3348 * Will cause expected interrupt when being syscall. (only before end of
3349 * statedump event) */
3350 // This will cause a "popping last state on stack, ignoring it."
3351 process
->execution_stack
= g_array_set_size(process
->execution_stack
, 1);
3352 es
= process
->state
= &g_array_index(process
->execution_stack
,
3353 LttvExecutionState
, 0);
3354 process
->type
= LTTV_STATE_KERNEL_THREAD
;
3355 es
->t
= LTTV_STATE_MAYBE_SYSCALL
;
3356 es
->s
= LTTV_STATE_UNNAMED
;
3357 es
->n
= LTTV_STATE_SUBMODE_UNKNOWN
;
3361 /* User space process :
3362 * bottom : user mode
3363 * either currently running or scheduled out.
3364 * can be scheduled out because interrupted in (user mode or in syscall)
3365 * or because of an explicit call to the scheduler in syscall. Note that
3366 * the scheduler call comes after the irq_exit, so never in interrupt
3368 // temp workaround : set size to 1 : only have user mode bottom of stack.
3369 // will cause g_info message of expected syscall mode when in fact being
3370 // in user mode. Can also cause expected trap when in fact being user
3371 // mode in the event of a page fault reenabling interrupts in the handler.
3372 // Expected syscall and trap can also happen after the end of statedump
3373 // This will cause a "popping last state on stack, ignoring it."
3374 process
->execution_stack
= g_array_set_size(process
->execution_stack
, 1);
3375 es
= process
->state
= &g_array_index(process
->execution_stack
,
3376 LttvExecutionState
, 0);
3377 es
->t
= LTTV_STATE_MAYBE_USER_MODE
;
3378 es
->s
= LTTV_STATE_UNNAMED
;
3379 es
->n
= LTTV_STATE_SUBMODE_UNKNOWN
;
3386 es
= process
->state
= &g_array_index(process
->execution_stack
,
3387 LttvExecutionState
, 1);
3388 es
->t
= LTTV_STATE_MODE_UNKNOWN
;
3389 es
->s
= LTTV_STATE_UNNAMED
;
3390 es
->n
= LTTV_STATE_SUBMODE_UNKNOWN
;
3394 /* The process has already been created :
3395 * Probably was forked while dumping the process state or
3396 * was simply scheduled in prior to get the state dump event.
3398 process
->ppid
= parent_pid
;
3399 process
->tgid
= tgid
;
3400 process
->name
= g_quark_from_string(command
);
3401 process
->type
= type
;
3402 es
= &g_array_index(process
->execution_stack
, LttvExecutionState
, 0);
3404 if(es
->t
== LTTV_STATE_MODE_UNKNOWN
) {
3405 if(type
== LTTV_STATE_KERNEL_THREAD
)
3406 es
->t
= LTTV_STATE_SYSCALL
;
3408 es
->t
= LTTV_STATE_USER_MODE
;
3411 /* Don't mess around with the stack, it will eventually become
3412 * ok after the end of state dump. */
3421 gint
lttv_state_hook_add_event_hooks(void *hook_data
, void *call_data
)
3423 LttvTraceset
*traceset
= (LttvTraceset
*)(call_data
);
3425 lttv_state_add_event_hooks(traceset
);
3430 void lttv_state_add_event_hooks(LttvTraceset
*traceset
)
3434 LttvAttributeValue value
;
3435 LttvHooks
*event_hook
;
3436 LttvIAttribute
*attributes
= LTTV_IATTRIBUTE(lttv_global_attributes());
3437 result
= lttv_iattribute_find_by_path(attributes
, "hooks/event",
3438 LTTV_POINTER
, &value
);
3440 event_hook
= *(value
.v_pointer
);
3441 g_assert(event_hook
);
3443 lttv_hooks_add(event_hook
,syscall_entry
, NULL
, LTTV_PRIO_STATE
);
3444 lttv_hooks_add(event_hook
,syscall_exit
, NULL
, LTTV_PRIO_STATE
);
3445 lttv_hooks_add(event_hook
,irq_entry
, NULL
, LTTV_PRIO_STATE
);
3446 lttv_hooks_add(event_hook
,irq_exit
, NULL
, LTTV_PRIO_STATE
);
3447 lttv_hooks_add(event_hook
,soft_irq_raise
, NULL
, LTTV_PRIO_STATE
);
3448 lttv_hooks_add(event_hook
,soft_irq_entry
, NULL
, LTTV_PRIO_STATE
);
3449 lttv_hooks_add(event_hook
,soft_irq_exit
, NULL
, LTTV_PRIO_STATE
);
3450 lttv_hooks_add(event_hook
,schedchange
, NULL
, LTTV_PRIO_STATE
);
3451 lttv_hooks_add(event_hook
,sched_try_wakeup
, NULL
, LTTV_PRIO_STATE
);
3452 lttv_hooks_add(event_hook
,process_exit
, NULL
, LTTV_PRIO_STATE
);
3453 lttv_hooks_add(event_hook
,process_free
, NULL
, LTTV_PRIO_STATE
);
3454 lttv_hooks_add(event_hook
,process_exec
, NULL
, LTTV_PRIO_STATE
);
3455 lttv_hooks_add(event_hook
,enum_process_state
, NULL
, LTTV_PRIO_STATE
);
3456 lttv_hooks_add(event_hook
,statedump_end
, NULL
, LTTV_PRIO_STATE
);
3457 lttv_hooks_add(event_hook
,enum_interrupt
, NULL
, LTTV_PRIO_STATE
);
3459 #ifdef BABEL_CLEANUP //For the whole function this time
3460 guint i
, j
, k
, nb_trace
;
3463 // LttvTraceHook *th;
3464 LttvAttributeValue val
;
3466 nb_trace
= lttv_traceset_number(traceset
);
3467 for (i
= 0 ; i
< nb_trace
; i
++) {
3468 ts
= lttv_traceset_get(traceset
, i
)-;
3470 /* Find the eventtype id for the following events and register the
3471 associated by id hooks. */
3473 hooks
= g_array_sized_new(FALSE
, FALSE
, sizeof(LttvTraceHook
), 20);
3474 //hooks = g_array_set_size(hooks, 19); // Max possible number of hooks.
3477 lttv_trace_find_hook(tss
->parent
.t
,
3479 LTT_EVENT_SYSCALL_ENTRY
,
3480 FIELD_ARRAY(LTT_FIELD_SYSCALL_ID
),
3481 syscall_entry
, NULL
, &hooks
);
3483 lttv_trace_find_hook(ts
->parent
.t
,
3485 LTT_EVENT_SYSCALL_EXIT
,
3487 syscall_exit
, NULL
, &hooks
);
3489 #ifdef BABEL_CLEANUP
3490 lttv_trace_find_hook(ts
->parent
.t
,
3492 LTT_EVENT_TRAP_ENTRY
,
3493 FIELD_ARRAY(LTT_FIELD_TRAP_ID
),
3494 trap_entry
, NULL
, &hooks
);
3496 lttv_trace_find_hook(ts
->parent
.t
,
3498 LTT_EVENT_TRAP_EXIT
,
3500 trap_exit
, NULL
, &hooks
);
3501 #endif /* BABEL_CLEANUP */
3503 lttv_trace_find_hook(ts
->parent
.t
,
3505 LTT_EVENT_PAGE_FAULT_ENTRY
,
3506 FIELD_ARRAY(LTT_FIELD_TRAP_ID
),
3507 trap_entry
, NULL
, &hooks
);
3509 lttv_trace_find_hook(ts
->parent
.t
,
3511 LTT_EVENT_PAGE_FAULT_EXIT
,
3513 trap_exit
, NULL
, &hooks
);
3515 #ifdef BABEL_CLEANUP
3516 lttv_trace_find_hook(ts
->parent
.t
,
3518 LTT_EVENT_PAGE_FAULT_NOSEM_ENTRY
,
3519 FIELD_ARRAY(LTT_FIELD_TRAP_ID
),
3520 trap_entry
, NULL
, &hooks
);
3522 lttv_trace_find_hook(ts
->parent
.t
,
3524 LTT_EVENT_PAGE_FAULT_NOSEM_EXIT
,
3526 trap_exit
, NULL
, &hooks
);
3527 #endif /* BABEL_CLEANUP */
3529 lttv_trace_find_hook(ts
->parent
.t
,
3531 LTT_EVENT_IRQ_ENTRY
,
3532 FIELD_ARRAY(LTT_FIELD_IRQ_ID
),
3533 irq_entry
, NULL
, &hooks
);
3535 lttv_trace_find_hook(ts
->parent
.t
,
3539 irq_exit
, NULL
, &hooks
);
3541 lttv_trace_find_hook(ts
->parent
.t
,
3543 LTT_EVENT_SOFT_IRQ_RAISE
,
3544 FIELD_ARRAY(LTT_FIELD_SOFT_IRQ_ID
),
3545 soft_irq_raise
, NULL
, &hooks
);
3547 lttv_trace_find_hook(ts
->parent
.t
,
3549 LTT_EVENT_SOFT_IRQ_ENTRY
,
3550 FIELD_ARRAY(LTT_FIELD_SOFT_IRQ_ID
),
3551 soft_irq_entry
, NULL
, &hooks
);
3553 lttv_trace_find_hook(ts
->parent
.t
,
3555 LTT_EVENT_SOFT_IRQ_EXIT
,
3557 soft_irq_exit
, NULL
, &hooks
);
3559 lttv_trace_find_hook(ts
->parent
.t
,
3561 LTT_EVENT_SCHED_SCHEDULE
,
3562 FIELD_ARRAY(LTT_FIELD_PREV_PID
, LTT_FIELD_NEXT_PID
,
3563 LTT_FIELD_PREV_STATE
),
3564 schedchange
, NULL
, &hooks
);
3566 lttv_trace_find_hook(ts
->parent
.t
,
3568 LTT_EVENT_SCHED_TRY_WAKEUP
,
3569 FIELD_ARRAY(LTT_FIELD_PID
, LTT_FIELD_CPU_ID
, LTT_FIELD_STATE
),
3570 sched_try_wakeup
, NULL
, &hooks
);
3572 lttv_trace_find_hook(ts
->parent
.t
,
3574 LTT_EVENT_PROCESS_FORK
,
3575 FIELD_ARRAY(LTT_FIELD_PARENT_PID
, LTT_FIELD_CHILD_PID
,
3576 LTT_FIELD_CHILD_TGID
),
3577 process_fork
, NULL
, &hooks
);
3579 lttv_trace_find_hook(ts
->parent
.t
,
3581 LTT_EVENT_KTHREAD_CREATE
,
3582 FIELD_ARRAY(LTT_FIELD_PID
),
3583 process_kernel_thread
, NULL
, &hooks
);
3585 lttv_trace_find_hook(ts
->parent
.t
,
3587 LTT_EVENT_PROCESS_EXIT
,
3588 FIELD_ARRAY(LTT_FIELD_PID
),
3589 process_exit
, NULL
, &hooks
);
3591 lttv_trace_find_hook(ts
->parent
.t
,
3593 LTT_EVENT_PROCESS_FREE
,
3594 FIELD_ARRAY(LTT_FIELD_PID
),
3595 process_free
, NULL
, &hooks
);
3597 lttv_trace_find_hook(ts
->parent
.t
,
3600 FIELD_ARRAY(LTT_FIELD_FILENAME
),
3601 process_exec
, NULL
, &hooks
);
3603 lttv_trace_find_hook(ts
->parent
.t
,
3604 LTT_CHANNEL_USERSPACE
,
3605 LTT_EVENT_THREAD_BRAND
,
3606 FIELD_ARRAY(LTT_FIELD_NAME
),
3607 thread_brand
, NULL
, &hooks
);
3609 /* statedump-related hooks */
3610 lttv_trace_find_hook(ts
->parent
.t
,
3611 LTT_CHANNEL_TASK_STATE
,
3612 LTT_EVENT_PROCESS_STATE
,
3613 FIELD_ARRAY(LTT_FIELD_PID
, LTT_FIELD_PARENT_PID
, LTT_FIELD_NAME
,
3614 LTT_FIELD_TYPE
, LTT_FIELD_MODE
, LTT_FIELD_SUBMODE
,
3615 LTT_FIELD_STATUS
, LTT_FIELD_TGID
),
3616 enum_process_state
, NULL
, &hooks
);
3618 lttv_trace_find_hook(ts
->parent
.t
,
3619 LTT_CHANNEL_GLOBAL_STATE
,
3620 LTT_EVENT_STATEDUMP_END
,
3622 statedump_end
, NULL
, &hooks
);
3624 lttv_trace_find_hook(ts
->parent
.t
,
3625 LTT_CHANNEL_IRQ_STATE
,
3626 LTT_EVENT_LIST_INTERRUPT
,
3627 FIELD_ARRAY(LTT_FIELD_ACTION
, LTT_FIELD_IRQ_ID
),
3628 enum_interrupt
, NULL
, &hooks
);
3630 lttv_trace_find_hook(ts
->parent
.t
,
3632 LTT_EVENT_REQUEST_ISSUE
,
3633 FIELD_ARRAY(LTT_FIELD_MAJOR
, LTT_FIELD_MINOR
, LTT_FIELD_OPERATION
),
3634 bdev_request_issue
, NULL
, &hooks
);
3636 lttv_trace_find_hook(ts
->parent
.t
,
3638 LTT_EVENT_REQUEST_COMPLETE
,
3639 FIELD_ARRAY(LTT_FIELD_MAJOR
, LTT_FIELD_MINOR
, LTT_FIELD_OPERATION
),
3640 bdev_request_complete
, NULL
, &hooks
);
3642 lttv_trace_find_hook(ts
->parent
.t
,
3643 LTT_CHANNEL_USERSPACE
,
3644 LTT_EVENT_FUNCTION_ENTRY
,
3645 FIELD_ARRAY(LTT_FIELD_THIS_FN
, LTT_FIELD_CALL_SITE
),
3646 function_entry
, NULL
, &hooks
);
3648 lttv_trace_find_hook(ts
->parent
.t
,
3649 LTT_CHANNEL_USERSPACE
,
3650 LTT_EVENT_FUNCTION_EXIT
,
3651 FIELD_ARRAY(LTT_FIELD_THIS_FN
, LTT_FIELD_CALL_SITE
),
3652 function_exit
, NULL
, &hooks
);
3654 lttv_trace_find_hook(ts
->parent
.t
,
3655 LTT_CHANNEL_SYSCALL_STATE
,
3656 LTT_EVENT_SYS_CALL_TABLE
,
3657 FIELD_ARRAY(LTT_FIELD_ID
, LTT_FIELD_ADDRESS
, LTT_FIELD_SYMBOL
),
3658 dump_syscall
, NULL
, &hooks
);
3660 lttv_trace_find_hook(ts
->parent
.t
,
3661 LTT_CHANNEL_KPROBE_STATE
,
3662 LTT_EVENT_KPROBE_TABLE
,
3663 FIELD_ARRAY(LTT_FIELD_IP
, LTT_FIELD_SYMBOL
),
3664 dump_kprobe
, NULL
, &hooks
);
3666 lttv_trace_find_hook(ts
->parent
.t
,
3667 LTT_CHANNEL_SOFTIRQ_STATE
,
3668 LTT_EVENT_SOFTIRQ_VEC
,
3669 FIELD_ARRAY(LTT_FIELD_ID
, LTT_FIELD_ADDRESS
, LTT_FIELD_SYMBOL
),
3670 dump_softirq
, NULL
, &hooks
);
3672 lttv_trace_find_hook(ts
->parent
.t
,
3675 FIELD_ARRAY(LTT_FIELD_FD
, LTT_FIELD_FILENAME
),
3676 fs_open
, NULL
, &hooks
);
3678 /* Add these hooks to each event_by_id hooks list */
3680 nb_tracefile
= ts
->parent
.tracefiles
->len
;
3682 for(j
= 0 ; j
< nb_tracefile
; j
++) {
3684 LTTV_TRACEFILE_STATE(g_array_index(ts
->parent
.tracefiles
,
3685 LttvTracefileContext
*, j
));
3687 for(k
= 0 ; k
< hooks
->len
; k
++) {
3688 th
= &g_array_index(hooks
, LttvTraceHook
, k
);
3689 if (th
->mdata
== tfs
->parent
.tf
->mdata
)
3691 lttv_hooks_by_id_find(tfs
->parent
.event_by_id
, th
->id
),
3697 lttv_attribute_find(ts
->parent
.a
, LTTV_STATE_HOOKS
, LTTV_POINTER
, &val
);
3698 *(val
.v_pointer
) = hooks
;
3703 gint
lttv_state_hook_remove_event_hooks(void *hook_data
, void *call_data
)
3705 //TODO ybrosseau 2012-05-11 Reactivate the remove
3707 LttvTracesetState
*tss
= (LttvTracesetState
*)(call_data
);
3709 lttv_state_remove_event_hooks(tss
);
3714 void lttv_state_remove_event_hooks(LttvTracesetState
*self
)
3716 LttvTraceset
*traceset
= self
->parent
.ts
;
3718 guint i
, j
, k
, nb_trace
, nb_tracefile
;
3722 LttvTracefileState
*tfs
;
3728 LttvAttributeValue val
;
3730 nb_trace
= lttv_traceset_number(traceset
);
3731 for(i
= 0 ; i
< nb_trace
; i
++) {
3732 ts
= LTTV_TRACE_STATE(self
->parent
.traces
[i
]);
3734 lttv_attribute_find(ts
->parent
.a
, LTTV_STATE_HOOKS
, LTTV_POINTER
, &val
);
3735 hooks
= *(val
.v_pointer
);
3737 /* Remove these hooks from each event_by_id hooks list */
3739 nb_tracefile
= ts
->parent
.tracefiles
->len
;
3741 for(j
= 0 ; j
< nb_tracefile
; j
++) {
3743 LTTV_TRACEFILE_STATE(g_array_index(ts
->parent
.tracefiles
,
3744 LttvTracefileContext
*, j
));
3746 for(k
= 0 ; k
< hooks
->len
; k
++) {
3747 th
= &g_array_index(hooks
, LttvTraceHook
, k
);
3748 if (th
->mdata
== tfs
->parent
.tf
->mdata
)
3749 lttv_hooks_remove_data(
3750 lttv_hooks_by_id_find(tfs
->parent
.event_by_id
, th
->id
),
3755 lttv_trace_hook_remove_all(&hooks
);
3756 g_array_free(hooks
, TRUE
);
3760 #ifdef BABEL_CLEANUP
3761 static gboolean
state_save_event_hook(void *hook_data
, void *call_data
)
3763 guint
*event_count
= (guint
*)hook_data
;
3765 /* Only save at LTTV_STATE_SAVE_INTERVAL */
3766 if(likely((*event_count
)++ < LTTV_STATE_SAVE_INTERVAL
))
3771 LttvTracefileState
*self
= (LttvTracefileState
*)call_data
;
3773 LttvTraceState
*tcs
= (LttvTraceState
*)(self
->parent
.t_context
);
3775 LttvAttribute
*saved_states_tree
, *saved_state_tree
;
3777 LttvAttributeValue value
;
3779 saved_states_tree
= lttv_attribute_find_subdir(tcs
->parent
.t_a
,
3780 LTTV_STATE_SAVED_STATES
);
3781 saved_state_tree
= g_object_new(LTTV_ATTRIBUTE_TYPE
, NULL
);
3782 value
= lttv_attribute_add(saved_states_tree
,
3783 lttv_attribute_get_number(saved_states_tree
), LTTV_GOBJECT
);
3784 *(value
.v_gobject
) = (GObject
*)saved_state_tree
;
3785 value
= lttv_attribute_add(saved_state_tree
, LTTV_STATE_TIME
, LTTV_TIME
);
3786 *(value
.v_time
) = self
->parent
.timestamp
;
3787 lttv_state_save(tcs
, saved_state_tree
);
3788 g_debug("Saving state at time %lu.%lu", self
->parent
.timestamp
.tv_sec
,
3789 self
->parent
.timestamp
.tv_nsec
);
3791 *(tcs
->max_time_state_recomputed_in_seek
) = self
->parent
.timestamp
;
3796 static gboolean
state_save_after_trace_hook(void *hook_data
, void *call_data
)
3798 LttvTraceState
*tcs
= (LttvTraceState
*)(call_data
);
3800 *(tcs
->max_time_state_recomputed_in_seek
) = tcs
->parent
.time_span
.end_time
;
3805 guint
lttv_state_current_cpu(LttvTracefileState
*tfs
)
3810 #endif //BABEL_CLEANUP
3813 static gboolean
block_start(void *hook_data
, void *call_data
)
3815 LttvTracefileState
*self
= (LttvTracefileState
*)call_data
;
3817 LttvTracefileState
*tfcs
;
3819 LttvTraceState
*tcs
= (LttvTraceState
*)(self
->parent
.t_context
);
3821 LttEventPosition
*ep
;
3823 guint i
, nb_block
, nb_event
, nb_tracefile
;
3827 LttvAttribute
*saved_states_tree
, *saved_state_tree
;
3829 LttvAttributeValue value
;
3831 ep
= ltt_event_position_new();
3833 nb_tracefile
= tcs
->parent
.tracefiles
->len
;
3835 /* Count the number of events added since the last block end in any
3838 for(i
= 0 ; i
< nb_tracefile
; i
++) {
3840 LTTV_TRACEFILE_STATE(&g_array_index(tcs
->parent
.tracefiles
,
3841 LttvTracefileContext
, i
));
3842 ltt_event_position(tfcs
->parent
.e
, ep
);
3843 ltt_event_position_get(ep
, &nb_block
, &nb_event
, &tf
);
3844 tcs
->nb_event
+= nb_event
- tfcs
->saved_position
;
3845 tfcs
->saved_position
= nb_event
;
3849 if(tcs
->nb_event
>= tcs
->save_interval
) {
3850 saved_states_tree
= lttv_attribute_find_subdir(tcs
->parent
.t_a
,
3851 LTTV_STATE_SAVED_STATES
);
3852 saved_state_tree
= g_object_new(LTTV_ATTRIBUTE_TYPE
, NULL
);
3853 value
= lttv_attribute_add(saved_states_tree
,
3854 lttv_attribute_get_number(saved_states_tree
), LTTV_GOBJECT
);
3855 *(value
.v_gobject
) = (GObject
*)saved_state_tree
;
3856 value
= lttv_attribute_add(saved_state_tree
, LTTV_STATE_TIME
, LTTV_TIME
);
3857 *(value
.v_time
) = self
->parent
.timestamp
;
3858 lttv_state_save(tcs
, saved_state_tree
);
3860 g_debug("Saving state at time %lu.%lu", self
->parent
.timestamp
.tv_sec
,
3861 self
->parent
.timestamp
.tv_nsec
);
3863 *(tcs
->max_time_state_recomputed_in_seek
) = self
->parent
.timestamp
;
3869 static gboolean
block_end(void *hook_data
, void *call_data
)
3871 LttvTracefileState
*self
= (LttvTracefileState
*)call_data
;
3873 LttvTraceState
*tcs
= (LttvTraceState
*)(self
->parent
.t_context
);
3877 LttEventPosition
*ep
;
3879 guint nb_block
, nb_event
;
3881 ep
= ltt_event_position_new();
3882 ltt_event_position(self
->parent
.e
, ep
);
3883 ltt_event_position_get(ep
, &nb_block
, &nb_event
, &tf
);
3884 tcs
->nb_event
+= nb_event
- self
->saved_position
+ 1;
3885 self
->saved_position
= 0;
3886 *(tcs
->max_time_state_recomputed_in_seek
) = self
->parent
.timestamp
;
3893 void lttv_state_save_add_event_hooks(LttvTracesetState
*self
)
3895 LttvTraceset
*traceset
= self
->parent
.ts
;
3897 guint i
, j
, nb_trace
, nb_tracefile
;
3901 LttvTracefileState
*tfs
;
3903 LttvTraceHook hook_start
, hook_end
;
3905 nb_trace
= lttv_traceset_number(traceset
);
3906 for(i
= 0 ; i
< nb_trace
; i
++) {
3907 ts
= (LttvTraceState
*)self
->parent
.traces
[i
];
3909 lttv_trace_find_hook(ts
->parent
.t
, "core","block_start",NULL
,
3910 NULL
, NULL
, block_start
, &hook_start
);
3911 lttv_trace_find_hook(ts
->parent
.t
, "core","block_end",NULL
,
3912 NULL
, NULL
, block_end
, &hook_end
);
3914 nb_tracefile
= ts
->parent
.tracefiles
->len
;
3916 for(j
= 0 ; j
< nb_tracefile
; j
++) {
3918 LTTV_TRACEFILE_STATE(&g_array_index(ts
->parent
.tracefiles
,
3919 LttvTracefileContext
, j
));
3920 lttv_hooks_add(lttv_hooks_by_id_find(tfs
->parent
.event_by_id
,
3921 hook_start
.id
), hook_start
.h
, NULL
, LTTV_PRIO_STATE
);
3922 lttv_hooks_add(lttv_hooks_by_id_find(tfs
->parent
.event_by_id
,
3923 hook_end
.id
), hook_end
.h
, NULL
, LTTV_PRIO_STATE
);
3928 #ifdef BABEL_CLEANUP
3929 void lttv_state_save_add_event_hooks(LttvTracesetState
*self
)
3931 LttvTraceset
*traceset
= self
->parent
.ts
;
3933 guint i
, j
, nb_trace
, nb_tracefile
;
3937 LttvTracefileState
*tfs
;
3940 nb_trace
= lttv_traceset_number(traceset
);
3941 for(i
= 0 ; i
< nb_trace
; i
++) {
3943 ts
= (LttvTraceState
*)self
->parent
.traces
[i
];
3944 nb_tracefile
= ts
->parent
.tracefiles
->len
;
3946 if(ts
->has_precomputed_states
) continue;
3948 guint
*event_count
= g_new(guint
, 1);
3951 for(j
= 0 ; j
< nb_tracefile
; j
++) {
3953 LTTV_TRACEFILE_STATE(g_array_index(ts
->parent
.tracefiles
,
3954 LttvTracefileContext
*, j
));
3955 lttv_hooks_add(tfs
->parent
.event
,
3956 state_save_event_hook
,
3963 lttv_process_traceset_begin(&self
->parent
,
3964 NULL
, NULL
, NULL
, NULL
, NULL
);
3968 gint
lttv_state_save_hook_add_event_hooks(void *hook_data
, void *call_data
)
3970 LttvTracesetState
*tss
= (LttvTracesetState
*)(call_data
);
3972 lttv_state_save_add_event_hooks(tss
);
3979 void lttv_state_save_remove_event_hooks(LttvTracesetState
*self
)
3981 LttvTraceset
*traceset
= self
->parent
.ts
;
3983 guint i
, j
, nb_trace
, nb_tracefile
;
3987 LttvTracefileState
*tfs
;
3989 LttvTraceHook hook_start
, hook_end
;
3991 nb_trace
= lttv_traceset_number(traceset
);
3992 for(i
= 0 ; i
< nb_trace
; i
++) {
3993 ts
= LTTV_TRACE_STATE(self
->parent
.traces
[i
]);
3995 lttv_trace_find_hook(ts
->parent
.t
, "core","block_start",NULL
,
3996 NULL
, NULL
, block_start
, &hook_start
);
3998 lttv_trace_find_hook(ts
->parent
.t
, "core","block_end",NULL
,
3999 NULL
, NULL
, block_end
, &hook_end
);
4001 nb_tracefile
= ts
->parent
.tracefiles
->len
;
4003 for(j
= 0 ; j
< nb_tracefile
; j
++) {
4005 LTTV_TRACEFILE_STATE(&g_array_index(ts
->parent
.tracefiles
,
4006 LttvTracefileContext
, j
));
4007 lttv_hooks_remove_data(lttv_hooks_by_id_find(
4008 tfs
->parent
.event_by_id
, hook_start
.id
), hook_start
.h
, NULL
);
4009 lttv_hooks_remove_data(lttv_hooks_by_id_find(
4010 tfs
->parent
.event_by_id
, hook_end
.id
), hook_end
.h
, NULL
);
4015 #ifdef BABEL_CLEANUP
4016 void lttv_state_save_remove_event_hooks(LttvTracesetState
*self
)
4018 LttvTraceset
*traceset
= self
->parent
.ts
;
4020 guint i
, j
, nb_trace
, nb_tracefile
;
4024 LttvTracefileState
*tfs
;
4026 LttvHooks
*after_trace
= lttv_hooks_new();
4028 lttv_hooks_add(after_trace
,
4029 state_save_after_trace_hook
,
4034 lttv_process_traceset_end(&self
->parent
,
4035 NULL
, after_trace
, NULL
, NULL
, NULL
);
4037 lttv_hooks_destroy(after_trace
);
4039 nb_trace
= lttv_traceset_number(traceset
);
4040 for(i
= 0 ; i
< nb_trace
; i
++) {
4042 ts
= (LttvTraceState
*)self
->parent
.traces
[i
];
4043 nb_tracefile
= ts
->parent
.tracefiles
->len
;
4045 if(ts
->has_precomputed_states
) continue;
4047 guint
*event_count
= NULL
;
4049 for(j
= 0 ; j
< nb_tracefile
; j
++) {
4051 LTTV_TRACEFILE_STATE(g_array_index(ts
->parent
.tracefiles
,
4052 LttvTracefileContext
*, j
));
4053 event_count
= lttv_hooks_remove(tfs
->parent
.event
,
4054 state_save_event_hook
);
4056 if(event_count
) g_free(event_count
);
4060 gint
lttv_state_save_hook_remove_event_hooks(void *hook_data
, void *call_data
)
4062 LttvTracesetState
*tss
= (LttvTracesetState
*)(call_data
);
4064 lttv_state_save_remove_event_hooks(tss
);
4069 void lttv_state_traceset_seek_time_closest(LttvTracesetState
*self
, LttTime t
)
4071 LttvTraceset
*traceset
= self
->parent
.ts
;
4075 int min_pos
, mid_pos
, max_pos
;
4077 guint call_rest
= 0;
4079 LttvTraceState
*tcs
;
4081 LttvAttributeValue value
;
4083 LttvAttributeType type
;
4085 LttvAttributeName name
;
4089 LttvAttribute
*saved_states_tree
, *saved_state_tree
, *closest_tree
= NULL
;
4091 //g_tree_destroy(self->parent.pqueue);
4092 //self->parent.pqueue = g_tree_new(compare_tracefile);
4094 g_info("Entering seek_time_closest for time %lu.%lu", t
.tv_sec
, t
.tv_nsec
);
4096 nb_trace
= lttv_traceset_number(traceset
);
4097 for(i
= 0 ; i
< nb_trace
; i
++) {
4098 tcs
= (LttvTraceState
*)self
->parent
.traces
[i
];
4100 if(ltt_time_compare(t
, *(tcs
->max_time_state_recomputed_in_seek
)) < 0) {
4101 saved_states_tree
= lttv_attribute_find_subdir(tcs
->parent
.t_a
,
4102 LTTV_STATE_SAVED_STATES
);
4105 if(saved_states_tree
) {
4106 max_pos
= lttv_attribute_get_number(saved_states_tree
) - 1;
4107 mid_pos
= max_pos
/ 2;
4108 while(min_pos
< max_pos
) {
4109 type
= lttv_attribute_get(saved_states_tree
, mid_pos
,
4110 &name
, &value
, &is_named
);
4111 g_assert(type
== LTTV_GOBJECT
);
4112 saved_state_tree
= *((LttvAttribute
**)(value
.v_gobject
));
4113 type
= lttv_attribute_get_by_name(saved_state_tree
,
4114 LTTV_STATE_TIME
, &value
);
4115 g_assert(type
== LTTV_TIME
);
4116 if(ltt_time_compare(*(value
.v_time
), t
) < 0) {
4118 closest_tree
= saved_state_tree
;
4120 else max_pos
= mid_pos
- 1;
4122 mid_pos
= (min_pos
+ max_pos
+ 1) / 2;
4126 /* restore the closest earlier saved state */
4128 lttv_state_restore(tcs
, closest_tree
);
4132 /* There is no saved state, yet we want to have it. Restart at T0 */
4134 restore_init_state(tcs
);
4135 lttv_process_trace_seek_time(&(tcs
->parent
), ltt_time_zero
);
4138 /* We want to seek quickly without restoring/updating the state */
4140 restore_init_state(tcs
);
4141 lttv_process_trace_seek_time(&(tcs
->parent
), t
);
4144 if(!call_rest
) g_info("NOT Calling restore");
4147 #ifdef BABEL_CLEANUP
4148 static void traceset_state_instance_init (GTypeInstance
*instance
, gpointer g_class
)
4153 static void traceset_state_finalize (LttvTracesetState
*self
)
4155 G_OBJECT_CLASS(g_type_class_peek(LTTV_TRACESET_CONTEXT_TYPE
))->
4156 finalize(G_OBJECT(self
));
4160 static void traceset_state_class_init (LttvTracesetContextClass
*klass
)
4162 GObjectClass
*gobject_class
= G_OBJECT_CLASS(klass
);
4164 gobject_class
->finalize
= (void (*)(GObject
*self
)) traceset_state_finalize
;
4165 klass
->init
= (void (*)(LttvTracesetContext
*self
, LttvTraceset
*ts
))init
;
4166 klass
->fini
= (void (*)(LttvTracesetContext
*self
))fini
;
4167 klass
->new_traceset_context
= new_traceset_context
;
4168 klass
->new_trace_context
= new_trace_context
;
4169 klass
->new_tracefile_context
= new_tracefile_context
;
4173 GType
lttv_traceset_state_get_type(void)
4175 static GType type
= 0;
4177 static const GTypeInfo info
= {
4178 sizeof (LttvTracesetStateClass
),
4179 NULL
, /* base_init */
4180 NULL
, /* base_finalize */
4181 (GClassInitFunc
) traceset_state_class_init
, /* class_init */
4182 NULL
, /* class_finalize */
4183 NULL
, /* class_data */
4184 sizeof (LttvTracesetState
),
4185 0, /* n_preallocs */
4186 (GInstanceInitFunc
) traceset_state_instance_init
, /* instance_init */
4187 NULL
/* value handling */
4190 type
= g_type_register_static (LTTV_TRACESET_CONTEXT_TYPE
, "LttvTracesetStateType",
4198 static void trace_state_instance_init (GTypeInstance
*instance
, gpointer g_class
)
4203 static void trace_state_finalize (LttvTraceState
*self
)
4205 G_OBJECT_CLASS(g_type_class_peek(LTTV_TRACE_CONTEXT_TYPE
))->
4206 finalize(G_OBJECT(self
));
4210 static void trace_state_class_init (LttvTraceStateClass
*klass
)
4212 GObjectClass
*gobject_class
= G_OBJECT_CLASS(klass
);
4214 gobject_class
->finalize
= (void (*)(GObject
*self
)) trace_state_finalize
;
4215 klass
->state_save
= state_save
;
4216 klass
->state_restore
= state_restore
;
4217 klass
->state_saved_free
= state_saved_free
;
4221 GType
lttv_trace_state_get_type(void)
4223 static GType type
= 0;
4225 static const GTypeInfo info
= {
4226 sizeof (LttvTraceStateClass
),
4227 NULL
, /* base_init */
4228 NULL
, /* base_finalize */
4229 (GClassInitFunc
) trace_state_class_init
, /* class_init */
4230 NULL
, /* class_finalize */
4231 NULL
, /* class_data */
4232 sizeof (LttvTraceState
),
4233 0, /* n_preallocs */
4234 (GInstanceInitFunc
) trace_state_instance_init
, /* instance_init */
4235 NULL
/* value handling */
4238 type
= g_type_register_static (LTTV_TRACE_CONTEXT_TYPE
,
4239 "LttvTraceStateType", &info
, 0);
4245 static void tracefile_state_instance_init (GTypeInstance
*instance
,
4251 static void tracefile_state_finalize (LttvTracefileState
*self
)
4253 G_OBJECT_CLASS(g_type_class_peek(LTTV_TRACEFILE_CONTEXT_TYPE
))->
4254 finalize(G_OBJECT(self
));
4258 static void tracefile_state_class_init (LttvTracefileStateClass
*klass
)
4260 GObjectClass
*gobject_class
= G_OBJECT_CLASS(klass
);
4262 gobject_class
->finalize
= (void (*)(GObject
*self
)) tracefile_state_finalize
;
4266 GType
lttv_tracefile_state_get_type(void)
4268 static GType type
= 0;
4270 static const GTypeInfo info
= {
4271 sizeof (LttvTracefileStateClass
),
4272 NULL
, /* base_init */
4273 NULL
, /* base_finalize */
4274 (GClassInitFunc
) tracefile_state_class_init
, /* class_init */
4275 NULL
, /* class_finalize */
4276 NULL
, /* class_data */
4277 sizeof (LttvTracefileState
),
4278 0, /* n_preallocs */
4279 (GInstanceInitFunc
) tracefile_state_instance_init
, /* instance_init */
4280 NULL
/* value handling */
4283 type
= g_type_register_static (LTTV_TRACEFILE_CONTEXT_TYPE
,
4284 "LttvTracefileStateType", &info
, 0);
4290 static void module_init(void)
4292 LTTV_STATE_UNNAMED
= g_quark_from_string("");
4293 LTTV_STATE_UNBRANDED
= g_quark_from_string("");
4294 LTTV_STATE_MODE_UNKNOWN
= g_quark_from_string("MODE_UNKNOWN");
4295 LTTV_STATE_USER_MODE
= g_quark_from_string("USER_MODE");
4296 LTTV_STATE_MAYBE_USER_MODE
= g_quark_from_string("MAYBE_USER_MODE");
4297 LTTV_STATE_SYSCALL
= g_quark_from_string("SYSCALL");
4298 LTTV_STATE_MAYBE_SYSCALL
= g_quark_from_string("MAYBE_SYSCALL");
4299 LTTV_STATE_TRAP
= g_quark_from_string("TRAP");
4300 LTTV_STATE_MAYBE_TRAP
= g_quark_from_string("MAYBE_TRAP");
4301 LTTV_STATE_IRQ
= g_quark_from_string("IRQ");
4302 LTTV_STATE_SOFT_IRQ
= g_quark_from_string("SOFTIRQ");
4303 LTTV_STATE_SUBMODE_UNKNOWN
= g_quark_from_string("UNKNOWN");
4304 LTTV_STATE_SUBMODE_NONE
= g_quark_from_string("NONE");
4305 LTTV_STATE_WAIT_FORK
= g_quark_from_string("WAIT_FORK");
4306 LTTV_STATE_WAIT_CPU
= g_quark_from_string("WAIT_CPU");
4307 LTTV_STATE_EXIT
= g_quark_from_string("EXIT");
4308 LTTV_STATE_ZOMBIE
= g_quark_from_string("ZOMBIE");
4309 LTTV_STATE_WAIT
= g_quark_from_string("WAIT");
4310 LTTV_STATE_RUN
= g_quark_from_string("RUN");
4311 LTTV_STATE_DEAD
= g_quark_from_string("DEAD");
4312 LTTV_STATE_USER_THREAD
= g_quark_from_string("USER_THREAD");
4313 LTTV_STATE_KERNEL_THREAD
= g_quark_from_string("KERNEL_THREAD");
4314 LTTV_STATE_TRACEFILES
= g_quark_from_string("tracefiles");
4315 LTTV_STATE_PROCESSES
= g_quark_from_string("processes");
4316 LTTV_STATE_PROCESS
= g_quark_from_string("process");
4317 LTTV_STATE_RUNNING_PROCESS
= g_quark_from_string("running_process");
4318 LTTV_STATE_POSITION
= g_quark_from_string("position");
4319 LTTV_STATE_SAVED_STATES
= g_quark_from_string("saved states");
4320 LTTV_STATE_SAVED_STATES_TIME
= g_quark_from_string("saved states time");
4321 LTTV_STATE_TIME
= g_quark_from_string("time");
4322 LTTV_STATE_HOOKS
= g_quark_from_string("saved state hooks");
4323 LTTV_STATE_NAME_TABLES
= g_quark_from_string("name tables");
4324 LTTV_STATE_TRACE_STATE_USE_COUNT
=
4325 g_quark_from_string("trace_state_use_count");
4326 LTTV_STATE_RESOURCE_CPUS
= g_quark_from_string("cpu resource states");
4327 LTTV_STATE_RESOURCE_CPUS
= g_quark_from_string("cpu count");
4328 LTTV_STATE_RESOURCE_IRQS
= g_quark_from_string("irq resource states");
4329 LTTV_STATE_RESOURCE_SOFT_IRQS
= g_quark_from_string("soft irq resource states");
4330 LTTV_STATE_RESOURCE_TRAPS
= g_quark_from_string("trap resource states");
4331 LTTV_STATE_RESOURCE_BLKDEVS
= g_quark_from_string("blkdevs resource states");
4333 LTT_CHANNEL_FD_STATE
= g_quark_from_string("fd_state");
4334 LTT_CHANNEL_GLOBAL_STATE
= g_quark_from_string("global_state");
4335 LTT_CHANNEL_IRQ_STATE
= g_quark_from_string("irq_state");
4336 LTT_CHANNEL_MODULE_STATE
= g_quark_from_string("module_state");
4337 LTT_CHANNEL_NETIF_STATE
= g_quark_from_string("netif_state");
4338 LTT_CHANNEL_SOFTIRQ_STATE
= g_quark_from_string("softirq_state");
4339 LTT_CHANNEL_SWAP_STATE
= g_quark_from_string("swap_state");
4340 LTT_CHANNEL_SYSCALL_STATE
= g_quark_from_string("syscall_state");
4341 LTT_CHANNEL_TASK_STATE
= g_quark_from_string("task_state");
4342 LTT_CHANNEL_VM_STATE
= g_quark_from_string("vm_state");
4343 LTT_CHANNEL_KPROBE_STATE
= g_quark_from_string("kprobe_state");
4344 LTT_CHANNEL_FS
= g_quark_from_string("fs");
4345 LTT_CHANNEL_KERNEL
= g_quark_from_string("kernel");
4346 LTT_CHANNEL_MM
= g_quark_from_string("mm");
4347 LTT_CHANNEL_USERSPACE
= g_quark_from_string("userspace");
4348 LTT_CHANNEL_BLOCK
= g_quark_from_string("block");
4350 LTT_EVENT_SYSCALL_ENTRY
= g_quark_from_string("syscall_entry");
4351 LTT_EVENT_SYSCALL_EXIT
= g_quark_from_string("syscall_exit");
4352 //LTT_EVENT_TRAP_ENTRY = g_quark_from_string("trap_entry");
4353 //LTT_EVENT_TRAP_EXIT = g_quark_from_string("trap_exit");
4354 LTT_EVENT_PAGE_FAULT_ENTRY
= g_quark_from_string("page_fault_entry");
4355 LTT_EVENT_PAGE_FAULT_EXIT
= g_quark_from_string("page_fault_exit");
4356 LTT_EVENT_PAGE_FAULT_NOSEM_ENTRY
= g_quark_from_string("page_fault_nosem_entry");
4357 LTT_EVENT_PAGE_FAULT_NOSEM_EXIT
= g_quark_from_string("page_fault_nosem_exit");
4358 LTT_EVENT_IRQ_ENTRY
= g_quark_from_string("irq_entry");
4359 LTT_EVENT_IRQ_EXIT
= g_quark_from_string("irq_exit");
4360 LTT_EVENT_SOFT_IRQ_RAISE
= g_quark_from_string("softirq_raise");
4361 LTT_EVENT_SOFT_IRQ_ENTRY
= g_quark_from_string("softirq_entry");
4362 LTT_EVENT_SOFT_IRQ_EXIT
= g_quark_from_string("softirq_exit");
4363 LTT_EVENT_SCHED_SCHEDULE
= g_quark_from_string("sched_schedule");
4364 LTT_EVENT_SCHED_TRY_WAKEUP
= g_quark_from_string("sched_try_wakeup");
4365 LTT_EVENT_PROCESS_FORK
= g_quark_from_string("process_fork");
4366 LTT_EVENT_KTHREAD_CREATE
= g_quark_from_string("kthread_create");
4367 LTT_EVENT_PROCESS_EXIT
= g_quark_from_string("process_exit");
4368 LTT_EVENT_PROCESS_FREE
= g_quark_from_string("process_free");
4369 LTT_EVENT_EXEC
= g_quark_from_string("exec");
4370 LTT_EVENT_PROCESS_STATE
= g_quark_from_string("process_state");
4371 LTT_EVENT_STATEDUMP_END
= g_quark_from_string("statedump_end");
4372 LTT_EVENT_FUNCTION_ENTRY
= g_quark_from_string("function_entry");
4373 LTT_EVENT_FUNCTION_EXIT
= g_quark_from_string("function_exit");
4374 LTT_EVENT_THREAD_BRAND
= g_quark_from_string("thread_brand");
4375 LTT_EVENT_REQUEST_ISSUE
= g_quark_from_string("_blk_request_issue");
4376 LTT_EVENT_REQUEST_COMPLETE
= g_quark_from_string("_blk_request_complete");
4377 LTT_EVENT_LIST_INTERRUPT
= g_quark_from_string("interrupt");
4378 LTT_EVENT_SYS_CALL_TABLE
= g_quark_from_string("sys_call_table");
4379 LTT_EVENT_SOFTIRQ_VEC
= g_quark_from_string("softirq_vec");
4380 LTT_EVENT_KPROBE_TABLE
= g_quark_from_string("kprobe_table");
4381 LTT_EVENT_KPROBE
= g_quark_from_string("kprobe");
4382 LTT_EVENT_OPEN
= g_quark_from_string("open");
4383 LTT_EVENT_READ
= g_quark_from_string("read");
4384 LTT_EVENT_POLL_EVENT
= g_quark_from_string("poll_event");
4386 LTT_FIELD_SYSCALL_ID
= g_quark_from_string("syscall_id");
4387 LTT_FIELD_TRAP_ID
= g_quark_from_string("trap_id");
4388 LTT_FIELD_IRQ_ID
= g_quark_from_string("irq_id");
4389 LTT_FIELD_SOFT_IRQ_ID
= g_quark_from_string("softirq_id");
4390 LTT_FIELD_PREV_PID
= g_quark_from_string("prev_pid");
4391 LTT_FIELD_NEXT_PID
= g_quark_from_string("next_pid");
4392 LTT_FIELD_PREV_STATE
= g_quark_from_string("prev_state");
4393 LTT_FIELD_PARENT_PID
= g_quark_from_string("parent_pid");
4394 LTT_FIELD_CHILD_PID
= g_quark_from_string("child_pid");
4395 LTT_FIELD_PID
= g_quark_from_string("pid");
4396 LTT_FIELD_TGID
= g_quark_from_string("tgid");
4397 LTT_FIELD_CHILD_TGID
= g_quark_from_string("child_tgid");
4398 LTT_FIELD_FILENAME
= g_quark_from_string("filename");
4399 LTT_FIELD_NAME
= g_quark_from_string("name");
4400 LTT_FIELD_TYPE
= g_quark_from_string("type");
4401 LTT_FIELD_MODE
= g_quark_from_string("mode");
4402 LTT_FIELD_SUBMODE
= g_quark_from_string("submode");
4403 LTT_FIELD_STATUS
= g_quark_from_string("status");
4404 LTT_FIELD_THIS_FN
= g_quark_from_string("this_fn");
4405 LTT_FIELD_CALL_SITE
= g_quark_from_string("call_site");
4406 LTT_FIELD_MAJOR
= g_quark_from_string("major");
4407 LTT_FIELD_MINOR
= g_quark_from_string("minor");
4408 LTT_FIELD_OPERATION
= g_quark_from_string("direction");
4409 LTT_FIELD_ACTION
= g_quark_from_string("action");
4410 LTT_FIELD_ID
= g_quark_from_string("id");
4411 LTT_FIELD_ADDRESS
= g_quark_from_string("address");
4412 LTT_FIELD_SYMBOL
= g_quark_from_string("symbol");
4413 LTT_FIELD_IP
= g_quark_from_string("ip");
4414 LTT_FIELD_FD
= g_quark_from_string("fd");
4415 LTT_FIELD_STATE
= g_quark_from_string("state");
4416 LTT_FIELD_CPU_ID
= g_quark_from_string("cpu_id");
4418 LTTV_CPU_UNKNOWN
= g_quark_from_string("unknown");
4419 LTTV_CPU_IDLE
= g_quark_from_string("idle");
4420 LTTV_CPU_BUSY
= g_quark_from_string("busy");
4421 LTTV_CPU_IRQ
= g_quark_from_string("irq");
4422 LTTV_CPU_SOFT_IRQ
= g_quark_from_string("softirq");
4423 LTTV_CPU_TRAP
= g_quark_from_string("trap");
4425 LTTV_IRQ_UNKNOWN
= g_quark_from_string("unknown");
4426 LTTV_IRQ_IDLE
= g_quark_from_string("idle");
4427 LTTV_IRQ_BUSY
= g_quark_from_string("busy");
4429 LTTV_BDEV_UNKNOWN
= g_quark_from_string("unknown");
4430 LTTV_BDEV_IDLE
= g_quark_from_string("idle");
4431 LTTV_BDEV_BUSY_READING
= g_quark_from_string("busy_reading");
4432 LTTV_BDEV_BUSY_WRITING
= g_quark_from_string("busy_writing");
4435 static void module_destroy()
4440 LTTV_MODULE("state", "State computation", \
4441 "Update the system state, possibly saving it at intervals", \
4442 module_init
, module_destroy
)