1 /* This file is part of the Linux Trace Toolkit viewer
2 * Copyright (C) 2003-2004 Michel Dagenais
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License Version 2 as
6 * published by the Free Software Foundation;
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
13 * You should have received a copy of the GNU General Public License
14 * along with this program; if not, write to the Free Software
15 * Foundation, Inc., 59 Temple Place - Suite 330, Boston,
25 #include <lttv/lttv.h>
26 #include <lttv/module.h>
27 #include <lttv/state.h>
28 #include <lttv/compiler.h>
29 #include <lttv/traceset.h>
30 #include <lttv/trace.h>
34 #include <babeltrace/babeltrace.h>
36 #define PREALLOCATED_EXECUTION_STACK 10
42 LTT_CHANNEL_GLOBAL_STATE
,
43 LTT_CHANNEL_IRQ_STATE
,
44 LTT_CHANNEL_MODULE_STATE
,
45 LTT_CHANNEL_NETIF_STATE
,
46 LTT_CHANNEL_SOFTIRQ_STATE
,
47 LTT_CHANNEL_SWAP_STATE
,
48 LTT_CHANNEL_SYSCALL_STATE
,
49 LTT_CHANNEL_TASK_STATE
,
51 LTT_CHANNEL_KPROBE_STATE
,
55 LTT_CHANNEL_USERSPACE
,
61 LTT_EVENT_SYSCALL_ENTRY
,
62 LTT_EVENT_SYSCALL_EXIT
,
63 LTT_EVENT_PAGE_FAULT_NOSEM_ENTRY
,
64 LTT_EVENT_PAGE_FAULT_NOSEM_EXIT
,
65 LTT_EVENT_PAGE_FAULT_ENTRY
,
66 LTT_EVENT_PAGE_FAULT_EXIT
,
67 //LTT_EVENT_TRAP_ENTRY,
68 //LTT_EVENT_TRAP_EXIT,
71 LTT_EVENT_SOFT_IRQ_RAISE
,
72 LTT_EVENT_SOFT_IRQ_ENTRY
,
73 LTT_EVENT_SOFT_IRQ_EXIT
,
74 LTT_EVENT_SCHED_SCHEDULE
,
75 LTT_EVENT_SCHED_TRY_WAKEUP
,
76 LTT_EVENT_PROCESS_FORK
,
77 LTT_EVENT_KTHREAD_CREATE
,
78 LTT_EVENT_PROCESS_EXIT
,
79 LTT_EVENT_PROCESS_FREE
,
81 LTT_EVENT_PROCESS_STATE
,
82 LTT_EVENT_STATEDUMP_END
,
83 LTT_EVENT_FUNCTION_ENTRY
,
84 LTT_EVENT_FUNCTION_EXIT
,
85 LTT_EVENT_REQUEST_ISSUE
,
86 LTT_EVENT_REQUEST_COMPLETE
,
87 LTT_EVENT_LIST_INTERRUPT
,
88 LTT_EVENT_SYS_CALL_TABLE
,
89 LTT_EVENT_SOFTIRQ_VEC
,
90 LTT_EVENT_KPROBE_TABLE
,
102 LTT_FIELD_SOFT_IRQ_ID
,
105 LTT_FIELD_PREV_STATE
,
106 LTT_FIELD_PARENT_PID
,
110 LTT_FIELD_CHILD_TGID
,
132 LTTV_STATE_MODE_UNKNOWN
,
133 LTTV_STATE_USER_MODE
,
134 LTTV_STATE_MAYBE_USER_MODE
,
136 LTTV_STATE_MAYBE_SYSCALL
,
138 LTTV_STATE_MAYBE_TRAP
,
143 LTTV_STATE_SUBMODE_UNKNOWN
,
144 LTTV_STATE_SUBMODE_NONE
;
148 LTTV_STATE_WAIT_FORK
,
157 LTTV_STATE_USER_THREAD
,
158 LTTV_STATE_KERNEL_THREAD
;
176 LTTV_BDEV_BUSY_READING
,
177 LTTV_BDEV_BUSY_WRITING
;
180 LTTV_STATE_TRACEFILES
,
181 LTTV_STATE_PROCESSES
,
183 LTTV_STATE_RUNNING_PROCESS
,
185 LTTV_STATE_SAVED_STATES
,
186 LTTV_STATE_SAVED_STATES_TIME
,
189 LTTV_STATE_NAME_TABLES
,
190 LTTV_STATE_TRACE_STATE_USE_COUNT
,
191 LTTV_STATE_RESOURCE_CPUS
,
192 LTTV_STATE_RESOURCE_CPUS_COUNT
,
193 LTTV_STATE_RESOURCE_IRQS
,
194 LTTV_STATE_RESOURCE_SOFT_IRQS
,
195 LTTV_STATE_RESOURCE_TRAPS
,
196 LTTV_STATE_RESOURCE_BLKDEVS
;
198 static void create_max_time(LttvTraceState
*tcs
);
200 static void get_max_time(LttvTraceState
*tcs
);
202 static void free_max_time(LttvTraceState
*tcs
);
204 static void create_name_tables(LttvTraceState
*tcs
);
206 static void get_name_tables(LttvTraceState
*tcs
);
208 static void free_name_tables(LttvTraceState
*tcs
);
210 static void free_saved_state(LttvTraceState
*tcs
);
212 static void lttv_state_free_process_table(GHashTable
*processes
);
214 static void lttv_trace_states_read_raw(LttvTraceState
*tcs
, FILE *fp
,
215 GPtrArray
*quarktable
);
217 /* Resource function prototypes */
218 static LttvBdevState
*get_hashed_bdevstate(LttvTraceState
*ts
, guint32 devcode
);
219 static LttvBdevState
*bdevstate_new(void);
220 static void bdevstate_free(LttvBdevState
*);
221 static void bdevstate_free_cb(gpointer key
, gpointer value
, gpointer user_data
);
222 static LttvBdevState
*bdevstate_copy(LttvBdevState
*bds
);
223 void lttv_state_add_event_hooks(LttvTraceset
*traceset
);
225 #if (__WORDSIZE == 32)
226 guint
guint64_hash(gconstpointer key
)
228 guint64 ukey
= *(const guint64
*)key
;
230 return (guint
)ukey
^ (guint
)(ukey
>> 32);
233 gboolean
guint64_equal(gconstpointer a
, gconstpointer b
)
235 guint64 ua
= *(const guint64
*)a
;
236 guint64 ub
= *(const guint64
*)b
;
242 guint
process_hash(gconstpointer key
)
244 guint pid
= ((const LttvProcessState
*)key
)->pid
;
245 return (pid
>>8 ^ pid
>>4 ^ pid
>>2 ^ pid
) ;
249 /* If the hash table hash function is well distributed,
250 * the process_equal should compare different pid */
251 gboolean
process_equal(gconstpointer a
, gconstpointer b
)
253 const LttvProcessState
*process_a
, *process_b
;
256 process_a
= (const LttvProcessState
*)a
;
257 process_b
= (const LttvProcessState
*)b
;
259 if(likely(process_a
->pid
!= process_b
->pid
)) ret
= FALSE
;
260 else if(likely(process_a
->pid
== 0 &&
261 process_a
->cpu
!= process_b
->cpu
)) ret
= FALSE
;
266 gboolean
rettrue(gpointer key
, gpointer value
, gpointer user_data
)
271 static guint
check_expand(nb
, id
)
276 return max(id
+ 1, nb
* 2);
279 static void expand_name_table(LttvTraceState
*ts
, GQuark
**table
,
280 guint nb
, guint new_nb
)
282 /* Expand an incomplete table */
283 GQuark
*old_table
= *table
;
284 *table
= g_new(GQuark
, new_nb
);
285 memcpy(*table
, old_table
, nb
* sizeof(GQuark
));
289 static void fill_name_table(LttvTraceState
*ts
, GQuark
*table
, guint nb
,
290 guint new_nb
, const char *def_string
)
293 GString
*fe_name
= g_string_new("");
294 for(i
= nb
; i
< new_nb
; i
++) {
295 g_string_printf(fe_name
, "%s %d", def_string
, i
);
296 table
[i
] = g_quark_from_string(fe_name
->str
);
298 g_string_free(fe_name
, TRUE
);
301 static void expand_kprobe_table(LttvTraceState
*ts
, guint64 ip
, char *symbol
)
303 LttvNameTables
*nt
= ts
->name_tables
;
304 #if (__WORDSIZE == 32)
305 guint64
*ip_ptr
= g_new(guint64
, 1);
306 g_hash_table_insert(nt
->kprobe_hash
, ip_ptr
,
307 (gpointer
)(glong
)g_quark_from_string(symbol
));
309 g_hash_table_insert(nt
->kprobe_hash
, (gpointer
)ip
,
310 (gpointer
)(glong
)g_quark_from_string(symbol
));
314 static void expand_trap_table(LttvTraceState
*ts
, int id
)
316 LttvNameTables
*nt
= ts
->name_tables
;
317 LttvTrapState
*old_table
;
320 new_nb
= check_expand(nt
->nb_traps
, id
);
321 if(likely(new_nb
== nt
->nb_traps
))
324 expand_name_table(ts
, &nt
->trap_names
, nt
->nb_traps
, new_nb
);
325 fill_name_table(ts
, nt
->trap_names
, nt
->nb_traps
, new_nb
, "trap");
327 old_table
= ts
->trap_states
;
328 ts
->trap_states
= g_new(LttvTrapState
, new_nb
);
329 memcpy(ts
->trap_states
, old_table
, nt
->nb_traps
* sizeof(LttvTrapState
));
331 for(i
= nt
->nb_traps
; i
< new_nb
; i
++)
332 ts
->trap_states
[i
].running
= 0;
334 /* Update the table size */
335 nt
->nb_traps
= new_nb
;
338 static void expand_irq_table(LttvTraceState
*ts
, int id
)
340 LttvNameTables
*nt
= ts
->name_tables
;
341 LttvIRQState
*old_table
;
344 new_nb
= check_expand(nt
->nb_irqs
, id
);
345 if(likely(new_nb
== nt
->nb_irqs
))
348 expand_name_table(ts
, &nt
->irq_names
, nt
->nb_irqs
, new_nb
);
349 fill_name_table(ts
, nt
->irq_names
, nt
->nb_irqs
, new_nb
, "irq");
351 old_table
= ts
->irq_states
;
352 ts
->irq_states
= g_new(LttvIRQState
, new_nb
);
353 memcpy(ts
->irq_states
, old_table
, nt
->nb_irqs
* sizeof(LttvIRQState
));
355 for(i
= nt
->nb_irqs
; i
< new_nb
; i
++)
356 ts
->irq_states
[i
].mode_stack
=
357 g_array_new(FALSE
, FALSE
, sizeof(LttvIRQMode
));
359 /* Update the table size */
360 nt
->nb_irqs
= new_nb
;
363 static void expand_soft_irq_table(LttvTraceState
*ts
, int id
)
365 LttvNameTables
*nt
= ts
->name_tables
;
366 LttvSoftIRQState
*old_table
;
369 new_nb
= check_expand(nt
->nb_soft_irqs
, id
);
370 if(likely(new_nb
== nt
->nb_soft_irqs
))
373 expand_name_table(ts
, &nt
->soft_irq_names
, nt
->nb_soft_irqs
, new_nb
);
374 fill_name_table(ts
, nt
->soft_irq_names
, nt
->nb_soft_irqs
, new_nb
, "softirq");
376 old_table
= ts
->soft_irq_states
;
377 ts
->soft_irq_states
= g_new(LttvSoftIRQState
, new_nb
);
378 memcpy(ts
->soft_irq_states
, old_table
,
379 nt
->nb_soft_irqs
* sizeof(LttvSoftIRQState
));
381 for(i
= nt
->nb_soft_irqs
; i
< new_nb
; i
++)
382 ts
->soft_irq_states
[i
].running
= 0;
384 /* Update the table size */
385 nt
->nb_soft_irqs
= new_nb
;
388 static void restore_init_state(LttvTraceState
*self
)
390 guint i
, nb_cpus
, nb_irqs
, nb_soft_irqs
, nb_traps
;
392 //LttvTracefileState *tfcs;
396 /* Free the process tables */
397 if(self
->processes
!= NULL
) lttv_state_free_process_table(self
->processes
);
398 self
->processes
= g_hash_table_new(process_hash
, process_equal
);
401 /* Seek time to beginning */
402 // Mathieu : fix : don't seek traceset here : causes inconsistency in seek
403 // closest. It's the tracecontext job to seek the trace to the beginning
404 // anyway : the init state might be used at the middle of the trace as well...
405 //g_tree_destroy(self->parent.ts_context->pqueue);
406 //self->parent.ts_context->pqueue = g_tree_new(compare_tracefile);
408 start_time
= ltt_time_from_uint64(
409 bt_trace_handle_get_timestamp_begin(self
->trace
->traceset
->context
,
410 self
->trace
->id
,BT_CLOCK_REAL
));
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 LTTV_STATE_UNNAMED
, &start_time
);
425 /* We are not sure is it's a kernel thread or normal thread, put the
426 * bottom stack state to unknown */
427 self
->running_process
[i
]->execution_stack
=
428 g_array_set_size(self
->running_process
[i
]->execution_stack
, 1);
429 es
= self
->running_process
[i
]->state
=
430 &g_array_index(self
->running_process
[i
]->execution_stack
,
431 LttvExecutionState
, 0);
432 es
->t
= LTTV_STATE_MODE_UNKNOWN
;
433 es
->s
= LTTV_STATE_UNNAMED
;
435 //self->running_process[i]->state->s = LTTV_STATE_RUN;
436 self
->running_process
[i
]->cpu
= i
;
438 /* reset cpu states */
439 if(self
->cpu_states
[i
].mode_stack
->len
> 0) {
440 g_array_remove_range(self
->cpu_states
[i
].mode_stack
, 0,
441 self
->cpu_states
[i
].mode_stack
->len
);
442 if(self
->cpu_states
[i
].irq_stack
->len
)
443 g_array_remove_range(self
->cpu_states
[i
].irq_stack
, 0,
444 self
->cpu_states
[i
].irq_stack
->len
);
445 if(self
->cpu_states
[i
].softirq_stack
->len
)
446 g_array_remove_range(self
->cpu_states
[i
].softirq_stack
, 0,
447 self
->cpu_states
[i
].softirq_stack
->len
);
448 if(self
->cpu_states
[i
].trap_stack
->len
)
449 g_array_remove_range(self
->cpu_states
[i
].trap_stack
, 0,
450 self
->cpu_states
[i
].trap_stack
->len
);
454 /* reset irq states */
455 for(i
=0; i
<nb_irqs
; i
++) {
456 if(self
->irq_states
[i
].mode_stack
->len
> 0)
457 g_array_remove_range(self
->irq_states
[i
].mode_stack
, 0,
458 self
->irq_states
[i
].mode_stack
->len
);
461 /* reset softirq states */
462 for(i
=0; i
<nb_soft_irqs
; i
++) {
463 self
->soft_irq_states
[i
].pending
= 0;
464 self
->soft_irq_states
[i
].running
= 0;
467 /* reset trap states */
468 for(i
=0; i
<nb_traps
; i
++) {
469 self
->trap_states
[i
].running
= 0;
472 /* reset bdev states */
473 g_hash_table_foreach(self
->bdev_states
, bdevstate_free_cb
, NULL
);
474 //g_hash_table_steal_all(self->bdev_states);
475 g_hash_table_foreach_steal(self
->bdev_states
, rettrue
, NULL
);
478 nb_tracefile
= self
->parent
.tracefiles
->len
;
480 for(i
= 0 ; i
< nb_tracefile
; i
++) {
482 LTTV_TRACEFILE_STATE(g_array_index(self
->parent
.tracefiles
,
483 LttvTracefileContext
*, i
));
484 ltt_trace_time_span_get(self
->parent
.t
, &tfcs
->parent
.timestamp
, NULL
);
485 // tfcs->saved_position = 0;
486 tfcs
->process
= lttv_state_create_process(tfcs
, NULL
,0);
487 tfcs
->process
->state
->s
= LTTV_STATE_RUN
;
488 tfcs
->process
->last_cpu
= tfcs
->cpu_name
;
489 tfcs
->process
->last_cpu_index
= ltt_tracefile_num(((LttvTracefileContext
*)tfcs
)->tf
);
494 //static LttTime time_zero = {0,0};
498 #define MAX_STRING_LEN 4096
500 static void state_load_saved_states(LttvTraceState
*tcs
)
503 GPtrArray
*quarktable
;
504 const char *trace_path
;
508 tcs
->has_precomputed_states
= FALSE
;
512 gchar buf
[MAX_STRING_LEN
];
516 trace_path
= g_quark_to_string(ltt_trace_name(tcs
->parent
.t
));
517 strncpy(path
, trace_path
, PATH_MAX
-1);
518 count
= strnlen(trace_path
, PATH_MAX
-1);
519 // quarktable : open, test
520 strncat(path
, "/precomputed/quarktable", PATH_MAX
-count
-1);
521 fp
= fopen(path
, "r");
523 quarktable
= g_ptr_array_sized_new(4096);
525 /* Index 0 is null */
527 if(hdr
== EOF
) return;
528 g_assert(hdr
== HDR_QUARKS
);
532 if(hdr
== EOF
) break;
533 g_assert(hdr
== HDR_QUARK
);
534 g_ptr_array_set_size(quarktable
, q
+1);
537 res
= fread(&buf
[i
], sizeof(gchar
), 1, fp
);
539 if(buf
[i
] == '\0' || feof(fp
)) break;
542 len
= strnlen(buf
, MAX_STRING_LEN
-1);
543 g_ptr_array_index (quarktable
, q
) = g_new(gchar
, len
+1);
544 strncpy(g_ptr_array_index (quarktable
, q
), buf
, len
+1);
550 // saved_states : open, test
551 strncpy(path
, trace_path
, PATH_MAX
-1);
552 count
= strnlen(trace_path
, PATH_MAX
-1);
553 strncat(path
, "/precomputed/states", PATH_MAX
-count
-1);
554 fp
= fopen(path
, "r");
558 if(hdr
!= HDR_TRACE
) goto end
;
560 lttv_trace_states_read_raw(tcs
, fp
, quarktable
);
562 tcs
->has_precomputed_states
= TRUE
;
567 /* Free the quarktable */
568 for(i
=0; i
<quarktable
->len
; i
++) {
569 string
= g_ptr_array_index (quarktable
, i
);
572 g_ptr_array_free(quarktable
, TRUE
);
575 #endif /* BABEL_CLEANUP */
577 void lttv_trace_state_init(LttvTraceState
*trace_state
, LttvTrace
*trace
)
581 LttvAttributeValue v
;
583 trace_state
->trace
= trace
;
585 trace_state
->save_interval
= LTTV_STATE_SAVE_INTERVAL
;
586 lttv_attribute_find(lttv_trace_attribute(trace
), LTTV_STATE_TRACE_STATE_USE_COUNT
,
590 if (*(v
.v_uint
) == 1) {
591 create_name_tables(trace_state
);
592 create_max_time(trace_state
);
594 get_name_tables(trace_state
);
595 get_max_time(trace_state
);
597 nb_cpu
= lttv_trace_get_num_cpu(trace
);
598 nb_irq
= trace_state
->name_tables
->nb_irqs
;
599 trace_state
->processes
= NULL
;
600 trace_state
->running_process
= g_new(LttvProcessState
*, nb_cpu
);
602 /* init cpu resource stuff */
603 trace_state
->cpu_states
= g_new(LttvCPUState
, nb_cpu
);
604 for (j
= 0; j
< nb_cpu
; j
++) {
605 trace_state
->cpu_states
[j
].mode_stack
= g_array_new(FALSE
, FALSE
, sizeof(LttvCPUMode
));
606 trace_state
->cpu_states
[j
].irq_stack
= g_array_new(FALSE
, FALSE
, sizeof(gint
));
607 trace_state
->cpu_states
[j
].softirq_stack
= g_array_new(FALSE
, FALSE
, sizeof(gint
));
608 trace_state
->cpu_states
[j
].trap_stack
= g_array_new(FALSE
, FALSE
, sizeof(gint
));
609 g_assert(trace_state
->cpu_states
[j
].mode_stack
!= NULL
);
612 /* init irq resource stuff */
613 trace_state
->irq_states
= g_new(LttvIRQState
, nb_irq
);
614 for (j
= 0; j
< nb_irq
; j
++) {
615 trace_state
->irq_states
[j
].mode_stack
= g_array_new(FALSE
, FALSE
, sizeof(LttvIRQMode
));
616 g_assert(trace_state
->irq_states
[j
].mode_stack
!= NULL
);
619 /* init soft irq stuff */
620 /* the kernel has a statically fixed max of 32 softirqs */
621 trace_state
->soft_irq_states
= g_new(LttvSoftIRQState
, trace_state
->name_tables
->nb_soft_irqs
);
623 /* init trap stuff */
624 trace_state
->trap_states
= g_new(LttvTrapState
, trace_state
->name_tables
->nb_traps
);
626 /* init bdev resource stuff */
627 trace_state
->bdev_states
= g_hash_table_new(g_int_hash
, g_int_equal
);
629 restore_init_state(trace_state
);
631 /* See if the trace has saved states */
632 //state_load_saved_states(trace_state);
635 void lttv_trace_state_fini(LttvTraceState
*trace_state
)
637 LttvTrace
*trace
= trace_state
->trace
;
638 LttvAttributeValue v
;
640 lttv_attribute_find(lttv_trace_attribute(trace
), LTTV_STATE_TRACE_STATE_USE_COUNT
,
643 g_assert(*(v
.v_uint
) != 0);
646 if (*(v
.v_uint
) == 0) {
647 free_name_tables(trace_state
);
648 free_max_time(trace_state
);
649 free_saved_state(trace_state
);
651 g_free(trace_state
->running_process
);
652 trace_state
->running_process
= NULL
;
653 lttv_state_free_process_table(trace_state
->processes
);
654 trace_state
->processes
= NULL
;
659 /* Write the process state of the trace */
661 static void write_process_state(gpointer key
, gpointer value
,
664 LttvProcessState
*process
;
666 LttvExecutionState
*es
;
668 FILE *fp
= (FILE *)user_data
;
673 process
= (LttvProcessState
*)value
;
674 fprintf(fp
," <PROCESS CORE=%p PID=%u TGID=%u PPID=%u TYPE=\"%s\" CTIME_S=%lu CTIME_NS=%lu ITIME_S=%lu ITIME_NS=%lu NAME=\"%s\" CPU=\"%u\" FREE_EVENTS=\"%u\">\n",
675 process
, process
->pid
, process
->tgid
, process
->ppid
,
676 g_quark_to_string(process
->type
),
677 process
->creation_time
.tv_sec
,
678 process
->creation_time
.tv_nsec
,
679 process
->insertion_time
.tv_sec
,
680 process
->insertion_time
.tv_nsec
,
681 g_quark_to_string(process
->name
),
682 process
->cpu
, process
->free_events
);
684 for(i
= 0 ; i
< process
->execution_stack
->len
; i
++) {
685 es
= &g_array_index(process
->execution_stack
, LttvExecutionState
, i
);
686 fprintf(fp
, " <ES MODE=\"%s\" SUBMODE=\"%s\" ENTRY_S=%lu ENTRY_NS=%lu",
687 g_quark_to_string(es
->t
), g_quark_to_string(es
->n
),
688 es
->entry
.tv_sec
, es
->entry
.tv_nsec
);
689 fprintf(fp
, " CHANGE_S=%lu CHANGE_NS=%lu STATUS=\"%s\"/>\n",
690 es
->change
.tv_sec
, es
->change
.tv_nsec
, g_quark_to_string(es
->s
));
693 for(i
= 0 ; i
< process
->user_stack
->len
; i
++) {
694 address
= g_array_index(process
->user_stack
, guint64
, i
);
695 fprintf(fp
, " <USER_STACK ADDRESS=\"%" PRIu64
"\"/>\n", address
);
698 fprintf(fp
, " </PROCESS>\n");
702 void lttv_state_write(LttvTraceState
*self
, LttTime t
, FILE *fp
)
704 guint i
, nb_tracefile
, nb_block
, offset
;
707 LttvTracefileState
*tfcs
;
711 LttEventPosition
*ep
;
715 ep
= ltt_event_position_new();
717 fprintf(fp
,"<PROCESS_STATE TIME_S=%lu TIME_NS=%lu>\n", t
.tv_sec
, t
.tv_nsec
);
719 g_hash_table_foreach(self
->processes
, write_process_state
, fp
);
721 nb_cpus
= ltt_trace_get_num_cpu(self
->parent
.t
);
722 for(i
=0;i
<nb_cpus
;i
++) {
723 fprintf(fp
," <CPU NUM=%u RUNNING_PROCESS=%u>\n",
724 i
, self
->running_process
[i
]->pid
);
727 nb_tracefile
= self
->parent
.tracefiles
->len
;
729 for(i
= 0 ; i
< nb_tracefile
; i
++) {
731 LTTV_TRACEFILE_STATE(g_array_index(self
->parent
.tracefiles
,
732 LttvTracefileContext
*, i
));
733 fprintf(fp
, " <TRACEFILE TIMESTAMP_S=%lu TIMESTAMP_NS=%lu",
734 tfcs
->parent
.timestamp
.tv_sec
,
735 tfcs
->parent
.timestamp
.tv_nsec
);
736 LttEvent
*e
= ltt_tracefile_get_event(tfcs
->parent
.tf
);
737 if(e
== NULL
) fprintf(fp
,"/>\n");
739 ltt_event_position(e
, ep
);
740 ltt_event_position_get(ep
, &tf
, &nb_block
, &offset
, &tsc
);
741 fprintf(fp
, " BLOCK=%u OFFSET=%u TSC=%" PRIu64
"/>\n", nb_block
, offset
,
746 fprintf(fp
,"</PROCESS_STATE>\n");
750 static void write_process_state_raw(gpointer key
, gpointer value
,
753 LttvProcessState
*process
;
755 LttvExecutionState
*es
;
757 FILE *fp
= (FILE *)user_data
;
762 process
= (LttvProcessState
*)value
;
763 fputc(HDR_PROCESS
, fp
);
764 //fwrite(&header, sizeof(header), 1, fp);
765 //fprintf(fp, "%s", g_quark_to_string(process->type));
767 fwrite(&process
->type
, sizeof(process
->type
), 1, fp
);
768 //fprintf(fp, "%s", g_quark_to_string(process->name));
770 fwrite(&process
->name
, sizeof(process
->name
), 1, fp
);
772 fwrite(&process
->pid
, sizeof(process
->pid
), 1, fp
);
773 fwrite(&process
->free_events
, sizeof(process
->free_events
), 1, fp
);
774 fwrite(&process
->tgid
, sizeof(process
->tgid
), 1, fp
);
775 fwrite(&process
->ppid
, sizeof(process
->ppid
), 1, fp
);
776 fwrite(&process
->cpu
, sizeof(process
->cpu
), 1, fp
);
777 fwrite(&process
->creation_time
, sizeof(process
->creation_time
), 1, fp
);
778 fwrite(&process
->insertion_time
, sizeof(process
->insertion_time
), 1, fp
);
781 fprintf(fp
," <PROCESS CORE=%p PID=%u TGID=%u PPID=%u TYPE=\"%s\" CTIME_S=%lu CTIME_NS=%lu ITIME_S=%lu ITIME_NS=%lu NAME=\"%s\" CPU=\"%u\" PROCESS_TYPE=%u>\n",
782 process
, process
->pid
, process
->tgid
, process
->ppid
,
783 g_quark_to_string(process
->type
),
784 process
->creation_time
.tv_sec
,
785 process
->creation_time
.tv_nsec
,
786 process
->insertion_time
.tv_sec
,
787 process
->insertion_time
.tv_nsec
,
788 g_quark_to_string(process
->name
),
792 for(i
= 0 ; i
< process
->execution_stack
->len
; i
++) {
793 es
= &g_array_index(process
->execution_stack
, LttvExecutionState
, i
);
796 //fprintf(fp, "%s", g_quark_to_string(es->t));
798 fwrite(&es
->t
, sizeof(es
->t
), 1, fp
);
799 //fprintf(fp, "%s", g_quark_to_string(es->n));
801 fwrite(&es
->n
, sizeof(es
->n
), 1, fp
);
802 //fprintf(fp, "%s", g_quark_to_string(es->s));
804 fwrite(&es
->s
, sizeof(es
->s
), 1, fp
);
805 fwrite(&es
->entry
, sizeof(es
->entry
), 1, fp
);
806 fwrite(&es
->change
, sizeof(es
->change
), 1, fp
);
807 fwrite(&es
->cum_cpu_time
, sizeof(es
->cum_cpu_time
), 1, fp
);
809 fprintf(fp
, " <ES MODE=\"%s\" SUBMODE=\"%s\" ENTRY_S=%lu ENTRY_NS=%lu",
810 g_quark_to_string(es
->t
), g_quark_to_string(es
->n
),
811 es
->entry
.tv_sec
, es
->entry
.tv_nsec
);
812 fprintf(fp
, " CHANGE_S=%lu CHANGE_NS=%lu STATUS=\"%s\"/>\n",
813 es
->change
.tv_sec
, es
->change
.tv_nsec
, g_quark_to_string(es
->s
));
817 for(i
= 0 ; i
< process
->user_stack
->len
; i
++) {
818 address
= g_array_index(process
->user_stack
, guint64
, i
);
819 fputc(HDR_USER_STACK
, fp
);
820 fwrite(&address
, sizeof(address
), 1, fp
);
822 fprintf(fp
, " <USER_STACK ADDRESS=\"%llu\"/>\n", address
);
828 void lttv_state_write_raw(LttvTraceState
*self
, LttTime t
, FILE *fp
)
830 guint i
, nb_tracefile
, nb_block
, offset
;
833 LttvTracefileState
*tfcs
;
837 LttEventPosition
*ep
;
841 ep
= ltt_event_position_new();
843 //fprintf(fp,"<PROCESS_STATE TIME_S=%lu TIME_NS=%lu>\n", t.tv_sec, t.tv_nsec);
844 fputc(HDR_PROCESS_STATE
, fp
);
845 fwrite(&t
, sizeof(t
), 1, fp
);
847 g_hash_table_foreach(self
->processes
, write_process_state_raw
, fp
);
849 nb_cpus
= ltt_trace_get_num_cpu(self
->parent
.t
);
850 for(i
=0;i
<nb_cpus
;i
++) {
852 fwrite(&i
, sizeof(i
), 1, fp
); /* cpu number */
853 fwrite(&self
->running_process
[i
]->pid
,
854 sizeof(self
->running_process
[i
]->pid
), 1, fp
);
855 //fprintf(fp," <CPU NUM=%u RUNNING_PROCESS=%u>\n",
856 // i, self->running_process[i]->pid);
859 nb_tracefile
= self
->parent
.tracefiles
->len
;
861 for(i
= 0 ; i
< nb_tracefile
; i
++) {
863 LTTV_TRACEFILE_STATE(g_array_index(self
->parent
.tracefiles
,
864 LttvTracefileContext
*, i
));
865 // fprintf(fp, " <TRACEFILE TIMESTAMP_S=%lu TIMESTAMP_NS=%lu",
866 // tfcs->parent.timestamp.tv_sec,
867 // tfcs->parent.timestamp.tv_nsec);
868 fputc(HDR_TRACEFILE
, fp
);
869 fwrite(&tfcs
->parent
.timestamp
, sizeof(tfcs
->parent
.timestamp
), 1, fp
);
870 /* Note : if timestamp if LTT_TIME_INFINITE, there will be no
871 * position following : end of trace */
872 LttEvent
*e
= ltt_tracefile_get_event(tfcs
->parent
.tf
);
874 ltt_event_position(e
, ep
);
875 ltt_event_position_get(ep
, &tf
, &nb_block
, &offset
, &tsc
);
876 //fprintf(fp, " BLOCK=%u OFFSET=%u TSC=%llu/>\n", nb_block, offset,
878 fwrite(&nb_block
, sizeof(nb_block
), 1, fp
);
879 fwrite(&offset
, sizeof(offset
), 1, fp
);
880 fwrite(&tsc
, sizeof(tsc
), 1, fp
);
887 /* Read process state from a file */
889 /* Called because a HDR_PROCESS was found */
890 static void read_process_state_raw(LttvTraceState
*self
, FILE *fp
,
891 GPtrArray
*quarktable
)
893 LttvExecutionState
*es
;
894 LttvProcessState
*process
, *parent_process
;
895 LttvProcessState tmp
;
901 res
= fread(&tmp
.type
, sizeof(tmp
.type
), 1, fp
);
902 res
+= fread(&tmp
.name
, sizeof(tmp
.name
), 1, fp
);
903 res
+= fread(&tmp
.pid
, sizeof(tmp
.pid
), 1, fp
);
904 res
+= fread(&tmp
.free_events
, sizeof(tmp
.free_events
), 1, fp
);
905 res
+= fread(&tmp
.tgid
, sizeof(tmp
.tgid
), 1, fp
);
906 res
+= fread(&tmp
.ppid
, sizeof(tmp
.ppid
), 1, fp
);
907 res
+= fread(&tmp
.cpu
, sizeof(tmp
.cpu
), 1, fp
);
908 res
+= fread(&tmp
.creation_time
, sizeof(tmp
.creation_time
), 1, fp
);
909 res
+= fread(&tmp
.insertion_time
, sizeof(tmp
.insertion_time
), 1, fp
);
913 process
= lttv_state_find_process(self
, tmp
.cpu
, tmp
.pid
);
915 /* We must link to the parent */
916 parent_process
= lttv_state_find_process_or_create(self
, ANY_CPU
, tmp
.ppid
,
918 process
= lttv_state_find_process(self
, ANY_CPU
, tmp
.pid
);
919 if(process
== NULL
) {
920 process
= lttv_state_create_process(self
, parent_process
, tmp
.cpu
,
922 g_quark_from_string((gchar
*)g_ptr_array_index(quarktable
, tmp
.name
)),
926 process
->insertion_time
= tmp
.insertion_time
;
927 process
->creation_time
= tmp
.creation_time
;
928 process
->type
= g_quark_from_string(
929 (gchar
*)g_ptr_array_index(quarktable
, tmp
.type
));
930 process
->tgid
= tmp
.tgid
;
931 process
->ppid
= tmp
.ppid
;
933 g_quark_from_string((gchar
*)g_ptr_array_index(quarktable
, tmp
.name
));
934 process
->free_events
= tmp
.free_events
;
937 if(feof(fp
) || ferror(fp
)) goto end_loop
;
939 gint hdr
= fgetc(fp
);
940 if(hdr
== EOF
) goto end_loop
;
944 process
->execution_stack
=
945 g_array_set_size(process
->execution_stack
,
946 process
->execution_stack
->len
+ 1);
947 es
= &g_array_index(process
->execution_stack
, LttvExecutionState
,
948 process
->execution_stack
->len
-1);
951 res
= fread(&es
->t
, sizeof(es
->t
), 1, fp
);
953 es
->t
= g_quark_from_string(
954 (gchar
*)g_ptr_array_index(quarktable
, es
->t
));
955 res
= fread(&es
->n
, sizeof(es
->n
), 1, fp
);
957 es
->n
= g_quark_from_string(
958 (gchar
*)g_ptr_array_index(quarktable
, es
->n
));
959 res
= fread(&es
->s
, sizeof(es
->s
), 1, fp
);
961 es
->s
= g_quark_from_string(
962 (gchar
*)g_ptr_array_index(quarktable
, es
->s
));
963 res
= fread(&es
->entry
, sizeof(es
->entry
), 1, fp
);
964 res
+= fread(&es
->change
, sizeof(es
->change
), 1, fp
);
965 res
+= fread(&es
->cum_cpu_time
, sizeof(es
->cum_cpu_time
), 1, fp
);
970 process
->user_stack
= g_array_set_size(process
->user_stack
,
971 process
->user_stack
->len
+ 1);
972 address
= &g_array_index(process
->user_stack
, guint64
,
973 process
->user_stack
->len
-1);
974 res
= fread(address
, sizeof(address
), 1, fp
);
976 process
->current_function
= *address
;
989 /* Called because a HDR_PROCESS_STATE was found */
990 /* Append a saved state to the trace states */
991 void lttv_state_read_raw(LttvTraceState
*self
, FILE *fp
, GPtrArray
*quarktable
)
993 guint i
, nb_tracefile
, nb_block
, offset
;
995 LttvTracefileState
*tfcs
;
997 LttEventPosition
*ep
;
1006 LttvAttribute
*saved_states_tree
, *saved_state_tree
;
1008 LttvAttributeValue value
;
1009 GTree
*pqueue
= self
->parent
.ts_context
->pqueue
;
1010 ep
= ltt_event_position_new();
1012 restore_init_state(self
);
1014 res
= fread(&t
, sizeof(t
), 1, fp
);
1018 if(feof(fp
) || ferror(fp
)) goto end_loop
;
1020 if(hdr
== EOF
) goto end_loop
;
1024 /* Call read_process_state_raw */
1025 read_process_state_raw(self
, fp
, quarktable
);
1033 case HDR_USER_STACK
:
1034 case HDR_PROCESS_STATE
:
1040 g_error("Error while parsing saved state file : unknown data header %d",
1046 nb_cpus
= ltt_trace_get_num_cpu(self
->parent
.t
);
1047 for(i
=0;i
<nb_cpus
;i
++) {
1050 g_assert(hdr
== HDR_CPU
);
1051 res
= fread(&cpu_num
, sizeof(cpu_num
), 1, fp
); /* cpu number */
1053 g_assert(i
== cpu_num
);
1054 res
= fread(&self
->running_process
[i
]->pid
,
1055 sizeof(self
->running_process
[i
]->pid
), 1, fp
);
1059 nb_tracefile
= self
->parent
.tracefiles
->len
;
1061 for(i
= 0 ; i
< nb_tracefile
; i
++) {
1063 LTTV_TRACEFILE_STATE(g_array_index(self
->parent
.tracefiles
,
1064 LttvTracefileContext
*, i
));
1065 // fprintf(fp, " <TRACEFILE TIMESTAMP_S=%lu TIMESTAMP_NS=%lu",
1066 // tfcs->parent.timestamp.tv_sec,
1067 // tfcs->parent.timestamp.tv_nsec);
1068 g_tree_remove(pqueue
, &tfcs
->parent
);
1070 g_assert(hdr
== HDR_TRACEFILE
);
1071 res
= fread(&tfcs
->parent
.timestamp
, sizeof(tfcs
->parent
.timestamp
), 1, fp
);
1073 /* Note : if timestamp if LTT_TIME_INFINITE, there will be no
1074 * position following : end of trace */
1075 if(ltt_time_compare(tfcs
->parent
.timestamp
, ltt_time_infinite
) != 0) {
1076 res
= fread(&nb_block
, sizeof(nb_block
), 1, fp
);
1077 res
+= fread(&offset
, sizeof(offset
), 1, fp
);
1078 res
+= fread(&tsc
, sizeof(tsc
), 1, fp
);
1080 ltt_event_position_set(ep
, tfcs
->parent
.tf
, nb_block
, offset
, tsc
);
1081 gint ret
= ltt_tracefile_seek_position(tfcs
->parent
.tf
, ep
);
1083 g_tree_insert(pqueue
, &tfcs
->parent
, &tfcs
->parent
);
1088 saved_states_tree
= lttv_attribute_find_subdir(self
->parent
.t_a
,
1089 LTTV_STATE_SAVED_STATES
);
1090 saved_state_tree
= g_object_new(LTTV_ATTRIBUTE_TYPE
, NULL
);
1091 value
= lttv_attribute_add(saved_states_tree
,
1092 lttv_attribute_get_number(saved_states_tree
), LTTV_GOBJECT
);
1093 *(value
.v_gobject
) = (GObject
*)saved_state_tree
;
1094 value
= lttv_attribute_add(saved_state_tree
, LTTV_STATE_TIME
, LTTV_TIME
);
1095 *(value
.v_time
) = t
;
1096 lttv_state_save(self
, saved_state_tree
);
1097 g_debug("Saving state at time %lu.%lu", t
.tv_sec
,
1100 *(self
->max_time_state_recomputed_in_seek
) = t
;
1104 /* Called when a HDR_TRACE is found */
1105 void lttv_trace_states_read_raw(LttvTraceState
*tcs
, FILE *fp
,
1106 GPtrArray
*quarktable
)
1111 if(feof(fp
) || ferror(fp
)) goto end_loop
;
1113 if(hdr
== EOF
) goto end_loop
;
1116 case HDR_PROCESS_STATE
:
1117 /* Call read_process_state_raw */
1118 lttv_state_read_raw(tcs
, fp
, quarktable
);
1126 case HDR_USER_STACK
:
1129 g_error("Error while parsing saved state file :"
1130 " unexpected data header %d",
1134 g_error("Error while parsing saved state file : unknown data header %d",
1139 *(tcs
->max_time_state_recomputed_in_seek
) = tcs
->parent
.time_span
.end_time
;
1140 restore_init_state(tcs
);
1141 lttv_process_trace_seek_time(&tcs
->parent
, ltt_time_zero
);
1144 #endif /* BABEL_CLEANUP */
1147 /* Copy each process from an existing hash table to a new one */
1149 static void copy_process_state(gpointer key
, gpointer value
,gpointer user_data
)
1151 LttvProcessState
*process
, *new_process
;
1153 GHashTable
*new_processes
= (GHashTable
*)user_data
;
1157 process
= (LttvProcessState
*)value
;
1158 new_process
= g_new(LttvProcessState
, 1);
1159 *new_process
= *process
;
1160 new_process
->execution_stack
= g_array_sized_new(FALSE
, FALSE
,
1161 sizeof(LttvExecutionState
), PREALLOCATED_EXECUTION_STACK
);
1162 new_process
->execution_stack
=
1163 g_array_set_size(new_process
->execution_stack
,
1164 process
->execution_stack
->len
);
1165 for(i
= 0 ; i
< process
->execution_stack
->len
; i
++) {
1166 g_array_index(new_process
->execution_stack
, LttvExecutionState
, i
) =
1167 g_array_index(process
->execution_stack
, LttvExecutionState
, i
);
1169 new_process
->state
= &g_array_index(new_process
->execution_stack
,
1170 LttvExecutionState
, new_process
->execution_stack
->len
- 1);
1171 #ifdef BABEL_CLEANUP
1172 new_process
->user_stack
= g_array_sized_new(FALSE
, FALSE
,
1173 sizeof(guint64
), 0);
1174 new_process
->user_stack
= g_array_set_size(new_process
->user_stack
,
1175 process
->user_stack
->len
);
1176 for(i
= 0 ; i
< process
->user_stack
->len
; i
++) {
1177 g_array_index(new_process
->user_stack
, guint64
, i
) =
1178 g_array_index(process
->user_stack
, guint64
, i
);
1180 new_process
->current_function
= process
->current_function
;
1181 #endif /* BABEL_CLEANUP */
1183 /* fd hash table stuff */
1189 /* copy every item in the hash table */
1190 new_process
->fds
= g_hash_table_new(g_direct_hash
, g_direct_equal
);
1192 g_hash_table_iter_init(&it
, process
->fds
);
1193 while (g_hash_table_iter_next (&it
, (void *)&key
, (void *)&value
)) {
1194 g_hash_table_insert(new_process
->fds
, key
, value
);
1198 /* When done creating the new process state, insert it in the
1200 g_hash_table_insert(new_processes
, new_process
, new_process
);
1204 static GHashTable
*lttv_state_copy_process_table(GHashTable
*processes
)
1206 GHashTable
*new_processes
= g_hash_table_new(process_hash
, process_equal
);
1208 g_hash_table_foreach(processes
, copy_process_state
, new_processes
);
1209 return new_processes
;
1212 static LttvCPUState
*lttv_state_copy_cpu_states(LttvCPUState
*states
, guint n
)
1215 LttvCPUState
*retval
;
1217 retval
= g_new(LttvCPUState
, n
);
1219 for(i
=0; i
<n
; i
++) {
1220 retval
[i
].irq_stack
= g_array_new(FALSE
, FALSE
, sizeof(gint
));
1221 g_array_set_size(retval
[i
].irq_stack
, states
[i
].irq_stack
->len
);
1222 for(j
=0; j
<states
[i
].irq_stack
->len
; j
++) {
1223 g_array_index(retval
[i
].irq_stack
, gint
, j
) =
1224 g_array_index(states
[i
].irq_stack
, gint
, j
);
1227 retval
[i
].softirq_stack
= g_array_new(FALSE
, FALSE
, sizeof(gint
));
1228 g_array_set_size(retval
[i
].softirq_stack
, states
[i
].softirq_stack
->len
);
1229 for(j
=0; j
<states
[i
].softirq_stack
->len
; j
++) {
1230 g_array_index(retval
[i
].softirq_stack
, gint
, j
) =
1231 g_array_index(states
[i
].softirq_stack
, gint
, j
);
1234 retval
[i
].trap_stack
= g_array_new(FALSE
, FALSE
, sizeof(gint
));
1235 g_array_set_size(retval
[i
].trap_stack
, states
[i
].trap_stack
->len
);
1236 for(j
=0; j
<states
[i
].trap_stack
->len
; j
++) {
1237 g_array_index(retval
[i
].trap_stack
, gint
, j
) =
1238 g_array_index(states
[i
].trap_stack
, gint
, j
);
1241 retval
[i
].mode_stack
= g_array_new(FALSE
, FALSE
, sizeof(LttvCPUMode
));
1242 g_array_set_size(retval
[i
].mode_stack
, states
[i
].mode_stack
->len
);
1243 for(j
=0; j
<states
[i
].mode_stack
->len
; j
++) {
1244 g_array_index(retval
[i
].mode_stack
, GQuark
, j
) =
1245 g_array_index(states
[i
].mode_stack
, GQuark
, j
);
1252 static void lttv_state_free_cpu_states(LttvCPUState
*states
, guint n
)
1256 for(i
=0; i
<n
; i
++) {
1257 g_array_free(states
[i
].mode_stack
, TRUE
);
1258 g_array_free(states
[i
].irq_stack
, TRUE
);
1259 g_array_free(states
[i
].softirq_stack
, TRUE
);
1260 g_array_free(states
[i
].trap_stack
, TRUE
);
1266 static LttvIRQState
*lttv_state_copy_irq_states(LttvIRQState
*states
, guint n
)
1269 LttvIRQState
*retval
;
1271 retval
= g_new(LttvIRQState
, n
);
1273 for(i
=0; i
<n
; i
++) {
1274 retval
[i
].mode_stack
= g_array_new(FALSE
, FALSE
, sizeof(LttvIRQMode
));
1275 g_array_set_size(retval
[i
].mode_stack
, states
[i
].mode_stack
->len
);
1276 for(j
=0; j
<states
[i
].mode_stack
->len
; j
++) {
1277 g_array_index(retval
[i
].mode_stack
, GQuark
, j
) =
1278 g_array_index(states
[i
].mode_stack
, GQuark
, j
);
1285 static void lttv_state_free_irq_states(LttvIRQState
*states
, guint n
)
1289 for(i
=0; i
<n
; i
++) {
1290 g_array_free(states
[i
].mode_stack
, TRUE
);
1296 static LttvSoftIRQState
*
1297 lttv_state_copy_soft_irq_states(LttvSoftIRQState
*states
, guint n
)
1300 LttvSoftIRQState
*retval
;
1302 retval
= g_new(LttvSoftIRQState
, n
);
1304 for(i
=0; i
<n
; i
++) {
1305 retval
[i
].pending
= states
[i
].pending
;
1306 retval
[i
].running
= states
[i
].running
;
1312 static void lttv_state_free_soft_irq_states(LttvSoftIRQState
*states
, guint n
)
1317 static LttvTrapState
*
1318 lttv_state_copy_trap_states(LttvTrapState
*states
, guint n
)
1321 LttvTrapState
*retval
;
1323 retval
= g_new(LttvTrapState
, n
);
1325 for(i
=0; i
<n
; i
++) {
1326 retval
[i
].running
= states
[i
].running
;
1332 static void lttv_state_free_trap_states(LttvTrapState
*states
, guint n
)
1337 /* bdevstate stuff */
1339 static LttvBdevState
*get_hashed_bdevstate(LttvTraceState
*ts
, guint32 devcode
)
1341 gint devcode_gint
= devcode
;
1342 gpointer bdev
= g_hash_table_lookup(ts
->bdev_states
, &devcode_gint
);
1344 LttvBdevState
*bdevstate
= g_new(LttvBdevState
, 1);
1345 bdevstate
->mode_stack
= g_array_new(FALSE
, FALSE
, sizeof(GQuark
));
1347 gint
* key
= g_new(gint
, 1);
1349 g_hash_table_insert(ts
->bdev_states
, key
, bdevstate
);
1357 static LttvBdevState
*bdevstate_new(void)
1359 LttvBdevState
*retval
;
1360 retval
= g_new(LttvBdevState
, 1);
1361 retval
->mode_stack
= g_array_new(FALSE
, FALSE
, sizeof(GQuark
));
1366 static void bdevstate_free(LttvBdevState
*bds
)
1368 g_array_free(bds
->mode_stack
, TRUE
);
1372 static void bdevstate_free_cb(gpointer key
, gpointer value
, gpointer user_data
)
1374 LttvBdevState
*bds
= (LttvBdevState
*) value
;
1376 bdevstate_free(bds
);
1379 static LttvBdevState
*bdevstate_copy(LttvBdevState
*bds
)
1381 LttvBdevState
*retval
;
1383 retval
= bdevstate_new();
1384 g_array_insert_vals(retval
->mode_stack
, 0, bds
->mode_stack
->data
,
1385 bds
->mode_stack
->len
);
1390 static void insert_and_copy_bdev_state(gpointer k
, gpointer v
, gpointer u
)
1392 //GHashTable *ht = (GHashTable *)u;
1393 LttvBdevState
*bds
= (LttvBdevState
*)v
;
1394 LttvBdevState
*newbds
;
1396 newbds
= bdevstate_copy(bds
);
1398 g_hash_table_insert(u
, k
, newbds
);
1401 static GHashTable
*lttv_state_copy_blkdev_hashtable(GHashTable
*ht
)
1405 retval
= g_hash_table_new(g_int_hash
, g_int_equal
);
1407 g_hash_table_foreach(ht
, insert_and_copy_bdev_state
, retval
);
1412 /* Free a hashtable and the LttvBdevState structures its values
1415 static void lttv_state_free_blkdev_hashtable(GHashTable
*ht
)
1417 g_hash_table_foreach(ht
, bdevstate_free_cb
, NULL
);
1418 g_hash_table_destroy(ht
);
1421 /* The saved state for each trace contains a member "processes", which
1422 stores a copy of the process table, and a member "tracefiles" with
1423 one entry per tracefile. Each tracefile has a "process" member pointing
1424 to the current process and a "position" member storing the tracefile
1425 position (needed to seek to the current "next" event. */
1427 void lttv_state_save(LttvTraceState
*self
, LttvAttribute
*container
)
1429 guint i
, nb_cpus
, nb_irqs
, nb_soft_irqs
, nb_traps
;
1431 guint
*running_process
;
1433 LttvAttributeValue value
;
1435 value
= lttv_attribute_add(container
, LTTV_STATE_PROCESSES
,
1437 *(value
.v_pointer
) = lttv_state_copy_process_table(self
->processes
);
1439 /* Add the currently running processes array */
1440 nb_cpus
= lttv_trace_get_num_cpu(self
->trace
);
1441 running_process
= g_new(guint
, nb_cpus
);
1442 for(i
=0;i
<nb_cpus
;i
++) {
1443 running_process
[i
] = self
->running_process
[i
]->pid
;
1445 value
= lttv_attribute_add(container
, LTTV_STATE_RUNNING_PROCESS
,
1447 *(value
.v_pointer
) = running_process
;
1449 g_info("State save");
1451 /* Save the current position */
1452 value
= lttv_attribute_add(container
, LTTV_STATE_POSITION
,
1454 *(value
.v_pointer
) = lttv_traceset_create_current_position(lttv_trace_get_traceset(self
->trace
));
1456 #ifdef BABEL_CLEANUP
1457 nb_tracefile
= self
->parent
.tracefiles
->len
;
1458 for(i
= 0 ; i
< nb_tracefile
; i
++) {
1460 LTTV_TRACEFILE_STATE(g_array_index(self
->parent
.tracefiles
,
1461 LttvTracefileContext
*, i
));
1462 tracefile_tree
= g_object_new(LTTV_ATTRIBUTE_TYPE
, NULL
);
1463 value
= lttv_attribute_add(tracefiles_tree
, i
,
1465 *(value
.v_gobject
) = (GObject
*)tracefile_tree
;
1467 value
= lttv_attribute_add(tracefile_tree
, LTTV_STATE_PROCESS
,
1469 *(value
.v_uint
) = tfcs
->process
->pid
;
1471 value
= lttv_attribute_add(tracefile_tree
, LTTV_STATE_EVENT
,
1473 /* Only save the position if the tfs has not infinite time. */
1474 //if(!g_tree_lookup(self->parent.ts_context->pqueue, &tfcs->parent)
1475 // && current_tfcs != tfcs) {
1476 if(ltt_time_compare(tfcs
->parent
.timestamp
, ltt_time_infinite
) == 0) {
1477 *(value
.v_pointer
) = NULL
;
1479 LttEvent
*e
= ltt_tracefile_get_event(tfcs
->parent
.tf
);
1480 ep
= ltt_event_position_new();
1481 ltt_event_position(e
, ep
);
1482 *(value
.v_pointer
) = ep
;
1484 guint nb_block
, offset
;
1487 ltt_event_position_get(ep
, &tf
, &nb_block
, &offset
, &tsc
);
1488 g_info("Block %u offset %u tsc %" PRIu64
" time %lu.%lu", nb_block
,
1489 offset
, tsc
, tfcs
->parent
.timestamp
.tv_sec
,
1490 tfcs
->parent
.timestamp
.tv_nsec
);
1493 #endif /* BABEL_CLEANUP */
1495 /* save the cpu state */
1497 value
= lttv_attribute_add(container
, LTTV_STATE_RESOURCE_CPUS_COUNT
,
1499 *(value
.v_uint
) = nb_cpus
;
1501 value
= lttv_attribute_add(container
, LTTV_STATE_RESOURCE_CPUS
,
1503 *(value
.v_pointer
) = lttv_state_copy_cpu_states(self
->cpu_states
, nb_cpus
);
1506 /* save the irq state */
1507 nb_irqs
= self
->name_tables
->nb_irqs
;
1509 value
= lttv_attribute_add(container
, LTTV_STATE_RESOURCE_IRQS
,
1511 *(value
.v_pointer
) = lttv_state_copy_irq_states(self
->irq_states
, nb_irqs
);
1514 /* save the soft irq state */
1515 nb_soft_irqs
= self
->name_tables
->nb_soft_irqs
;
1517 value
= lttv_attribute_add(container
, LTTV_STATE_RESOURCE_SOFT_IRQS
,
1519 *(value
.v_pointer
) = lttv_state_copy_soft_irq_states(self
->soft_irq_states
, nb_soft_irqs
);
1522 /* save the trap state */
1523 nb_traps
= self
->name_tables
->nb_traps
;
1525 value
= lttv_attribute_add(container
, LTTV_STATE_RESOURCE_TRAPS
,
1527 *(value
.v_pointer
) = lttv_state_copy_trap_states(self
->trap_states
, nb_traps
);
1530 /* save the blkdev states */
1531 value
= lttv_attribute_add(container
, LTTV_STATE_RESOURCE_BLKDEVS
,
1533 *(value
.v_pointer
) = lttv_state_copy_blkdev_hashtable(self
->bdev_states
);
1536 void lttv_state_restore(LttvTraceState
*self
, LttvAttribute
*container
)
1538 guint i
, pid
, nb_cpus
, nb_irqs
, nb_soft_irqs
, nb_traps
;
1539 guint
*running_process
;
1540 LttvAttributeType type
;
1541 LttvAttributeValue value
;
1543 type
= lttv_attribute_get_by_name(container
, LTTV_STATE_PROCESSES
,
1545 g_assert(type
== LTTV_POINTER
);
1546 lttv_state_free_process_table(self
->processes
);
1547 self
->processes
= lttv_state_copy_process_table(*(value
.v_pointer
));
1549 /* Add the currently running processes array */
1550 nb_cpus
= lttv_trace_get_num_cpu(self
->trace
);
1551 type
= lttv_attribute_get_by_name(container
, LTTV_STATE_RUNNING_PROCESS
,
1553 g_assert(type
== LTTV_POINTER
);
1554 running_process
= *(value
.v_pointer
);
1555 for(i
=0;i
<nb_cpus
;i
++) {
1556 pid
= running_process
[i
];
1557 self
->running_process
[i
] = lttv_state_find_process(self
, i
, pid
);
1558 g_assert(self
->running_process
[i
] != NULL
);
1561 //nb_tracefile = self->parent.tracefiles->len;
1563 //g_tree_destroy(tsc->pqueue);
1564 //tsc->pqueue = g_tree_new(compare_tracefile);
1566 /* restore cpu resource states */
1567 type
= lttv_attribute_get_by_name(container
, LTTV_STATE_RESOURCE_CPUS
, &value
);
1568 g_assert(type
== LTTV_POINTER
);
1569 lttv_state_free_cpu_states(self
->cpu_states
, nb_cpus
);
1570 self
->cpu_states
= lttv_state_copy_cpu_states(*(value
.v_pointer
), nb_cpus
);
1572 /* restore irq resource states */
1573 nb_irqs
= self
->name_tables
->nb_irqs
;
1574 type
= lttv_attribute_get_by_name(container
, LTTV_STATE_RESOURCE_IRQS
, &value
);
1575 g_assert(type
== LTTV_POINTER
);
1576 lttv_state_free_irq_states(self
->irq_states
, nb_irqs
);
1577 self
->irq_states
= lttv_state_copy_irq_states(*(value
.v_pointer
), nb_irqs
);
1579 /* restore soft irq resource states */
1580 nb_soft_irqs
= self
->name_tables
->nb_soft_irqs
;
1581 type
= lttv_attribute_get_by_name(container
, LTTV_STATE_RESOURCE_SOFT_IRQS
, &value
);
1582 g_assert(type
== LTTV_POINTER
);
1583 lttv_state_free_soft_irq_states(self
->soft_irq_states
, nb_soft_irqs
);
1584 self
->soft_irq_states
= lttv_state_copy_soft_irq_states(*(value
.v_pointer
), nb_soft_irqs
);
1586 /* restore trap resource states */
1587 nb_traps
= self
->name_tables
->nb_traps
;
1588 type
= lttv_attribute_get_by_name(container
, LTTV_STATE_RESOURCE_TRAPS
, &value
);
1589 g_assert(type
== LTTV_POINTER
);
1590 lttv_state_free_trap_states(self
->trap_states
, nb_traps
);
1591 self
->trap_states
= lttv_state_copy_trap_states(*(value
.v_pointer
), nb_traps
);
1593 /* restore the blkdev states */
1594 type
= lttv_attribute_get_by_name(container
, LTTV_STATE_RESOURCE_BLKDEVS
, &value
);
1595 g_assert(type
== LTTV_POINTER
);
1596 lttv_state_free_blkdev_hashtable(self
->bdev_states
);
1597 self
->bdev_states
= lttv_state_copy_blkdev_hashtable(*(value
.v_pointer
));
1599 #ifdef BABEL_CLEANUP
1600 for(i
= 0 ; i
< nb_tracefile
; i
++) {
1602 LTTV_TRACEFILE_STATE(g_array_index(self
->parent
.tracefiles
,
1603 LttvTracefileContext
*, i
));
1604 type
= lttv_attribute_get(tracefiles_tree
, i
, &name
, &value
, &is_named
);
1605 g_assert(type
== LTTV_GOBJECT
);
1606 tracefile_tree
= *((LttvAttribute
**)(value
.v_gobject
));
1608 type
= lttv_attribute_get_by_name(tracefile_tree
, LTTV_STATE_PROCESS
,
1610 g_assert(type
== LTTV_UINT
);
1611 pid
= *(value
.v_uint
);
1612 tfcs
->process
= lttv_state_find_process_or_create(tfcs
, pid
);
1614 type
= lttv_attribute_get_by_name(tracefile_tree
, LTTV_STATE_EVENT
,
1616 g_assert(type
== LTTV_POINTER
);
1617 //g_assert(*(value.v_pointer) != NULL);
1618 ep
= *(value
.v_pointer
);
1619 g_assert(tfcs
->parent
.t_context
!= NULL
);
1621 tfcs
->cpu_state
= &self
->cpu_states
[tfcs
->cpu
];
1623 LttvTracefileContext
*tfc
= LTTV_TRACEFILE_CONTEXT(tfcs
);
1624 g_tree_remove(tsc
->pqueue
, tfc
);
1627 retval
= ltt_tracefile_seek_position(tfc
->tf
, ep
);
1628 g_assert_cmpint(retval
, ==, 0);
1629 tfc
->timestamp
= ltt_event_time(ltt_tracefile_get_event(tfc
->tf
));
1630 g_assert_cmpint(ltt_time_compare(tfc
->timestamp
, ltt_time_infinite
),
1632 g_tree_insert(tsc
->pqueue
, tfc
, tfc
);
1633 g_info("Restoring state for a tf at time %lu.%lu",
1634 tfc
->timestamp
.tv_sec
, tfc
->timestamp
.tv_nsec
);
1636 tfc
->timestamp
= ltt_time_infinite
;
1639 #endif /* BABEL_CLEANUP */
1643 * Note: the position must be explicitely set on the entire traceset to
1644 * match the trace states.
1646 LttvTracesetPosition
*lttv_trace_state_get_position(LttvAttribute
*container
)
1648 LttvAttributeType type
;
1649 LttvAttributeValue value
;
1651 type
= lttv_attribute_get_by_name(container
, LTTV_STATE_POSITION
, &value
);
1652 g_assert(type
== LTTV_POINTER
);
1653 return *(value
.v_pointer
);
1656 void lttv_state_saved_free(LttvTraceState
*self
, LttvAttribute
*container
)
1658 guint nb_cpus
, nb_irqs
, nb_soft_irqs
;
1659 guint
*running_process
;
1660 LttvAttributeType type
;
1661 LttvAttributeValue value
;
1663 type
= lttv_attribute_get_by_name(container
, LTTV_STATE_PROCESSES
,
1665 g_assert(type
== LTTV_POINTER
);
1666 lttv_state_free_process_table(*(value
.v_pointer
));
1667 *(value
.v_pointer
) = NULL
;
1668 lttv_attribute_remove_by_name(container
, LTTV_STATE_PROCESSES
);
1670 /* Free running processes array */
1671 type
= lttv_attribute_get_by_name(container
, LTTV_STATE_RUNNING_PROCESS
,
1673 g_assert(type
== LTTV_POINTER
);
1674 running_process
= *(value
.v_pointer
);
1675 g_free(running_process
);
1677 /* free cpu resources */
1678 type
= lttv_attribute_get_by_name(container
, LTTV_STATE_RESOURCE_CPUS_COUNT
, &value
);
1679 g_assert(type
== LTTV_UINT
);
1680 nb_cpus
= *value
.v_uint
;
1681 type
= lttv_attribute_get_by_name(container
, LTTV_STATE_RESOURCE_CPUS
, &value
);
1682 g_assert(type
== LTTV_POINTER
);
1683 lttv_state_free_cpu_states(*(value
.v_pointer
), nb_cpus
);
1685 /* free irq resource states */
1686 nb_irqs
= self
->name_tables
->nb_irqs
;
1687 type
= lttv_attribute_get_by_name(container
, LTTV_STATE_RESOURCE_IRQS
, &value
);
1688 g_assert(type
== LTTV_POINTER
);
1689 lttv_state_free_irq_states(*(value
.v_pointer
), nb_irqs
);
1691 /* free softirq resource states */
1692 nb_soft_irqs
= self
->name_tables
->nb_soft_irqs
;
1693 type
= lttv_attribute_get_by_name(container
, LTTV_STATE_RESOURCE_SOFT_IRQS
, &value
);
1694 g_assert(type
== LTTV_POINTER
);
1695 lttv_state_free_soft_irq_states(*(value
.v_pointer
), nb_soft_irqs
);
1697 /* free the blkdev states */
1698 type
= lttv_attribute_get_by_name(container
, LTTV_STATE_RESOURCE_BLKDEVS
, &value
);
1699 g_assert(type
== LTTV_POINTER
);
1700 lttv_state_free_blkdev_hashtable(*(value
.v_pointer
));
1702 /* remove the position */
1703 type
= lttv_attribute_get_by_name(container
, LTTV_STATE_POSITION
, &value
);
1704 g_assert(type
== LTTV_POINTER
);
1705 lttv_traceset_destroy_position(*(value
.v_pointer
));
1707 #ifdef BABEL_CLEANUP
1708 nb_tracefile
= self
->parent
.tracefiles
->len
;
1710 for(i
= 0 ; i
< nb_tracefile
; i
++) {
1712 type
= lttv_attribute_get(tracefiles_tree
, i
, &name
, &value
, &is_named
);
1713 g_assert(type
== LTTV_GOBJECT
);
1714 tracefile_tree
= *((LttvAttribute
**)(value
.v_gobject
));
1716 type
= lttv_attribute_get_by_name(tracefile_tree
, LTTV_STATE_EVENT
,
1718 g_assert(type
== LTTV_POINTER
);
1719 if(*(value
.v_pointer
) != NULL
) g_free(*(value
.v_pointer
));
1721 g_object_unref(G_OBJECT(tracefiles_tree
));
1722 #endif /* BABEL_CLEANUP */
1726 static void free_saved_state(LttvTraceState
*self
)
1729 LttvAttributeType type
;
1730 LttvAttributeValue value
;
1731 LttvAttributeName name
;
1733 LttvAttribute
*saved_states
;
1735 saved_states
= lttv_attribute_find_subdir(lttv_trace_attribute(self
->trace
),
1736 LTTV_STATE_SAVED_STATES
);
1738 nb
= lttv_attribute_get_number(saved_states
);
1739 for(i
= 0 ; i
< nb
; i
++) {
1740 type
= lttv_attribute_get(saved_states
, i
, &name
, &value
, &is_named
);
1741 g_assert(type
== LTTV_GOBJECT
);
1742 lttv_state_saved_free(self
, *((LttvAttribute
**)value
.v_gobject
));
1745 lttv_attribute_remove_by_name(lttv_trace_attribute(self
->trace
),
1746 LTTV_STATE_SAVED_STATES
);
1750 static void create_max_time(LttvTraceState
*trace_state
)
1752 LttvAttributeValue v
;
1754 lttv_attribute_find(lttv_trace_attribute(trace_state
->trace
),
1755 LTTV_STATE_SAVED_STATES_TIME
,
1757 g_assert(*(v
.v_pointer
) == NULL
);
1758 *(v
.v_pointer
) = g_new(LttTime
,1);
1759 *((LttTime
*)*(v
.v_pointer
)) = ltt_time_zero
;
1763 static void get_max_time(LttvTraceState
*trace_state
)
1765 LttvAttributeValue v
;
1767 lttv_attribute_find(lttv_trace_attribute(trace_state
->trace
),
1768 LTTV_STATE_SAVED_STATES_TIME
,
1770 g_assert(*(v
.v_pointer
) != NULL
);
1771 trace_state
->max_time_state_recomputed_in_seek
= (LttTime
*)*(v
.v_pointer
);
1775 static void free_max_time(LttvTraceState
*trace_state
)
1777 LttvAttributeValue v
;
1779 lttv_attribute_find(lttv_trace_attribute(trace_state
->trace
),
1780 LTTV_STATE_SAVED_STATES_TIME
,
1782 g_free(*(v
.v_pointer
));
1783 *(v
.v_pointer
) = NULL
;
1786 static void create_name_tables(LttvTraceState
*tcs
)
1790 GString
*fe_name
= g_string_new("");
1792 LttvNameTables
*name_tables
= g_new(LttvNameTables
, 1);
1794 LttvAttributeValue v
;
1798 lttv_attribute_find(lttv_trace_attribute(tcs
->trace
), LTTV_STATE_NAME_TABLES
,
1800 g_assert(*(v
.v_pointer
) == NULL
);
1801 *(v
.v_pointer
) = name_tables
;
1803 #ifdef BABEL_CLEANUP
1804 hooks
= g_array_sized_new(FALSE
, FALSE
, sizeof(LttvTraceHook
), 1);
1806 if(!lttv_trace_find_hook(tcs
->parent
.t
,
1808 LTT_EVENT_SYSCALL_ENTRY
,
1809 FIELD_ARRAY(LTT_FIELD_SYSCALL_ID
),
1810 NULL
, NULL
, &hooks
)) {
1812 // th = lttv_trace_hook_get_first(&th);
1814 // t = ltt_field_type(lttv_trace_get_hook_field(th, 0));
1815 // nb = ltt_type_element_number(t);
1817 // name_tables->syscall_names = g_new(GQuark, nb);
1818 // name_tables->nb_syscalls = nb;
1820 // for(i = 0 ; i < nb ; i++) {
1821 // name_tables->syscall_names[i] = ltt_enum_string_get(t, i);
1822 // if(!name_tables->syscall_names[i]) {
1823 // GString *string = g_string_new("");
1824 // g_string_printf(string, "syscall %u", i);
1825 // name_tables->syscall_names[i] = g_quark_from_string(string->str);
1826 // g_string_free(string, TRUE);
1829 #endif /* BABEL_CLEANUP */
1831 name_tables
->nb_syscalls
= PREALLOC_NB_SYSCALLS
;
1832 name_tables
->syscall_names
= g_new(GQuark
, name_tables
->nb_syscalls
);
1833 for(i
= 0 ; i
< name_tables
->nb_syscalls
; i
++) {
1834 g_string_printf(fe_name
, "syscall %d", i
);
1835 name_tables
->syscall_names
[i
] = g_quark_from_string(fe_name
->str
);
1837 #ifdef BABEL_CLEANUP
1839 name_tables
->syscall_names
= NULL
;
1840 name_tables
->nb_syscalls
= 0;
1842 lttv_trace_hook_remove_all(&hooks
);
1843 #endif /* BABEL_CLEANUP */
1845 #ifdef BABEL_CLEANUP
1846 if(!lttv_trace_find_hook(tcs
->parent
.t
,
1848 LTT_EVENT_TRAP_ENTRY
,
1849 FIELD_ARRAY(LTT_FIELD_TRAP_ID
),
1850 NULL
, NULL
, &hooks
) ||
1851 !lttv_trace_find_hook(tcs
->parent
.t
,
1853 LTT_EVENT_PAGE_FAULT_ENTRY
,
1854 FIELD_ARRAY(LTT_FIELD_TRAP_ID
),
1855 NULL
, NULL
, &hooks
)) {
1857 // th = lttv_trace_hook_get_first(&th);
1859 // t = ltt_field_type(lttv_trace_get_hook_field(th, 0));
1860 // //nb = ltt_type_element_number(t);
1862 // name_tables->trap_names = g_new(GQuark, nb);
1863 // for(i = 0 ; i < nb ; i++) {
1864 // name_tables->trap_names[i] = g_quark_from_string(
1865 // ltt_enum_string_get(t, i));
1868 #endif /* BABEL_CLEANUP */
1869 name_tables
->nb_traps
= PREALLOC_NB_TRAPS
;
1870 name_tables
->trap_names
= g_new(GQuark
, name_tables
->nb_traps
);
1871 for(i
= 0 ; i
< name_tables
->nb_traps
; i
++) {
1872 g_string_printf(fe_name
, "trap %d", i
);
1873 name_tables
->trap_names
[i
] = g_quark_from_string(fe_name
->str
);
1875 #ifdef BABEL_CLEANUP
1877 name_tables
->trap_names
= NULL
;
1878 name_tables
->nb_traps
= 0;
1880 lttv_trace_hook_remove_all(&hooks
);
1881 #endif /* BABEL_CLEANUP */
1883 #ifdef BABEL_CLEANUP
1884 if(!lttv_trace_find_hook(tcs
->parent
.t
,
1886 LTT_EVENT_IRQ_ENTRY
,
1887 FIELD_ARRAY(LTT_FIELD_IRQ_ID
),
1888 NULL
, NULL
, &hooks
)) {
1891 name_tables->irq_names = g_new(GQuark, nb);
1892 for(i = 0 ; i < nb ; i++) {
1893 name_tables->irq_names[i] = g_quark_from_string(ltt_enum_string_get(t, i));
1896 /* FIXME: LttvIRQState *irq_states should become a g_array */
1898 #endif /* BABEL_CLEANUP */
1899 name_tables
->nb_irqs
= PREALLOC_NB_IRQS
;
1900 name_tables
->irq_names
= g_new(GQuark
, name_tables
->nb_irqs
);
1901 for(i
= 0 ; i
< name_tables
->nb_irqs
; i
++) {
1902 g_string_printf(fe_name
, "irq %d", i
);
1903 name_tables
->irq_names
[i
] = g_quark_from_string(fe_name
->str
);
1905 #ifdef BABEL_CLEANUP
1907 name_tables
->nb_irqs
= 0;
1908 name_tables
->irq_names
= NULL
;
1910 lttv_trace_hook_remove_all(&hooks
);
1911 #endif /* BABEL_CLEANUP */
1913 name_tables->soft_irq_names = g_new(GQuark, nb);
1914 for(i = 0 ; i < nb ; i++) {
1915 name_tables->soft_irq_names[i] = g_quark_from_string(ltt_enum_string_get(t, i));
1919 name_tables
->nb_soft_irqs
= PREALLOC_NB_SOFT_IRQS
;
1920 name_tables
->soft_irq_names
= g_new(GQuark
, name_tables
->nb_soft_irqs
);
1921 for(i
= 0 ; i
< name_tables
->nb_soft_irqs
; i
++) {
1922 g_string_printf(fe_name
, "softirq %d", i
);
1923 name_tables
->soft_irq_names
[i
] = g_quark_from_string(fe_name
->str
);
1925 // g_array_free(hooks, TRUE);
1927 g_string_free(fe_name
, TRUE
);
1929 #if (__WORDSIZE == 32)
1930 name_tables
->kprobe_hash
= g_hash_table_new_full(guint64_hash
, guint64_equal
,
1933 name_tables
->kprobe_hash
= g_hash_table_new(g_direct_hash
, g_direct_equal
);
1938 static void get_name_tables(LttvTraceState
*tcs
)
1940 LttvAttributeValue v
;
1942 lttv_attribute_find(lttv_trace_attribute(tcs
->trace
), LTTV_STATE_NAME_TABLES
,
1944 g_assert(*(v
.v_pointer
) != NULL
);
1945 tcs
->name_tables
= (LttvNameTables
*)*(v
.v_pointer
);
1949 static void free_name_tables(LttvTraceState
*tcs
)
1951 LttvNameTables
*name_tables
;
1953 LttvAttributeValue v
;
1955 lttv_attribute_find(lttv_trace_attribute(tcs
->trace
), LTTV_STATE_NAME_TABLES
,
1957 name_tables
= (LttvNameTables
*)*(v
.v_pointer
);
1958 *(v
.v_pointer
) = NULL
;
1960 // g_free(name_tables->eventtype_names);
1961 if(name_tables
->syscall_names
) g_free(name_tables
->syscall_names
);
1962 if(name_tables
->trap_names
) g_free(name_tables
->trap_names
);
1963 if(name_tables
->irq_names
) g_free(name_tables
->irq_names
);
1964 if(name_tables
->soft_irq_names
) g_free(name_tables
->soft_irq_names
);
1965 g_hash_table_destroy(name_tables
->kprobe_hash
);
1966 g_free(name_tables
);
1969 #ifdef HASH_TABLE_DEBUG
1971 static void test_process(gpointer key
, gpointer value
, gpointer user_data
)
1973 LttvProcessState
*process
= (LttvProcessState
*)value
;
1975 /* Test for process corruption */
1976 guint stack_len
= process
->execution_stack
->len
;
1979 static void hash_table_check(GHashTable
*table
)
1981 g_hash_table_foreach(table
, test_process
, NULL
);
1987 /* clears the stack and sets the state passed as argument */
1988 static void cpu_set_base_mode(LttvCPUState
*cpust
, LttvCPUMode state
)
1990 g_array_set_size(cpust
->mode_stack
, 1);
1991 ((GQuark
*)cpust
->mode_stack
->data
)[0] = state
;
1994 static void cpu_push_mode(LttvCPUState
*cpust
, LttvCPUMode state
)
1996 g_array_set_size(cpust
->mode_stack
, cpust
->mode_stack
->len
+ 1);
1997 ((GQuark
*)cpust
->mode_stack
->data
)[cpust
->mode_stack
->len
- 1] = state
;
2000 static void cpu_pop_mode(LttvCPUState
*cpust
)
2002 if(cpust
->mode_stack
->len
<= 1)
2003 cpu_set_base_mode(cpust
, LTTV_CPU_UNKNOWN
);
2005 g_array_set_size(cpust
->mode_stack
, cpust
->mode_stack
->len
- 1);
2008 /* clears the stack and sets the state passed as argument */
2009 static void bdev_set_base_mode(LttvBdevState
*bdevst
, LttvBdevMode state
)
2011 g_array_set_size(bdevst
->mode_stack
, 1);
2012 ((GQuark
*)bdevst
->mode_stack
->data
)[0] = state
;
2015 static void bdev_push_mode(LttvBdevState
*bdevst
, LttvBdevMode state
)
2017 g_array_set_size(bdevst
->mode_stack
, bdevst
->mode_stack
->len
+ 1);
2018 ((GQuark
*)bdevst
->mode_stack
->data
)[bdevst
->mode_stack
->len
- 1] = state
;
2021 static void bdev_pop_mode(LttvBdevState
*bdevst
)
2023 if(bdevst
->mode_stack
->len
<= 1)
2024 bdev_set_base_mode(bdevst
, LTTV_BDEV_UNKNOWN
);
2026 g_array_set_size(bdevst
->mode_stack
, bdevst
->mode_stack
->len
- 1);
2029 static void irq_set_base_mode(LttvIRQState
*irqst
, LttvIRQMode state
)
2031 g_array_set_size(irqst
->mode_stack
, 1);
2032 ((GQuark
*)irqst
->mode_stack
->data
)[0] = state
;
2035 static void irq_push_mode(LttvIRQState
*irqst
, LttvIRQMode state
)
2037 g_array_set_size(irqst
->mode_stack
, irqst
->mode_stack
->len
+ 1);
2038 ((GQuark
*)irqst
->mode_stack
->data
)[irqst
->mode_stack
->len
- 1] = state
;
2041 static void irq_pop_mode(LttvIRQState
*irqst
)
2043 if(irqst
->mode_stack
->len
<= 1)
2044 irq_set_base_mode(irqst
, LTTV_IRQ_UNKNOWN
);
2046 g_array_set_size(irqst
->mode_stack
, irqst
->mode_stack
->len
- 1);
2049 static void push_state(LttvEvent
*event
,
2050 LttvTraceState
*ts
, LttvExecutionMode t
,
2053 LttvExecutionState
*es
;
2056 cpu
= lttv_traceset_get_cpuid_from_event(event
);
2059 #ifdef HASH_TABLE_DEBUG
2060 hash_table_check(ts
->processes
);
2062 LttvProcessState
*process
= ts
->running_process
[cpu
];
2064 guint depth
= process
->execution_stack
->len
;
2066 process
->execution_stack
=
2067 g_array_set_size(process
->execution_stack
, depth
+ 1);
2070 &g_array_index(process
->execution_stack
, LttvExecutionState
, depth
- 1);
2072 es
= &g_array_index(process
->execution_stack
, LttvExecutionState
, depth
);
2075 es
->entry
= es
->change
= lttv_event_get_timestamp(event
);
2076 es
->cum_cpu_time
= ltt_time_zero
;
2077 es
->s
= process
->state
->s
;
2078 process
->state
= es
;
2082 * return 1 when empty, else 0 */
2084 lttv_state_pop_state_cleanup(LttvProcessState
*process
, LttvEvent
*event
)
2086 guint depth
= process
->execution_stack
->len
;
2092 process
->execution_stack
=
2093 g_array_set_size(process
->execution_stack
, depth
- 1);
2094 process
->state
= &g_array_index(process
->execution_stack
, LttvExecutionState
,
2096 process
->state
->change
= lttv_event_get_timestamp(event
);
2101 static void pop_state(LttvEvent
*event
,
2102 LttvTraceState
*ts
, LttvExecutionMode t
)
2104 LttvProcessState
*process
;
2107 cpu
= lttv_traceset_get_cpuid_from_event(event
);
2109 process
= ts
->running_process
[cpu
];
2111 guint depth
= process
->execution_stack
->len
;
2113 if(process
->state
->t
!= t
){
2114 g_info("Different execution mode type: ignore it\n"
2117 g_info("process state has %s when pop_int is %s\n",
2118 g_quark_to_string(process
->state
->t
),
2119 g_quark_to_string(t
));
2120 g_info("{ %u, %u, %s, %s }\n",
2123 g_quark_to_string(process
->name
),
2124 g_quark_to_string(process
->state
->s
));
2129 //TODO ybrosseau readd debug
2130 //g_info("Trying to pop last state on stack (%lu.%09lu): ignore it\n",
2131 // tfs->parent.timestamp.tv_sec, tfs->parent.timestamp.tv_nsec);
2132 g_info("Trying to pop last state on stack: ignore it\n");
2136 process
->execution_stack
=
2137 g_array_set_size(process
->execution_stack
, depth
- 1);
2139 process
->state
= &g_array_index(process
->execution_stack
, LttvExecutionState
,
2141 process
->state
->change
= lttv_event_get_timestamp(event
);
2143 if((process
->state
->t
== LTTV_STATE_MODE_UNKNOWN
) && (t
== LTTV_STATE_SYSCALL
)) {
2144 //Force state at running
2145 process
->state
->t
= LTTV_STATE_USER_MODE
;
2146 process
->state
->s
= LTTV_STATE_RUN
;
2150 struct search_result
{
2151 const LttTime
*time
; /* Requested time */
2152 LttTime
*best
; /* Best result */
2155 /* Return a new and initialized LttvProcessState structure */
2157 LttvProcessState
*lttv_state_create_process(LttvTraceState
*tcs
,
2158 LttvProcessState
*parent
, guint cpu
, guint pid
,
2159 guint tgid
, GQuark name
, const LttTime
*timestamp
)
2161 LttvProcessState
*process
= g_new(LttvProcessState
, 1);
2163 LttvExecutionState
*es
;
2168 process
->tgid
= tgid
;
2170 process
->name
= name
;
2171 //process->last_cpu = tfs->cpu_name;
2172 //process->last_cpu_index = ltt_tracefile_num(((LttvTracefileContext*)tfs)->tf);
2173 process
->type
= LTTV_STATE_USER_THREAD
;
2175 g_info("Process %u, core %p", process
->pid
, process
);
2176 g_hash_table_insert(tcs
->processes
, process
, process
);
2179 process
->ppid
= parent
->pid
;
2180 process
->creation_time
= *timestamp
;
2183 /* No parent. This process exists but we are missing all information about
2184 its creation. The birth time is set to zero but we remember the time of
2189 process
->creation_time
= ltt_time_zero
;
2192 process
->insertion_time
= *timestamp
;
2193 sprintf(buffer
,"%d-%lu.%lu",pid
, process
->creation_time
.tv_sec
,
2194 process
->creation_time
.tv_nsec
);
2195 process
->pid_time
= g_quark_from_string(buffer
);
2197 process
->free_events
= 0;
2198 //process->last_cpu = tfs->cpu_name;
2199 //process->last_cpu_index = ltt_tracefile_num(((LttvTracefileContext*)tfs)->tf);
2200 process
->execution_stack
= g_array_sized_new(FALSE
, FALSE
,
2201 sizeof(LttvExecutionState
), PREALLOCATED_EXECUTION_STACK
);
2202 process
->execution_stack
= g_array_set_size(process
->execution_stack
, 2);
2203 es
= process
->state
= &g_array_index(process
->execution_stack
,
2204 LttvExecutionState
, 0);
2205 es
->t
= LTTV_STATE_USER_MODE
;
2206 es
->n
= LTTV_STATE_SUBMODE_NONE
;
2207 es
->entry
= *timestamp
;
2208 //g_assert(timestamp->tv_sec != 0);
2209 es
->change
= *timestamp
;
2210 es
->cum_cpu_time
= ltt_time_zero
;
2211 es
->s
= LTTV_STATE_RUN
;
2213 es
= process
->state
= &g_array_index(process
->execution_stack
,
2214 LttvExecutionState
, 1);
2215 es
->t
= LTTV_STATE_SYSCALL
;
2216 es
->n
= LTTV_STATE_SUBMODE_NONE
;
2217 es
->entry
= *timestamp
;
2218 //g_assert(timestamp->tv_sec != 0);
2219 es
->change
= *timestamp
;
2220 es
->cum_cpu_time
= ltt_time_zero
;
2221 es
->s
= LTTV_STATE_WAIT_FORK
;
2223 /* Allocate an empty function call stack. If it's empty, use 0x0. */
2224 #ifdef BABEL_CLEANUP
2225 //process->user_stack = g_array_sized_new(FALSE, FALSE,
2226 // sizeof(guint64), 0);
2228 process
->fds
= g_hash_table_new(g_direct_hash
, g_direct_equal
);
2234 lttv_state_find_process(LttvTraceState
*ts
, guint cpu
, guint pid
)
2236 LttvProcessState key
;
2237 LttvProcessState
*process
;
2241 process
= g_hash_table_lookup(ts
->processes
, &key
);
2245 LttvProcessState
*lttv_state_find_process_or_create(LttvTraceState
*ts
,
2246 guint cpu
, guint pid
, const LttTime
*timestamp
)
2248 LttvProcessState
*process
= lttv_state_find_process(ts
, cpu
, pid
);
2249 LttvExecutionState
*es
;
2251 /* Put ltt_time_zero creation time for unexisting processes */
2252 if(unlikely(process
== NULL
)) {
2253 process
= lttv_state_create_process(ts
,
2254 NULL
, cpu
, pid
, 0, LTTV_STATE_UNNAMED
, timestamp
);
2255 /* We are not sure is it's a kernel thread or normal thread, put the
2256 * bottom stack state to unknown */
2257 process
->execution_stack
=
2258 g_array_set_size(process
->execution_stack
, 1);
2259 process
->state
= es
=
2260 &g_array_index(process
->execution_stack
, LttvExecutionState
, 0);
2261 es
->t
= LTTV_STATE_MODE_UNKNOWN
;
2262 es
->s
= LTTV_STATE_UNNAMED
;
2267 /* FIXME : this function should be called when we receive an event telling that
2268 * release_task has been called in the kernel. In happens generally when
2269 * the parent waits for its child termination, but may also happens in special
2270 * cases in the child's exit : when the parent ignores its children SIGCCHLD or
2271 * has the flag SA_NOCLDWAIT. It can also happen when the child is part
2272 * of a killed thread group, but isn't the leader.
2274 static int exit_process(LttvEvent
*event
, LttvProcessState
*process
)
2276 LttvTraceState
*ts
= event
->state
;
2277 LttvProcessState key
;
2279 /* Wait for both schedule with exit dead and process free to happen.
2280 * They can happen in any order. */
2281 if (++(process
->free_events
) < 2)
2284 key
.pid
= process
->pid
;
2285 key
.cpu
= process
->cpu
;
2286 g_hash_table_remove(ts
->processes
, &key
);
2287 g_array_free(process
->execution_stack
, TRUE
);
2289 /* the following also clears the content */
2290 g_hash_table_destroy(process
->fds
);
2297 static void free_process_state(gpointer key
, gpointer value
,gpointer user_data
)
2299 g_array_free(((LttvProcessState
*)value
)->execution_stack
, TRUE
);
2301 /* the following also clears the content */
2302 g_hash_table_destroy(((LttvProcessState
*)value
)->fds
);
2308 static void lttv_state_free_process_table(GHashTable
*processes
)
2310 g_hash_table_foreach(processes
, free_process_state
, NULL
);
2311 g_hash_table_destroy(processes
);
2315 static gboolean
syscall_entry(void *hook_data
, void *call_data
)
2320 LttvProcessState
*process
;
2321 LttvExecutionSubmode submode
;
2322 char syscall_name
[200];
2324 event
= (LttvEvent
*) call_data
;
2325 if (strncmp(lttv_traceset_get_name_from_event(event
),
2326 "sys_", sizeof("sys_") - 1) != 0)
2329 strncpy(syscall_name
,lttv_traceset_get_name_from_event(event
)+4,200);
2331 cpu
= lttv_traceset_get_cpuid_from_event(event
);
2333 process
= ts
->running_process
[cpu
];
2335 submode
= g_quark_from_string(syscall_name
);
2336 /* There can be no system call from PID 0 : unknown state */
2337 if(process
->pid
!= 0)
2338 push_state(event
, ts
, LTTV_STATE_SYSCALL
, submode
);
2343 static gboolean
syscall_exit(void *hook_data
, void *call_data
)
2348 LttvProcessState
*process
;
2351 event
= (LttvEvent
*) call_data
;
2352 if (strcmp(lttv_traceset_get_name_from_event(event
),
2353 "exit_syscall") != 0)
2356 cpu
= lttv_traceset_get_cpuid_from_event(event
);
2358 process
= ts
->running_process
[cpu
];
2360 /* There can be no system call from PID 0 : unknown state */
2361 if (process
->pid
!= 0)
2362 pop_state(event
, ts
, LTTV_STATE_SYSCALL
);
2366 #ifdef BABEL_CLEANUP
2367 static gboolean
trap_entry(void *hook_data
, void *call_data
)
2369 LttvTracefileState
*s
= (LttvTracefileState
*)call_data
;
2370 LttvTraceState
*ts
= (LttvTraceState
*)s
->parent
.t_context
;
2371 LttEvent
*e
= ltt_tracefile_get_event(s
->parent
.tf
);
2372 LttvTraceHook
*th
= (LttvTraceHook
*)hook_data
;
2373 struct marker_field
*f
= lttv_trace_get_hook_field(th
, 0);
2374 LttvNameTables
*nt
= ((LttvTraceState
*)(s
->parent
.t_context
))->name_tables
;
2376 LttvExecutionSubmode submode
;
2378 guint64 trap
= ltt_event_get_long_unsigned(e
, f
);
2380 expand_trap_table(ts
, trap
);
2382 submode
= nt
->trap_names
[trap
];
2384 push_state(s
, LTTV_STATE_TRAP
, submode
);
2386 /* update cpu status */
2387 cpu_push_mode(s
->cpu_state
, LTTV_CPU_TRAP
);
2389 /* update trap status */
2390 g_array_append_val(s
->cpu_state
->trap_stack
, trap
);
2391 ts
->trap_states
[trap
].running
++;
2396 static gboolean
trap_exit(void *hook_data
, void *call_data
)
2398 LttvTracefileState
*s
= (LttvTracefileState
*)call_data
;
2399 LttvTraceState
*ts
= (LttvTraceState
*)s
->parent
.t_context
;
2401 pop_state(s
, LTTV_STATE_TRAP
);
2403 /* update cpu status */
2404 cpu_pop_mode(s
->cpu_state
);
2406 /* update trap status */
2407 if (s
->cpu_state
->trap_stack
->len
> 0) {
2408 gint last
= g_array_index(s
->cpu_state
->trap_stack
, gint
,
2409 s
->cpu_state
->trap_stack
->len
-1);
2410 if(ts
->trap_states
[last
].running
)
2411 ts
->trap_states
[last
].running
--;
2412 g_array_remove_index(s
->cpu_state
->trap_stack
,
2413 s
->cpu_state
->trap_stack
->len
-1);
2417 #endif /* BABEL_CLEANUP */
2419 static gboolean
irq_entry(void *hook_data
, void *call_data
)
2425 LttvExecutionSubmode submode
;
2429 event
= (LttvEvent
*) call_data
;
2430 if (strcmp(lttv_traceset_get_name_from_event(event
),
2431 "irq_handler_entry") != 0)
2434 cpu
= lttv_traceset_get_cpuid_from_event(event
);
2437 nt
= ts
->name_tables
;
2438 irq
= lttv_event_get_long(event
, "irq");
2440 expand_irq_table(ts
, irq
);
2442 submode
= nt
->irq_names
[irq
];
2444 /* Do something with the info about being in user or system mode when int? */
2445 push_state(event
, ts
, LTTV_STATE_IRQ
, submode
);
2447 /* update cpu status */
2448 cpu_push_mode(&(ts
->cpu_states
[cpu
]), LTTV_CPU_IRQ
);
2450 /* update irq status */
2451 g_array_append_val(ts
->cpu_states
[cpu
].irq_stack
, irq
);
2452 irq_push_mode(&ts
->irq_states
[irq
], LTTV_IRQ_BUSY
);
2457 static gboolean
soft_irq_exit(void *hook_data
, void *call_data
)
2463 LttvCPUState
*cpu_state
;
2465 event
= (LttvEvent
*) call_data
;
2466 if (strcmp(lttv_traceset_get_name_from_event(event
),
2467 "softirq_exit") != 0)
2470 cpu
= lttv_traceset_get_cpuid_from_event(event
);
2473 cpu_state
= &(ts
->cpu_states
[cpu
]);
2474 pop_state(event
, ts
, LTTV_STATE_SOFT_IRQ
);
2476 /* update cpu status */
2477 cpu_pop_mode(cpu_state
);
2479 /* update softirq status */
2480 if (cpu_state
->softirq_stack
->len
> 0) {
2481 gint last
= g_array_index(cpu_state
->softirq_stack
, gint
, cpu_state
->softirq_stack
->len
-1);
2482 if(ts
->soft_irq_states
[last
].running
)
2483 ts
->soft_irq_states
[last
].running
--;
2484 g_array_remove_index(cpu_state
->softirq_stack
, cpu_state
->softirq_stack
->len
-1);
2489 static gboolean
irq_exit(void *hook_data
, void *call_data
)
2495 LttvCPUState
*cpu_state
;
2497 event
= (LttvEvent
*) call_data
;
2498 if (strcmp(lttv_traceset_get_name_from_event(event
),
2499 "irq_handler_exit") != 0)
2502 cpu
= lttv_traceset_get_cpuid_from_event(event
);
2504 cpu_state
= &(ts
->cpu_states
[cpu
]);
2506 pop_state(event
, ts
, LTTV_STATE_IRQ
);
2508 /* update cpu status */
2509 cpu_pop_mode(cpu_state
);
2511 /* update irq status */
2512 if (cpu_state
->irq_stack
->len
> 0) {
2513 gint last
= g_array_index(cpu_state
->irq_stack
, gint
, cpu_state
->irq_stack
->len
-1);
2514 g_array_remove_index(cpu_state
->irq_stack
, cpu_state
->irq_stack
->len
-1);
2515 irq_pop_mode(&ts
->irq_states
[last
]);
2521 static gboolean
soft_irq_raise(void *hook_data
, void *call_data
)
2529 event
= (LttvEvent
*) call_data
;
2530 if (strcmp(lttv_traceset_get_name_from_event(event
),
2531 "softirq_raise") != 0)
2534 //cpu = lttv_traceset_get_cpuid_from_event(event);
2536 softirq
= lttv_event_get_long_unsigned(event
, "vec");
2538 expand_soft_irq_table(ts
, softirq
);
2540 /* update softirq status */
2541 /* a soft irq raises are not cumulative */
2542 ts
->soft_irq_states
[softirq
].pending
=1;
2547 static gboolean
soft_irq_entry(void *hook_data
, void *call_data
)
2552 LttvExecutionSubmode submode
;
2556 event
= (LttvEvent
*) call_data
;
2557 if (strcmp(lttv_traceset_get_name_from_event(event
),
2558 "softirq_entry") != 0)
2561 cpu
= lttv_traceset_get_cpuid_from_event(event
);
2567 softirq
= lttv_event_get_long_unsigned(event
, "vec");
2568 expand_soft_irq_table(ts
, softirq
);
2569 nt
= ts
->name_tables
;
2570 submode
= nt
->soft_irq_names
[softirq
];
2572 /* Do something with the info about being in user or system mode when int? */
2573 push_state(event
, ts
, LTTV_STATE_SOFT_IRQ
, submode
);
2575 /* update cpu status */
2576 cpu_push_mode(&(ts
->cpu_states
[cpu
]), LTTV_CPU_SOFT_IRQ
);
2578 /* update softirq status */
2579 g_array_append_val(ts
->cpu_states
[cpu
].softirq_stack
, softirq
);
2580 if (ts
->soft_irq_states
[softirq
].pending
)
2581 ts
->soft_irq_states
[softirq
].pending
--;
2582 ts
->soft_irq_states
[softirq
].running
++;
2587 static gboolean
enum_interrupt(void *hook_data
, void *call_data
)
2597 event
= (LttvEvent
*) call_data
;
2598 if (strcmp(lttv_traceset_get_name_from_event(event
),
2599 "lttng_statedump_interrupt") != 0)
2603 nt
= ts
->name_tables
;
2604 irq
= lttv_event_get_long_unsigned(event
, "irq");
2605 action
= g_quark_from_string(lttv_event_get_string(event
,
2607 expand_irq_table(ts
, irq
);
2608 nt
->irq_names
[irq
] = action
;
2613 #ifdef BABEL_CLEANUP
2614 static gboolean
bdev_request_issue(void *hook_data
, void *call_data
)
2625 event
= (LttvEvent
*) call_data
;
2626 if (strcmp(lttv_traceset_get_name_from_event(event
),
2627 "block_rq_issue") != 0)
2631 major
= lttv_event_get_long_unsigned(event
,);
2633 minor
= lttv_event_get_long_unsigned(event
,);
2635 oper
= lttv_event_get_long_unsigned(event
,);
2637 devcode
= MKDEV(major
,minor
);
2639 /* have we seen this block device before? */
2640 bdev
= get_hashed_bdevstate(ts
, devcode
);
2642 bdev_push_mode(bdev
, LTTV_BDEV_BUSY_READING
);
2644 bdev_push_mode(bdev
, LTTV_BDEV_BUSY_WRITING
);
2649 static gboolean
bdev_request_complete(void *hook_data
, void *call_data
)
2651 LttvTracefileState
*s
= (LttvTracefileState
*)call_data
;
2652 LttvTraceState
*ts
= (LttvTraceState
*)s
->parent
.t_context
;
2653 LttEvent
*e
= ltt_tracefile_get_event(s
->parent
.tf
);
2654 LttvTraceHook
*th
= (LttvTraceHook
*)hook_data
;
2656 guint major
= ltt_event_get_long_unsigned(e
,
2657 lttv_trace_get_hook_field(th
, 0));
2658 guint minor
= ltt_event_get_long_unsigned(e
,
2659 lttv_trace_get_hook_field(th
, 1));
2660 //guint oper = ltt_event_get_long_unsigned(e,
2661 // lttv_trace_get_hook_field(th, 2));
2662 guint32 devcode
= MKDEV(major
,minor
);
2664 /* have we seen this block device before? */
2665 gpointer bdev
= get_hashed_bdevstate(ts
, devcode
);
2667 /* update block device */
2668 bdev_pop_mode(bdev
);
2673 #ifdef BABEL_CLEANUP
2674 // We dont have the syscall table in LTTng 2.0
2675 static gboolean
dump_syscall(void *hook_data
, void *call_data
)
2677 LttvTracefileState
*s
= (LttvTracefileState
*)call_data
;
2678 LttvTraceState
*ts
= (LttvTraceState
*)s
->parent
.t_context
;
2679 LttvNameTables
*nt
= ts
->name_tables
;
2680 LttEvent
*e
= ltt_tracefile_get_event(s
->parent
.tf
);
2681 LttvTraceHook
*th
= (LttvTraceHook
*)hook_data
;
2685 id
= ltt_event_get_unsigned(e
, lttv_trace_get_hook_field(th
, 0));
2686 symbol
= ltt_event_get_string(e
, lttv_trace_get_hook_field(th
, 2));
2688 expand_syscall_table(ts
, id
);
2689 nt
->syscall_names
[id
] = g_quark_from_string(symbol
);
2694 static gboolean
dump_kprobe(void *hook_data
, void *call_data
)
2696 LttvTracefileState
*s
= (LttvTracefileState
*)call_data
;
2697 LttvTraceState
*ts
= (LttvTraceState
*)s
->parent
.t_context
;
2698 LttEvent
*e
= ltt_tracefile_get_event(s
->parent
.tf
);
2699 LttvTraceHook
*th
= (LttvTraceHook
*)hook_data
;
2703 ip
= ltt_event_get_long_unsigned(e
, lttv_trace_get_hook_field(th
, 0));
2704 symbol
= ltt_event_get_string(e
, lttv_trace_get_hook_field(th
, 1));
2706 expand_kprobe_table(ts
, ip
, symbol
);
2711 #ifdef BABEL_CLEANUP
2712 static gboolean
dump_softirq(void *hook_data
, void *call_data
)
2715 LttvTracefileState
*s
= (LttvTracefileState
*)call_data
;
2716 LttvTraceState
*ts
= (LttvTraceState
*)s
->parent
.t_context
;
2717 LttvNameTables
*nt
= ts
->name_tables
;
2718 LttEvent
*e
= ltt_tracefile_get_event(s
->parent
.tf
);
2719 LttvTraceHook
*th
= (LttvTraceHook
*)hook_data
;
2723 id
= ltt_event_get_unsigned(e
, lttv_trace_get_hook_field(th
, 0));
2724 symbol
= ltt_event_get_string(e
, lttv_trace_get_hook_field(th
, 2));
2726 expand_soft_irq_table(ts
, id
);
2727 nt
->soft_irq_names
[id
] = g_quark_from_string(symbol
);
2733 static gboolean
sched_try_wakeup(void *hook_data
, void *call_data
)
2737 LttvProcessState
*process
;
2742 event
= (LttvEvent
*) call_data
;
2743 if (strcmp(lttv_traceset_get_name_from_event(event
),
2744 "sched_wakeup") != 0)
2749 woken_pid
= lttv_event_get_long(event
, "tid");
2750 woken_cpu
= lttv_event_get_long(event
, "target_cpu");
2752 timestamp
= lttv_event_get_timestamp(event
);
2753 process
= lttv_state_find_process_or_create(
2755 woken_cpu
, woken_pid
,
2758 if (process
->state
->s
== LTTV_STATE_WAIT
|| process
->state
->s
== LTTV_STATE_WAIT_FORK
)
2760 process
->state
->s
= LTTV_STATE_WAIT_CPU
;
2761 process
->state
->change
= timestamp
;
2764 g_debug("Wakeup: process %d on CPU %u\n", woken_pid
, woken_cpu
);
2769 static gboolean
schedchange(void *hook_data
, void *call_data
)
2774 LttvProcessState
*process
;
2777 //LttvProcessState *old_process = ts->running_process[cpu];
2779 guint pid_in
, pid_out
;
2781 //TODO ybrosseau 2012-07-13: manage this 20 in a constact or dynamically
2784 event
= (LttvEvent
*) call_data
;
2785 if (strcmp(lttv_traceset_get_name_from_event(event
),
2786 "sched_switch") != 0)
2789 cpu
= lttv_traceset_get_cpuid_from_event(event
);
2791 process
= ts
->running_process
[cpu
];
2792 pid_out
= lttv_event_get_long(event
, "prev_tid");
2793 pid_in
= lttv_event_get_long(event
, "next_tid");
2794 state_out
= lttv_event_get_long(event
, "prev_state");
2796 strncpy(next_comm
, lttv_event_get_string(event
, "next_comm"), 20);
2797 next_comm
[20-1] = '\0';
2799 timestamp
= lttv_event_get_timestamp(event
);
2801 if(likely(process
!= NULL
)) {
2803 /* We could not know but it was not the idle process executing.
2804 This should only happen at the beginning, before the first schedule
2805 event, and when the initial information (current process for each CPU)
2806 is missing. It is not obvious how we could, after the fact, compensate
2807 the wrongly attributed statistics. */
2809 //This test only makes sense once the state is known and if there is no
2810 //missing events. We need to silently ignore schedchange coming after a
2811 //process_free, or it causes glitches. (FIXME)
2812 //if(unlikely(process->pid != pid_out)) {
2813 // g_assert(process->pid == 0);
2815 if(process
->pid
== 0
2816 && process
->state
->t
== LTTV_STATE_MODE_UNKNOWN
) {
2819 * Scheduling out of pid 0 at beginning of the trace.
2820 * We are typically in system call mode at this point although
2821 * (FIXME) we might be in a trap handler.
2823 g_assert(process
->execution_stack
->len
== 1);
2824 process
->state
->t
= LTTV_STATE_SYSCALL
;
2825 process
->state
->s
= LTTV_STATE_WAIT
;
2826 process
->state
->change
= timestamp
;
2827 process
->state
->entry
= timestamp
;
2830 if(unlikely(process
->state
->s
== LTTV_STATE_EXIT
)) {
2831 process
->state
->s
= LTTV_STATE_ZOMBIE
;
2832 process
->state
->change
= timestamp
;
2834 if(unlikely(state_out
== 0)) process
->state
->s
= LTTV_STATE_WAIT_CPU
;
2835 else process
->state
->s
= LTTV_STATE_WAIT
;
2836 process
->state
->change
= timestamp
;
2839 if(state_out
== 32 || state_out
== 64) { /* EXIT_DEAD || TASK_DEAD */
2840 /* see sched.h for states */
2841 if (!exit_process(event
, process
)) {
2842 process
->state
->s
= LTTV_STATE_DEAD
;
2843 process
->state
->change
= timestamp
;
2848 process
= ts
->running_process
[cpu
] = lttv_state_find_process_or_create(
2852 process
->state
->s
= LTTV_STATE_RUN
;
2854 // process->last_cpu_index = ltt_tracefile_num(((LttvTracefileContext*)s)->tf);
2855 process
->state
->change
= timestamp
;
2856 process
->name
= g_quark_from_string(next_comm
);
2858 /* update cpu status */
2860 /* going to idle task */
2861 cpu_set_base_mode(&(ts
->cpu_states
[cpu
]), LTTV_CPU_IDLE
);
2863 /* scheduling a real task.
2864 * we must be careful here:
2865 * if we just schedule()'ed to a process that is
2866 * in a trap, we must put the cpu in trap mode
2868 cpu_set_base_mode(&(ts
->cpu_states
[cpu
]), LTTV_CPU_BUSY
);
2869 if(process
->state
->t
== LTTV_STATE_TRAP
)
2870 cpu_push_mode(&(ts
->cpu_states
[cpu
]), LTTV_CPU_TRAP
);
2876 static gboolean
process_fork(void *hook_data
, void *call_data
)
2880 LttvProcessState
*process
;
2881 LttvProcessState
*child_process
;
2882 guint child_pid
; /* In the Linux Kernel, there is one PID per thread. */
2883 guint child_tgid
; /* tgid in the Linux kernel is the "real" POSIX PID. */
2884 //LttvProcessState *zombie_process;
2888 event
= (LttvEvent
*) call_data
;
2889 if (strcmp(lttv_traceset_get_name_from_event(event
),
2890 "sched_process_fork") != 0)
2892 cpu
= lttv_traceset_get_cpuid_from_event(event
);
2894 process
= ts
->running_process
[cpu
];
2895 timestamp
= lttv_event_get_timestamp(event
);
2897 /* Skip Parent PID param */
2900 child_pid
= lttv_event_get_long(event
, "child_tid");
2901 //ts->target_pid = child_pid;
2907 /* Mathieu : it seems like the process might have been scheduled in before the
2908 * fork, and, in a rare case, might be the current process. This might happen
2909 * in a SMP case where we don't have enough precision on the clocks.
2911 * Test reenabled after precision fixes on time. (Mathieu) */
2913 zombie_process
= lttv_state_find_process(ts
, ANY_CPU
, child_pid
);
2915 if(unlikely(zombie_process
!= NULL
)) {
2916 /* Reutilisation of PID. Only now we are sure that the old PID
2917 * has been released. FIXME : should know when release_task happens instead.
2919 guint num_cpus
= ltt_trace_get_num_cpu(ts
->parent
.t
);
2921 for(i
=0; i
< num_cpus
; i
++) {
2922 g_assert(zombie_process
!= ts
->running_process
[i
]);
2925 exit_process(s
, zombie_process
);
2928 g_assert(process
->pid
!= child_pid
);
2929 // FIXME : Add this test in the "known state" section
2930 // g_assert(process->pid == parent_pid);
2931 child_process
= lttv_state_find_process(ts
, ANY_CPU
, child_pid
);
2932 if(child_process
== NULL
) {
2933 child_process
= lttv_state_create_process(ts
, process
, cpu
,
2934 child_pid
, child_tgid
,
2935 LTTV_STATE_UNNAMED
, ×tamp
);
2937 /* The process has already been created : due to time imprecision between
2938 * multiple CPUs : it has been scheduled in before creation. Note that we
2939 * shouldn't have this kind of imprecision.
2941 * Simply put a correct parent.
2943 g_error("Process %u has been created at [%lu.%09lu] "
2944 "and inserted at [%lu.%09lu] before \n"
2945 "fork on cpu %u[%lu.%09lu].\n"
2946 "Probably an unsynchronized TSC problem on the traced machine.",
2948 child_process
->creation_time
.tv_sec
,
2949 child_process
->creation_time
.tv_nsec
,
2950 child_process
->insertion_time
.tv_sec
,
2951 child_process
->insertion_time
.tv_nsec
,
2952 cpu
, timestamp
.tv_sec
, timestamp
.tv_nsec
);
2953 //g_assert(0); /* This is a problematic case : the process has been created
2954 // before the fork event */
2955 child_process
->ppid
= process
->pid
;
2956 child_process
->tgid
= child_tgid
;
2958 g_assert(child_process
->name
== LTTV_STATE_UNNAMED
);
2959 child_process
->name
= process
->name
;
2964 #ifdef BABEL_CLEANUP
2965 //NO KTHREAD_CREATE in LTTng 2.0
2966 /* We stamp a newly created process as kernel_thread.
2967 * The thread should not be running yet. */
2968 static gboolean
process_kernel_thread(void *hook_data
, void *call_data
)
2970 LttvTracefileState
*s
= (LttvTracefileState
*)call_data
;
2971 LttEvent
*e
= ltt_tracefile_get_event(s
->parent
.tf
);
2972 LttvTraceHook
*th
= (LttvTraceHook
*)hook_data
;
2974 LttvTraceState
*ts
= (LttvTraceState
*)s
->parent
.t_context
;
2975 LttvProcessState
*process
;
2976 LttvExecutionState
*es
;
2979 pid
= (guint
)ltt_event_get_long_unsigned(e
, lttv_trace_get_hook_field(th
, 0));
2980 //s->parent.target_pid = pid;
2982 process
= lttv_state_find_process_or_create(ts
, ANY_CPU
, pid
,
2984 if (process
->state
->s
!= LTTV_STATE_DEAD
) {
2985 process
->execution_stack
=
2986 g_array_set_size(process
->execution_stack
, 1);
2987 es
= process
->state
=
2988 &g_array_index(process
->execution_stack
, LttvExecutionState
, 0);
2989 es
->t
= LTTV_STATE_SYSCALL
;
2991 process
->type
= LTTV_STATE_KERNEL_THREAD
;
2996 static gboolean
process_exit(void *hook_data
, void *call_data
)
3002 LttvProcessState
*process
; // = ts->running_process[cpu];
3004 event
= (LttvEvent
*) call_data
;
3005 if (strcmp(lttv_traceset_get_name_from_event(event
),
3006 "sched_process_exit") != 0)
3008 cpu
= lttv_traceset_get_cpuid_from_event(event
);
3010 process
= ts
->running_process
[cpu
];
3012 pid
= lttv_event_get_long(event
, "tid");
3013 //s->parent.target_pid = pid;
3015 // FIXME : Add this test in the "known state" section
3016 // g_assert(process->pid == pid);
3018 process
= lttv_state_find_process(ts
, ANY_CPU
, pid
);
3019 if(likely(process
!= NULL
)) {
3020 process
->state
->s
= LTTV_STATE_EXIT
;
3025 static gboolean
process_free(void *hook_data
, void *call_data
)
3031 LttvProcessState
*process
;
3033 event
= (LttvEvent
*) call_data
;
3034 if (strcmp(lttv_traceset_get_name_from_event(event
),
3035 "sched_process_free") != 0)
3037 cpu
= lttv_traceset_get_cpuid_from_event(event
);
3039 process
= ts
->running_process
[cpu
];
3041 /* PID of the process to release */
3042 release_pid
= lttv_event_get_long(event
, "_tid");
3043 //s->parent.target_pid = release_pid;
3045 g_assert(release_pid
!= 0);
3047 process
= lttv_state_find_process(ts
, ANY_CPU
, release_pid
);
3048 if(likely(process
!= NULL
))
3049 exit_process(event
, process
);
3053 if(likely(process
!= NULL
)) {
3054 /* release_task is happening at kernel level : we can now safely release
3055 * the data structure of the process */
3056 //This test is fun, though, as it may happen that
3057 //at time t : CPU 0 : process_free
3058 //at time t+150ns : CPU 1 : schedule out
3059 //Clearly due to time imprecision, we disable it. (Mathieu)
3060 //If this weird case happen, we have no choice but to put the
3061 //Currently running process on the cpu to 0.
3062 //I re-enable it following time precision fixes. (Mathieu)
3063 //Well, in the case where an process is freed by a process on another CPU
3064 //and still scheduled, it happens that this is the schedchange that will
3065 //drop the last reference count. Do not free it here!
3066 guint num_cpus
= ltt_trace_get_num_cpu(ts
->parent
.t
);
3068 for(i
=0; i
< num_cpus
; i
++) {
3069 //g_assert(process != ts->running_process[i]);
3070 if(process
== ts
->running_process
[i
]) {
3071 //ts->running_process[i] = lttv_state_find_process(ts, i, 0);
3075 if(i
== num_cpus
) /* process is not scheduled */
3076 exit_process(s
, process
);
3084 static gboolean
process_exec(void *hook_data
, void *call_data
)
3090 LttvProcessState
*process
;
3092 event
= (LttvEvent
*) call_data
;
3093 if (strcmp(lttv_traceset_get_name_from_event(event
),
3096 cpu
= lttv_traceset_get_cpuid_from_event(event
);
3098 process
= ts
->running_process
[cpu
];
3100 #if 0//how to use a sequence that must be transformed in a string
3101 /* PID of the process to release */
3102 guint64 name_len
= ltt_event_field_element_number(e
,
3103 lttv_trace_get_hook_field(th
, 0));
3104 //name = ltt_event_get_string(e, lttv_trace_get_hook_field(th, 0));
3105 LttField
*child
= ltt_event_field_element_select(e
,
3106 lttv_trace_get_hook_field(th
, 0), 0);
3108 (gchar
*)(ltt_event_data(e
)+ltt_event_field_offset(e
, child
));
3109 gchar
*null_term_name
= g_new(gchar
, name_len
+1);
3110 memcpy(null_term_name
, name_begin
, name_len
);
3111 null_term_name
[name_len
] = '\0';
3112 process
->name
= g_quark_from_string(null_term_name
);
3115 process
->name
= g_quark_from_string(lttv_event_get_string(event
,
3117 //g_free(null_term_name);
3121 // TODO We only have sys_open, without the FD
3122 // manage to do somehting better
3123 static gboolean
fs_open(void *hook_data
, void *call_data
)
3125 LttvTracefileState
*s
= (LttvTracefileState
*)call_data
;
3126 LttvTraceState
*ts
= (LttvTraceState
*)s
->parent
.t_context
;
3127 LttEvent
*e
= ltt_tracefile_get_event(s
->parent
.tf
);
3128 LttvTraceHook
*th
= (LttvTraceHook
*)hook_data
;
3129 struct marker_field
*f
;
3133 LttvProcessState
*process
= ts
->running_process
[cpu
];
3135 f
= lttv_trace_get_hook_field(th
, 0);
3136 fd
= ltt_event_get_int(e
, f
);
3138 f
= lttv_trace_get_hook_field(th
, 1);
3139 filename
= ltt_event_get_string(e
, f
);
3141 g_hash_table_insert(process
->fds
, (gpointer
)(long)fd
,
3142 (gpointer
)(unsigned long)g_quark_from_string(filename
));
3147 static void print_stack(LttvProcessState
*process
)
3149 LttvExecutionState
*es
;
3152 g_debug("Execution stack for process %u %s:\n",
3153 process
->pid
, g_quark_to_string(process
->name
));
3155 for (i
= 0; i
< process
->execution_stack
->len
; i
++) {
3156 es
= &g_array_index(process
->execution_stack
,
3157 LttvExecutionState
, i
);
3158 g_debug("Depth %d mode %s submode %s status %s\n",
3159 i
, g_quark_to_string(es
->t
),
3160 g_quark_to_string(es
->n
),
3161 g_quark_to_string(es
->s
));
3166 static void fix_process(gpointer key
, gpointer value
, gpointer user_data
)
3168 LttvProcessState
*process
;
3169 LttvExecutionState
*es
;
3170 process
= (LttvProcessState
*)value
;
3171 LttTime
*timestamp
= (LttTime
*)user_data
;
3173 print_stack(process
);
3175 if(process
->type
== LTTV_STATE_KERNEL_THREAD
) {
3176 es
= &g_array_index(process
->execution_stack
, LttvExecutionState
, 0);
3177 if(es
->t
== LTTV_STATE_MAYBE_SYSCALL
) {
3178 es
->t
= LTTV_STATE_SYSCALL
;
3179 es
->n
= LTTV_STATE_SUBMODE_NONE
;
3180 es
->entry
= *timestamp
;
3181 es
->change
= *timestamp
;
3182 es
->cum_cpu_time
= ltt_time_zero
;
3183 if(es
->s
== LTTV_STATE_UNNAMED
)
3184 es
->s
= LTTV_STATE_WAIT
;
3187 es
= &g_array_index(process
->execution_stack
, LttvExecutionState
, 0);
3188 if(es
->t
== LTTV_STATE_MAYBE_USER_MODE
) {
3189 es
->t
= LTTV_STATE_USER_MODE
;
3190 es
->n
= LTTV_STATE_SUBMODE_NONE
;
3191 es
->entry
= *timestamp
;
3192 //g_assert(timestamp->tv_sec != 0);
3193 es
->change
= *timestamp
;
3194 es
->cum_cpu_time
= ltt_time_zero
;
3195 if(es
->s
== LTTV_STATE_UNNAMED
)
3196 es
->s
= LTTV_STATE_RUN
;
3198 if(process
->execution_stack
->len
== 1) {
3199 /* Still in bottom unknown mode, means we either:
3200 * - never did a system call
3201 * - are scheduled out from user mode.
3202 * May be either in user mode, syscall mode, running or waiting.*/
3203 /* CHECK : we may be tagging syscall mode when being user mode
3204 * (should be fixed now) */
3205 if (es
->s
== LTTV_STATE_WAIT_CPU
) {
3206 /* nothing to do: scheduled out from userspace */
3208 process
->execution_stack
=
3209 g_array_set_size(process
->execution_stack
, 2);
3210 es
= process
->state
= &g_array_index(process
->execution_stack
,
3211 LttvExecutionState
, 1);
3212 es
->t
= LTTV_STATE_SYSCALL
;
3213 es
->n
= LTTV_STATE_SUBMODE_NONE
;
3214 es
->entry
= *timestamp
;
3215 //g_assert(timestamp->tv_sec != 0);
3216 es
->change
= *timestamp
;
3217 es
->cum_cpu_time
= ltt_time_zero
;
3218 if(es
->s
== LTTV_STATE_WAIT_FORK
)
3219 es
->s
= LTTV_STATE_WAIT
;
3226 static gboolean
statedump_end(void *hook_data
, void *call_data
)
3231 //LttEvent *e = ltt_tracefile_get_event(s->parent.tf);
3232 //LttvTraceHook *th = (LttvTraceHook *)hook_data;
3233 event
= (LttvEvent
*) call_data
;
3234 if (strcmp(lttv_traceset_get_name_from_event(event
),
3235 "lttng_statedump_end") != 0)
3239 timestamp
= lttv_event_get_timestamp(event
);
3241 /* For all processes */
3242 /* if kernel thread, if stack[0] is unknown, set to syscall mode, wait */
3243 /* else, if stack[0] is unknown, set to user mode, running */
3245 g_hash_table_foreach(ts
->processes
, fix_process
, ×tamp
);
3250 static gboolean
enum_process_state(void *hook_data
, void *call_data
)
3260 LttvProcessState
*parent_process
;
3261 LttvProcessState
*process
;
3264 LttvExecutionState
*es
;
3267 event
= (LttvEvent
*) call_data
;
3268 if (strcmp(lttv_traceset_get_name_from_event(event
),
3269 "lttng_statedump_process_state") != 0)
3271 cpu
= lttv_traceset_get_cpuid_from_event(event
);
3273 process
= ts
->running_process
[cpu
];
3274 timestamp
= lttv_event_get_timestamp(event
);
3277 pid
= lttv_event_get_long(event
, "tid");
3278 //s->parent.target_pid = pid;
3281 parent_pid
= lttv_event_get_long(event
, "ppid");
3284 command
= lttv_event_get_string(event
, "name");
3288 type
= lttv_event_get_long(event
, "type");
3290 //FIXME: type is rarely used, enum must match possible types.
3292 /* Skip mode 4th param */
3294 /* Skip submode 5th param */
3296 /* Skip status 6th param */
3298 tgid
= lttv_event_get_long(event
, "pid");
3301 nb_cpus
= lttv_trace_get_num_cpu(ts
->trace
);
3302 for(i
=0; i
<nb_cpus
; i
++) {
3303 process
= lttv_state_find_process(ts
, i
, pid
);
3304 g_assert(process
!= NULL
);
3306 process
->ppid
= parent_pid
;
3307 process
->tgid
= tgid
;
3308 process
->name
= g_quark_from_string(command
);
3309 es
= &g_array_index(process
->execution_stack
, LttvExecutionState
, 0);
3310 process
->type
= LTTV_STATE_KERNEL_THREAD
;
3314 /* The process might exist if a process was forked while performing the
3316 process
= lttv_state_find_process(ts
, ANY_CPU
, pid
);
3317 if(process
== NULL
) {
3318 parent_process
= lttv_state_find_process(ts
, ANY_CPU
, parent_pid
);
3319 process
= lttv_state_create_process(ts
, parent_process
, cpu
,
3320 pid
, tgid
, g_quark_from_string(command
),
3323 /* Keep the stack bottom : a running user mode */
3324 /* Disabled because of inconsistencies in the current statedump states. */
3325 //if(type == LTTV_STATE_KERNEL_THREAD) {
3327 /* Only keep the bottom
3328 * FIXME Kernel thread : can be in syscall or interrupt or trap. */
3329 /* Will cause expected trap when in fact being syscall (even after end of
3331 * Will cause expected interrupt when being syscall. (only before end of
3332 * statedump event) */
3333 // This will cause a "popping last state on stack, ignoring it."
3334 process
->execution_stack
= g_array_set_size(process
->execution_stack
, 1);
3335 es
= process
->state
= &g_array_index(process
->execution_stack
,
3336 LttvExecutionState
, 0);
3337 process
->type
= LTTV_STATE_KERNEL_THREAD
;
3338 es
->t
= LTTV_STATE_MAYBE_SYSCALL
;
3339 es
->s
= LTTV_STATE_UNNAMED
;
3340 es
->n
= LTTV_STATE_SUBMODE_UNKNOWN
;
3344 /* User space process :
3345 * bottom : user mode
3346 * either currently running or scheduled out.
3347 * can be scheduled out because interrupted in (user mode or in syscall)
3348 * or because of an explicit call to the scheduler in syscall. Note that
3349 * the scheduler call comes after the irq_exit, so never in interrupt
3351 // temp workaround : set size to 1 : only have user mode bottom of stack.
3352 // will cause g_info message of expected syscall mode when in fact being
3353 // in user mode. Can also cause expected trap when in fact being user
3354 // mode in the event of a page fault reenabling interrupts in the handler.
3355 // Expected syscall and trap can also happen after the end of statedump
3356 // This will cause a "popping last state on stack, ignoring it."
3357 process
->execution_stack
= g_array_set_size(process
->execution_stack
, 1);
3358 es
= process
->state
= &g_array_index(process
->execution_stack
,
3359 LttvExecutionState
, 0);
3360 es
->t
= LTTV_STATE_MAYBE_USER_MODE
;
3361 es
->s
= LTTV_STATE_UNNAMED
;
3362 es
->n
= LTTV_STATE_SUBMODE_UNKNOWN
;
3369 es
= process
->state
= &g_array_index(process
->execution_stack
,
3370 LttvExecutionState
, 1);
3371 es
->t
= LTTV_STATE_MODE_UNKNOWN
;
3372 es
->s
= LTTV_STATE_UNNAMED
;
3373 es
->n
= LTTV_STATE_SUBMODE_UNKNOWN
;
3377 /* The process has already been created :
3378 * Probably was forked while dumping the process state or
3379 * was simply scheduled in prior to get the state dump event.
3381 process
->ppid
= parent_pid
;
3382 process
->tgid
= tgid
;
3383 process
->name
= g_quark_from_string(command
);
3384 process
->type
= type
;
3385 es
= &g_array_index(process
->execution_stack
, LttvExecutionState
, 0);
3387 if(es
->t
== LTTV_STATE_MODE_UNKNOWN
) {
3388 if(type
== LTTV_STATE_KERNEL_THREAD
)
3389 es
->t
= LTTV_STATE_SYSCALL
;
3391 es
->t
= LTTV_STATE_USER_MODE
;
3394 /* Don't mess around with the stack, it will eventually become
3395 * ok after the end of state dump. */
3404 gint
lttv_state_hook_add_event_hooks(void *hook_data
, void *call_data
)
3406 LttvTraceset
*traceset
= (LttvTraceset
*)(call_data
);
3408 lttv_state_add_event_hooks(traceset
);
3413 void lttv_state_add_event_hooks(LttvTraceset
*traceset
)
3417 LttvAttributeValue value
;
3418 LttvHooks
*event_hook
;
3419 #ifdef BABEL_CLEANUP
3420 LttvIAttribute
*attributes
= LTTV_IATTRIBUTE(lttv_global_attributes());
3421 result
= lttv_iattribute_find_by_path(attributes
, "hooks/event",
3422 LTTV_POINTER
, &value
);
3424 event_hook
= *(value
.v_pointer
);
3426 //TODO ybrosseau 2012-07-12: Validate that using traceset hooks instead of the global one is valid
3427 //Use traceset hooks
3428 event_hook
= lttv_traceset_get_hooks(traceset
);
3429 g_assert(event_hook
);
3431 lttv_hooks_add(event_hook
,syscall_entry
, NULL
, LTTV_PRIO_STATE
);
3432 lttv_hooks_add(event_hook
,syscall_exit
, NULL
, LTTV_PRIO_STATE
);
3433 lttv_hooks_add(event_hook
,irq_entry
, NULL
, LTTV_PRIO_STATE
);
3434 lttv_hooks_add(event_hook
,irq_exit
, NULL
, LTTV_PRIO_STATE
);
3435 lttv_hooks_add(event_hook
,soft_irq_raise
, NULL
, LTTV_PRIO_STATE
);
3436 lttv_hooks_add(event_hook
,soft_irq_entry
, NULL
, LTTV_PRIO_STATE
);
3437 lttv_hooks_add(event_hook
,soft_irq_exit
, NULL
, LTTV_PRIO_STATE
);
3438 lttv_hooks_add(event_hook
,schedchange
, NULL
, LTTV_PRIO_STATE
);
3439 lttv_hooks_add(event_hook
,sched_try_wakeup
, NULL
, LTTV_PRIO_STATE
);
3440 lttv_hooks_add(event_hook
,process_exit
, NULL
, LTTV_PRIO_STATE
);
3441 lttv_hooks_add(event_hook
,process_free
, NULL
, LTTV_PRIO_STATE
);
3442 lttv_hooks_add(event_hook
,process_fork
, NULL
, LTTV_PRIO_STATE
);
3443 lttv_hooks_add(event_hook
,process_exec
, NULL
, LTTV_PRIO_STATE
);
3444 lttv_hooks_add(event_hook
,enum_process_state
, NULL
, LTTV_PRIO_STATE
);
3445 lttv_hooks_add(event_hook
,statedump_end
, NULL
, LTTV_PRIO_STATE
);
3446 lttv_hooks_add(event_hook
,enum_interrupt
, NULL
, LTTV_PRIO_STATE
);
3448 #ifdef BABEL_CLEANUP //For the whole function this time
3449 guint i
, j
, k
, nb_trace
;
3452 // LttvTraceHook *th;
3453 LttvAttributeValue val
;
3455 nb_trace
= lttv_traceset_number(traceset
);
3456 for (i
= 0 ; i
< nb_trace
; i
++) {
3457 ts
= lttv_traceset_get(traceset
, i
)-;
3459 /* Find the eventtype id for the following events and register the
3460 associated by id hooks. */
3462 hooks
= g_array_sized_new(FALSE
, FALSE
, sizeof(LttvTraceHook
), 20);
3463 //hooks = g_array_set_size(hooks, 19); // Max possible number of hooks.
3466 lttv_trace_find_hook(tss
->parent
.t
,
3468 LTT_EVENT_SYSCALL_ENTRY
,
3469 FIELD_ARRAY(LTT_FIELD_SYSCALL_ID
),
3470 syscall_entry
, NULL
, &hooks
);
3472 lttv_trace_find_hook(ts
->parent
.t
,
3474 LTT_EVENT_SYSCALL_EXIT
,
3476 syscall_exit
, NULL
, &hooks
);
3478 #ifdef BABEL_CLEANUP
3479 lttv_trace_find_hook(ts
->parent
.t
,
3481 LTT_EVENT_TRAP_ENTRY
,
3482 FIELD_ARRAY(LTT_FIELD_TRAP_ID
),
3483 trap_entry
, NULL
, &hooks
);
3485 lttv_trace_find_hook(ts
->parent
.t
,
3487 LTT_EVENT_TRAP_EXIT
,
3489 trap_exit
, NULL
, &hooks
);
3490 #endif /* BABEL_CLEANUP */
3492 lttv_trace_find_hook(ts
->parent
.t
,
3494 LTT_EVENT_PAGE_FAULT_ENTRY
,
3495 FIELD_ARRAY(LTT_FIELD_TRAP_ID
),
3496 trap_entry
, NULL
, &hooks
);
3498 lttv_trace_find_hook(ts
->parent
.t
,
3500 LTT_EVENT_PAGE_FAULT_EXIT
,
3502 trap_exit
, NULL
, &hooks
);
3504 #ifdef BABEL_CLEANUP
3505 lttv_trace_find_hook(ts
->parent
.t
,
3507 LTT_EVENT_PAGE_FAULT_NOSEM_ENTRY
,
3508 FIELD_ARRAY(LTT_FIELD_TRAP_ID
),
3509 trap_entry
, NULL
, &hooks
);
3511 lttv_trace_find_hook(ts
->parent
.t
,
3513 LTT_EVENT_PAGE_FAULT_NOSEM_EXIT
,
3515 trap_exit
, NULL
, &hooks
);
3516 #endif /* BABEL_CLEANUP */
3518 lttv_trace_find_hook(ts
->parent
.t
,
3520 LTT_EVENT_IRQ_ENTRY
,
3521 FIELD_ARRAY(LTT_FIELD_IRQ_ID
),
3522 irq_entry
, NULL
, &hooks
);
3524 lttv_trace_find_hook(ts
->parent
.t
,
3528 irq_exit
, NULL
, &hooks
);
3530 lttv_trace_find_hook(ts
->parent
.t
,
3532 LTT_EVENT_SOFT_IRQ_RAISE
,
3533 FIELD_ARRAY(LTT_FIELD_SOFT_IRQ_ID
),
3534 soft_irq_raise
, NULL
, &hooks
);
3536 lttv_trace_find_hook(ts
->parent
.t
,
3538 LTT_EVENT_SOFT_IRQ_ENTRY
,
3539 FIELD_ARRAY(LTT_FIELD_SOFT_IRQ_ID
),
3540 soft_irq_entry
, NULL
, &hooks
);
3542 lttv_trace_find_hook(ts
->parent
.t
,
3544 LTT_EVENT_SOFT_IRQ_EXIT
,
3546 soft_irq_exit
, NULL
, &hooks
);
3548 lttv_trace_find_hook(ts
->parent
.t
,
3550 LTT_EVENT_SCHED_SCHEDULE
,
3551 FIELD_ARRAY(LTT_FIELD_PREV_PID
, LTT_FIELD_NEXT_PID
,
3552 LTT_FIELD_PREV_STATE
),
3553 schedchange
, NULL
, &hooks
);
3555 lttv_trace_find_hook(ts
->parent
.t
,
3557 LTT_EVENT_SCHED_TRY_WAKEUP
,
3558 FIELD_ARRAY(LTT_FIELD_PID
, LTT_FIELD_CPU_ID
, LTT_FIELD_STATE
),
3559 sched_try_wakeup
, NULL
, &hooks
);
3561 lttv_trace_find_hook(ts
->parent
.t
,
3563 LTT_EVENT_PROCESS_FORK
,
3564 FIELD_ARRAY(LTT_FIELD_PARENT_PID
, LTT_FIELD_CHILD_PID
,
3565 LTT_FIELD_CHILD_TGID
),
3566 process_fork
, NULL
, &hooks
);
3568 lttv_trace_find_hook(ts
->parent
.t
,
3570 LTT_EVENT_KTHREAD_CREATE
,
3571 FIELD_ARRAY(LTT_FIELD_PID
),
3572 process_kernel_thread
, NULL
, &hooks
);
3574 lttv_trace_find_hook(ts
->parent
.t
,
3576 LTT_EVENT_PROCESS_EXIT
,
3577 FIELD_ARRAY(LTT_FIELD_PID
),
3578 process_exit
, NULL
, &hooks
);
3580 lttv_trace_find_hook(ts
->parent
.t
,
3582 LTT_EVENT_PROCESS_FREE
,
3583 FIELD_ARRAY(LTT_FIELD_PID
),
3584 process_free
, NULL
, &hooks
);
3586 lttv_trace_find_hook(ts
->parent
.t
,
3589 FIELD_ARRAY(LTT_FIELD_FILENAME
),
3590 process_exec
, NULL
, &hooks
);
3592 /* statedump-related hooks */
3593 lttv_trace_find_hook(ts
->parent
.t
,
3594 LTT_CHANNEL_TASK_STATE
,
3595 LTT_EVENT_PROCESS_STATE
,
3596 FIELD_ARRAY(LTT_FIELD_PID
, LTT_FIELD_PARENT_PID
, LTT_FIELD_NAME
,
3597 LTT_FIELD_TYPE
, LTT_FIELD_MODE
, LTT_FIELD_SUBMODE
,
3598 LTT_FIELD_STATUS
, LTT_FIELD_TGID
),
3599 enum_process_state
, NULL
, &hooks
);
3601 lttv_trace_find_hook(ts
->parent
.t
,
3602 LTT_CHANNEL_GLOBAL_STATE
,
3603 LTT_EVENT_STATEDUMP_END
,
3605 statedump_end
, NULL
, &hooks
);
3607 lttv_trace_find_hook(ts
->parent
.t
,
3608 LTT_CHANNEL_IRQ_STATE
,
3609 LTT_EVENT_LIST_INTERRUPT
,
3610 FIELD_ARRAY(LTT_FIELD_ACTION
, LTT_FIELD_IRQ_ID
),
3611 enum_interrupt
, NULL
, &hooks
);
3613 lttv_trace_find_hook(ts
->parent
.t
,
3615 LTT_EVENT_REQUEST_ISSUE
,
3616 FIELD_ARRAY(LTT_FIELD_MAJOR
, LTT_FIELD_MINOR
, LTT_FIELD_OPERATION
),
3617 bdev_request_issue
, NULL
, &hooks
);
3619 lttv_trace_find_hook(ts
->parent
.t
,
3621 LTT_EVENT_REQUEST_COMPLETE
,
3622 FIELD_ARRAY(LTT_FIELD_MAJOR
, LTT_FIELD_MINOR
, LTT_FIELD_OPERATION
),
3623 bdev_request_complete
, NULL
, &hooks
);
3625 lttv_trace_find_hook(ts
->parent
.t
,
3626 LTT_CHANNEL_USERSPACE
,
3627 LTT_EVENT_FUNCTION_ENTRY
,
3628 FIELD_ARRAY(LTT_FIELD_THIS_FN
, LTT_FIELD_CALL_SITE
),
3629 function_entry
, NULL
, &hooks
);
3631 lttv_trace_find_hook(ts
->parent
.t
,
3632 LTT_CHANNEL_USERSPACE
,
3633 LTT_EVENT_FUNCTION_EXIT
,
3634 FIELD_ARRAY(LTT_FIELD_THIS_FN
, LTT_FIELD_CALL_SITE
),
3635 function_exit
, NULL
, &hooks
);
3637 lttv_trace_find_hook(ts
->parent
.t
,
3638 LTT_CHANNEL_SYSCALL_STATE
,
3639 LTT_EVENT_SYS_CALL_TABLE
,
3640 FIELD_ARRAY(LTT_FIELD_ID
, LTT_FIELD_ADDRESS
, LTT_FIELD_SYMBOL
),
3641 dump_syscall
, NULL
, &hooks
);
3643 lttv_trace_find_hook(ts
->parent
.t
,
3644 LTT_CHANNEL_KPROBE_STATE
,
3645 LTT_EVENT_KPROBE_TABLE
,
3646 FIELD_ARRAY(LTT_FIELD_IP
, LTT_FIELD_SYMBOL
),
3647 dump_kprobe
, NULL
, &hooks
);
3649 lttv_trace_find_hook(ts
->parent
.t
,
3650 LTT_CHANNEL_SOFTIRQ_STATE
,
3651 LTT_EVENT_SOFTIRQ_VEC
,
3652 FIELD_ARRAY(LTT_FIELD_ID
, LTT_FIELD_ADDRESS
, LTT_FIELD_SYMBOL
),
3653 dump_softirq
, NULL
, &hooks
);
3655 lttv_trace_find_hook(ts
->parent
.t
,
3658 FIELD_ARRAY(LTT_FIELD_FD
, LTT_FIELD_FILENAME
),
3659 fs_open
, NULL
, &hooks
);
3661 /* Add these hooks to each event_by_id hooks list */
3663 nb_tracefile
= ts
->parent
.tracefiles
->len
;
3665 for(j
= 0 ; j
< nb_tracefile
; j
++) {
3667 LTTV_TRACEFILE_STATE(g_array_index(ts
->parent
.tracefiles
,
3668 LttvTracefileContext
*, j
));
3670 for(k
= 0 ; k
< hooks
->len
; k
++) {
3671 th
= &g_array_index(hooks
, LttvTraceHook
, k
);
3672 if (th
->mdata
== tfs
->parent
.tf
->mdata
)
3674 lttv_hooks_by_id_find(tfs
->parent
.event_by_id
, th
->id
),
3680 lttv_attribute_find(ts
->parent
.a
, LTTV_STATE_HOOKS
, LTTV_POINTER
, &val
);
3681 *(val
.v_pointer
) = hooks
;
3686 gint
lttv_state_hook_remove_event_hooks(void *hook_data
, void *call_data
)
3689 LttvTraceset
*traceset
= (LttvTraceset
*)(call_data
);
3691 lttv_state_remove_event_hooks(traceset
);
3696 void lttv_state_remove_event_hooks(LttvTraceset
*traceset
)
3699 guint i
, j
, k
, nb_trace
, nb_tracefile
;
3701 //LttvTraceState *ts;
3705 //LttvTraceHook *th;
3707 //LttvAttributeValue val;
3709 LttvHooks
*event_hook
;
3710 //TODO ybrosseau 2012-07-17 validate this. Reversed what's done in the add
3711 event_hook
= lttv_traceset_get_hooks(traceset
);
3713 g_assert(event_hook
);
3716 lttv_hooks_remove(event_hook
,syscall_entry
);
3717 lttv_hooks_remove(event_hook
,syscall_exit
);
3718 lttv_hooks_remove(event_hook
,irq_entry
);
3719 lttv_hooks_remove(event_hook
,irq_exit
);
3720 lttv_hooks_remove(event_hook
,soft_irq_raise
);
3721 lttv_hooks_remove(event_hook
,soft_irq_entry
);
3722 lttv_hooks_remove(event_hook
,soft_irq_exit
);
3723 lttv_hooks_remove(event_hook
,schedchange
);
3724 lttv_hooks_remove(event_hook
,sched_try_wakeup
);
3725 lttv_hooks_remove(event_hook
,process_exit
);
3726 lttv_hooks_remove(event_hook
,process_free
);
3727 lttv_hooks_remove(event_hook
,process_exec
);
3728 lttv_hooks_remove(event_hook
,enum_process_state
);
3729 lttv_hooks_remove(event_hook
,statedump_end
);
3730 lttv_hooks_remove(event_hook
,enum_interrupt
);
3731 #ifdef BABEL_CLEANUP
3732 nb_trace
= lttv_traceset_number(traceset
);
3733 for(i
= 0 ; i
< nb_trace
; i
++) {
3734 ts
= lttv_traceset_get(i
);
3736 lttv_attribute_find(ts
->parent
.a
, LTTV_STATE_HOOKS
, LTTV_POINTER
, &val
);
3737 hooks
= *(val
.v_pointer
);
3739 /* Remove these hooks from each event_by_id hooks list */
3741 nb_tracefile
= ts
->parent
.tracefiles
->len
;
3743 for(j
= 0 ; j
< nb_tracefile
; j
++) {
3745 LTTV_TRACEFILE_STATE(g_array_index(ts
->parent
.tracefiles
,
3746 LttvTracefileContext
*, j
));
3748 for(k
= 0 ; k
< hooks
->len
; k
++) {
3749 th
= &g_array_index(hooks
, LttvTraceHook
, k
);
3750 if (th
->mdata
== tfs
->parent
.tf
->mdata
)
3751 lttv_hooks_remove_data(
3752 lttv_hooks_by_id_find(tfs
->parent
.event_by_id
, th
->id
),
3757 lttv_trace_hook_remove_all(&hooks
);
3758 g_array_free(hooks
, TRUE
);
3764 static gboolean
state_save_event_hook(void *hook_data
, void *call_data
)
3766 guint
*event_count
= (guint
*)hook_data
;
3768 /* Only save at LTTV_STATE_SAVE_INTERVAL */
3769 if(likely((*event_count
)++ < LTTV_STATE_SAVE_INTERVAL
))
3774 LttvEvent
*event
= (LttvEvent
*)call_data
;
3776 LttvTraceset
*traceset
= lttv_trace_get_traceset(event
->state
->trace
);
3778 LttvAttribute
*saved_states_tree
, *saved_state_tree
;
3780 LttvAttributeValue value
;
3781 LttTime currentTime
;
3783 currentTime
= lttv_event_get_timestamp(event
);
3784 int nb_trace
= lttv_traceset_number(traceset
);
3785 for(i
= 0 ; i
< nb_trace
; i
++) {
3787 LttvTrace
*trace
= lttv_traceset_get(traceset
, i
);
3788 LttvTraceState
*tstate
= trace
->state
;
3789 saved_states_tree
= lttv_attribute_find_subdir(trace
->a
,
3790 LTTV_STATE_SAVED_STATES
);
3792 saved_state_tree
= g_object_new(LTTV_ATTRIBUTE_TYPE
, NULL
);
3793 value
= lttv_attribute_add(saved_states_tree
,
3794 lttv_attribute_get_number(saved_states_tree
), LTTV_GOBJECT
);
3795 *(value
.v_gobject
) = (GObject
*)saved_state_tree
;
3798 value
= lttv_attribute_add(saved_state_tree
, LTTV_STATE_TIME
, LTTV_TIME
);
3799 *(value
.v_time
) = currentTime
;
3801 lttv_state_save(tstate
, saved_state_tree
);
3802 g_debug("Saving state at time %lu.%lu", currentTime
.tv_sec
,
3803 currentTime
.tv_nsec
);
3805 *(tstate
->max_time_state_recomputed_in_seek
) = currentTime
;
3810 static gboolean
state_save_after_trace_hook(void *hook_data
, void *call_data
)
3812 #warning "Would we move max_time to traceset"
3813 LttvTrace
*trace
= (LttvTrace
*)(call_data
);
3814 LttvTraceState
*tcs
= trace
->state
;
3815 TimeInterval time_span
= lttv_traceset_get_time_span_real(lttv_trace_get_traceset(trace
));
3817 *(tcs
->max_time_state_recomputed_in_seek
) = time_span
.end_time
;
3821 #ifdef BABEL_CLEANUP
3822 guint
lttv_state_current_cpu(LttvTracefileState
*tfs
)
3827 #endif //BABEL_CLEANUP
3830 static gboolean
block_start(void *hook_data
, void *call_data
)
3832 LttvTracefileState
*self
= (LttvTracefileState
*)call_data
;
3834 LttvTracefileState
*tfcs
;
3836 LttvTraceState
*tcs
= (LttvTraceState
*)(self
->parent
.t_context
);
3838 LttEventPosition
*ep
;
3840 guint i
, nb_block
, nb_event
, nb_tracefile
;
3844 LttvAttribute
*saved_states_tree
, *saved_state_tree
;
3846 LttvAttributeValue value
;
3848 ep
= ltt_event_position_new();
3850 nb_tracefile
= tcs
->parent
.tracefiles
->len
;
3852 /* Count the number of events added since the last block end in any
3855 for(i
= 0 ; i
< nb_tracefile
; i
++) {
3857 LTTV_TRACEFILE_STATE(&g_array_index(tcs
->parent
.tracefiles
,
3858 LttvTracefileContext
, i
));
3859 ltt_event_position(tfcs
->parent
.e
, ep
);
3860 ltt_event_position_get(ep
, &nb_block
, &nb_event
, &tf
);
3861 tcs
->nb_event
+= nb_event
- tfcs
->saved_position
;
3862 tfcs
->saved_position
= nb_event
;
3866 if(tcs
->nb_event
>= tcs
->save_interval
) {
3867 saved_states_tree
= lttv_attribute_find_subdir(tcs
->parent
.t_a
,
3868 LTTV_STATE_SAVED_STATES
);
3869 saved_state_tree
= g_object_new(LTTV_ATTRIBUTE_TYPE
, NULL
);
3870 value
= lttv_attribute_add(saved_states_tree
,
3871 lttv_attribute_get_number(saved_states_tree
), LTTV_GOBJECT
);
3872 *(value
.v_gobject
) = (GObject
*)saved_state_tree
;
3873 value
= lttv_attribute_add(saved_state_tree
, LTTV_STATE_TIME
, LTTV_TIME
);
3874 *(value
.v_time
) = self
->parent
.timestamp
;
3875 lttv_state_save(tcs
, saved_state_tree
);
3877 g_debug("Saving state at time %lu.%lu", self
->parent
.timestamp
.tv_sec
,
3878 self
->parent
.timestamp
.tv_nsec
);
3880 *(tcs
->max_time_state_recomputed_in_seek
) = self
->parent
.timestamp
;
3886 static gboolean
block_end(void *hook_data
, void *call_data
)
3888 LttvTracefileState
*self
= (LttvTracefileState
*)call_data
;
3890 LttvTraceState
*tcs
= (LttvTraceState
*)(self
->parent
.t_context
);
3894 LttEventPosition
*ep
;
3896 guint nb_block
, nb_event
;
3898 ep
= ltt_event_position_new();
3899 ltt_event_position(self
->parent
.e
, ep
);
3900 ltt_event_position_get(ep
, &nb_block
, &nb_event
, &tf
);
3901 tcs
->nb_event
+= nb_event
- self
->saved_position
+ 1;
3902 self
->saved_position
= 0;
3903 *(tcs
->max_time_state_recomputed_in_seek
) = self
->parent
.timestamp
;
3910 void lttv_state_save_add_event_hooks(LttvTracesetState
*self
)
3912 LttvTraceset
*traceset
= self
->parent
.ts
;
3914 guint i
, j
, nb_trace
, nb_tracefile
;
3918 LttvTracefileState
*tfs
;
3920 LttvTraceHook hook_start
, hook_end
;
3922 nb_trace
= lttv_traceset_number(traceset
);
3923 for(i
= 0 ; i
< nb_trace
; i
++) {
3924 ts
= (LttvTraceState
*)self
->parent
.traces
[i
];
3926 lttv_trace_find_hook(ts
->parent
.t
, "core","block_start",NULL
,
3927 NULL
, NULL
, block_start
, &hook_start
);
3928 lttv_trace_find_hook(ts
->parent
.t
, "core","block_end",NULL
,
3929 NULL
, NULL
, block_end
, &hook_end
);
3931 nb_tracefile
= ts
->parent
.tracefiles
->len
;
3933 for(j
= 0 ; j
< nb_tracefile
; j
++) {
3935 LTTV_TRACEFILE_STATE(&g_array_index(ts
->parent
.tracefiles
,
3936 LttvTracefileContext
, j
));
3937 lttv_hooks_add(lttv_hooks_by_id_find(tfs
->parent
.event_by_id
,
3938 hook_start
.id
), hook_start
.h
, NULL
, LTTV_PRIO_STATE
);
3939 lttv_hooks_add(lttv_hooks_by_id_find(tfs
->parent
.event_by_id
,
3940 hook_end
.id
), hook_end
.h
, NULL
, LTTV_PRIO_STATE
);
3946 void lttv_state_save_add_event_hooks(LttvTraceset
*traceset
)
3949 guint i
, j
, nb_trace
, nb_tracefile
;
3953 LttvTracefileState
*tfs
;
3956 if(!traceset
->has_precomputed_states
) {
3957 guint
*event_count
= g_new(guint
, 1);
3960 lttv_hooks_add(traceset
->event_hooks
,
3961 state_save_event_hook
,
3965 #ifdef BABEL_CLEANUP
3966 nb_trace
= lttv_traceset_number(traceset
);
3967 for(i
= 0 ; i
< nb_trace
; i
++) {
3969 ts
= (LttvTraceState
*)self
->parent
.traces
[i
];
3970 nb_tracefile
= ts
->parent
.tracefiles
->len
;
3972 if(ts
->has_precomputed_states
) continue;
3974 guint
*event_count
= g_new(guint
, 1);
3977 for(j
= 0 ; j
< nb_tracefile
; j
++) {
3979 LTTV_TRACEFILE_STATE(g_array_index(ts
->parent
.tracefiles
,
3980 LttvTracefileContext
*, j
));
3981 lttv_hooks_add(tfs
->parent
.event
,
3982 state_save_event_hook
,
3989 lttv_process_traceset_begin(traceset
,
3990 NULL
, NULL
, NULL
, NULL
, NULL
);
3995 gint
lttv_state_save_hook_add_event_hooks(void *hook_data
, void *call_data
)
3997 LttvTraceset
*ts
= (LttvTraceset
*)(call_data
);
3999 lttv_state_save_add_event_hooks(ts
);
4006 void lttv_state_save_remove_event_hooks(LttvTracesetState
*self
)
4008 LttvTraceset
*traceset
= self
->parent
.ts
;
4010 guint i
, j
, nb_trace
, nb_tracefile
;
4014 LttvTracefileState
*tfs
;
4016 LttvTraceHook hook_start
, hook_end
;
4018 nb_trace
= lttv_traceset_number(traceset
);
4019 for(i
= 0 ; i
< nb_trace
; i
++) {
4020 ts
= LTTV_TRACE_STATE(self
->parent
.traces
[i
]);
4022 lttv_trace_find_hook(ts
->parent
.t
, "core","block_start",NULL
,
4023 NULL
, NULL
, block_start
, &hook_start
);
4025 lttv_trace_find_hook(ts
->parent
.t
, "core","block_end",NULL
,
4026 NULL
, NULL
, block_end
, &hook_end
);
4028 nb_tracefile
= ts
->parent
.tracefiles
->len
;
4030 for(j
= 0 ; j
< nb_tracefile
; j
++) {
4032 LTTV_TRACEFILE_STATE(&g_array_index(ts
->parent
.tracefiles
,
4033 LttvTracefileContext
, j
));
4034 lttv_hooks_remove_data(lttv_hooks_by_id_find(
4035 tfs
->parent
.event_by_id
, hook_start
.id
), hook_start
.h
, NULL
);
4036 lttv_hooks_remove_data(lttv_hooks_by_id_find(
4037 tfs
->parent
.event_by_id
, hook_end
.id
), hook_end
.h
, NULL
);
4043 void lttv_state_save_remove_event_hooks(LttvTraceset
*traceset
)
4046 guint i
, j
, nb_trace
, nb_tracefile
;
4050 LttvTracefileState
*tfs
;
4052 LttvHooks
*after_trace
= lttv_hooks_new();
4053 guint
*event_count
= NULL
;
4055 lttv_hooks_add(after_trace
,
4056 state_save_after_trace_hook
,
4061 lttv_process_traceset_end(traceset
,
4062 NULL
, after_trace
, NULL
, NULL
);
4064 lttv_hooks_destroy(after_trace
);
4066 //nb_trace = lttv_traceset_number(traceset);
4068 event_count
= lttv_hooks_remove(traceset
->event_hooks
,
4069 state_save_event_hook
);
4071 if(event_count
) g_free(event_count
);
4073 #ifdef BABEL_CLEANUP
4074 for(i
= 0 ; i
< nb_trace
; i
++) {
4076 ts
= (LttvTraceState
*)self
->parent
.traces
[i
];
4077 nb_tracefile
= ts
->parent
.tracefiles
->len
;
4079 if(ts
->has_precomputed_states
) continue;
4081 guint
*event_count
= NULL
;
4083 for(j
= 0 ; j
< nb_tracefile
; j
++) {
4085 LTTV_TRACEFILE_STATE(g_array_index(ts
->parent
.tracefiles
,
4086 LttvTracefileContext
*, j
));
4087 event_count
= lttv_hooks_remove(tfs
->parent
.event
,
4088 state_save_event_hook
);
4090 if(event_count
) g_free(event_count
);
4095 gint
lttv_state_save_hook_remove_event_hooks(void *hook_data
, void *call_data
)
4097 LttvTraceset
*ts
= (LttvTraceset
*)(call_data
);
4099 lttv_state_save_remove_event_hooks(ts
);
4105 void lttv_state_traceset_seek_time(LttvTraceset
*traceset
, LttTime t
)
4107 lttv_state_traceset_seek_time_closest(traceset
,
4109 lttv_process_traceset_middle(traceset
, t
, G_MAXUINT
,
4113 void lttv_state_traceset_seek_position(LttvTraceset
*traceset
, LttvTracesetPosition
*position
)
4115 LttTime t
= lttv_traceset_position_get_time(position
);
4117 lttv_state_traceset_seek_time_closest(traceset
,
4119 lttv_process_traceset_middle(traceset
,
4125 void lttv_state_traceset_seek_time_closest(LttvTraceset
*traceset
, LttTime t
)
4129 int min_pos
, mid_pos
, max_pos
;
4131 guint call_rest
= 0;
4132 guint resto_start
= 0;
4135 LttvAttributeValue value
;
4137 LttvAttributeType type
;
4139 LttvAttributeName name
;
4143 LttvAttribute
*saved_states_tree
, *saved_state_tree
, *closest_tree
= NULL
;
4145 LttTime closest_tree_time
, restored_time
;
4146 guint first_restored_time
= 1;
4148 //g_tree_destroy(self->parent.pqueue);
4149 //self->parent.pqueue = g_tree_new(compare_tracefile);
4151 g_debug("Entering seek_time_closest for time %lu.%lu", t
.tv_sec
, t
.tv_nsec
);
4153 nb_trace
= lttv_traceset_number(traceset
);
4154 for(i
= 0 ; i
< nb_trace
; i
++) {
4156 LttvTrace
*trace
= lttv_traceset_get(traceset
, i
);
4157 LttvTraceState
*tstate
= trace
->state
;
4159 if(ltt_time_compare(t
, *(tstate
->max_time_state_recomputed_in_seek
)) < 0) {
4160 saved_states_tree
= lttv_attribute_find_subdir(trace
->a
,
4161 LTTV_STATE_SAVED_STATES
);
4164 if(saved_states_tree
) {
4165 max_pos
= lttv_attribute_get_number(saved_states_tree
) - 1;
4166 mid_pos
= max_pos
/ 2;
4167 while(min_pos
< max_pos
) {
4168 type
= lttv_attribute_get(saved_states_tree
, mid_pos
,
4169 &name
, &value
, &is_named
);
4170 g_assert(type
== LTTV_GOBJECT
);
4171 saved_state_tree
= *((LttvAttribute
**)(value
.v_gobject
));
4172 type
= lttv_attribute_get_by_name(saved_state_tree
,
4173 LTTV_STATE_TIME
, &value
);
4174 g_assert(type
== LTTV_TIME
);
4175 if(ltt_time_compare(*(value
.v_time
), t
) < 0) {
4177 closest_tree
= saved_state_tree
;
4178 closest_tree_time
= *(value
.v_time
);
4180 else max_pos
= mid_pos
- 1;
4182 mid_pos
= (min_pos
+ max_pos
+ 1) / 2;
4186 /* restore the closest earlier saved state */
4188 if(first_restored_time
|| (ltt_time_compare(restored_time
, closest_tree_time
) == 0)) {
4189 first_restored_time
= 0;
4190 lttv_state_restore(tstate
, closest_tree
);
4192 restored_time
= closest_tree_time
;
4195 g_debug("State: restored time mismatch between traces");
4202 /* There is no saved state, yet we want to have it. Restart at T0 */
4208 /* We want to seek quickly without restoring/updating the state */
4215 if(resto_start
|| resto_at
) {
4216 // Restore init state and seek so
4217 for(i
= 0 ; i
< nb_trace
; i
++) {
4219 LttvTrace
*trace
= lttv_traceset_get(traceset
, i
);
4220 LttvTraceState
*tstate
= trace
->state
;
4222 restore_init_state(tstate
);
4225 // If t > max saved state
4227 lttv_process_traceset_seek_time(traceset
, t
);
4228 } else if (resto_start
) {
4229 // If no saved state
4230 lttv_process_traceset_seek_time(traceset
, ltt_time_zero
);
4234 g_info("NOT Calling restore");
4237 // Seek at checkpoint
4238 lttv_process_traceset_seek_time(traceset
, restored_time
);
4246 #ifdef BABEL_CLEANUP
4247 static void traceset_state_instance_init (GTypeInstance
*instance
, gpointer g_class
)
4252 static void traceset_state_finalize (LttvTracesetState
*self
)
4254 G_OBJECT_CLASS(g_type_class_peek(LTTV_TRACESET_CONTEXT_TYPE
))->
4255 finalize(G_OBJECT(self
));
4259 static void traceset_state_class_init (LttvTracesetContextClass
*klass
)
4261 GObjectClass
*gobject_class
= G_OBJECT_CLASS(klass
);
4263 gobject_class
->finalize
= (void (*)(GObject
*self
)) traceset_state_finalize
;
4264 klass
->init
= (void (*)(LttvTracesetContext
*self
, LttvTraceset
*ts
))init
;
4265 klass
->fini
= (void (*)(LttvTracesetContext
*self
))fini
;
4266 klass
->new_traceset_context
= new_traceset_context
;
4267 klass
->new_trace_context
= new_trace_context
;
4268 klass
->new_tracefile_context
= new_tracefile_context
;
4272 GType
lttv_traceset_state_get_type(void)
4274 static GType type
= 0;
4276 static const GTypeInfo info
= {
4277 sizeof (LttvTracesetStateClass
),
4278 NULL
, /* base_init */
4279 NULL
, /* base_finalize */
4280 (GClassInitFunc
) traceset_state_class_init
, /* class_init */
4281 NULL
, /* class_finalize */
4282 NULL
, /* class_data */
4283 sizeof (LttvTracesetState
),
4284 0, /* n_preallocs */
4285 (GInstanceInitFunc
) traceset_state_instance_init
, /* instance_init */
4286 NULL
/* value handling */
4289 type
= g_type_register_static (LTTV_TRACESET_CONTEXT_TYPE
, "LttvTracesetStateType",
4297 static void trace_state_instance_init (GTypeInstance
*instance
, gpointer g_class
)
4302 static void trace_state_finalize (LttvTraceState
*self
)
4304 G_OBJECT_CLASS(g_type_class_peek(LTTV_TRACE_CONTEXT_TYPE
))->
4305 finalize(G_OBJECT(self
));
4309 static void trace_state_class_init (LttvTraceStateClass
*klass
)
4311 GObjectClass
*gobject_class
= G_OBJECT_CLASS(klass
);
4313 gobject_class
->finalize
= (void (*)(GObject
*self
)) trace_state_finalize
;
4314 klass
->state_save
= state_save
;
4315 klass
->state_restore
= state_restore
;
4316 klass
->state_saved_free
= state_saved_free
;
4320 GType
lttv_trace_state_get_type(void)
4322 static GType type
= 0;
4324 static const GTypeInfo info
= {
4325 sizeof (LttvTraceStateClass
),
4326 NULL
, /* base_init */
4327 NULL
, /* base_finalize */
4328 (GClassInitFunc
) trace_state_class_init
, /* class_init */
4329 NULL
, /* class_finalize */
4330 NULL
, /* class_data */
4331 sizeof (LttvTraceState
),
4332 0, /* n_preallocs */
4333 (GInstanceInitFunc
) trace_state_instance_init
, /* instance_init */
4334 NULL
/* value handling */
4337 type
= g_type_register_static (LTTV_TRACE_CONTEXT_TYPE
,
4338 "LttvTraceStateType", &info
, 0);
4344 static void tracefile_state_instance_init (GTypeInstance
*instance
,
4350 static void tracefile_state_finalize (LttvTracefileState
*self
)
4352 G_OBJECT_CLASS(g_type_class_peek(LTTV_TRACEFILE_CONTEXT_TYPE
))->
4353 finalize(G_OBJECT(self
));
4357 static void tracefile_state_class_init (LttvTracefileStateClass
*klass
)
4359 GObjectClass
*gobject_class
= G_OBJECT_CLASS(klass
);
4361 gobject_class
->finalize
= (void (*)(GObject
*self
)) tracefile_state_finalize
;
4365 GType
lttv_tracefile_state_get_type(void)
4367 static GType type
= 0;
4369 static const GTypeInfo info
= {
4370 sizeof (LttvTracefileStateClass
),
4371 NULL
, /* base_init */
4372 NULL
, /* base_finalize */
4373 (GClassInitFunc
) tracefile_state_class_init
, /* class_init */
4374 NULL
, /* class_finalize */
4375 NULL
, /* class_data */
4376 sizeof (LttvTracefileState
),
4377 0, /* n_preallocs */
4378 (GInstanceInitFunc
) tracefile_state_instance_init
, /* instance_init */
4379 NULL
/* value handling */
4382 type
= g_type_register_static (LTTV_TRACEFILE_CONTEXT_TYPE
,
4383 "LttvTracefileStateType", &info
, 0);
4389 static void module_init(void)
4391 LTTV_STATE_UNNAMED
= g_quark_from_string("");
4392 LTTV_STATE_MODE_UNKNOWN
= g_quark_from_string("MODE_UNKNOWN");
4393 LTTV_STATE_USER_MODE
= g_quark_from_string("USER_MODE");
4394 LTTV_STATE_MAYBE_USER_MODE
= g_quark_from_string("MAYBE_USER_MODE");
4395 LTTV_STATE_SYSCALL
= g_quark_from_string("SYSCALL");
4396 LTTV_STATE_MAYBE_SYSCALL
= g_quark_from_string("MAYBE_SYSCALL");
4397 LTTV_STATE_TRAP
= g_quark_from_string("TRAP");
4398 LTTV_STATE_MAYBE_TRAP
= g_quark_from_string("MAYBE_TRAP");
4399 LTTV_STATE_IRQ
= g_quark_from_string("IRQ");
4400 LTTV_STATE_SOFT_IRQ
= g_quark_from_string("SOFTIRQ");
4401 LTTV_STATE_SUBMODE_UNKNOWN
= g_quark_from_string("UNKNOWN");
4402 LTTV_STATE_SUBMODE_NONE
= g_quark_from_string("NONE");
4403 LTTV_STATE_WAIT_FORK
= g_quark_from_string("WAIT_FORK");
4404 LTTV_STATE_WAIT_CPU
= g_quark_from_string("WAIT_CPU");
4405 LTTV_STATE_EXIT
= g_quark_from_string("EXIT");
4406 LTTV_STATE_ZOMBIE
= g_quark_from_string("ZOMBIE");
4407 LTTV_STATE_WAIT
= g_quark_from_string("WAIT");
4408 LTTV_STATE_RUN
= g_quark_from_string("RUN");
4409 LTTV_STATE_DEAD
= g_quark_from_string("DEAD");
4410 LTTV_STATE_USER_THREAD
= g_quark_from_string("USER_THREAD");
4411 LTTV_STATE_KERNEL_THREAD
= g_quark_from_string("KERNEL_THREAD");
4412 LTTV_STATE_TRACEFILES
= g_quark_from_string("tracefiles");
4413 LTTV_STATE_PROCESSES
= g_quark_from_string("processes");
4414 LTTV_STATE_PROCESS
= g_quark_from_string("process");
4415 LTTV_STATE_RUNNING_PROCESS
= g_quark_from_string("running_process");
4416 LTTV_STATE_POSITION
= g_quark_from_string("position");
4417 LTTV_STATE_SAVED_STATES
= g_quark_from_string("saved states");
4418 LTTV_STATE_SAVED_STATES_TIME
= g_quark_from_string("saved states time");
4419 LTTV_STATE_TIME
= g_quark_from_string("time");
4420 LTTV_STATE_HOOKS
= g_quark_from_string("saved state hooks");
4421 LTTV_STATE_NAME_TABLES
= g_quark_from_string("name tables");
4422 LTTV_STATE_TRACE_STATE_USE_COUNT
=
4423 g_quark_from_string("trace_state_use_count");
4424 LTTV_STATE_RESOURCE_CPUS
= g_quark_from_string("cpu resource states");
4425 LTTV_STATE_RESOURCE_CPUS
= g_quark_from_string("cpu count");
4426 LTTV_STATE_RESOURCE_IRQS
= g_quark_from_string("irq resource states");
4427 LTTV_STATE_RESOURCE_SOFT_IRQS
= g_quark_from_string("soft irq resource states");
4428 LTTV_STATE_RESOURCE_TRAPS
= g_quark_from_string("trap resource states");
4429 LTTV_STATE_RESOURCE_BLKDEVS
= g_quark_from_string("blkdevs resource states");
4431 LTT_CHANNEL_FD_STATE
= g_quark_from_string("fd_state");
4432 LTT_CHANNEL_GLOBAL_STATE
= g_quark_from_string("global_state");
4433 LTT_CHANNEL_IRQ_STATE
= g_quark_from_string("irq_state");
4434 LTT_CHANNEL_MODULE_STATE
= g_quark_from_string("module_state");
4435 LTT_CHANNEL_NETIF_STATE
= g_quark_from_string("netif_state");
4436 LTT_CHANNEL_SOFTIRQ_STATE
= g_quark_from_string("softirq_state");
4437 LTT_CHANNEL_SWAP_STATE
= g_quark_from_string("swap_state");
4438 LTT_CHANNEL_SYSCALL_STATE
= g_quark_from_string("syscall_state");
4439 LTT_CHANNEL_TASK_STATE
= g_quark_from_string("task_state");
4440 LTT_CHANNEL_VM_STATE
= g_quark_from_string("vm_state");
4441 LTT_CHANNEL_KPROBE_STATE
= g_quark_from_string("kprobe_state");
4442 LTT_CHANNEL_FS
= g_quark_from_string("fs");
4443 LTT_CHANNEL_KERNEL
= g_quark_from_string("kernel");
4444 LTT_CHANNEL_MM
= g_quark_from_string("mm");
4445 LTT_CHANNEL_USERSPACE
= g_quark_from_string("userspace");
4446 LTT_CHANNEL_BLOCK
= g_quark_from_string("block");
4448 LTT_EVENT_SYSCALL_ENTRY
= g_quark_from_string("syscall_entry");
4449 LTT_EVENT_SYSCALL_EXIT
= g_quark_from_string("syscall_exit");
4450 //LTT_EVENT_TRAP_ENTRY = g_quark_from_string("trap_entry");
4451 //LTT_EVENT_TRAP_EXIT = g_quark_from_string("trap_exit");
4452 LTT_EVENT_PAGE_FAULT_ENTRY
= g_quark_from_string("page_fault_entry");
4453 LTT_EVENT_PAGE_FAULT_EXIT
= g_quark_from_string("page_fault_exit");
4454 LTT_EVENT_PAGE_FAULT_NOSEM_ENTRY
= g_quark_from_string("page_fault_nosem_entry");
4455 LTT_EVENT_PAGE_FAULT_NOSEM_EXIT
= g_quark_from_string("page_fault_nosem_exit");
4456 LTT_EVENT_IRQ_ENTRY
= g_quark_from_string("irq_entry");
4457 LTT_EVENT_IRQ_EXIT
= g_quark_from_string("irq_exit");
4458 LTT_EVENT_SOFT_IRQ_RAISE
= g_quark_from_string("softirq_raise");
4459 LTT_EVENT_SOFT_IRQ_ENTRY
= g_quark_from_string("softirq_entry");
4460 LTT_EVENT_SOFT_IRQ_EXIT
= g_quark_from_string("softirq_exit");
4461 LTT_EVENT_SCHED_SCHEDULE
= g_quark_from_string("sched_schedule");
4462 LTT_EVENT_SCHED_TRY_WAKEUP
= g_quark_from_string("sched_try_wakeup");
4463 LTT_EVENT_PROCESS_FORK
= g_quark_from_string("process_fork");
4464 LTT_EVENT_KTHREAD_CREATE
= g_quark_from_string("kthread_create");
4465 LTT_EVENT_PROCESS_EXIT
= g_quark_from_string("process_exit");
4466 LTT_EVENT_PROCESS_FREE
= g_quark_from_string("process_free");
4467 LTT_EVENT_EXEC
= g_quark_from_string("exec");
4468 LTT_EVENT_PROCESS_STATE
= g_quark_from_string("process_state");
4469 LTT_EVENT_STATEDUMP_END
= g_quark_from_string("statedump_end");
4470 LTT_EVENT_FUNCTION_ENTRY
= g_quark_from_string("function_entry");
4471 LTT_EVENT_FUNCTION_EXIT
= g_quark_from_string("function_exit");
4472 LTT_EVENT_REQUEST_ISSUE
= g_quark_from_string("_blk_request_issue");
4473 LTT_EVENT_REQUEST_COMPLETE
= g_quark_from_string("_blk_request_complete");
4474 LTT_EVENT_LIST_INTERRUPT
= g_quark_from_string("interrupt");
4475 LTT_EVENT_SYS_CALL_TABLE
= g_quark_from_string("sys_call_table");
4476 LTT_EVENT_SOFTIRQ_VEC
= g_quark_from_string("softirq_vec");
4477 LTT_EVENT_KPROBE_TABLE
= g_quark_from_string("kprobe_table");
4478 LTT_EVENT_KPROBE
= g_quark_from_string("kprobe");
4479 LTT_EVENT_OPEN
= g_quark_from_string("open");
4480 LTT_EVENT_READ
= g_quark_from_string("read");
4481 LTT_EVENT_POLL_EVENT
= g_quark_from_string("poll_event");
4483 LTT_FIELD_SYSCALL_ID
= g_quark_from_string("syscall_id");
4484 LTT_FIELD_TRAP_ID
= g_quark_from_string("trap_id");
4485 LTT_FIELD_IRQ_ID
= g_quark_from_string("irq_id");
4486 LTT_FIELD_SOFT_IRQ_ID
= g_quark_from_string("softirq_id");
4487 LTT_FIELD_PREV_PID
= g_quark_from_string("prev_pid");
4488 LTT_FIELD_NEXT_PID
= g_quark_from_string("next_pid");
4489 LTT_FIELD_PREV_STATE
= g_quark_from_string("prev_state");
4490 LTT_FIELD_PARENT_PID
= g_quark_from_string("parent_pid");
4491 LTT_FIELD_CHILD_PID
= g_quark_from_string("child_pid");
4492 LTT_FIELD_PID
= g_quark_from_string("pid");
4493 LTT_FIELD_TGID
= g_quark_from_string("tgid");
4494 LTT_FIELD_CHILD_TGID
= g_quark_from_string("child_tgid");
4495 LTT_FIELD_FILENAME
= g_quark_from_string("filename");
4496 LTT_FIELD_NAME
= g_quark_from_string("name");
4497 LTT_FIELD_TYPE
= g_quark_from_string("type");
4498 LTT_FIELD_MODE
= g_quark_from_string("mode");
4499 LTT_FIELD_SUBMODE
= g_quark_from_string("submode");
4500 LTT_FIELD_STATUS
= g_quark_from_string("status");
4501 LTT_FIELD_THIS_FN
= g_quark_from_string("this_fn");
4502 LTT_FIELD_CALL_SITE
= g_quark_from_string("call_site");
4503 LTT_FIELD_MAJOR
= g_quark_from_string("major");
4504 LTT_FIELD_MINOR
= g_quark_from_string("minor");
4505 LTT_FIELD_OPERATION
= g_quark_from_string("direction");
4506 LTT_FIELD_ACTION
= g_quark_from_string("action");
4507 LTT_FIELD_ID
= g_quark_from_string("id");
4508 LTT_FIELD_ADDRESS
= g_quark_from_string("address");
4509 LTT_FIELD_SYMBOL
= g_quark_from_string("symbol");
4510 LTT_FIELD_IP
= g_quark_from_string("ip");
4511 LTT_FIELD_FD
= g_quark_from_string("fd");
4512 LTT_FIELD_STATE
= g_quark_from_string("state");
4513 LTT_FIELD_CPU_ID
= g_quark_from_string("cpu_id");
4515 LTTV_CPU_UNKNOWN
= g_quark_from_string("unknown");
4516 LTTV_CPU_IDLE
= g_quark_from_string("idle");
4517 LTTV_CPU_BUSY
= g_quark_from_string("busy");
4518 LTTV_CPU_IRQ
= g_quark_from_string("irq");
4519 LTTV_CPU_SOFT_IRQ
= g_quark_from_string("softirq");
4520 LTTV_CPU_TRAP
= g_quark_from_string("trap");
4522 LTTV_IRQ_UNKNOWN
= g_quark_from_string("unknown");
4523 LTTV_IRQ_IDLE
= g_quark_from_string("idle");
4524 LTTV_IRQ_BUSY
= g_quark_from_string("busy");
4526 LTTV_BDEV_UNKNOWN
= g_quark_from_string("unknown");
4527 LTTV_BDEV_IDLE
= g_quark_from_string("idle");
4528 LTTV_BDEV_BUSY_READING
= g_quark_from_string("busy_reading");
4529 LTTV_BDEV_BUSY_WRITING
= g_quark_from_string("busy_writing");
4532 static void module_destroy()
4537 LTTV_MODULE("state", "State computation", \
4538 "Update the system state, possibly saving it at intervals", \
4539 module_init
, module_destroy
)