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_THREAD_BRAND
,
86 LTT_EVENT_REQUEST_ISSUE
,
87 LTT_EVENT_REQUEST_COMPLETE
,
88 LTT_EVENT_LIST_INTERRUPT
,
89 LTT_EVENT_SYS_CALL_TABLE
,
90 LTT_EVENT_SOFTIRQ_VEC
,
91 LTT_EVENT_KPROBE_TABLE
,
100 LTT_FIELD_SYSCALL_ID
,
103 LTT_FIELD_SOFT_IRQ_ID
,
106 LTT_FIELD_PREV_STATE
,
107 LTT_FIELD_PARENT_PID
,
111 LTT_FIELD_CHILD_TGID
,
133 LTTV_STATE_MODE_UNKNOWN
,
134 LTTV_STATE_USER_MODE
,
135 LTTV_STATE_MAYBE_USER_MODE
,
137 LTTV_STATE_MAYBE_SYSCALL
,
139 LTTV_STATE_MAYBE_TRAP
,
144 LTTV_STATE_SUBMODE_UNKNOWN
,
145 LTTV_STATE_SUBMODE_NONE
;
149 LTTV_STATE_WAIT_FORK
,
158 LTTV_STATE_UNBRANDED
;
161 LTTV_STATE_USER_THREAD
,
162 LTTV_STATE_KERNEL_THREAD
;
180 LTTV_BDEV_BUSY_READING
,
181 LTTV_BDEV_BUSY_WRITING
;
184 LTTV_STATE_TRACEFILES
,
185 LTTV_STATE_PROCESSES
,
187 LTTV_STATE_RUNNING_PROCESS
,
189 LTTV_STATE_SAVED_STATES
,
190 LTTV_STATE_SAVED_STATES_TIME
,
193 LTTV_STATE_NAME_TABLES
,
194 LTTV_STATE_TRACE_STATE_USE_COUNT
,
195 LTTV_STATE_RESOURCE_CPUS
,
196 LTTV_STATE_RESOURCE_CPUS_COUNT
,
197 LTTV_STATE_RESOURCE_IRQS
,
198 LTTV_STATE_RESOURCE_SOFT_IRQS
,
199 LTTV_STATE_RESOURCE_TRAPS
,
200 LTTV_STATE_RESOURCE_BLKDEVS
;
202 static void create_max_time(LttvTraceState
*tcs
);
204 static void get_max_time(LttvTraceState
*tcs
);
206 static void free_max_time(LttvTraceState
*tcs
);
208 static void create_name_tables(LttvTraceState
*tcs
);
210 static void get_name_tables(LttvTraceState
*tcs
);
212 static void free_name_tables(LttvTraceState
*tcs
);
214 static void free_saved_state(LttvTraceState
*tcs
);
216 static void lttv_state_free_process_table(GHashTable
*processes
);
218 static void lttv_trace_states_read_raw(LttvTraceState
*tcs
, FILE *fp
,
219 GPtrArray
*quarktable
);
221 /* Resource function prototypes */
222 static LttvBdevState
*get_hashed_bdevstate(LttvTraceState
*ts
, guint32 devcode
);
223 static LttvBdevState
*bdevstate_new(void);
224 static void bdevstate_free(LttvBdevState
*);
225 static void bdevstate_free_cb(gpointer key
, gpointer value
, gpointer user_data
);
226 static LttvBdevState
*bdevstate_copy(LttvBdevState
*bds
);
227 void lttv_state_add_event_hooks(LttvTraceset
*traceset
);
229 #if (__WORDSIZE == 32)
230 guint
guint64_hash(gconstpointer key
)
232 guint64 ukey
= *(const guint64
*)key
;
234 return (guint
)ukey
^ (guint
)(ukey
>> 32);
237 gboolean
guint64_equal(gconstpointer a
, gconstpointer b
)
239 guint64 ua
= *(const guint64
*)a
;
240 guint64 ub
= *(const guint64
*)b
;
246 guint
process_hash(gconstpointer key
)
248 guint pid
= ((const LttvProcessState
*)key
)->pid
;
249 return (pid
>>8 ^ pid
>>4 ^ pid
>>2 ^ pid
) ;
253 /* If the hash table hash function is well distributed,
254 * the process_equal should compare different pid */
255 gboolean
process_equal(gconstpointer a
, gconstpointer b
)
257 const LttvProcessState
*process_a
, *process_b
;
260 process_a
= (const LttvProcessState
*)a
;
261 process_b
= (const LttvProcessState
*)b
;
263 if(likely(process_a
->pid
!= process_b
->pid
)) ret
= FALSE
;
264 else if(likely(process_a
->pid
== 0 &&
265 process_a
->cpu
!= process_b
->cpu
)) ret
= FALSE
;
270 gboolean
rettrue(gpointer key
, gpointer value
, gpointer user_data
)
275 static guint
check_expand(nb
, id
)
280 return max(id
+ 1, nb
* 2);
283 static void expand_name_table(LttvTraceState
*ts
, GQuark
**table
,
284 guint nb
, guint new_nb
)
286 /* Expand an incomplete table */
287 GQuark
*old_table
= *table
;
288 *table
= g_new(GQuark
, new_nb
);
289 memcpy(*table
, old_table
, nb
* sizeof(GQuark
));
293 static void fill_name_table(LttvTraceState
*ts
, GQuark
*table
, guint nb
,
294 guint new_nb
, const char *def_string
)
297 GString
*fe_name
= g_string_new("");
298 for(i
= nb
; i
< new_nb
; i
++) {
299 g_string_printf(fe_name
, "%s %d", def_string
, i
);
300 table
[i
] = g_quark_from_string(fe_name
->str
);
302 g_string_free(fe_name
, TRUE
);
305 static void expand_kprobe_table(LttvTraceState
*ts
, guint64 ip
, char *symbol
)
307 LttvNameTables
*nt
= ts
->name_tables
;
308 #if (__WORDSIZE == 32)
309 guint64
*ip_ptr
= g_new(guint64
, 1);
310 g_hash_table_insert(nt
->kprobe_hash
, ip_ptr
,
311 (gpointer
)(glong
)g_quark_from_string(symbol
));
313 g_hash_table_insert(nt
->kprobe_hash
, (gpointer
)ip
,
314 (gpointer
)(glong
)g_quark_from_string(symbol
));
318 static void expand_trap_table(LttvTraceState
*ts
, int id
)
320 LttvNameTables
*nt
= ts
->name_tables
;
321 LttvTrapState
*old_table
;
324 new_nb
= check_expand(nt
->nb_traps
, id
);
325 if(likely(new_nb
== nt
->nb_traps
))
328 expand_name_table(ts
, &nt
->trap_names
, nt
->nb_traps
, new_nb
);
329 fill_name_table(ts
, nt
->trap_names
, nt
->nb_traps
, new_nb
, "trap");
331 old_table
= ts
->trap_states
;
332 ts
->trap_states
= g_new(LttvTrapState
, new_nb
);
333 memcpy(ts
->trap_states
, old_table
, nt
->nb_traps
* sizeof(LttvTrapState
));
335 for(i
= nt
->nb_traps
; i
< new_nb
; i
++)
336 ts
->trap_states
[i
].running
= 0;
338 /* Update the table size */
339 nt
->nb_traps
= new_nb
;
342 static void expand_irq_table(LttvTraceState
*ts
, int id
)
344 LttvNameTables
*nt
= ts
->name_tables
;
345 LttvIRQState
*old_table
;
348 new_nb
= check_expand(nt
->nb_irqs
, id
);
349 if(likely(new_nb
== nt
->nb_irqs
))
352 expand_name_table(ts
, &nt
->irq_names
, nt
->nb_irqs
, new_nb
);
353 fill_name_table(ts
, nt
->irq_names
, nt
->nb_irqs
, new_nb
, "irq");
355 old_table
= ts
->irq_states
;
356 ts
->irq_states
= g_new(LttvIRQState
, new_nb
);
357 memcpy(ts
->irq_states
, old_table
, nt
->nb_irqs
* sizeof(LttvIRQState
));
359 for(i
= nt
->nb_irqs
; i
< new_nb
; i
++)
360 ts
->irq_states
[i
].mode_stack
=
361 g_array_new(FALSE
, FALSE
, sizeof(LttvIRQMode
));
363 /* Update the table size */
364 nt
->nb_irqs
= new_nb
;
367 static void expand_soft_irq_table(LttvTraceState
*ts
, int id
)
369 LttvNameTables
*nt
= ts
->name_tables
;
370 LttvSoftIRQState
*old_table
;
373 new_nb
= check_expand(nt
->nb_soft_irqs
, id
);
374 if(likely(new_nb
== nt
->nb_soft_irqs
))
377 expand_name_table(ts
, &nt
->soft_irq_names
, nt
->nb_soft_irqs
, new_nb
);
378 fill_name_table(ts
, nt
->soft_irq_names
, nt
->nb_soft_irqs
, new_nb
, "softirq");
380 old_table
= ts
->soft_irq_states
;
381 ts
->soft_irq_states
= g_new(LttvSoftIRQState
, new_nb
);
382 memcpy(ts
->soft_irq_states
, old_table
,
383 nt
->nb_soft_irqs
* sizeof(LttvSoftIRQState
));
385 for(i
= nt
->nb_soft_irqs
; i
< new_nb
; i
++)
386 ts
->soft_irq_states
[i
].running
= 0;
388 /* Update the table size */
389 nt
->nb_soft_irqs
= new_nb
;
392 static void restore_init_state(LttvTraceState
*self
)
394 guint i
, nb_cpus
, nb_irqs
, nb_soft_irqs
, nb_traps
;
396 //LttvTracefileState *tfcs;
400 /* Free the process tables */
401 if(self
->processes
!= NULL
) lttv_state_free_process_table(self
->processes
);
402 self
->processes
= g_hash_table_new(process_hash
, process_equal
);
405 /* Seek time to beginning */
406 // Mathieu : fix : don't seek traceset here : causes inconsistency in seek
407 // closest. It's the tracecontext job to seek the trace to the beginning
408 // anyway : the init state might be used at the middle of the trace as well...
409 //g_tree_destroy(self->parent.ts_context->pqueue);
410 //self->parent.ts_context->pqueue = g_tree_new(compare_tracefile);
412 start_time
= ltt_time_from_uint64(
413 bt_trace_handle_get_timestamp_begin(self
->trace
->traceset
->context
,
414 self
->trace
->id
,BT_CLOCK_REAL
));
417 //lttv_process_trace_seek_time(&self->parent, ltt_time_zero);
419 nb_cpus
= lttv_trace_get_num_cpu(self
->trace
);
420 nb_irqs
= self
->name_tables
->nb_irqs
;
421 nb_soft_irqs
= self
->name_tables
->nb_soft_irqs
;
422 nb_traps
= self
->name_tables
->nb_traps
;
424 /* Put the per cpu running_process to beginning state : process 0. */
425 for(i
=0; i
< nb_cpus
; i
++) {
426 LttvExecutionState
*es
;
427 self
->running_process
[i
] = lttv_state_create_process(self
, NULL
, i
, 0, 0,
428 LTTV_STATE_UNNAMED
, &start_time
);
429 /* We are not sure is it's a kernel thread or normal thread, put the
430 * bottom stack state to unknown */
431 self
->running_process
[i
]->execution_stack
=
432 g_array_set_size(self
->running_process
[i
]->execution_stack
, 1);
433 es
= self
->running_process
[i
]->state
=
434 &g_array_index(self
->running_process
[i
]->execution_stack
,
435 LttvExecutionState
, 0);
436 es
->t
= LTTV_STATE_MODE_UNKNOWN
;
437 es
->s
= LTTV_STATE_UNNAMED
;
439 //self->running_process[i]->state->s = LTTV_STATE_RUN;
440 self
->running_process
[i
]->cpu
= i
;
442 /* reset cpu states */
443 if(self
->cpu_states
[i
].mode_stack
->len
> 0) {
444 g_array_remove_range(self
->cpu_states
[i
].mode_stack
, 0,
445 self
->cpu_states
[i
].mode_stack
->len
);
446 if(self
->cpu_states
[i
].irq_stack
->len
)
447 g_array_remove_range(self
->cpu_states
[i
].irq_stack
, 0,
448 self
->cpu_states
[i
].irq_stack
->len
);
449 if(self
->cpu_states
[i
].softirq_stack
->len
)
450 g_array_remove_range(self
->cpu_states
[i
].softirq_stack
, 0,
451 self
->cpu_states
[i
].softirq_stack
->len
);
452 if(self
->cpu_states
[i
].trap_stack
->len
)
453 g_array_remove_range(self
->cpu_states
[i
].trap_stack
, 0,
454 self
->cpu_states
[i
].trap_stack
->len
);
458 /* reset irq states */
459 for(i
=0; i
<nb_irqs
; i
++) {
460 if(self
->irq_states
[i
].mode_stack
->len
> 0)
461 g_array_remove_range(self
->irq_states
[i
].mode_stack
, 0,
462 self
->irq_states
[i
].mode_stack
->len
);
465 /* reset softirq states */
466 for(i
=0; i
<nb_soft_irqs
; i
++) {
467 self
->soft_irq_states
[i
].pending
= 0;
468 self
->soft_irq_states
[i
].running
= 0;
471 /* reset trap states */
472 for(i
=0; i
<nb_traps
; i
++) {
473 self
->trap_states
[i
].running
= 0;
476 /* reset bdev states */
477 g_hash_table_foreach(self
->bdev_states
, bdevstate_free_cb
, NULL
);
478 //g_hash_table_steal_all(self->bdev_states);
479 g_hash_table_foreach_steal(self
->bdev_states
, rettrue
, NULL
);
482 nb_tracefile
= self
->parent
.tracefiles
->len
;
484 for(i
= 0 ; i
< nb_tracefile
; i
++) {
486 LTTV_TRACEFILE_STATE(g_array_index(self
->parent
.tracefiles
,
487 LttvTracefileContext
*, i
));
488 ltt_trace_time_span_get(self
->parent
.t
, &tfcs
->parent
.timestamp
, NULL
);
489 // tfcs->saved_position = 0;
490 tfcs
->process
= lttv_state_create_process(tfcs
, NULL
,0);
491 tfcs
->process
->state
->s
= LTTV_STATE_RUN
;
492 tfcs
->process
->last_cpu
= tfcs
->cpu_name
;
493 tfcs
->process
->last_cpu_index
= ltt_tracefile_num(((LttvTracefileContext
*)tfcs
)->tf
);
498 //static LttTime time_zero = {0,0};
502 #define MAX_STRING_LEN 4096
504 static void state_load_saved_states(LttvTraceState
*tcs
)
507 GPtrArray
*quarktable
;
508 const char *trace_path
;
512 tcs
->has_precomputed_states
= FALSE
;
516 gchar buf
[MAX_STRING_LEN
];
520 trace_path
= g_quark_to_string(ltt_trace_name(tcs
->parent
.t
));
521 strncpy(path
, trace_path
, PATH_MAX
-1);
522 count
= strnlen(trace_path
, PATH_MAX
-1);
523 // quarktable : open, test
524 strncat(path
, "/precomputed/quarktable", PATH_MAX
-count
-1);
525 fp
= fopen(path
, "r");
527 quarktable
= g_ptr_array_sized_new(4096);
529 /* Index 0 is null */
531 if(hdr
== EOF
) return;
532 g_assert(hdr
== HDR_QUARKS
);
536 if(hdr
== EOF
) break;
537 g_assert(hdr
== HDR_QUARK
);
538 g_ptr_array_set_size(quarktable
, q
+1);
541 res
= fread(&buf
[i
], sizeof(gchar
), 1, fp
);
543 if(buf
[i
] == '\0' || feof(fp
)) break;
546 len
= strnlen(buf
, MAX_STRING_LEN
-1);
547 g_ptr_array_index (quarktable
, q
) = g_new(gchar
, len
+1);
548 strncpy(g_ptr_array_index (quarktable
, q
), buf
, len
+1);
554 // saved_states : open, test
555 strncpy(path
, trace_path
, PATH_MAX
-1);
556 count
= strnlen(trace_path
, PATH_MAX
-1);
557 strncat(path
, "/precomputed/states", PATH_MAX
-count
-1);
558 fp
= fopen(path
, "r");
562 if(hdr
!= HDR_TRACE
) goto end
;
564 lttv_trace_states_read_raw(tcs
, fp
, quarktable
);
566 tcs
->has_precomputed_states
= TRUE
;
571 /* Free the quarktable */
572 for(i
=0; i
<quarktable
->len
; i
++) {
573 string
= g_ptr_array_index (quarktable
, i
);
576 g_ptr_array_free(quarktable
, TRUE
);
579 #endif /* BABEL_CLEANUP */
581 void lttv_trace_state_init(LttvTraceState
*trace_state
, LttvTrace
*trace
)
585 LttvAttributeValue v
;
587 trace_state
->trace
= trace
;
589 trace_state
->save_interval
= LTTV_STATE_SAVE_INTERVAL
;
590 lttv_attribute_find(lttv_trace_attribute(trace
), LTTV_STATE_TRACE_STATE_USE_COUNT
,
594 if (*(v
.v_uint
) == 1) {
595 create_name_tables(trace_state
);
596 create_max_time(trace_state
);
598 get_name_tables(trace_state
);
599 get_max_time(trace_state
);
601 nb_cpu
= lttv_trace_get_num_cpu(trace
);
602 nb_irq
= trace_state
->name_tables
->nb_irqs
;
603 trace_state
->processes
= NULL
;
604 trace_state
->running_process
= g_new(LttvProcessState
*, nb_cpu
);
606 /* init cpu resource stuff */
607 trace_state
->cpu_states
= g_new(LttvCPUState
, nb_cpu
);
608 for (j
= 0; j
< nb_cpu
; j
++) {
609 trace_state
->cpu_states
[j
].mode_stack
= g_array_new(FALSE
, FALSE
, sizeof(LttvCPUMode
));
610 trace_state
->cpu_states
[j
].irq_stack
= g_array_new(FALSE
, FALSE
, sizeof(gint
));
611 trace_state
->cpu_states
[j
].softirq_stack
= g_array_new(FALSE
, FALSE
, sizeof(gint
));
612 trace_state
->cpu_states
[j
].trap_stack
= g_array_new(FALSE
, FALSE
, sizeof(gint
));
613 g_assert(trace_state
->cpu_states
[j
].mode_stack
!= NULL
);
616 /* init irq resource stuff */
617 trace_state
->irq_states
= g_new(LttvIRQState
, nb_irq
);
618 for (j
= 0; j
< nb_irq
; j
++) {
619 trace_state
->irq_states
[j
].mode_stack
= g_array_new(FALSE
, FALSE
, sizeof(LttvIRQMode
));
620 g_assert(trace_state
->irq_states
[j
].mode_stack
!= NULL
);
623 /* init soft irq stuff */
624 /* the kernel has a statically fixed max of 32 softirqs */
625 trace_state
->soft_irq_states
= g_new(LttvSoftIRQState
, trace_state
->name_tables
->nb_soft_irqs
);
627 /* init trap stuff */
628 trace_state
->trap_states
= g_new(LttvTrapState
, trace_state
->name_tables
->nb_traps
);
630 /* init bdev resource stuff */
631 trace_state
->bdev_states
= g_hash_table_new(g_int_hash
, g_int_equal
);
633 restore_init_state(trace_state
);
635 /* See if the trace has saved states */
636 //state_load_saved_states(trace_state);
639 void lttv_trace_state_fini(LttvTraceState
*trace_state
)
641 LttvTrace
*trace
= trace_state
->trace
;
642 LttvAttributeValue v
;
644 lttv_attribute_find(lttv_trace_attribute(trace
), LTTV_STATE_TRACE_STATE_USE_COUNT
,
647 g_assert(*(v
.v_uint
) != 0);
650 if (*(v
.v_uint
) == 0) {
651 free_name_tables(trace_state
);
652 free_max_time(trace_state
);
653 free_saved_state(trace_state
);
655 g_free(trace_state
->running_process
);
656 trace_state
->running_process
= NULL
;
657 lttv_state_free_process_table(trace_state
->processes
);
658 trace_state
->processes
= NULL
;
663 /* Write the process state of the trace */
665 static void write_process_state(gpointer key
, gpointer value
,
668 LttvProcessState
*process
;
670 LttvExecutionState
*es
;
672 FILE *fp
= (FILE *)user_data
;
677 process
= (LttvProcessState
*)value
;
678 fprintf(fp
," <PROCESS CORE=%p PID=%u TGID=%u PPID=%u TYPE=\"%s\" CTIME_S=%lu CTIME_NS=%lu ITIME_S=%lu ITIME_NS=%lu NAME=\"%s\" BRAND=\"%s\" CPU=\"%u\" FREE_EVENTS=\"%u\">\n",
679 process
, process
->pid
, process
->tgid
, process
->ppid
,
680 g_quark_to_string(process
->type
),
681 process
->creation_time
.tv_sec
,
682 process
->creation_time
.tv_nsec
,
683 process
->insertion_time
.tv_sec
,
684 process
->insertion_time
.tv_nsec
,
685 g_quark_to_string(process
->name
),
686 g_quark_to_string(process
->brand
),
687 process
->cpu
, process
->free_events
);
689 for(i
= 0 ; i
< process
->execution_stack
->len
; i
++) {
690 es
= &g_array_index(process
->execution_stack
, LttvExecutionState
, i
);
691 fprintf(fp
, " <ES MODE=\"%s\" SUBMODE=\"%s\" ENTRY_S=%lu ENTRY_NS=%lu",
692 g_quark_to_string(es
->t
), g_quark_to_string(es
->n
),
693 es
->entry
.tv_sec
, es
->entry
.tv_nsec
);
694 fprintf(fp
, " CHANGE_S=%lu CHANGE_NS=%lu STATUS=\"%s\"/>\n",
695 es
->change
.tv_sec
, es
->change
.tv_nsec
, g_quark_to_string(es
->s
));
698 for(i
= 0 ; i
< process
->user_stack
->len
; i
++) {
699 address
= g_array_index(process
->user_stack
, guint64
, i
);
700 fprintf(fp
, " <USER_STACK ADDRESS=\"%" PRIu64
"\"/>\n", address
);
703 fprintf(fp
, " </PROCESS>\n");
707 void lttv_state_write(LttvTraceState
*self
, LttTime t
, FILE *fp
)
709 guint i
, nb_tracefile
, nb_block
, offset
;
712 LttvTracefileState
*tfcs
;
716 LttEventPosition
*ep
;
720 ep
= ltt_event_position_new();
722 fprintf(fp
,"<PROCESS_STATE TIME_S=%lu TIME_NS=%lu>\n", t
.tv_sec
, t
.tv_nsec
);
724 g_hash_table_foreach(self
->processes
, write_process_state
, fp
);
726 nb_cpus
= ltt_trace_get_num_cpu(self
->parent
.t
);
727 for(i
=0;i
<nb_cpus
;i
++) {
728 fprintf(fp
," <CPU NUM=%u RUNNING_PROCESS=%u>\n",
729 i
, self
->running_process
[i
]->pid
);
732 nb_tracefile
= self
->parent
.tracefiles
->len
;
734 for(i
= 0 ; i
< nb_tracefile
; i
++) {
736 LTTV_TRACEFILE_STATE(g_array_index(self
->parent
.tracefiles
,
737 LttvTracefileContext
*, i
));
738 fprintf(fp
, " <TRACEFILE TIMESTAMP_S=%lu TIMESTAMP_NS=%lu",
739 tfcs
->parent
.timestamp
.tv_sec
,
740 tfcs
->parent
.timestamp
.tv_nsec
);
741 LttEvent
*e
= ltt_tracefile_get_event(tfcs
->parent
.tf
);
742 if(e
== NULL
) fprintf(fp
,"/>\n");
744 ltt_event_position(e
, ep
);
745 ltt_event_position_get(ep
, &tf
, &nb_block
, &offset
, &tsc
);
746 fprintf(fp
, " BLOCK=%u OFFSET=%u TSC=%" PRIu64
"/>\n", nb_block
, offset
,
751 fprintf(fp
,"</PROCESS_STATE>\n");
755 static void write_process_state_raw(gpointer key
, gpointer value
,
758 LttvProcessState
*process
;
760 LttvExecutionState
*es
;
762 FILE *fp
= (FILE *)user_data
;
767 process
= (LttvProcessState
*)value
;
768 fputc(HDR_PROCESS
, fp
);
769 //fwrite(&header, sizeof(header), 1, fp);
770 //fprintf(fp, "%s", g_quark_to_string(process->type));
772 fwrite(&process
->type
, sizeof(process
->type
), 1, fp
);
773 //fprintf(fp, "%s", g_quark_to_string(process->name));
775 fwrite(&process
->name
, sizeof(process
->name
), 1, fp
);
776 //fprintf(fp, "%s", g_quark_to_string(process->brand));
778 fwrite(&process
->brand
, sizeof(process
->brand
), 1, fp
);
779 fwrite(&process
->pid
, sizeof(process
->pid
), 1, fp
);
780 fwrite(&process
->free_events
, sizeof(process
->free_events
), 1, fp
);
781 fwrite(&process
->tgid
, sizeof(process
->tgid
), 1, fp
);
782 fwrite(&process
->ppid
, sizeof(process
->ppid
), 1, fp
);
783 fwrite(&process
->cpu
, sizeof(process
->cpu
), 1, fp
);
784 fwrite(&process
->creation_time
, sizeof(process
->creation_time
), 1, fp
);
785 fwrite(&process
->insertion_time
, sizeof(process
->insertion_time
), 1, fp
);
788 fprintf(fp
," <PROCESS CORE=%p PID=%u TGID=%u PPID=%u TYPE=\"%s\" CTIME_S=%lu CTIME_NS=%lu ITIME_S=%lu ITIME_NS=%lu NAME=\"%s\" BRAND=\"%s\" CPU=\"%u\" PROCESS_TYPE=%u>\n",
789 process
, process
->pid
, process
->tgid
, process
->ppid
,
790 g_quark_to_string(process
->type
),
791 process
->creation_time
.tv_sec
,
792 process
->creation_time
.tv_nsec
,
793 process
->insertion_time
.tv_sec
,
794 process
->insertion_time
.tv_nsec
,
795 g_quark_to_string(process
->name
),
796 g_quark_to_string(process
->brand
),
800 for(i
= 0 ; i
< process
->execution_stack
->len
; i
++) {
801 es
= &g_array_index(process
->execution_stack
, LttvExecutionState
, i
);
804 //fprintf(fp, "%s", g_quark_to_string(es->t));
806 fwrite(&es
->t
, sizeof(es
->t
), 1, fp
);
807 //fprintf(fp, "%s", g_quark_to_string(es->n));
809 fwrite(&es
->n
, sizeof(es
->n
), 1, fp
);
810 //fprintf(fp, "%s", g_quark_to_string(es->s));
812 fwrite(&es
->s
, sizeof(es
->s
), 1, fp
);
813 fwrite(&es
->entry
, sizeof(es
->entry
), 1, fp
);
814 fwrite(&es
->change
, sizeof(es
->change
), 1, fp
);
815 fwrite(&es
->cum_cpu_time
, sizeof(es
->cum_cpu_time
), 1, fp
);
817 fprintf(fp
, " <ES MODE=\"%s\" SUBMODE=\"%s\" ENTRY_S=%lu ENTRY_NS=%lu",
818 g_quark_to_string(es
->t
), g_quark_to_string(es
->n
),
819 es
->entry
.tv_sec
, es
->entry
.tv_nsec
);
820 fprintf(fp
, " CHANGE_S=%lu CHANGE_NS=%lu STATUS=\"%s\"/>\n",
821 es
->change
.tv_sec
, es
->change
.tv_nsec
, g_quark_to_string(es
->s
));
825 for(i
= 0 ; i
< process
->user_stack
->len
; i
++) {
826 address
= g_array_index(process
->user_stack
, guint64
, i
);
827 fputc(HDR_USER_STACK
, fp
);
828 fwrite(&address
, sizeof(address
), 1, fp
);
830 fprintf(fp
, " <USER_STACK ADDRESS=\"%llu\"/>\n", address
);
836 void lttv_state_write_raw(LttvTraceState
*self
, LttTime t
, FILE *fp
)
838 guint i
, nb_tracefile
, nb_block
, offset
;
841 LttvTracefileState
*tfcs
;
845 LttEventPosition
*ep
;
849 ep
= ltt_event_position_new();
851 //fprintf(fp,"<PROCESS_STATE TIME_S=%lu TIME_NS=%lu>\n", t.tv_sec, t.tv_nsec);
852 fputc(HDR_PROCESS_STATE
, fp
);
853 fwrite(&t
, sizeof(t
), 1, fp
);
855 g_hash_table_foreach(self
->processes
, write_process_state_raw
, fp
);
857 nb_cpus
= ltt_trace_get_num_cpu(self
->parent
.t
);
858 for(i
=0;i
<nb_cpus
;i
++) {
860 fwrite(&i
, sizeof(i
), 1, fp
); /* cpu number */
861 fwrite(&self
->running_process
[i
]->pid
,
862 sizeof(self
->running_process
[i
]->pid
), 1, fp
);
863 //fprintf(fp," <CPU NUM=%u RUNNING_PROCESS=%u>\n",
864 // i, self->running_process[i]->pid);
867 nb_tracefile
= self
->parent
.tracefiles
->len
;
869 for(i
= 0 ; i
< nb_tracefile
; i
++) {
871 LTTV_TRACEFILE_STATE(g_array_index(self
->parent
.tracefiles
,
872 LttvTracefileContext
*, i
));
873 // fprintf(fp, " <TRACEFILE TIMESTAMP_S=%lu TIMESTAMP_NS=%lu",
874 // tfcs->parent.timestamp.tv_sec,
875 // tfcs->parent.timestamp.tv_nsec);
876 fputc(HDR_TRACEFILE
, fp
);
877 fwrite(&tfcs
->parent
.timestamp
, sizeof(tfcs
->parent
.timestamp
), 1, fp
);
878 /* Note : if timestamp if LTT_TIME_INFINITE, there will be no
879 * position following : end of trace */
880 LttEvent
*e
= ltt_tracefile_get_event(tfcs
->parent
.tf
);
882 ltt_event_position(e
, ep
);
883 ltt_event_position_get(ep
, &tf
, &nb_block
, &offset
, &tsc
);
884 //fprintf(fp, " BLOCK=%u OFFSET=%u TSC=%llu/>\n", nb_block, offset,
886 fwrite(&nb_block
, sizeof(nb_block
), 1, fp
);
887 fwrite(&offset
, sizeof(offset
), 1, fp
);
888 fwrite(&tsc
, sizeof(tsc
), 1, fp
);
895 /* Read process state from a file */
897 /* Called because a HDR_PROCESS was found */
898 static void read_process_state_raw(LttvTraceState
*self
, FILE *fp
,
899 GPtrArray
*quarktable
)
901 LttvExecutionState
*es
;
902 LttvProcessState
*process
, *parent_process
;
903 LttvProcessState tmp
;
909 res
= fread(&tmp
.type
, sizeof(tmp
.type
), 1, fp
);
910 res
+= fread(&tmp
.name
, sizeof(tmp
.name
), 1, fp
);
911 res
+= fread(&tmp
.brand
, sizeof(tmp
.brand
), 1, fp
);
912 res
+= fread(&tmp
.pid
, sizeof(tmp
.pid
), 1, fp
);
913 res
+= fread(&tmp
.free_events
, sizeof(tmp
.free_events
), 1, fp
);
914 res
+= fread(&tmp
.tgid
, sizeof(tmp
.tgid
), 1, fp
);
915 res
+= fread(&tmp
.ppid
, sizeof(tmp
.ppid
), 1, fp
);
916 res
+= fread(&tmp
.cpu
, sizeof(tmp
.cpu
), 1, fp
);
917 res
+= fread(&tmp
.creation_time
, sizeof(tmp
.creation_time
), 1, fp
);
918 res
+= fread(&tmp
.insertion_time
, sizeof(tmp
.insertion_time
), 1, fp
);
922 process
= lttv_state_find_process(self
, tmp
.cpu
, tmp
.pid
);
924 /* We must link to the parent */
925 parent_process
= lttv_state_find_process_or_create(self
, ANY_CPU
, tmp
.ppid
,
927 process
= lttv_state_find_process(self
, ANY_CPU
, tmp
.pid
);
928 if(process
== NULL
) {
929 process
= lttv_state_create_process(self
, parent_process
, tmp
.cpu
,
931 g_quark_from_string((gchar
*)g_ptr_array_index(quarktable
, tmp
.name
)),
935 process
->insertion_time
= tmp
.insertion_time
;
936 process
->creation_time
= tmp
.creation_time
;
937 process
->type
= g_quark_from_string(
938 (gchar
*)g_ptr_array_index(quarktable
, tmp
.type
));
939 process
->tgid
= tmp
.tgid
;
940 process
->ppid
= tmp
.ppid
;
941 process
->brand
= g_quark_from_string(
942 (gchar
*)g_ptr_array_index(quarktable
, tmp
.brand
));
944 g_quark_from_string((gchar
*)g_ptr_array_index(quarktable
, tmp
.name
));
945 process
->free_events
= tmp
.free_events
;
948 if(feof(fp
) || ferror(fp
)) goto end_loop
;
950 gint hdr
= fgetc(fp
);
951 if(hdr
== EOF
) goto end_loop
;
955 process
->execution_stack
=
956 g_array_set_size(process
->execution_stack
,
957 process
->execution_stack
->len
+ 1);
958 es
= &g_array_index(process
->execution_stack
, LttvExecutionState
,
959 process
->execution_stack
->len
-1);
962 res
= fread(&es
->t
, sizeof(es
->t
), 1, fp
);
964 es
->t
= g_quark_from_string(
965 (gchar
*)g_ptr_array_index(quarktable
, es
->t
));
966 res
= fread(&es
->n
, sizeof(es
->n
), 1, fp
);
968 es
->n
= g_quark_from_string(
969 (gchar
*)g_ptr_array_index(quarktable
, es
->n
));
970 res
= fread(&es
->s
, sizeof(es
->s
), 1, fp
);
972 es
->s
= g_quark_from_string(
973 (gchar
*)g_ptr_array_index(quarktable
, es
->s
));
974 res
= fread(&es
->entry
, sizeof(es
->entry
), 1, fp
);
975 res
+= fread(&es
->change
, sizeof(es
->change
), 1, fp
);
976 res
+= fread(&es
->cum_cpu_time
, sizeof(es
->cum_cpu_time
), 1, fp
);
981 process
->user_stack
= g_array_set_size(process
->user_stack
,
982 process
->user_stack
->len
+ 1);
983 address
= &g_array_index(process
->user_stack
, guint64
,
984 process
->user_stack
->len
-1);
985 res
= fread(address
, sizeof(address
), 1, fp
);
987 process
->current_function
= *address
;
1000 /* Called because a HDR_PROCESS_STATE was found */
1001 /* Append a saved state to the trace states */
1002 void lttv_state_read_raw(LttvTraceState
*self
, FILE *fp
, GPtrArray
*quarktable
)
1004 guint i
, nb_tracefile
, nb_block
, offset
;
1006 LttvTracefileState
*tfcs
;
1008 LttEventPosition
*ep
;
1017 LttvAttribute
*saved_states_tree
, *saved_state_tree
;
1019 LttvAttributeValue value
;
1020 GTree
*pqueue
= self
->parent
.ts_context
->pqueue
;
1021 ep
= ltt_event_position_new();
1023 restore_init_state(self
);
1025 res
= fread(&t
, sizeof(t
), 1, fp
);
1029 if(feof(fp
) || ferror(fp
)) goto end_loop
;
1031 if(hdr
== EOF
) goto end_loop
;
1035 /* Call read_process_state_raw */
1036 read_process_state_raw(self
, fp
, quarktable
);
1044 case HDR_USER_STACK
:
1045 case HDR_PROCESS_STATE
:
1051 g_error("Error while parsing saved state file : unknown data header %d",
1057 nb_cpus
= ltt_trace_get_num_cpu(self
->parent
.t
);
1058 for(i
=0;i
<nb_cpus
;i
++) {
1061 g_assert(hdr
== HDR_CPU
);
1062 res
= fread(&cpu_num
, sizeof(cpu_num
), 1, fp
); /* cpu number */
1064 g_assert(i
== cpu_num
);
1065 res
= fread(&self
->running_process
[i
]->pid
,
1066 sizeof(self
->running_process
[i
]->pid
), 1, fp
);
1070 nb_tracefile
= self
->parent
.tracefiles
->len
;
1072 for(i
= 0 ; i
< nb_tracefile
; i
++) {
1074 LTTV_TRACEFILE_STATE(g_array_index(self
->parent
.tracefiles
,
1075 LttvTracefileContext
*, i
));
1076 // fprintf(fp, " <TRACEFILE TIMESTAMP_S=%lu TIMESTAMP_NS=%lu",
1077 // tfcs->parent.timestamp.tv_sec,
1078 // tfcs->parent.timestamp.tv_nsec);
1079 g_tree_remove(pqueue
, &tfcs
->parent
);
1081 g_assert(hdr
== HDR_TRACEFILE
);
1082 res
= fread(&tfcs
->parent
.timestamp
, sizeof(tfcs
->parent
.timestamp
), 1, fp
);
1084 /* Note : if timestamp if LTT_TIME_INFINITE, there will be no
1085 * position following : end of trace */
1086 if(ltt_time_compare(tfcs
->parent
.timestamp
, ltt_time_infinite
) != 0) {
1087 res
= fread(&nb_block
, sizeof(nb_block
), 1, fp
);
1088 res
+= fread(&offset
, sizeof(offset
), 1, fp
);
1089 res
+= fread(&tsc
, sizeof(tsc
), 1, fp
);
1091 ltt_event_position_set(ep
, tfcs
->parent
.tf
, nb_block
, offset
, tsc
);
1092 gint ret
= ltt_tracefile_seek_position(tfcs
->parent
.tf
, ep
);
1094 g_tree_insert(pqueue
, &tfcs
->parent
, &tfcs
->parent
);
1099 saved_states_tree
= lttv_attribute_find_subdir(self
->parent
.t_a
,
1100 LTTV_STATE_SAVED_STATES
);
1101 saved_state_tree
= g_object_new(LTTV_ATTRIBUTE_TYPE
, NULL
);
1102 value
= lttv_attribute_add(saved_states_tree
,
1103 lttv_attribute_get_number(saved_states_tree
), LTTV_GOBJECT
);
1104 *(value
.v_gobject
) = (GObject
*)saved_state_tree
;
1105 value
= lttv_attribute_add(saved_state_tree
, LTTV_STATE_TIME
, LTTV_TIME
);
1106 *(value
.v_time
) = t
;
1107 lttv_state_save(self
, saved_state_tree
);
1108 g_debug("Saving state at time %lu.%lu", t
.tv_sec
,
1111 *(self
->max_time_state_recomputed_in_seek
) = t
;
1115 /* Called when a HDR_TRACE is found */
1116 void lttv_trace_states_read_raw(LttvTraceState
*tcs
, FILE *fp
,
1117 GPtrArray
*quarktable
)
1122 if(feof(fp
) || ferror(fp
)) goto end_loop
;
1124 if(hdr
== EOF
) goto end_loop
;
1127 case HDR_PROCESS_STATE
:
1128 /* Call read_process_state_raw */
1129 lttv_state_read_raw(tcs
, fp
, quarktable
);
1137 case HDR_USER_STACK
:
1140 g_error("Error while parsing saved state file :"
1141 " unexpected data header %d",
1145 g_error("Error while parsing saved state file : unknown data header %d",
1150 *(tcs
->max_time_state_recomputed_in_seek
) = tcs
->parent
.time_span
.end_time
;
1151 restore_init_state(tcs
);
1152 lttv_process_trace_seek_time(&tcs
->parent
, ltt_time_zero
);
1155 #endif /* BABEL_CLEANUP */
1158 /* Copy each process from an existing hash table to a new one */
1160 static void copy_process_state(gpointer key
, gpointer value
,gpointer user_data
)
1162 LttvProcessState
*process
, *new_process
;
1164 GHashTable
*new_processes
= (GHashTable
*)user_data
;
1168 process
= (LttvProcessState
*)value
;
1169 new_process
= g_new(LttvProcessState
, 1);
1170 *new_process
= *process
;
1171 new_process
->execution_stack
= g_array_sized_new(FALSE
, FALSE
,
1172 sizeof(LttvExecutionState
), PREALLOCATED_EXECUTION_STACK
);
1173 new_process
->execution_stack
=
1174 g_array_set_size(new_process
->execution_stack
,
1175 process
->execution_stack
->len
);
1176 for(i
= 0 ; i
< process
->execution_stack
->len
; i
++) {
1177 g_array_index(new_process
->execution_stack
, LttvExecutionState
, i
) =
1178 g_array_index(process
->execution_stack
, LttvExecutionState
, i
);
1180 new_process
->state
= &g_array_index(new_process
->execution_stack
,
1181 LttvExecutionState
, new_process
->execution_stack
->len
- 1);
1182 #ifdef BABEL_CLEANUP
1183 new_process
->user_stack
= g_array_sized_new(FALSE
, FALSE
,
1184 sizeof(guint64
), 0);
1185 new_process
->user_stack
= g_array_set_size(new_process
->user_stack
,
1186 process
->user_stack
->len
);
1187 for(i
= 0 ; i
< process
->user_stack
->len
; i
++) {
1188 g_array_index(new_process
->user_stack
, guint64
, i
) =
1189 g_array_index(process
->user_stack
, guint64
, i
);
1191 new_process
->current_function
= process
->current_function
;
1192 #endif /* BABEL_CLEANUP */
1194 /* fd hash table stuff */
1200 /* copy every item in the hash table */
1201 new_process
->fds
= g_hash_table_new(g_direct_hash
, g_direct_equal
);
1203 g_hash_table_iter_init(&it
, process
->fds
);
1204 while (g_hash_table_iter_next (&it
, (void *)&key
, (void *)&value
)) {
1205 g_hash_table_insert(new_process
->fds
, key
, value
);
1209 /* When done creating the new process state, insert it in the
1211 g_hash_table_insert(new_processes
, new_process
, new_process
);
1215 static GHashTable
*lttv_state_copy_process_table(GHashTable
*processes
)
1217 GHashTable
*new_processes
= g_hash_table_new(process_hash
, process_equal
);
1219 g_hash_table_foreach(processes
, copy_process_state
, new_processes
);
1220 return new_processes
;
1223 static LttvCPUState
*lttv_state_copy_cpu_states(LttvCPUState
*states
, guint n
)
1226 LttvCPUState
*retval
;
1228 retval
= g_new(LttvCPUState
, n
);
1230 for(i
=0; i
<n
; i
++) {
1231 retval
[i
].irq_stack
= g_array_new(FALSE
, FALSE
, sizeof(gint
));
1232 g_array_set_size(retval
[i
].irq_stack
, states
[i
].irq_stack
->len
);
1233 for(j
=0; j
<states
[i
].irq_stack
->len
; j
++) {
1234 g_array_index(retval
[i
].irq_stack
, gint
, j
) =
1235 g_array_index(states
[i
].irq_stack
, gint
, j
);
1238 retval
[i
].softirq_stack
= g_array_new(FALSE
, FALSE
, sizeof(gint
));
1239 g_array_set_size(retval
[i
].softirq_stack
, states
[i
].softirq_stack
->len
);
1240 for(j
=0; j
<states
[i
].softirq_stack
->len
; j
++) {
1241 g_array_index(retval
[i
].softirq_stack
, gint
, j
) =
1242 g_array_index(states
[i
].softirq_stack
, gint
, j
);
1245 retval
[i
].trap_stack
= g_array_new(FALSE
, FALSE
, sizeof(gint
));
1246 g_array_set_size(retval
[i
].trap_stack
, states
[i
].trap_stack
->len
);
1247 for(j
=0; j
<states
[i
].trap_stack
->len
; j
++) {
1248 g_array_index(retval
[i
].trap_stack
, gint
, j
) =
1249 g_array_index(states
[i
].trap_stack
, gint
, j
);
1252 retval
[i
].mode_stack
= g_array_new(FALSE
, FALSE
, sizeof(LttvCPUMode
));
1253 g_array_set_size(retval
[i
].mode_stack
, states
[i
].mode_stack
->len
);
1254 for(j
=0; j
<states
[i
].mode_stack
->len
; j
++) {
1255 g_array_index(retval
[i
].mode_stack
, GQuark
, j
) =
1256 g_array_index(states
[i
].mode_stack
, GQuark
, j
);
1263 static void lttv_state_free_cpu_states(LttvCPUState
*states
, guint n
)
1267 for(i
=0; i
<n
; i
++) {
1268 g_array_free(states
[i
].mode_stack
, TRUE
);
1269 g_array_free(states
[i
].irq_stack
, TRUE
);
1270 g_array_free(states
[i
].softirq_stack
, TRUE
);
1271 g_array_free(states
[i
].trap_stack
, TRUE
);
1277 static LttvIRQState
*lttv_state_copy_irq_states(LttvIRQState
*states
, guint n
)
1280 LttvIRQState
*retval
;
1282 retval
= g_new(LttvIRQState
, n
);
1284 for(i
=0; i
<n
; i
++) {
1285 retval
[i
].mode_stack
= g_array_new(FALSE
, FALSE
, sizeof(LttvIRQMode
));
1286 g_array_set_size(retval
[i
].mode_stack
, states
[i
].mode_stack
->len
);
1287 for(j
=0; j
<states
[i
].mode_stack
->len
; j
++) {
1288 g_array_index(retval
[i
].mode_stack
, GQuark
, j
) =
1289 g_array_index(states
[i
].mode_stack
, GQuark
, j
);
1296 static void lttv_state_free_irq_states(LttvIRQState
*states
, guint n
)
1300 for(i
=0; i
<n
; i
++) {
1301 g_array_free(states
[i
].mode_stack
, TRUE
);
1307 static LttvSoftIRQState
*
1308 lttv_state_copy_soft_irq_states(LttvSoftIRQState
*states
, guint n
)
1311 LttvSoftIRQState
*retval
;
1313 retval
= g_new(LttvSoftIRQState
, n
);
1315 for(i
=0; i
<n
; i
++) {
1316 retval
[i
].pending
= states
[i
].pending
;
1317 retval
[i
].running
= states
[i
].running
;
1323 static void lttv_state_free_soft_irq_states(LttvSoftIRQState
*states
, guint n
)
1328 static LttvTrapState
*
1329 lttv_state_copy_trap_states(LttvTrapState
*states
, guint n
)
1332 LttvTrapState
*retval
;
1334 retval
= g_new(LttvTrapState
, n
);
1336 for(i
=0; i
<n
; i
++) {
1337 retval
[i
].running
= states
[i
].running
;
1343 static void lttv_state_free_trap_states(LttvTrapState
*states
, guint n
)
1348 /* bdevstate stuff */
1350 static LttvBdevState
*get_hashed_bdevstate(LttvTraceState
*ts
, guint32 devcode
)
1352 gint devcode_gint
= devcode
;
1353 gpointer bdev
= g_hash_table_lookup(ts
->bdev_states
, &devcode_gint
);
1355 LttvBdevState
*bdevstate
= g_new(LttvBdevState
, 1);
1356 bdevstate
->mode_stack
= g_array_new(FALSE
, FALSE
, sizeof(GQuark
));
1358 gint
* key
= g_new(gint
, 1);
1360 g_hash_table_insert(ts
->bdev_states
, key
, bdevstate
);
1368 static LttvBdevState
*bdevstate_new(void)
1370 LttvBdevState
*retval
;
1371 retval
= g_new(LttvBdevState
, 1);
1372 retval
->mode_stack
= g_array_new(FALSE
, FALSE
, sizeof(GQuark
));
1377 static void bdevstate_free(LttvBdevState
*bds
)
1379 g_array_free(bds
->mode_stack
, TRUE
);
1383 static void bdevstate_free_cb(gpointer key
, gpointer value
, gpointer user_data
)
1385 LttvBdevState
*bds
= (LttvBdevState
*) value
;
1387 bdevstate_free(bds
);
1390 static LttvBdevState
*bdevstate_copy(LttvBdevState
*bds
)
1392 LttvBdevState
*retval
;
1394 retval
= bdevstate_new();
1395 g_array_insert_vals(retval
->mode_stack
, 0, bds
->mode_stack
->data
,
1396 bds
->mode_stack
->len
);
1401 static void insert_and_copy_bdev_state(gpointer k
, gpointer v
, gpointer u
)
1403 //GHashTable *ht = (GHashTable *)u;
1404 LttvBdevState
*bds
= (LttvBdevState
*)v
;
1405 LttvBdevState
*newbds
;
1407 newbds
= bdevstate_copy(bds
);
1409 g_hash_table_insert(u
, k
, newbds
);
1412 static GHashTable
*lttv_state_copy_blkdev_hashtable(GHashTable
*ht
)
1416 retval
= g_hash_table_new(g_int_hash
, g_int_equal
);
1418 g_hash_table_foreach(ht
, insert_and_copy_bdev_state
, retval
);
1423 /* Free a hashtable and the LttvBdevState structures its values
1426 static void lttv_state_free_blkdev_hashtable(GHashTable
*ht
)
1428 g_hash_table_foreach(ht
, bdevstate_free_cb
, NULL
);
1429 g_hash_table_destroy(ht
);
1432 /* The saved state for each trace contains a member "processes", which
1433 stores a copy of the process table, and a member "tracefiles" with
1434 one entry per tracefile. Each tracefile has a "process" member pointing
1435 to the current process and a "position" member storing the tracefile
1436 position (needed to seek to the current "next" event. */
1438 void lttv_state_save(LttvTraceState
*self
, LttvAttribute
*container
)
1440 guint i
, nb_cpus
, nb_irqs
, nb_soft_irqs
, nb_traps
;
1442 guint
*running_process
;
1444 LttvAttributeValue value
;
1446 value
= lttv_attribute_add(container
, LTTV_STATE_PROCESSES
,
1448 *(value
.v_pointer
) = lttv_state_copy_process_table(self
->processes
);
1450 /* Add the currently running processes array */
1451 nb_cpus
= lttv_trace_get_num_cpu(self
->trace
);
1452 running_process
= g_new(guint
, nb_cpus
);
1453 for(i
=0;i
<nb_cpus
;i
++) {
1454 running_process
[i
] = self
->running_process
[i
]->pid
;
1456 value
= lttv_attribute_add(container
, LTTV_STATE_RUNNING_PROCESS
,
1458 *(value
.v_pointer
) = running_process
;
1460 g_info("State save");
1462 /* Save the current position */
1463 value
= lttv_attribute_add(container
, LTTV_STATE_POSITION
,
1465 *(value
.v_pointer
) = lttv_traceset_create_current_position(lttv_trace_get_traceset(self
->trace
));
1467 #ifdef BABEL_CLEANUP
1468 nb_tracefile
= self
->parent
.tracefiles
->len
;
1469 for(i
= 0 ; i
< nb_tracefile
; i
++) {
1471 LTTV_TRACEFILE_STATE(g_array_index(self
->parent
.tracefiles
,
1472 LttvTracefileContext
*, i
));
1473 tracefile_tree
= g_object_new(LTTV_ATTRIBUTE_TYPE
, NULL
);
1474 value
= lttv_attribute_add(tracefiles_tree
, i
,
1476 *(value
.v_gobject
) = (GObject
*)tracefile_tree
;
1478 value
= lttv_attribute_add(tracefile_tree
, LTTV_STATE_PROCESS
,
1480 *(value
.v_uint
) = tfcs
->process
->pid
;
1482 value
= lttv_attribute_add(tracefile_tree
, LTTV_STATE_EVENT
,
1484 /* Only save the position if the tfs has not infinite time. */
1485 //if(!g_tree_lookup(self->parent.ts_context->pqueue, &tfcs->parent)
1486 // && current_tfcs != tfcs) {
1487 if(ltt_time_compare(tfcs
->parent
.timestamp
, ltt_time_infinite
) == 0) {
1488 *(value
.v_pointer
) = NULL
;
1490 LttEvent
*e
= ltt_tracefile_get_event(tfcs
->parent
.tf
);
1491 ep
= ltt_event_position_new();
1492 ltt_event_position(e
, ep
);
1493 *(value
.v_pointer
) = ep
;
1495 guint nb_block
, offset
;
1498 ltt_event_position_get(ep
, &tf
, &nb_block
, &offset
, &tsc
);
1499 g_info("Block %u offset %u tsc %" PRIu64
" time %lu.%lu", nb_block
,
1500 offset
, tsc
, tfcs
->parent
.timestamp
.tv_sec
,
1501 tfcs
->parent
.timestamp
.tv_nsec
);
1504 #endif /* BABEL_CLEANUP */
1506 /* save the cpu state */
1508 value
= lttv_attribute_add(container
, LTTV_STATE_RESOURCE_CPUS_COUNT
,
1510 *(value
.v_uint
) = nb_cpus
;
1512 value
= lttv_attribute_add(container
, LTTV_STATE_RESOURCE_CPUS
,
1514 *(value
.v_pointer
) = lttv_state_copy_cpu_states(self
->cpu_states
, nb_cpus
);
1517 /* save the irq state */
1518 nb_irqs
= self
->name_tables
->nb_irqs
;
1520 value
= lttv_attribute_add(container
, LTTV_STATE_RESOURCE_IRQS
,
1522 *(value
.v_pointer
) = lttv_state_copy_irq_states(self
->irq_states
, nb_irqs
);
1525 /* save the soft irq state */
1526 nb_soft_irqs
= self
->name_tables
->nb_soft_irqs
;
1528 value
= lttv_attribute_add(container
, LTTV_STATE_RESOURCE_SOFT_IRQS
,
1530 *(value
.v_pointer
) = lttv_state_copy_soft_irq_states(self
->soft_irq_states
, nb_soft_irqs
);
1533 /* save the trap state */
1534 nb_traps
= self
->name_tables
->nb_traps
;
1536 value
= lttv_attribute_add(container
, LTTV_STATE_RESOURCE_TRAPS
,
1538 *(value
.v_pointer
) = lttv_state_copy_trap_states(self
->trap_states
, nb_traps
);
1541 /* save the blkdev states */
1542 value
= lttv_attribute_add(container
, LTTV_STATE_RESOURCE_BLKDEVS
,
1544 *(value
.v_pointer
) = lttv_state_copy_blkdev_hashtable(self
->bdev_states
);
1547 void lttv_state_restore(LttvTraceState
*self
, LttvAttribute
*container
)
1549 guint i
, pid
, nb_cpus
, nb_irqs
, nb_soft_irqs
, nb_traps
;
1550 guint
*running_process
;
1551 LttvAttributeType type
;
1552 LttvAttributeValue value
;
1554 type
= lttv_attribute_get_by_name(container
, LTTV_STATE_PROCESSES
,
1556 g_assert(type
== LTTV_POINTER
);
1557 lttv_state_free_process_table(self
->processes
);
1558 self
->processes
= lttv_state_copy_process_table(*(value
.v_pointer
));
1560 /* Add the currently running processes array */
1561 nb_cpus
= lttv_trace_get_num_cpu(self
->trace
);
1562 type
= lttv_attribute_get_by_name(container
, LTTV_STATE_RUNNING_PROCESS
,
1564 g_assert(type
== LTTV_POINTER
);
1565 running_process
= *(value
.v_pointer
);
1566 for(i
=0;i
<nb_cpus
;i
++) {
1567 pid
= running_process
[i
];
1568 self
->running_process
[i
] = lttv_state_find_process(self
, i
, pid
);
1569 g_assert(self
->running_process
[i
] != NULL
);
1572 //nb_tracefile = self->parent.tracefiles->len;
1574 //g_tree_destroy(tsc->pqueue);
1575 //tsc->pqueue = g_tree_new(compare_tracefile);
1577 /* restore cpu resource states */
1578 type
= lttv_attribute_get_by_name(container
, LTTV_STATE_RESOURCE_CPUS
, &value
);
1579 g_assert(type
== LTTV_POINTER
);
1580 lttv_state_free_cpu_states(self
->cpu_states
, nb_cpus
);
1581 self
->cpu_states
= lttv_state_copy_cpu_states(*(value
.v_pointer
), nb_cpus
);
1583 /* restore irq resource states */
1584 nb_irqs
= self
->name_tables
->nb_irqs
;
1585 type
= lttv_attribute_get_by_name(container
, LTTV_STATE_RESOURCE_IRQS
, &value
);
1586 g_assert(type
== LTTV_POINTER
);
1587 lttv_state_free_irq_states(self
->irq_states
, nb_irqs
);
1588 self
->irq_states
= lttv_state_copy_irq_states(*(value
.v_pointer
), nb_irqs
);
1590 /* restore soft irq resource states */
1591 nb_soft_irqs
= self
->name_tables
->nb_soft_irqs
;
1592 type
= lttv_attribute_get_by_name(container
, LTTV_STATE_RESOURCE_SOFT_IRQS
, &value
);
1593 g_assert(type
== LTTV_POINTER
);
1594 lttv_state_free_soft_irq_states(self
->soft_irq_states
, nb_soft_irqs
);
1595 self
->soft_irq_states
= lttv_state_copy_soft_irq_states(*(value
.v_pointer
), nb_soft_irqs
);
1597 /* restore trap resource states */
1598 nb_traps
= self
->name_tables
->nb_traps
;
1599 type
= lttv_attribute_get_by_name(container
, LTTV_STATE_RESOURCE_TRAPS
, &value
);
1600 g_assert(type
== LTTV_POINTER
);
1601 lttv_state_free_trap_states(self
->trap_states
, nb_traps
);
1602 self
->trap_states
= lttv_state_copy_trap_states(*(value
.v_pointer
), nb_traps
);
1604 /* restore the blkdev states */
1605 type
= lttv_attribute_get_by_name(container
, LTTV_STATE_RESOURCE_BLKDEVS
, &value
);
1606 g_assert(type
== LTTV_POINTER
);
1607 lttv_state_free_blkdev_hashtable(self
->bdev_states
);
1608 self
->bdev_states
= lttv_state_copy_blkdev_hashtable(*(value
.v_pointer
));
1610 #ifdef BABEL_CLEANUP
1611 for(i
= 0 ; i
< nb_tracefile
; i
++) {
1613 LTTV_TRACEFILE_STATE(g_array_index(self
->parent
.tracefiles
,
1614 LttvTracefileContext
*, i
));
1615 type
= lttv_attribute_get(tracefiles_tree
, i
, &name
, &value
, &is_named
);
1616 g_assert(type
== LTTV_GOBJECT
);
1617 tracefile_tree
= *((LttvAttribute
**)(value
.v_gobject
));
1619 type
= lttv_attribute_get_by_name(tracefile_tree
, LTTV_STATE_PROCESS
,
1621 g_assert(type
== LTTV_UINT
);
1622 pid
= *(value
.v_uint
);
1623 tfcs
->process
= lttv_state_find_process_or_create(tfcs
, pid
);
1625 type
= lttv_attribute_get_by_name(tracefile_tree
, LTTV_STATE_EVENT
,
1627 g_assert(type
== LTTV_POINTER
);
1628 //g_assert(*(value.v_pointer) != NULL);
1629 ep
= *(value
.v_pointer
);
1630 g_assert(tfcs
->parent
.t_context
!= NULL
);
1632 tfcs
->cpu_state
= &self
->cpu_states
[tfcs
->cpu
];
1634 LttvTracefileContext
*tfc
= LTTV_TRACEFILE_CONTEXT(tfcs
);
1635 g_tree_remove(tsc
->pqueue
, tfc
);
1638 retval
= ltt_tracefile_seek_position(tfc
->tf
, ep
);
1639 g_assert_cmpint(retval
, ==, 0);
1640 tfc
->timestamp
= ltt_event_time(ltt_tracefile_get_event(tfc
->tf
));
1641 g_assert_cmpint(ltt_time_compare(tfc
->timestamp
, ltt_time_infinite
),
1643 g_tree_insert(tsc
->pqueue
, tfc
, tfc
);
1644 g_info("Restoring state for a tf at time %lu.%lu",
1645 tfc
->timestamp
.tv_sec
, tfc
->timestamp
.tv_nsec
);
1647 tfc
->timestamp
= ltt_time_infinite
;
1650 #endif /* BABEL_CLEANUP */
1654 * Note: the position must be explicitely set on the entire traceset to
1655 * match the trace states.
1657 LttvTracesetPosition
*lttv_trace_state_get_position(LttvAttribute
*container
)
1659 LttvAttributeType type
;
1660 LttvAttributeValue value
;
1662 type
= lttv_attribute_get_by_name(container
, LTTV_STATE_POSITION
, &value
);
1663 g_assert(type
== LTTV_POINTER
);
1664 return *(value
.v_pointer
);
1667 void lttv_state_saved_free(LttvTraceState
*self
, LttvAttribute
*container
)
1669 guint nb_cpus
, nb_irqs
, nb_soft_irqs
;
1670 guint
*running_process
;
1671 LttvAttributeType type
;
1672 LttvAttributeValue value
;
1674 type
= lttv_attribute_get_by_name(container
, LTTV_STATE_PROCESSES
,
1676 g_assert(type
== LTTV_POINTER
);
1677 lttv_state_free_process_table(*(value
.v_pointer
));
1678 *(value
.v_pointer
) = NULL
;
1679 lttv_attribute_remove_by_name(container
, LTTV_STATE_PROCESSES
);
1681 /* Free running processes array */
1682 type
= lttv_attribute_get_by_name(container
, LTTV_STATE_RUNNING_PROCESS
,
1684 g_assert(type
== LTTV_POINTER
);
1685 running_process
= *(value
.v_pointer
);
1686 g_free(running_process
);
1688 /* free cpu resources */
1689 type
= lttv_attribute_get_by_name(container
, LTTV_STATE_RESOURCE_CPUS_COUNT
, &value
);
1690 g_assert(type
== LTTV_UINT
);
1691 nb_cpus
= *value
.v_uint
;
1692 type
= lttv_attribute_get_by_name(container
, LTTV_STATE_RESOURCE_CPUS
, &value
);
1693 g_assert(type
== LTTV_POINTER
);
1694 lttv_state_free_cpu_states(*(value
.v_pointer
), nb_cpus
);
1696 /* free irq resource states */
1697 nb_irqs
= self
->name_tables
->nb_irqs
;
1698 type
= lttv_attribute_get_by_name(container
, LTTV_STATE_RESOURCE_IRQS
, &value
);
1699 g_assert(type
== LTTV_POINTER
);
1700 lttv_state_free_irq_states(*(value
.v_pointer
), nb_irqs
);
1702 /* free softirq resource states */
1703 nb_soft_irqs
= self
->name_tables
->nb_soft_irqs
;
1704 type
= lttv_attribute_get_by_name(container
, LTTV_STATE_RESOURCE_SOFT_IRQS
, &value
);
1705 g_assert(type
== LTTV_POINTER
);
1706 lttv_state_free_soft_irq_states(*(value
.v_pointer
), nb_soft_irqs
);
1708 /* free the blkdev states */
1709 type
= lttv_attribute_get_by_name(container
, LTTV_STATE_RESOURCE_BLKDEVS
, &value
);
1710 g_assert(type
== LTTV_POINTER
);
1711 lttv_state_free_blkdev_hashtable(*(value
.v_pointer
));
1713 /* remove the position */
1714 type
= lttv_attribute_get_by_name(container
, LTTV_STATE_POSITION
, &value
);
1715 g_assert(type
== LTTV_POINTER
);
1716 lttv_traceset_destroy_position(*(value
.v_pointer
));
1718 #ifdef BABEL_CLEANUP
1719 nb_tracefile
= self
->parent
.tracefiles
->len
;
1721 for(i
= 0 ; i
< nb_tracefile
; i
++) {
1723 type
= lttv_attribute_get(tracefiles_tree
, i
, &name
, &value
, &is_named
);
1724 g_assert(type
== LTTV_GOBJECT
);
1725 tracefile_tree
= *((LttvAttribute
**)(value
.v_gobject
));
1727 type
= lttv_attribute_get_by_name(tracefile_tree
, LTTV_STATE_EVENT
,
1729 g_assert(type
== LTTV_POINTER
);
1730 if(*(value
.v_pointer
) != NULL
) g_free(*(value
.v_pointer
));
1732 g_object_unref(G_OBJECT(tracefiles_tree
));
1733 #endif /* BABEL_CLEANUP */
1737 static void free_saved_state(LttvTraceState
*self
)
1740 LttvAttributeType type
;
1741 LttvAttributeValue value
;
1742 LttvAttributeName name
;
1744 LttvAttribute
*saved_states
;
1746 saved_states
= lttv_attribute_find_subdir(lttv_trace_attribute(self
->trace
),
1747 LTTV_STATE_SAVED_STATES
);
1749 nb
= lttv_attribute_get_number(saved_states
);
1750 for(i
= 0 ; i
< nb
; i
++) {
1751 type
= lttv_attribute_get(saved_states
, i
, &name
, &value
, &is_named
);
1752 g_assert(type
== LTTV_GOBJECT
);
1753 lttv_state_saved_free(self
, *((LttvAttribute
**)value
.v_gobject
));
1756 lttv_attribute_remove_by_name(lttv_trace_attribute(self
->trace
),
1757 LTTV_STATE_SAVED_STATES
);
1761 static void create_max_time(LttvTraceState
*trace_state
)
1763 LttvAttributeValue v
;
1765 lttv_attribute_find(lttv_trace_attribute(trace_state
->trace
),
1766 LTTV_STATE_SAVED_STATES_TIME
,
1768 g_assert(*(v
.v_pointer
) == NULL
);
1769 *(v
.v_pointer
) = g_new(LttTime
,1);
1770 *((LttTime
*)*(v
.v_pointer
)) = ltt_time_zero
;
1774 static void get_max_time(LttvTraceState
*trace_state
)
1776 LttvAttributeValue v
;
1778 lttv_attribute_find(lttv_trace_attribute(trace_state
->trace
),
1779 LTTV_STATE_SAVED_STATES_TIME
,
1781 g_assert(*(v
.v_pointer
) != NULL
);
1782 trace_state
->max_time_state_recomputed_in_seek
= (LttTime
*)*(v
.v_pointer
);
1786 static void free_max_time(LttvTraceState
*trace_state
)
1788 LttvAttributeValue v
;
1790 lttv_attribute_find(lttv_trace_attribute(trace_state
->trace
),
1791 LTTV_STATE_SAVED_STATES_TIME
,
1793 g_free(*(v
.v_pointer
));
1794 *(v
.v_pointer
) = NULL
;
1797 static void create_name_tables(LttvTraceState
*tcs
)
1801 GString
*fe_name
= g_string_new("");
1803 LttvNameTables
*name_tables
= g_new(LttvNameTables
, 1);
1805 LttvAttributeValue v
;
1809 lttv_attribute_find(lttv_trace_attribute(tcs
->trace
), LTTV_STATE_NAME_TABLES
,
1811 g_assert(*(v
.v_pointer
) == NULL
);
1812 *(v
.v_pointer
) = name_tables
;
1814 #ifdef BABEL_CLEANUP
1815 hooks
= g_array_sized_new(FALSE
, FALSE
, sizeof(LttvTraceHook
), 1);
1817 if(!lttv_trace_find_hook(tcs
->parent
.t
,
1819 LTT_EVENT_SYSCALL_ENTRY
,
1820 FIELD_ARRAY(LTT_FIELD_SYSCALL_ID
),
1821 NULL
, NULL
, &hooks
)) {
1823 // th = lttv_trace_hook_get_first(&th);
1825 // t = ltt_field_type(lttv_trace_get_hook_field(th, 0));
1826 // nb = ltt_type_element_number(t);
1828 // name_tables->syscall_names = g_new(GQuark, nb);
1829 // name_tables->nb_syscalls = nb;
1831 // for(i = 0 ; i < nb ; i++) {
1832 // name_tables->syscall_names[i] = ltt_enum_string_get(t, i);
1833 // if(!name_tables->syscall_names[i]) {
1834 // GString *string = g_string_new("");
1835 // g_string_printf(string, "syscall %u", i);
1836 // name_tables->syscall_names[i] = g_quark_from_string(string->str);
1837 // g_string_free(string, TRUE);
1840 #endif /* BABEL_CLEANUP */
1842 name_tables
->nb_syscalls
= PREALLOC_NB_SYSCALLS
;
1843 name_tables
->syscall_names
= g_new(GQuark
, name_tables
->nb_syscalls
);
1844 for(i
= 0 ; i
< name_tables
->nb_syscalls
; i
++) {
1845 g_string_printf(fe_name
, "syscall %d", i
);
1846 name_tables
->syscall_names
[i
] = g_quark_from_string(fe_name
->str
);
1848 #ifdef BABEL_CLEANUP
1850 name_tables
->syscall_names
= NULL
;
1851 name_tables
->nb_syscalls
= 0;
1853 lttv_trace_hook_remove_all(&hooks
);
1854 #endif /* BABEL_CLEANUP */
1856 #ifdef BABEL_CLEANUP
1857 if(!lttv_trace_find_hook(tcs
->parent
.t
,
1859 LTT_EVENT_TRAP_ENTRY
,
1860 FIELD_ARRAY(LTT_FIELD_TRAP_ID
),
1861 NULL
, NULL
, &hooks
) ||
1862 !lttv_trace_find_hook(tcs
->parent
.t
,
1864 LTT_EVENT_PAGE_FAULT_ENTRY
,
1865 FIELD_ARRAY(LTT_FIELD_TRAP_ID
),
1866 NULL
, NULL
, &hooks
)) {
1868 // th = lttv_trace_hook_get_first(&th);
1870 // t = ltt_field_type(lttv_trace_get_hook_field(th, 0));
1871 // //nb = ltt_type_element_number(t);
1873 // name_tables->trap_names = g_new(GQuark, nb);
1874 // for(i = 0 ; i < nb ; i++) {
1875 // name_tables->trap_names[i] = g_quark_from_string(
1876 // ltt_enum_string_get(t, i));
1879 #endif /* BABEL_CLEANUP */
1880 name_tables
->nb_traps
= PREALLOC_NB_TRAPS
;
1881 name_tables
->trap_names
= g_new(GQuark
, name_tables
->nb_traps
);
1882 for(i
= 0 ; i
< name_tables
->nb_traps
; i
++) {
1883 g_string_printf(fe_name
, "trap %d", i
);
1884 name_tables
->trap_names
[i
] = g_quark_from_string(fe_name
->str
);
1886 #ifdef BABEL_CLEANUP
1888 name_tables
->trap_names
= NULL
;
1889 name_tables
->nb_traps
= 0;
1891 lttv_trace_hook_remove_all(&hooks
);
1892 #endif /* BABEL_CLEANUP */
1894 #ifdef BABEL_CLEANUP
1895 if(!lttv_trace_find_hook(tcs
->parent
.t
,
1897 LTT_EVENT_IRQ_ENTRY
,
1898 FIELD_ARRAY(LTT_FIELD_IRQ_ID
),
1899 NULL
, NULL
, &hooks
)) {
1902 name_tables->irq_names = g_new(GQuark, nb);
1903 for(i = 0 ; i < nb ; i++) {
1904 name_tables->irq_names[i] = g_quark_from_string(ltt_enum_string_get(t, i));
1907 /* FIXME: LttvIRQState *irq_states should become a g_array */
1909 #endif /* BABEL_CLEANUP */
1910 name_tables
->nb_irqs
= PREALLOC_NB_IRQS
;
1911 name_tables
->irq_names
= g_new(GQuark
, name_tables
->nb_irqs
);
1912 for(i
= 0 ; i
< name_tables
->nb_irqs
; i
++) {
1913 g_string_printf(fe_name
, "irq %d", i
);
1914 name_tables
->irq_names
[i
] = g_quark_from_string(fe_name
->str
);
1916 #ifdef BABEL_CLEANUP
1918 name_tables
->nb_irqs
= 0;
1919 name_tables
->irq_names
= NULL
;
1921 lttv_trace_hook_remove_all(&hooks
);
1922 #endif /* BABEL_CLEANUP */
1924 name_tables->soft_irq_names = g_new(GQuark, nb);
1925 for(i = 0 ; i < nb ; i++) {
1926 name_tables->soft_irq_names[i] = g_quark_from_string(ltt_enum_string_get(t, i));
1930 name_tables
->nb_soft_irqs
= PREALLOC_NB_SOFT_IRQS
;
1931 name_tables
->soft_irq_names
= g_new(GQuark
, name_tables
->nb_soft_irqs
);
1932 for(i
= 0 ; i
< name_tables
->nb_soft_irqs
; i
++) {
1933 g_string_printf(fe_name
, "softirq %d", i
);
1934 name_tables
->soft_irq_names
[i
] = g_quark_from_string(fe_name
->str
);
1936 // g_array_free(hooks, TRUE);
1938 g_string_free(fe_name
, TRUE
);
1940 #if (__WORDSIZE == 32)
1941 name_tables
->kprobe_hash
= g_hash_table_new_full(guint64_hash
, guint64_equal
,
1944 name_tables
->kprobe_hash
= g_hash_table_new(g_direct_hash
, g_direct_equal
);
1949 static void get_name_tables(LttvTraceState
*tcs
)
1951 LttvAttributeValue v
;
1953 lttv_attribute_find(lttv_trace_attribute(tcs
->trace
), LTTV_STATE_NAME_TABLES
,
1955 g_assert(*(v
.v_pointer
) != NULL
);
1956 tcs
->name_tables
= (LttvNameTables
*)*(v
.v_pointer
);
1960 static void free_name_tables(LttvTraceState
*tcs
)
1962 LttvNameTables
*name_tables
;
1964 LttvAttributeValue v
;
1966 lttv_attribute_find(lttv_trace_attribute(tcs
->trace
), LTTV_STATE_NAME_TABLES
,
1968 name_tables
= (LttvNameTables
*)*(v
.v_pointer
);
1969 *(v
.v_pointer
) = NULL
;
1971 // g_free(name_tables->eventtype_names);
1972 if(name_tables
->syscall_names
) g_free(name_tables
->syscall_names
);
1973 if(name_tables
->trap_names
) g_free(name_tables
->trap_names
);
1974 if(name_tables
->irq_names
) g_free(name_tables
->irq_names
);
1975 if(name_tables
->soft_irq_names
) g_free(name_tables
->soft_irq_names
);
1976 g_hash_table_destroy(name_tables
->kprobe_hash
);
1977 g_free(name_tables
);
1980 #ifdef HASH_TABLE_DEBUG
1982 static void test_process(gpointer key
, gpointer value
, gpointer user_data
)
1984 LttvProcessState
*process
= (LttvProcessState
*)value
;
1986 /* Test for process corruption */
1987 guint stack_len
= process
->execution_stack
->len
;
1990 static void hash_table_check(GHashTable
*table
)
1992 g_hash_table_foreach(table
, test_process
, NULL
);
1998 /* clears the stack and sets the state passed as argument */
1999 static void cpu_set_base_mode(LttvCPUState
*cpust
, LttvCPUMode state
)
2001 g_array_set_size(cpust
->mode_stack
, 1);
2002 ((GQuark
*)cpust
->mode_stack
->data
)[0] = state
;
2005 static void cpu_push_mode(LttvCPUState
*cpust
, LttvCPUMode state
)
2007 g_array_set_size(cpust
->mode_stack
, cpust
->mode_stack
->len
+ 1);
2008 ((GQuark
*)cpust
->mode_stack
->data
)[cpust
->mode_stack
->len
- 1] = state
;
2011 static void cpu_pop_mode(LttvCPUState
*cpust
)
2013 if(cpust
->mode_stack
->len
<= 1)
2014 cpu_set_base_mode(cpust
, LTTV_CPU_UNKNOWN
);
2016 g_array_set_size(cpust
->mode_stack
, cpust
->mode_stack
->len
- 1);
2019 /* clears the stack and sets the state passed as argument */
2020 static void bdev_set_base_mode(LttvBdevState
*bdevst
, LttvBdevMode state
)
2022 g_array_set_size(bdevst
->mode_stack
, 1);
2023 ((GQuark
*)bdevst
->mode_stack
->data
)[0] = state
;
2026 static void bdev_push_mode(LttvBdevState
*bdevst
, LttvBdevMode state
)
2028 g_array_set_size(bdevst
->mode_stack
, bdevst
->mode_stack
->len
+ 1);
2029 ((GQuark
*)bdevst
->mode_stack
->data
)[bdevst
->mode_stack
->len
- 1] = state
;
2032 static void bdev_pop_mode(LttvBdevState
*bdevst
)
2034 if(bdevst
->mode_stack
->len
<= 1)
2035 bdev_set_base_mode(bdevst
, LTTV_BDEV_UNKNOWN
);
2037 g_array_set_size(bdevst
->mode_stack
, bdevst
->mode_stack
->len
- 1);
2040 static void irq_set_base_mode(LttvIRQState
*irqst
, LttvIRQMode state
)
2042 g_array_set_size(irqst
->mode_stack
, 1);
2043 ((GQuark
*)irqst
->mode_stack
->data
)[0] = state
;
2046 static void irq_push_mode(LttvIRQState
*irqst
, LttvIRQMode state
)
2048 g_array_set_size(irqst
->mode_stack
, irqst
->mode_stack
->len
+ 1);
2049 ((GQuark
*)irqst
->mode_stack
->data
)[irqst
->mode_stack
->len
- 1] = state
;
2052 static void irq_pop_mode(LttvIRQState
*irqst
)
2054 if(irqst
->mode_stack
->len
<= 1)
2055 irq_set_base_mode(irqst
, LTTV_IRQ_UNKNOWN
);
2057 g_array_set_size(irqst
->mode_stack
, irqst
->mode_stack
->len
- 1);
2060 static void push_state(LttvEvent
*event
,
2061 LttvTraceState
*ts
, LttvExecutionMode t
,
2064 LttvExecutionState
*es
;
2067 cpu
= lttv_traceset_get_cpuid_from_event(event
);
2070 #ifdef HASH_TABLE_DEBUG
2071 hash_table_check(ts
->processes
);
2073 LttvProcessState
*process
= ts
->running_process
[cpu
];
2075 guint depth
= process
->execution_stack
->len
;
2077 process
->execution_stack
=
2078 g_array_set_size(process
->execution_stack
, depth
+ 1);
2081 &g_array_index(process
->execution_stack
, LttvExecutionState
, depth
- 1);
2083 es
= &g_array_index(process
->execution_stack
, LttvExecutionState
, depth
);
2086 es
->entry
= es
->change
= lttv_event_get_timestamp(event
);
2087 es
->cum_cpu_time
= ltt_time_zero
;
2088 es
->s
= process
->state
->s
;
2089 process
->state
= es
;
2093 * return 1 when empty, else 0 */
2095 lttv_state_pop_state_cleanup(LttvProcessState
*process
, LttvEvent
*event
)
2097 guint depth
= process
->execution_stack
->len
;
2103 process
->execution_stack
=
2104 g_array_set_size(process
->execution_stack
, depth
- 1);
2105 process
->state
= &g_array_index(process
->execution_stack
, LttvExecutionState
,
2107 process
->state
->change
= lttv_event_get_timestamp(event
);
2112 static void pop_state(LttvEvent
*event
,
2113 LttvTraceState
*ts
, LttvExecutionMode t
)
2115 LttvProcessState
*process
;
2118 cpu
= lttv_traceset_get_cpuid_from_event(event
);
2120 process
= ts
->running_process
[cpu
];
2122 guint depth
= process
->execution_stack
->len
;
2124 if(process
->state
->t
!= t
){
2125 g_info("Different execution mode type: ignore it\n"
2128 g_info("process state has %s when pop_int is %s\n",
2129 g_quark_to_string(process
->state
->t
),
2130 g_quark_to_string(t
));
2131 g_info("{ %u, %u, %s, %s, %s }\n",
2134 g_quark_to_string(process
->name
),
2135 g_quark_to_string(process
->brand
),
2136 g_quark_to_string(process
->state
->s
));
2141 //TODO ybrosseau readd debug
2142 //g_info("Trying to pop last state on stack (%lu.%09lu): ignore it\n",
2143 // tfs->parent.timestamp.tv_sec, tfs->parent.timestamp.tv_nsec);
2144 g_info("Trying to pop last state on stack: ignore it\n");
2148 process
->execution_stack
=
2149 g_array_set_size(process
->execution_stack
, depth
- 1);
2150 process
->state
= &g_array_index(process
->execution_stack
, LttvExecutionState
,
2152 process
->state
->change
= lttv_event_get_timestamp(event
);
2155 struct search_result
{
2156 const LttTime
*time
; /* Requested time */
2157 LttTime
*best
; /* Best result */
2160 /* Return a new and initialized LttvProcessState structure */
2162 LttvProcessState
*lttv_state_create_process(LttvTraceState
*tcs
,
2163 LttvProcessState
*parent
, guint cpu
, guint pid
,
2164 guint tgid
, GQuark name
, const LttTime
*timestamp
)
2166 LttvProcessState
*process
= g_new(LttvProcessState
, 1);
2168 LttvExecutionState
*es
;
2173 process
->tgid
= tgid
;
2175 process
->name
= name
;
2176 process
->brand
= LTTV_STATE_UNBRANDED
;
2177 //process->last_cpu = tfs->cpu_name;
2178 //process->last_cpu_index = ltt_tracefile_num(((LttvTracefileContext*)tfs)->tf);
2179 process
->type
= LTTV_STATE_USER_THREAD
;
2181 g_info("Process %u, core %p", process
->pid
, process
);
2182 g_hash_table_insert(tcs
->processes
, process
, process
);
2185 process
->ppid
= parent
->pid
;
2186 process
->creation_time
= *timestamp
;
2189 /* No parent. This process exists but we are missing all information about
2190 its creation. The birth time is set to zero but we remember the time of
2195 process
->creation_time
= ltt_time_zero
;
2198 process
->insertion_time
= *timestamp
;
2199 sprintf(buffer
,"%d-%lu.%lu",pid
, process
->creation_time
.tv_sec
,
2200 process
->creation_time
.tv_nsec
);
2201 process
->pid_time
= g_quark_from_string(buffer
);
2203 process
->free_events
= 0;
2204 //process->last_cpu = tfs->cpu_name;
2205 //process->last_cpu_index = ltt_tracefile_num(((LttvTracefileContext*)tfs)->tf);
2206 process
->execution_stack
= g_array_sized_new(FALSE
, FALSE
,
2207 sizeof(LttvExecutionState
), PREALLOCATED_EXECUTION_STACK
);
2208 process
->execution_stack
= g_array_set_size(process
->execution_stack
, 2);
2209 es
= process
->state
= &g_array_index(process
->execution_stack
,
2210 LttvExecutionState
, 0);
2211 es
->t
= LTTV_STATE_USER_MODE
;
2212 es
->n
= LTTV_STATE_SUBMODE_NONE
;
2213 es
->entry
= *timestamp
;
2214 //g_assert(timestamp->tv_sec != 0);
2215 es
->change
= *timestamp
;
2216 es
->cum_cpu_time
= ltt_time_zero
;
2217 es
->s
= LTTV_STATE_RUN
;
2219 es
= process
->state
= &g_array_index(process
->execution_stack
,
2220 LttvExecutionState
, 1);
2221 es
->t
= LTTV_STATE_SYSCALL
;
2222 es
->n
= LTTV_STATE_SUBMODE_NONE
;
2223 es
->entry
= *timestamp
;
2224 //g_assert(timestamp->tv_sec != 0);
2225 es
->change
= *timestamp
;
2226 es
->cum_cpu_time
= ltt_time_zero
;
2227 es
->s
= LTTV_STATE_WAIT_FORK
;
2229 /* Allocate an empty function call stack. If it's empty, use 0x0. */
2230 #ifdef BABEL_CLEANUP
2231 //process->user_stack = g_array_sized_new(FALSE, FALSE,
2232 // sizeof(guint64), 0);
2234 process
->fds
= g_hash_table_new(g_direct_hash
, g_direct_equal
);
2240 lttv_state_find_process(LttvTraceState
*ts
, guint cpu
, guint pid
)
2242 LttvProcessState key
;
2243 LttvProcessState
*process
;
2247 process
= g_hash_table_lookup(ts
->processes
, &key
);
2251 LttvProcessState
*lttv_state_find_process_or_create(LttvTraceState
*ts
,
2252 guint cpu
, guint pid
, const LttTime
*timestamp
)
2254 LttvProcessState
*process
= lttv_state_find_process(ts
, cpu
, pid
);
2255 LttvExecutionState
*es
;
2257 /* Put ltt_time_zero creation time for unexisting processes */
2258 if(unlikely(process
== NULL
)) {
2259 process
= lttv_state_create_process(ts
,
2260 NULL
, cpu
, pid
, 0, LTTV_STATE_UNNAMED
, timestamp
);
2261 /* We are not sure is it's a kernel thread or normal thread, put the
2262 * bottom stack state to unknown */
2263 process
->execution_stack
=
2264 g_array_set_size(process
->execution_stack
, 1);
2265 process
->state
= es
=
2266 &g_array_index(process
->execution_stack
, LttvExecutionState
, 0);
2267 es
->t
= LTTV_STATE_MODE_UNKNOWN
;
2268 es
->s
= LTTV_STATE_UNNAMED
;
2273 /* FIXME : this function should be called when we receive an event telling that
2274 * release_task has been called in the kernel. In happens generally when
2275 * the parent waits for its child termination, but may also happens in special
2276 * cases in the child's exit : when the parent ignores its children SIGCCHLD or
2277 * has the flag SA_NOCLDWAIT. It can also happen when the child is part
2278 * of a killed thread group, but isn't the leader.
2280 static int exit_process(LttvEvent
*event
, LttvProcessState
*process
)
2282 LttvTraceState
*ts
= event
->state
;
2283 LttvProcessState key
;
2285 /* Wait for both schedule with exit dead and process free to happen.
2286 * They can happen in any order. */
2287 if (++(process
->free_events
) < 2)
2290 key
.pid
= process
->pid
;
2291 key
.cpu
= process
->cpu
;
2292 g_hash_table_remove(ts
->processes
, &key
);
2293 g_array_free(process
->execution_stack
, TRUE
);
2295 /* the following also clears the content */
2296 g_hash_table_destroy(process
->fds
);
2303 static void free_process_state(gpointer key
, gpointer value
,gpointer user_data
)
2305 g_array_free(((LttvProcessState
*)value
)->execution_stack
, TRUE
);
2307 /* the following also clears the content */
2308 g_hash_table_destroy(((LttvProcessState
*)value
)->fds
);
2314 static void lttv_state_free_process_table(GHashTable
*processes
)
2316 g_hash_table_foreach(processes
, free_process_state
, NULL
);
2317 g_hash_table_destroy(processes
);
2321 static gboolean
syscall_entry(void *hook_data
, void *call_data
)
2326 LttvProcessState
*process
;
2327 LttvExecutionSubmode submode
;
2328 char syscall_name
[200];
2330 event
= (LttvEvent
*) call_data
;
2331 if (strncmp(lttv_traceset_get_name_from_event(event
),
2332 "sys_", sizeof("sys_") - 1) != 0)
2335 strncpy(syscall_name
,lttv_traceset_get_name_from_event(event
)+4,200);
2337 cpu
= lttv_traceset_get_cpuid_from_event(event
);
2339 process
= ts
->running_process
[cpu
];
2341 submode
= g_quark_from_string(syscall_name
);
2342 /* There can be no system call from PID 0 : unknown state */
2343 if(process
->pid
!= 0)
2344 push_state(event
, ts
, LTTV_STATE_SYSCALL
, submode
);
2349 static gboolean
syscall_exit(void *hook_data
, void *call_data
)
2354 LttvProcessState
*process
;
2357 event
= (LttvEvent
*) call_data
;
2358 if (strcmp(lttv_traceset_get_name_from_event(event
),
2359 "exit_syscall") != 0)
2362 cpu
= lttv_traceset_get_cpuid_from_event(event
);
2364 process
= ts
->running_process
[cpu
];
2366 /* There can be no system call from PID 0 : unknown state */
2367 if (process
->pid
!= 0)
2368 pop_state(event
, ts
, LTTV_STATE_SYSCALL
);
2372 #ifdef BABEL_CLEANUP
2373 static gboolean
trap_entry(void *hook_data
, void *call_data
)
2375 LttvTracefileState
*s
= (LttvTracefileState
*)call_data
;
2376 LttvTraceState
*ts
= (LttvTraceState
*)s
->parent
.t_context
;
2377 LttEvent
*e
= ltt_tracefile_get_event(s
->parent
.tf
);
2378 LttvTraceHook
*th
= (LttvTraceHook
*)hook_data
;
2379 struct marker_field
*f
= lttv_trace_get_hook_field(th
, 0);
2380 LttvNameTables
*nt
= ((LttvTraceState
*)(s
->parent
.t_context
))->name_tables
;
2382 LttvExecutionSubmode submode
;
2384 guint64 trap
= ltt_event_get_long_unsigned(e
, f
);
2386 expand_trap_table(ts
, trap
);
2388 submode
= nt
->trap_names
[trap
];
2390 push_state(s
, LTTV_STATE_TRAP
, submode
);
2392 /* update cpu status */
2393 cpu_push_mode(s
->cpu_state
, LTTV_CPU_TRAP
);
2395 /* update trap status */
2396 g_array_append_val(s
->cpu_state
->trap_stack
, trap
);
2397 ts
->trap_states
[trap
].running
++;
2402 static gboolean
trap_exit(void *hook_data
, void *call_data
)
2404 LttvTracefileState
*s
= (LttvTracefileState
*)call_data
;
2405 LttvTraceState
*ts
= (LttvTraceState
*)s
->parent
.t_context
;
2407 pop_state(s
, LTTV_STATE_TRAP
);
2409 /* update cpu status */
2410 cpu_pop_mode(s
->cpu_state
);
2412 /* update trap status */
2413 if (s
->cpu_state
->trap_stack
->len
> 0) {
2414 gint last
= g_array_index(s
->cpu_state
->trap_stack
, gint
,
2415 s
->cpu_state
->trap_stack
->len
-1);
2416 if(ts
->trap_states
[last
].running
)
2417 ts
->trap_states
[last
].running
--;
2418 g_array_remove_index(s
->cpu_state
->trap_stack
,
2419 s
->cpu_state
->trap_stack
->len
-1);
2423 #endif /* BABEL_CLEANUP */
2425 static gboolean
irq_entry(void *hook_data
, void *call_data
)
2431 LttvExecutionSubmode submode
;
2435 event
= (LttvEvent
*) call_data
;
2436 if (strcmp(lttv_traceset_get_name_from_event(event
),
2437 "irq_handler_entry") != 0)
2440 cpu
= lttv_traceset_get_cpuid_from_event(event
);
2443 nt
= ts
->name_tables
;
2444 irq
= lttv_event_get_long(event
, "irq");
2446 expand_irq_table(ts
, irq
);
2448 submode
= nt
->irq_names
[irq
];
2450 /* Do something with the info about being in user or system mode when int? */
2451 push_state(event
, ts
, LTTV_STATE_IRQ
, submode
);
2453 /* update cpu status */
2454 cpu_push_mode(&(ts
->cpu_states
[cpu
]), LTTV_CPU_IRQ
);
2456 /* update irq status */
2457 g_array_append_val(ts
->cpu_states
[cpu
].irq_stack
, irq
);
2458 irq_push_mode(&ts
->irq_states
[irq
], LTTV_IRQ_BUSY
);
2463 static gboolean
soft_irq_exit(void *hook_data
, void *call_data
)
2469 LttvCPUState
*cpu_state
;
2471 event
= (LttvEvent
*) call_data
;
2472 if (strcmp(lttv_traceset_get_name_from_event(event
),
2473 "softirq_exit") != 0)
2476 cpu
= lttv_traceset_get_cpuid_from_event(event
);
2479 cpu_state
= &(ts
->cpu_states
[cpu
]);
2480 pop_state(event
, ts
, LTTV_STATE_SOFT_IRQ
);
2482 /* update cpu status */
2483 cpu_pop_mode(cpu_state
);
2485 /* update softirq status */
2486 if (cpu_state
->softirq_stack
->len
> 0) {
2487 gint last
= g_array_index(cpu_state
->softirq_stack
, gint
, cpu_state
->softirq_stack
->len
-1);
2488 if(ts
->soft_irq_states
[last
].running
)
2489 ts
->soft_irq_states
[last
].running
--;
2490 g_array_remove_index(cpu_state
->softirq_stack
, cpu_state
->softirq_stack
->len
-1);
2495 static gboolean
irq_exit(void *hook_data
, void *call_data
)
2501 LttvCPUState
*cpu_state
;
2503 event
= (LttvEvent
*) call_data
;
2504 if (strcmp(lttv_traceset_get_name_from_event(event
),
2505 "irq_handler_exit") != 0)
2508 cpu
= lttv_traceset_get_cpuid_from_event(event
);
2510 cpu_state
= &(ts
->cpu_states
[cpu
]);
2512 pop_state(event
, ts
, LTTV_STATE_IRQ
);
2514 /* update cpu status */
2515 cpu_pop_mode(cpu_state
);
2517 /* update irq status */
2518 if (cpu_state
->irq_stack
->len
> 0) {
2519 gint last
= g_array_index(cpu_state
->irq_stack
, gint
, cpu_state
->irq_stack
->len
-1);
2520 g_array_remove_index(cpu_state
->irq_stack
, cpu_state
->irq_stack
->len
-1);
2521 irq_pop_mode(&ts
->irq_states
[last
]);
2527 static gboolean
soft_irq_raise(void *hook_data
, void *call_data
)
2535 event
= (LttvEvent
*) call_data
;
2536 if (strcmp(lttv_traceset_get_name_from_event(event
),
2537 "softirq_raise") != 0)
2540 //cpu = lttv_traceset_get_cpuid_from_event(event);
2542 softirq
= lttv_event_get_long_unsigned(event
, "vec");
2544 expand_soft_irq_table(ts
, softirq
);
2546 /* update softirq status */
2547 /* a soft irq raises are not cumulative */
2548 ts
->soft_irq_states
[softirq
].pending
=1;
2553 static gboolean
soft_irq_entry(void *hook_data
, void *call_data
)
2558 LttvExecutionSubmode submode
;
2562 event
= (LttvEvent
*) call_data
;
2563 if (strcmp(lttv_traceset_get_name_from_event(event
),
2564 "softirq_entry") != 0)
2567 cpu
= lttv_traceset_get_cpuid_from_event(event
);
2573 softirq
= lttv_event_get_long_unsigned(event
, "vec");
2574 expand_soft_irq_table(ts
, softirq
);
2575 nt
= ts
->name_tables
;
2576 submode
= nt
->soft_irq_names
[softirq
];
2578 /* Do something with the info about being in user or system mode when int? */
2579 push_state(event
, ts
, LTTV_STATE_SOFT_IRQ
, submode
);
2581 /* update cpu status */
2582 cpu_push_mode(&(ts
->cpu_states
[cpu
]), LTTV_CPU_SOFT_IRQ
);
2584 /* update softirq status */
2585 g_array_append_val(ts
->cpu_states
[cpu
].softirq_stack
, softirq
);
2586 if (ts
->soft_irq_states
[softirq
].pending
)
2587 ts
->soft_irq_states
[softirq
].pending
--;
2588 ts
->soft_irq_states
[softirq
].running
++;
2593 static gboolean
enum_interrupt(void *hook_data
, void *call_data
)
2603 event
= (LttvEvent
*) call_data
;
2604 if (strcmp(lttv_traceset_get_name_from_event(event
),
2605 "lttng_statedump_interrupt") != 0)
2609 nt
= ts
->name_tables
;
2610 irq
= lttv_event_get_long_unsigned(event
, "irq");
2611 action
= g_quark_from_string(lttv_event_get_string(event
,
2613 expand_irq_table(ts
, irq
);
2614 nt
->irq_names
[irq
] = action
;
2619 #ifdef BABEL_CLEANUP
2620 static gboolean
bdev_request_issue(void *hook_data
, void *call_data
)
2631 event
= (LttvEvent
*) call_data
;
2632 if (strcmp(lttv_traceset_get_name_from_event(event
),
2633 "block_rq_issue") != 0)
2637 major
= lttv_event_get_long_unsigned(event
,);
2639 minor
= lttv_event_get_long_unsigned(event
,);
2641 oper
= lttv_event_get_long_unsigned(event
,);
2643 devcode
= MKDEV(major
,minor
);
2645 /* have we seen this block device before? */
2646 bdev
= get_hashed_bdevstate(ts
, devcode
);
2648 bdev_push_mode(bdev
, LTTV_BDEV_BUSY_READING
);
2650 bdev_push_mode(bdev
, LTTV_BDEV_BUSY_WRITING
);
2655 static gboolean
bdev_request_complete(void *hook_data
, void *call_data
)
2657 LttvTracefileState
*s
= (LttvTracefileState
*)call_data
;
2658 LttvTraceState
*ts
= (LttvTraceState
*)s
->parent
.t_context
;
2659 LttEvent
*e
= ltt_tracefile_get_event(s
->parent
.tf
);
2660 LttvTraceHook
*th
= (LttvTraceHook
*)hook_data
;
2662 guint major
= ltt_event_get_long_unsigned(e
,
2663 lttv_trace_get_hook_field(th
, 0));
2664 guint minor
= ltt_event_get_long_unsigned(e
,
2665 lttv_trace_get_hook_field(th
, 1));
2666 //guint oper = ltt_event_get_long_unsigned(e,
2667 // lttv_trace_get_hook_field(th, 2));
2668 guint32 devcode
= MKDEV(major
,minor
);
2670 /* have we seen this block device before? */
2671 gpointer bdev
= get_hashed_bdevstate(ts
, devcode
);
2673 /* update block device */
2674 bdev_pop_mode(bdev
);
2679 #ifdef BABEL_CLEANUP
2680 // We dont have the syscall table in LTTng 2.0
2681 static gboolean
dump_syscall(void *hook_data
, void *call_data
)
2683 LttvTracefileState
*s
= (LttvTracefileState
*)call_data
;
2684 LttvTraceState
*ts
= (LttvTraceState
*)s
->parent
.t_context
;
2685 LttvNameTables
*nt
= ts
->name_tables
;
2686 LttEvent
*e
= ltt_tracefile_get_event(s
->parent
.tf
);
2687 LttvTraceHook
*th
= (LttvTraceHook
*)hook_data
;
2691 id
= ltt_event_get_unsigned(e
, lttv_trace_get_hook_field(th
, 0));
2692 symbol
= ltt_event_get_string(e
, lttv_trace_get_hook_field(th
, 2));
2694 expand_syscall_table(ts
, id
);
2695 nt
->syscall_names
[id
] = g_quark_from_string(symbol
);
2700 static gboolean
dump_kprobe(void *hook_data
, void *call_data
)
2702 LttvTracefileState
*s
= (LttvTracefileState
*)call_data
;
2703 LttvTraceState
*ts
= (LttvTraceState
*)s
->parent
.t_context
;
2704 LttEvent
*e
= ltt_tracefile_get_event(s
->parent
.tf
);
2705 LttvTraceHook
*th
= (LttvTraceHook
*)hook_data
;
2709 ip
= ltt_event_get_long_unsigned(e
, lttv_trace_get_hook_field(th
, 0));
2710 symbol
= ltt_event_get_string(e
, lttv_trace_get_hook_field(th
, 1));
2712 expand_kprobe_table(ts
, ip
, symbol
);
2717 #ifdef BABEL_CLEANUP
2718 static gboolean
dump_softirq(void *hook_data
, void *call_data
)
2721 LttvTracefileState
*s
= (LttvTracefileState
*)call_data
;
2722 LttvTraceState
*ts
= (LttvTraceState
*)s
->parent
.t_context
;
2723 LttvNameTables
*nt
= ts
->name_tables
;
2724 LttEvent
*e
= ltt_tracefile_get_event(s
->parent
.tf
);
2725 LttvTraceHook
*th
= (LttvTraceHook
*)hook_data
;
2729 id
= ltt_event_get_unsigned(e
, lttv_trace_get_hook_field(th
, 0));
2730 symbol
= ltt_event_get_string(e
, lttv_trace_get_hook_field(th
, 2));
2732 expand_soft_irq_table(ts
, id
);
2733 nt
->soft_irq_names
[id
] = g_quark_from_string(symbol
);
2739 static gboolean
sched_try_wakeup(void *hook_data
, void *call_data
)
2743 LttvProcessState
*process
;
2748 event
= (LttvEvent
*) call_data
;
2749 if (strcmp(lttv_traceset_get_name_from_event(event
),
2750 "sched_wakeup") != 0)
2755 woken_pid
= lttv_event_get_long(event
, "tid");
2756 woken_cpu
= lttv_event_get_long(event
, "target_cpu");
2758 timestamp
= lttv_event_get_timestamp(event
);
2759 process
= lttv_state_find_process_or_create(
2761 woken_cpu
, woken_pid
,
2764 if (process
->state
->s
== LTTV_STATE_WAIT
|| process
->state
->s
== LTTV_STATE_WAIT_FORK
)
2766 process
->state
->s
= LTTV_STATE_WAIT_CPU
;
2767 process
->state
->change
= timestamp
;
2770 g_debug("Wakeup: process %d on CPU %u\n", woken_pid
, woken_cpu
);
2775 static gboolean
schedchange(void *hook_data
, void *call_data
)
2780 LttvProcessState
*process
;
2783 //LttvProcessState *old_process = ts->running_process[cpu];
2785 guint pid_in
, pid_out
;
2787 //TODO ybrosseau 2012-07-13: manage this 20 in a constact or dynamically
2790 event
= (LttvEvent
*) call_data
;
2791 if (strcmp(lttv_traceset_get_name_from_event(event
),
2792 "sched_switch") != 0)
2795 cpu
= lttv_traceset_get_cpuid_from_event(event
);
2797 process
= ts
->running_process
[cpu
];
2798 pid_out
= lttv_event_get_long(event
, "prev_tid");
2799 pid_in
= lttv_event_get_long(event
, "next_tid");
2800 state_out
= lttv_event_get_long(event
, "prev_state");
2802 strncpy(next_comm
, lttv_event_get_string(event
, "next_comm"), 20);
2803 next_comm
[20-1] = '\0';
2805 timestamp
= lttv_event_get_timestamp(event
);
2807 if(likely(process
!= NULL
)) {
2809 /* We could not know but it was not the idle process executing.
2810 This should only happen at the beginning, before the first schedule
2811 event, and when the initial information (current process for each CPU)
2812 is missing. It is not obvious how we could, after the fact, compensate
2813 the wrongly attributed statistics. */
2815 //This test only makes sense once the state is known and if there is no
2816 //missing events. We need to silently ignore schedchange coming after a
2817 //process_free, or it causes glitches. (FIXME)
2818 //if(unlikely(process->pid != pid_out)) {
2819 // g_assert(process->pid == 0);
2821 if(process
->pid
== 0
2822 && process
->state
->t
== LTTV_STATE_MODE_UNKNOWN
) {
2825 * Scheduling out of pid 0 at beginning of the trace.
2826 * We are typically in system call mode at this point although
2827 * (FIXME) we might be in a trap handler.
2829 g_assert(process
->execution_stack
->len
== 1);
2830 process
->state
->t
= LTTV_STATE_SYSCALL
;
2831 process
->state
->s
= LTTV_STATE_WAIT
;
2832 process
->state
->change
= timestamp
;
2833 process
->state
->entry
= timestamp
;
2836 if(unlikely(process
->state
->s
== LTTV_STATE_EXIT
)) {
2837 process
->state
->s
= LTTV_STATE_ZOMBIE
;
2838 process
->state
->change
= timestamp
;
2840 if(unlikely(state_out
== 0)) process
->state
->s
= LTTV_STATE_WAIT_CPU
;
2841 else process
->state
->s
= LTTV_STATE_WAIT
;
2842 process
->state
->change
= timestamp
;
2845 if(state_out
== 32 || state_out
== 64) { /* EXIT_DEAD || TASK_DEAD */
2846 /* see sched.h for states */
2847 if (!exit_process(event
, process
)) {
2848 process
->state
->s
= LTTV_STATE_DEAD
;
2849 process
->state
->change
= timestamp
;
2854 process
= ts
->running_process
[cpu
] = lttv_state_find_process_or_create(
2858 process
->state
->s
= LTTV_STATE_RUN
;
2860 // process->last_cpu_index = ltt_tracefile_num(((LttvTracefileContext*)s)->tf);
2861 process
->state
->change
= timestamp
;
2862 process
->name
= g_quark_from_string(next_comm
);
2864 /* update cpu status */
2866 /* going to idle task */
2867 cpu_set_base_mode(&(ts
->cpu_states
[cpu
]), LTTV_CPU_IDLE
);
2869 /* scheduling a real task.
2870 * we must be careful here:
2871 * if we just schedule()'ed to a process that is
2872 * in a trap, we must put the cpu in trap mode
2874 cpu_set_base_mode(&(ts
->cpu_states
[cpu
]), LTTV_CPU_BUSY
);
2875 if(process
->state
->t
== LTTV_STATE_TRAP
)
2876 cpu_push_mode(&(ts
->cpu_states
[cpu
]), LTTV_CPU_TRAP
);
2882 static gboolean
process_fork(void *hook_data
, void *call_data
)
2886 LttvProcessState
*process
;
2887 LttvProcessState
*child_process
;
2888 guint child_pid
; /* In the Linux Kernel, there is one PID per thread. */
2889 guint child_tgid
; /* tgid in the Linux kernel is the "real" POSIX PID. */
2890 //LttvProcessState *zombie_process;
2894 event
= (LttvEvent
*) call_data
;
2895 if (strcmp(lttv_traceset_get_name_from_event(event
),
2896 "sched_process_fork") != 0)
2898 cpu
= lttv_traceset_get_cpuid_from_event(event
);
2900 process
= ts
->running_process
[cpu
];
2901 timestamp
= lttv_event_get_timestamp(event
);
2903 /* Skip Parent PID param */
2906 child_pid
= lttv_event_get_long(event
, "child_tid");
2907 //ts->target_pid = child_pid;
2913 /* Mathieu : it seems like the process might have been scheduled in before the
2914 * fork, and, in a rare case, might be the current process. This might happen
2915 * in a SMP case where we don't have enough precision on the clocks.
2917 * Test reenabled after precision fixes on time. (Mathieu) */
2919 zombie_process
= lttv_state_find_process(ts
, ANY_CPU
, child_pid
);
2921 if(unlikely(zombie_process
!= NULL
)) {
2922 /* Reutilisation of PID. Only now we are sure that the old PID
2923 * has been released. FIXME : should know when release_task happens instead.
2925 guint num_cpus
= ltt_trace_get_num_cpu(ts
->parent
.t
);
2927 for(i
=0; i
< num_cpus
; i
++) {
2928 g_assert(zombie_process
!= ts
->running_process
[i
]);
2931 exit_process(s
, zombie_process
);
2934 g_assert(process
->pid
!= child_pid
);
2935 // FIXME : Add this test in the "known state" section
2936 // g_assert(process->pid == parent_pid);
2937 child_process
= lttv_state_find_process(ts
, ANY_CPU
, child_pid
);
2938 if(child_process
== NULL
) {
2939 child_process
= lttv_state_create_process(ts
, process
, cpu
,
2940 child_pid
, child_tgid
,
2941 LTTV_STATE_UNNAMED
, ×tamp
);
2943 /* The process has already been created : due to time imprecision between
2944 * multiple CPUs : it has been scheduled in before creation. Note that we
2945 * shouldn't have this kind of imprecision.
2947 * Simply put a correct parent.
2949 g_error("Process %u has been created at [%lu.%09lu] "
2950 "and inserted at [%lu.%09lu] before \n"
2951 "fork on cpu %u[%lu.%09lu].\n"
2952 "Probably an unsynchronized TSC problem on the traced machine.",
2954 child_process
->creation_time
.tv_sec
,
2955 child_process
->creation_time
.tv_nsec
,
2956 child_process
->insertion_time
.tv_sec
,
2957 child_process
->insertion_time
.tv_nsec
,
2958 cpu
, timestamp
.tv_sec
, timestamp
.tv_nsec
);
2959 //g_assert(0); /* This is a problematic case : the process has been created
2960 // before the fork event */
2961 child_process
->ppid
= process
->pid
;
2962 child_process
->tgid
= child_tgid
;
2964 g_assert(child_process
->name
== LTTV_STATE_UNNAMED
);
2965 child_process
->name
= process
->name
;
2966 child_process
->brand
= process
->brand
;
2971 #ifdef BABEL_CLEANUP
2972 //NO KTHREAD_CREATE in LTTng 2.0
2973 /* We stamp a newly created process as kernel_thread.
2974 * The thread should not be running yet. */
2975 static gboolean
process_kernel_thread(void *hook_data
, void *call_data
)
2977 LttvTracefileState
*s
= (LttvTracefileState
*)call_data
;
2978 LttEvent
*e
= ltt_tracefile_get_event(s
->parent
.tf
);
2979 LttvTraceHook
*th
= (LttvTraceHook
*)hook_data
;
2981 LttvTraceState
*ts
= (LttvTraceState
*)s
->parent
.t_context
;
2982 LttvProcessState
*process
;
2983 LttvExecutionState
*es
;
2986 pid
= (guint
)ltt_event_get_long_unsigned(e
, lttv_trace_get_hook_field(th
, 0));
2987 //s->parent.target_pid = pid;
2989 process
= lttv_state_find_process_or_create(ts
, ANY_CPU
, pid
,
2991 if (process
->state
->s
!= LTTV_STATE_DEAD
) {
2992 process
->execution_stack
=
2993 g_array_set_size(process
->execution_stack
, 1);
2994 es
= process
->state
=
2995 &g_array_index(process
->execution_stack
, LttvExecutionState
, 0);
2996 es
->t
= LTTV_STATE_SYSCALL
;
2998 process
->type
= LTTV_STATE_KERNEL_THREAD
;
3003 static gboolean
process_exit(void *hook_data
, void *call_data
)
3009 LttvProcessState
*process
; // = ts->running_process[cpu];
3011 event
= (LttvEvent
*) call_data
;
3012 if (strcmp(lttv_traceset_get_name_from_event(event
),
3013 "sched_process_exit") != 0)
3015 cpu
= lttv_traceset_get_cpuid_from_event(event
);
3017 process
= ts
->running_process
[cpu
];
3019 pid
= lttv_event_get_long(event
, "tid");
3020 //s->parent.target_pid = pid;
3022 // FIXME : Add this test in the "known state" section
3023 // g_assert(process->pid == pid);
3025 process
= lttv_state_find_process(ts
, ANY_CPU
, pid
);
3026 if(likely(process
!= NULL
)) {
3027 process
->state
->s
= LTTV_STATE_EXIT
;
3032 static gboolean
process_free(void *hook_data
, void *call_data
)
3038 LttvProcessState
*process
;
3040 event
= (LttvEvent
*) call_data
;
3041 if (strcmp(lttv_traceset_get_name_from_event(event
),
3042 "sched_process_free") != 0)
3044 cpu
= lttv_traceset_get_cpuid_from_event(event
);
3046 process
= ts
->running_process
[cpu
];
3048 /* PID of the process to release */
3049 release_pid
= lttv_event_get_long(event
, "_tid");
3050 //s->parent.target_pid = release_pid;
3052 g_assert(release_pid
!= 0);
3054 process
= lttv_state_find_process(ts
, ANY_CPU
, release_pid
);
3055 if(likely(process
!= NULL
))
3056 exit_process(event
, process
);
3060 if(likely(process
!= NULL
)) {
3061 /* release_task is happening at kernel level : we can now safely release
3062 * the data structure of the process */
3063 //This test is fun, though, as it may happen that
3064 //at time t : CPU 0 : process_free
3065 //at time t+150ns : CPU 1 : schedule out
3066 //Clearly due to time imprecision, we disable it. (Mathieu)
3067 //If this weird case happen, we have no choice but to put the
3068 //Currently running process on the cpu to 0.
3069 //I re-enable it following time precision fixes. (Mathieu)
3070 //Well, in the case where an process is freed by a process on another CPU
3071 //and still scheduled, it happens that this is the schedchange that will
3072 //drop the last reference count. Do not free it here!
3073 guint num_cpus
= ltt_trace_get_num_cpu(ts
->parent
.t
);
3075 for(i
=0; i
< num_cpus
; i
++) {
3076 //g_assert(process != ts->running_process[i]);
3077 if(process
== ts
->running_process
[i
]) {
3078 //ts->running_process[i] = lttv_state_find_process(ts, i, 0);
3082 if(i
== num_cpus
) /* process is not scheduled */
3083 exit_process(s
, process
);
3091 static gboolean
process_exec(void *hook_data
, void *call_data
)
3097 LttvProcessState
*process
;
3099 event
= (LttvEvent
*) call_data
;
3100 if (strcmp(lttv_traceset_get_name_from_event(event
),
3103 cpu
= lttv_traceset_get_cpuid_from_event(event
);
3105 process
= ts
->running_process
[cpu
];
3107 #if 0//how to use a sequence that must be transformed in a string
3108 /* PID of the process to release */
3109 guint64 name_len
= ltt_event_field_element_number(e
,
3110 lttv_trace_get_hook_field(th
, 0));
3111 //name = ltt_event_get_string(e, lttv_trace_get_hook_field(th, 0));
3112 LttField
*child
= ltt_event_field_element_select(e
,
3113 lttv_trace_get_hook_field(th
, 0), 0);
3115 (gchar
*)(ltt_event_data(e
)+ltt_event_field_offset(e
, child
));
3116 gchar
*null_term_name
= g_new(gchar
, name_len
+1);
3117 memcpy(null_term_name
, name_begin
, name_len
);
3118 null_term_name
[name_len
] = '\0';
3119 process
->name
= g_quark_from_string(null_term_name
);
3122 process
->name
= g_quark_from_string(lttv_event_get_string(event
,
3124 process
->brand
= LTTV_STATE_UNBRANDED
;
3125 //g_free(null_term_name);
3128 #ifdef BABEL_CLEANUP
3129 static gboolean
thread_brand(void *hook_data
, void *call_data
)
3131 LttvTracefileState
*s
= (LttvTracefileState
*)call_data
;
3132 LttvTraceState
*ts
= (LttvTraceState
*)s
->parent
.t_context
;
3133 LttEvent
*e
= ltt_tracefile_get_event(s
->parent
.tf
);
3134 LttvTraceHook
*th
= (LttvTraceHook
*)hook_data
;
3137 LttvProcessState
*process
= ts
->running_process
[cpu
];
3139 name
= ltt_event_get_string(e
, lttv_trace_get_hook_field(th
, 0));
3140 process
->brand
= g_quark_from_string(name
);
3146 // TODO We only have sys_open, without the FD
3147 // manage to do somehting better
3148 static gboolean
fs_open(void *hook_data
, void *call_data
)
3150 LttvTracefileState
*s
= (LttvTracefileState
*)call_data
;
3151 LttvTraceState
*ts
= (LttvTraceState
*)s
->parent
.t_context
;
3152 LttEvent
*e
= ltt_tracefile_get_event(s
->parent
.tf
);
3153 LttvTraceHook
*th
= (LttvTraceHook
*)hook_data
;
3154 struct marker_field
*f
;
3158 LttvProcessState
*process
= ts
->running_process
[cpu
];
3160 f
= lttv_trace_get_hook_field(th
, 0);
3161 fd
= ltt_event_get_int(e
, f
);
3163 f
= lttv_trace_get_hook_field(th
, 1);
3164 filename
= ltt_event_get_string(e
, f
);
3166 g_hash_table_insert(process
->fds
, (gpointer
)(long)fd
,
3167 (gpointer
)(unsigned long)g_quark_from_string(filename
));
3172 static void print_stack(LttvProcessState
*process
)
3174 LttvExecutionState
*es
;
3177 g_debug("Execution stack for process %u %s:\n",
3178 process
->pid
, g_quark_to_string(process
->name
));
3180 for (i
= 0; i
< process
->execution_stack
->len
; i
++) {
3181 es
= &g_array_index(process
->execution_stack
,
3182 LttvExecutionState
, i
);
3183 g_debug("Depth %d mode %s submode %s status %s\n",
3184 i
, g_quark_to_string(es
->t
),
3185 g_quark_to_string(es
->n
),
3186 g_quark_to_string(es
->s
));
3191 static void fix_process(gpointer key
, gpointer value
, gpointer user_data
)
3193 LttvProcessState
*process
;
3194 LttvExecutionState
*es
;
3195 process
= (LttvProcessState
*)value
;
3196 LttTime
*timestamp
= (LttTime
*)user_data
;
3198 print_stack(process
);
3200 if(process
->type
== LTTV_STATE_KERNEL_THREAD
) {
3201 es
= &g_array_index(process
->execution_stack
, LttvExecutionState
, 0);
3202 if(es
->t
== LTTV_STATE_MAYBE_SYSCALL
) {
3203 es
->t
= LTTV_STATE_SYSCALL
;
3204 es
->n
= LTTV_STATE_SUBMODE_NONE
;
3205 es
->entry
= *timestamp
;
3206 es
->change
= *timestamp
;
3207 es
->cum_cpu_time
= ltt_time_zero
;
3208 if(es
->s
== LTTV_STATE_UNNAMED
)
3209 es
->s
= LTTV_STATE_WAIT
;
3212 es
= &g_array_index(process
->execution_stack
, LttvExecutionState
, 0);
3213 if(es
->t
== LTTV_STATE_MAYBE_USER_MODE
) {
3214 es
->t
= LTTV_STATE_USER_MODE
;
3215 es
->n
= LTTV_STATE_SUBMODE_NONE
;
3216 es
->entry
= *timestamp
;
3217 //g_assert(timestamp->tv_sec != 0);
3218 es
->change
= *timestamp
;
3219 es
->cum_cpu_time
= ltt_time_zero
;
3220 if(es
->s
== LTTV_STATE_UNNAMED
)
3221 es
->s
= LTTV_STATE_RUN
;
3223 if(process
->execution_stack
->len
== 1) {
3224 /* Still in bottom unknown mode, means we either:
3225 * - never did a system call
3226 * - are scheduled out from user mode.
3227 * May be either in user mode, syscall mode, running or waiting.*/
3228 /* CHECK : we may be tagging syscall mode when being user mode
3229 * (should be fixed now) */
3230 if (es
->s
== LTTV_STATE_WAIT_CPU
) {
3231 /* nothing to do: scheduled out from userspace */
3233 process
->execution_stack
=
3234 g_array_set_size(process
->execution_stack
, 2);
3235 es
= process
->state
= &g_array_index(process
->execution_stack
,
3236 LttvExecutionState
, 1);
3237 es
->t
= LTTV_STATE_SYSCALL
;
3238 es
->n
= LTTV_STATE_SUBMODE_NONE
;
3239 es
->entry
= *timestamp
;
3240 //g_assert(timestamp->tv_sec != 0);
3241 es
->change
= *timestamp
;
3242 es
->cum_cpu_time
= ltt_time_zero
;
3243 if(es
->s
== LTTV_STATE_WAIT_FORK
)
3244 es
->s
= LTTV_STATE_WAIT
;
3251 static gboolean
statedump_end(void *hook_data
, void *call_data
)
3256 //LttEvent *e = ltt_tracefile_get_event(s->parent.tf);
3257 //LttvTraceHook *th = (LttvTraceHook *)hook_data;
3258 event
= (LttvEvent
*) call_data
;
3259 if (strcmp(lttv_traceset_get_name_from_event(event
),
3260 "lttng_statedump_end") != 0)
3264 timestamp
= lttv_event_get_timestamp(event
);
3266 /* For all processes */
3267 /* if kernel thread, if stack[0] is unknown, set to syscall mode, wait */
3268 /* else, if stack[0] is unknown, set to user mode, running */
3270 g_hash_table_foreach(ts
->processes
, fix_process
, ×tamp
);
3275 static gboolean
enum_process_state(void *hook_data
, void *call_data
)
3285 LttvProcessState
*parent_process
;
3286 LttvProcessState
*process
;
3289 LttvExecutionState
*es
;
3292 event
= (LttvEvent
*) call_data
;
3293 if (strcmp(lttv_traceset_get_name_from_event(event
),
3294 "lttng_statedump_process_state") != 0)
3296 cpu
= lttv_traceset_get_cpuid_from_event(event
);
3298 process
= ts
->running_process
[cpu
];
3299 timestamp
= lttv_event_get_timestamp(event
);
3302 pid
= lttv_event_get_long(event
, "tid");
3303 //s->parent.target_pid = pid;
3306 parent_pid
= lttv_event_get_long(event
, "ppid");
3309 command
= lttv_event_get_string(event
, "name");
3313 type
= lttv_event_get_long(event
, "type");
3315 //FIXME: type is rarely used, enum must match possible types.
3317 /* Skip mode 4th param */
3319 /* Skip submode 5th param */
3321 /* Skip status 6th param */
3323 tgid
= lttv_event_get_long(event
, "pid");
3326 nb_cpus
= lttv_trace_get_num_cpu(ts
->trace
);
3327 for(i
=0; i
<nb_cpus
; i
++) {
3328 process
= lttv_state_find_process(ts
, i
, pid
);
3329 g_assert(process
!= NULL
);
3331 process
->ppid
= parent_pid
;
3332 process
->tgid
= tgid
;
3333 process
->name
= g_quark_from_string(command
);
3334 es
= &g_array_index(process
->execution_stack
, LttvExecutionState
, 0);
3335 process
->type
= LTTV_STATE_KERNEL_THREAD
;
3339 /* The process might exist if a process was forked while performing the
3341 process
= lttv_state_find_process(ts
, ANY_CPU
, pid
);
3342 if(process
== NULL
) {
3343 parent_process
= lttv_state_find_process(ts
, ANY_CPU
, parent_pid
);
3344 process
= lttv_state_create_process(ts
, parent_process
, cpu
,
3345 pid
, tgid
, g_quark_from_string(command
),
3348 /* Keep the stack bottom : a running user mode */
3349 /* Disabled because of inconsistencies in the current statedump states. */
3350 //if(type == LTTV_STATE_KERNEL_THREAD) {
3352 /* Only keep the bottom
3353 * FIXME Kernel thread : can be in syscall or interrupt or trap. */
3354 /* Will cause expected trap when in fact being syscall (even after end of
3356 * Will cause expected interrupt when being syscall. (only before end of
3357 * statedump event) */
3358 // This will cause a "popping last state on stack, ignoring it."
3359 process
->execution_stack
= g_array_set_size(process
->execution_stack
, 1);
3360 es
= process
->state
= &g_array_index(process
->execution_stack
,
3361 LttvExecutionState
, 0);
3362 process
->type
= LTTV_STATE_KERNEL_THREAD
;
3363 es
->t
= LTTV_STATE_MAYBE_SYSCALL
;
3364 es
->s
= LTTV_STATE_UNNAMED
;
3365 es
->n
= LTTV_STATE_SUBMODE_UNKNOWN
;
3369 /* User space process :
3370 * bottom : user mode
3371 * either currently running or scheduled out.
3372 * can be scheduled out because interrupted in (user mode or in syscall)
3373 * or because of an explicit call to the scheduler in syscall. Note that
3374 * the scheduler call comes after the irq_exit, so never in interrupt
3376 // temp workaround : set size to 1 : only have user mode bottom of stack.
3377 // will cause g_info message of expected syscall mode when in fact being
3378 // in user mode. Can also cause expected trap when in fact being user
3379 // mode in the event of a page fault reenabling interrupts in the handler.
3380 // Expected syscall and trap can also happen after the end of statedump
3381 // This will cause a "popping last state on stack, ignoring it."
3382 process
->execution_stack
= g_array_set_size(process
->execution_stack
, 1);
3383 es
= process
->state
= &g_array_index(process
->execution_stack
,
3384 LttvExecutionState
, 0);
3385 es
->t
= LTTV_STATE_MAYBE_USER_MODE
;
3386 es
->s
= LTTV_STATE_UNNAMED
;
3387 es
->n
= LTTV_STATE_SUBMODE_UNKNOWN
;
3394 es
= process
->state
= &g_array_index(process
->execution_stack
,
3395 LttvExecutionState
, 1);
3396 es
->t
= LTTV_STATE_MODE_UNKNOWN
;
3397 es
->s
= LTTV_STATE_UNNAMED
;
3398 es
->n
= LTTV_STATE_SUBMODE_UNKNOWN
;
3402 /* The process has already been created :
3403 * Probably was forked while dumping the process state or
3404 * was simply scheduled in prior to get the state dump event.
3406 process
->ppid
= parent_pid
;
3407 process
->tgid
= tgid
;
3408 process
->name
= g_quark_from_string(command
);
3409 process
->type
= type
;
3410 es
= &g_array_index(process
->execution_stack
, LttvExecutionState
, 0);
3412 if(es
->t
== LTTV_STATE_MODE_UNKNOWN
) {
3413 if(type
== LTTV_STATE_KERNEL_THREAD
)
3414 es
->t
= LTTV_STATE_SYSCALL
;
3416 es
->t
= LTTV_STATE_USER_MODE
;
3419 /* Don't mess around with the stack, it will eventually become
3420 * ok after the end of state dump. */
3429 gint
lttv_state_hook_add_event_hooks(void *hook_data
, void *call_data
)
3431 LttvTraceset
*traceset
= (LttvTraceset
*)(call_data
);
3433 lttv_state_add_event_hooks(traceset
);
3438 void lttv_state_add_event_hooks(LttvTraceset
*traceset
)
3442 LttvAttributeValue value
;
3443 LttvHooks
*event_hook
;
3444 #ifdef BABEL_CLEANUP
3445 LttvIAttribute
*attributes
= LTTV_IATTRIBUTE(lttv_global_attributes());
3446 result
= lttv_iattribute_find_by_path(attributes
, "hooks/event",
3447 LTTV_POINTER
, &value
);
3449 event_hook
= *(value
.v_pointer
);
3451 //TODO ybrosseau 2012-07-12: Validate that using traceset hooks instead of the global one is valid
3452 //Use traceset hooks
3453 event_hook
= lttv_traceset_get_hooks(traceset
);
3454 g_assert(event_hook
);
3456 lttv_hooks_add(event_hook
,syscall_entry
, NULL
, LTTV_PRIO_STATE
);
3457 lttv_hooks_add(event_hook
,syscall_exit
, NULL
, LTTV_PRIO_STATE
);
3458 lttv_hooks_add(event_hook
,irq_entry
, NULL
, LTTV_PRIO_STATE
);
3459 lttv_hooks_add(event_hook
,irq_exit
, NULL
, LTTV_PRIO_STATE
);
3460 lttv_hooks_add(event_hook
,soft_irq_raise
, NULL
, LTTV_PRIO_STATE
);
3461 lttv_hooks_add(event_hook
,soft_irq_entry
, NULL
, LTTV_PRIO_STATE
);
3462 lttv_hooks_add(event_hook
,soft_irq_exit
, NULL
, LTTV_PRIO_STATE
);
3463 lttv_hooks_add(event_hook
,schedchange
, NULL
, LTTV_PRIO_STATE
);
3464 lttv_hooks_add(event_hook
,sched_try_wakeup
, NULL
, LTTV_PRIO_STATE
);
3465 lttv_hooks_add(event_hook
,process_exit
, NULL
, LTTV_PRIO_STATE
);
3466 lttv_hooks_add(event_hook
,process_free
, NULL
, LTTV_PRIO_STATE
);
3467 lttv_hooks_add(event_hook
,process_fork
, NULL
, LTTV_PRIO_STATE
);
3468 lttv_hooks_add(event_hook
,process_exec
, NULL
, LTTV_PRIO_STATE
);
3469 lttv_hooks_add(event_hook
,enum_process_state
, NULL
, LTTV_PRIO_STATE
);
3470 lttv_hooks_add(event_hook
,statedump_end
, NULL
, LTTV_PRIO_STATE
);
3471 lttv_hooks_add(event_hook
,enum_interrupt
, NULL
, LTTV_PRIO_STATE
);
3473 #ifdef BABEL_CLEANUP //For the whole function this time
3474 guint i
, j
, k
, nb_trace
;
3477 // LttvTraceHook *th;
3478 LttvAttributeValue val
;
3480 nb_trace
= lttv_traceset_number(traceset
);
3481 for (i
= 0 ; i
< nb_trace
; i
++) {
3482 ts
= lttv_traceset_get(traceset
, i
)-;
3484 /* Find the eventtype id for the following events and register the
3485 associated by id hooks. */
3487 hooks
= g_array_sized_new(FALSE
, FALSE
, sizeof(LttvTraceHook
), 20);
3488 //hooks = g_array_set_size(hooks, 19); // Max possible number of hooks.
3491 lttv_trace_find_hook(tss
->parent
.t
,
3493 LTT_EVENT_SYSCALL_ENTRY
,
3494 FIELD_ARRAY(LTT_FIELD_SYSCALL_ID
),
3495 syscall_entry
, NULL
, &hooks
);
3497 lttv_trace_find_hook(ts
->parent
.t
,
3499 LTT_EVENT_SYSCALL_EXIT
,
3501 syscall_exit
, NULL
, &hooks
);
3503 #ifdef BABEL_CLEANUP
3504 lttv_trace_find_hook(ts
->parent
.t
,
3506 LTT_EVENT_TRAP_ENTRY
,
3507 FIELD_ARRAY(LTT_FIELD_TRAP_ID
),
3508 trap_entry
, NULL
, &hooks
);
3510 lttv_trace_find_hook(ts
->parent
.t
,
3512 LTT_EVENT_TRAP_EXIT
,
3514 trap_exit
, NULL
, &hooks
);
3515 #endif /* BABEL_CLEANUP */
3517 lttv_trace_find_hook(ts
->parent
.t
,
3519 LTT_EVENT_PAGE_FAULT_ENTRY
,
3520 FIELD_ARRAY(LTT_FIELD_TRAP_ID
),
3521 trap_entry
, NULL
, &hooks
);
3523 lttv_trace_find_hook(ts
->parent
.t
,
3525 LTT_EVENT_PAGE_FAULT_EXIT
,
3527 trap_exit
, NULL
, &hooks
);
3529 #ifdef BABEL_CLEANUP
3530 lttv_trace_find_hook(ts
->parent
.t
,
3532 LTT_EVENT_PAGE_FAULT_NOSEM_ENTRY
,
3533 FIELD_ARRAY(LTT_FIELD_TRAP_ID
),
3534 trap_entry
, NULL
, &hooks
);
3536 lttv_trace_find_hook(ts
->parent
.t
,
3538 LTT_EVENT_PAGE_FAULT_NOSEM_EXIT
,
3540 trap_exit
, NULL
, &hooks
);
3541 #endif /* BABEL_CLEANUP */
3543 lttv_trace_find_hook(ts
->parent
.t
,
3545 LTT_EVENT_IRQ_ENTRY
,
3546 FIELD_ARRAY(LTT_FIELD_IRQ_ID
),
3547 irq_entry
, NULL
, &hooks
);
3549 lttv_trace_find_hook(ts
->parent
.t
,
3553 irq_exit
, NULL
, &hooks
);
3555 lttv_trace_find_hook(ts
->parent
.t
,
3557 LTT_EVENT_SOFT_IRQ_RAISE
,
3558 FIELD_ARRAY(LTT_FIELD_SOFT_IRQ_ID
),
3559 soft_irq_raise
, NULL
, &hooks
);
3561 lttv_trace_find_hook(ts
->parent
.t
,
3563 LTT_EVENT_SOFT_IRQ_ENTRY
,
3564 FIELD_ARRAY(LTT_FIELD_SOFT_IRQ_ID
),
3565 soft_irq_entry
, NULL
, &hooks
);
3567 lttv_trace_find_hook(ts
->parent
.t
,
3569 LTT_EVENT_SOFT_IRQ_EXIT
,
3571 soft_irq_exit
, NULL
, &hooks
);
3573 lttv_trace_find_hook(ts
->parent
.t
,
3575 LTT_EVENT_SCHED_SCHEDULE
,
3576 FIELD_ARRAY(LTT_FIELD_PREV_PID
, LTT_FIELD_NEXT_PID
,
3577 LTT_FIELD_PREV_STATE
),
3578 schedchange
, NULL
, &hooks
);
3580 lttv_trace_find_hook(ts
->parent
.t
,
3582 LTT_EVENT_SCHED_TRY_WAKEUP
,
3583 FIELD_ARRAY(LTT_FIELD_PID
, LTT_FIELD_CPU_ID
, LTT_FIELD_STATE
),
3584 sched_try_wakeup
, NULL
, &hooks
);
3586 lttv_trace_find_hook(ts
->parent
.t
,
3588 LTT_EVENT_PROCESS_FORK
,
3589 FIELD_ARRAY(LTT_FIELD_PARENT_PID
, LTT_FIELD_CHILD_PID
,
3590 LTT_FIELD_CHILD_TGID
),
3591 process_fork
, NULL
, &hooks
);
3593 lttv_trace_find_hook(ts
->parent
.t
,
3595 LTT_EVENT_KTHREAD_CREATE
,
3596 FIELD_ARRAY(LTT_FIELD_PID
),
3597 process_kernel_thread
, NULL
, &hooks
);
3599 lttv_trace_find_hook(ts
->parent
.t
,
3601 LTT_EVENT_PROCESS_EXIT
,
3602 FIELD_ARRAY(LTT_FIELD_PID
),
3603 process_exit
, NULL
, &hooks
);
3605 lttv_trace_find_hook(ts
->parent
.t
,
3607 LTT_EVENT_PROCESS_FREE
,
3608 FIELD_ARRAY(LTT_FIELD_PID
),
3609 process_free
, NULL
, &hooks
);
3611 lttv_trace_find_hook(ts
->parent
.t
,
3614 FIELD_ARRAY(LTT_FIELD_FILENAME
),
3615 process_exec
, NULL
, &hooks
);
3617 lttv_trace_find_hook(ts
->parent
.t
,
3618 LTT_CHANNEL_USERSPACE
,
3619 LTT_EVENT_THREAD_BRAND
,
3620 FIELD_ARRAY(LTT_FIELD_NAME
),
3621 thread_brand
, NULL
, &hooks
);
3623 /* statedump-related hooks */
3624 lttv_trace_find_hook(ts
->parent
.t
,
3625 LTT_CHANNEL_TASK_STATE
,
3626 LTT_EVENT_PROCESS_STATE
,
3627 FIELD_ARRAY(LTT_FIELD_PID
, LTT_FIELD_PARENT_PID
, LTT_FIELD_NAME
,
3628 LTT_FIELD_TYPE
, LTT_FIELD_MODE
, LTT_FIELD_SUBMODE
,
3629 LTT_FIELD_STATUS
, LTT_FIELD_TGID
),
3630 enum_process_state
, NULL
, &hooks
);
3632 lttv_trace_find_hook(ts
->parent
.t
,
3633 LTT_CHANNEL_GLOBAL_STATE
,
3634 LTT_EVENT_STATEDUMP_END
,
3636 statedump_end
, NULL
, &hooks
);
3638 lttv_trace_find_hook(ts
->parent
.t
,
3639 LTT_CHANNEL_IRQ_STATE
,
3640 LTT_EVENT_LIST_INTERRUPT
,
3641 FIELD_ARRAY(LTT_FIELD_ACTION
, LTT_FIELD_IRQ_ID
),
3642 enum_interrupt
, NULL
, &hooks
);
3644 lttv_trace_find_hook(ts
->parent
.t
,
3646 LTT_EVENT_REQUEST_ISSUE
,
3647 FIELD_ARRAY(LTT_FIELD_MAJOR
, LTT_FIELD_MINOR
, LTT_FIELD_OPERATION
),
3648 bdev_request_issue
, NULL
, &hooks
);
3650 lttv_trace_find_hook(ts
->parent
.t
,
3652 LTT_EVENT_REQUEST_COMPLETE
,
3653 FIELD_ARRAY(LTT_FIELD_MAJOR
, LTT_FIELD_MINOR
, LTT_FIELD_OPERATION
),
3654 bdev_request_complete
, NULL
, &hooks
);
3656 lttv_trace_find_hook(ts
->parent
.t
,
3657 LTT_CHANNEL_USERSPACE
,
3658 LTT_EVENT_FUNCTION_ENTRY
,
3659 FIELD_ARRAY(LTT_FIELD_THIS_FN
, LTT_FIELD_CALL_SITE
),
3660 function_entry
, NULL
, &hooks
);
3662 lttv_trace_find_hook(ts
->parent
.t
,
3663 LTT_CHANNEL_USERSPACE
,
3664 LTT_EVENT_FUNCTION_EXIT
,
3665 FIELD_ARRAY(LTT_FIELD_THIS_FN
, LTT_FIELD_CALL_SITE
),
3666 function_exit
, NULL
, &hooks
);
3668 lttv_trace_find_hook(ts
->parent
.t
,
3669 LTT_CHANNEL_SYSCALL_STATE
,
3670 LTT_EVENT_SYS_CALL_TABLE
,
3671 FIELD_ARRAY(LTT_FIELD_ID
, LTT_FIELD_ADDRESS
, LTT_FIELD_SYMBOL
),
3672 dump_syscall
, NULL
, &hooks
);
3674 lttv_trace_find_hook(ts
->parent
.t
,
3675 LTT_CHANNEL_KPROBE_STATE
,
3676 LTT_EVENT_KPROBE_TABLE
,
3677 FIELD_ARRAY(LTT_FIELD_IP
, LTT_FIELD_SYMBOL
),
3678 dump_kprobe
, NULL
, &hooks
);
3680 lttv_trace_find_hook(ts
->parent
.t
,
3681 LTT_CHANNEL_SOFTIRQ_STATE
,
3682 LTT_EVENT_SOFTIRQ_VEC
,
3683 FIELD_ARRAY(LTT_FIELD_ID
, LTT_FIELD_ADDRESS
, LTT_FIELD_SYMBOL
),
3684 dump_softirq
, NULL
, &hooks
);
3686 lttv_trace_find_hook(ts
->parent
.t
,
3689 FIELD_ARRAY(LTT_FIELD_FD
, LTT_FIELD_FILENAME
),
3690 fs_open
, NULL
, &hooks
);
3692 /* Add these hooks to each event_by_id hooks list */
3694 nb_tracefile
= ts
->parent
.tracefiles
->len
;
3696 for(j
= 0 ; j
< nb_tracefile
; j
++) {
3698 LTTV_TRACEFILE_STATE(g_array_index(ts
->parent
.tracefiles
,
3699 LttvTracefileContext
*, j
));
3701 for(k
= 0 ; k
< hooks
->len
; k
++) {
3702 th
= &g_array_index(hooks
, LttvTraceHook
, k
);
3703 if (th
->mdata
== tfs
->parent
.tf
->mdata
)
3705 lttv_hooks_by_id_find(tfs
->parent
.event_by_id
, th
->id
),
3711 lttv_attribute_find(ts
->parent
.a
, LTTV_STATE_HOOKS
, LTTV_POINTER
, &val
);
3712 *(val
.v_pointer
) = hooks
;
3717 gint
lttv_state_hook_remove_event_hooks(void *hook_data
, void *call_data
)
3720 LttvTraceset
*traceset
= (LttvTraceset
*)(call_data
);
3722 lttv_state_remove_event_hooks(traceset
);
3727 void lttv_state_remove_event_hooks(LttvTraceset
*traceset
)
3730 guint i
, j
, k
, nb_trace
, nb_tracefile
;
3732 //LttvTraceState *ts;
3736 //LttvTraceHook *th;
3738 //LttvAttributeValue val;
3740 LttvHooks
*event_hook
;
3741 //TODO ybrosseau 2012-07-17 validate this. Reversed what's done in the add
3742 event_hook
= lttv_traceset_get_hooks(traceset
);
3744 g_assert(event_hook
);
3747 lttv_hooks_remove(event_hook
,syscall_entry
);
3748 lttv_hooks_remove(event_hook
,syscall_exit
);
3749 lttv_hooks_remove(event_hook
,irq_entry
);
3750 lttv_hooks_remove(event_hook
,irq_exit
);
3751 lttv_hooks_remove(event_hook
,soft_irq_raise
);
3752 lttv_hooks_remove(event_hook
,soft_irq_entry
);
3753 lttv_hooks_remove(event_hook
,soft_irq_exit
);
3754 lttv_hooks_remove(event_hook
,schedchange
);
3755 lttv_hooks_remove(event_hook
,sched_try_wakeup
);
3756 lttv_hooks_remove(event_hook
,process_exit
);
3757 lttv_hooks_remove(event_hook
,process_free
);
3758 lttv_hooks_remove(event_hook
,process_exec
);
3759 lttv_hooks_remove(event_hook
,enum_process_state
);
3760 lttv_hooks_remove(event_hook
,statedump_end
);
3761 lttv_hooks_remove(event_hook
,enum_interrupt
);
3762 #ifdef BABEL_CLEANUP
3763 nb_trace
= lttv_traceset_number(traceset
);
3764 for(i
= 0 ; i
< nb_trace
; i
++) {
3765 ts
= lttv_traceset_get(i
);
3767 lttv_attribute_find(ts
->parent
.a
, LTTV_STATE_HOOKS
, LTTV_POINTER
, &val
);
3768 hooks
= *(val
.v_pointer
);
3770 /* Remove these hooks from each event_by_id hooks list */
3772 nb_tracefile
= ts
->parent
.tracefiles
->len
;
3774 for(j
= 0 ; j
< nb_tracefile
; j
++) {
3776 LTTV_TRACEFILE_STATE(g_array_index(ts
->parent
.tracefiles
,
3777 LttvTracefileContext
*, j
));
3779 for(k
= 0 ; k
< hooks
->len
; k
++) {
3780 th
= &g_array_index(hooks
, LttvTraceHook
, k
);
3781 if (th
->mdata
== tfs
->parent
.tf
->mdata
)
3782 lttv_hooks_remove_data(
3783 lttv_hooks_by_id_find(tfs
->parent
.event_by_id
, th
->id
),
3788 lttv_trace_hook_remove_all(&hooks
);
3789 g_array_free(hooks
, TRUE
);
3795 static gboolean
state_save_event_hook(void *hook_data
, void *call_data
)
3797 guint
*event_count
= (guint
*)hook_data
;
3799 /* Only save at LTTV_STATE_SAVE_INTERVAL */
3800 if(likely((*event_count
)++ < LTTV_STATE_SAVE_INTERVAL
))
3805 LttvEvent
*event
= (LttvEvent
*)call_data
;
3807 LttvTraceset
*traceset
= lttv_trace_get_traceset(event
->state
->trace
);
3809 LttvAttribute
*saved_states_tree
, *saved_state_tree
;
3811 LttvAttributeValue value
;
3812 LttTime currentTime
;
3814 currentTime
= lttv_event_get_timestamp(event
);
3815 int nb_trace
= lttv_traceset_number(traceset
);
3816 for(i
= 0 ; i
< nb_trace
; i
++) {
3818 LttvTrace
*trace
= lttv_traceset_get(traceset
, i
);
3819 LttvTraceState
*tstate
= trace
->state
;
3820 saved_states_tree
= lttv_attribute_find_subdir(trace
->a
,
3821 LTTV_STATE_SAVED_STATES
);
3823 saved_state_tree
= g_object_new(LTTV_ATTRIBUTE_TYPE
, NULL
);
3824 value
= lttv_attribute_add(saved_states_tree
,
3825 lttv_attribute_get_number(saved_states_tree
), LTTV_GOBJECT
);
3826 *(value
.v_gobject
) = (GObject
*)saved_state_tree
;
3829 value
= lttv_attribute_add(saved_state_tree
, LTTV_STATE_TIME
, LTTV_TIME
);
3830 *(value
.v_time
) = currentTime
;
3832 lttv_state_save(tstate
, saved_state_tree
);
3833 g_debug("Saving state at time %lu.%lu", currentTime
.tv_sec
,
3834 currentTime
.tv_nsec
);
3836 *(tstate
->max_time_state_recomputed_in_seek
) = currentTime
;
3841 static gboolean
state_save_after_trace_hook(void *hook_data
, void *call_data
)
3843 #warning "Would we move max_time to traceset"
3844 LttvTrace
*trace
= (LttvTrace
*)(call_data
);
3845 LttvTraceState
*tcs
= trace
->state
;
3846 TimeInterval time_span
= lttv_traceset_get_time_span_real(lttv_trace_get_traceset(trace
));
3848 *(tcs
->max_time_state_recomputed_in_seek
) = time_span
.end_time
;
3852 #ifdef BABEL_CLEANUP
3853 guint
lttv_state_current_cpu(LttvTracefileState
*tfs
)
3858 #endif //BABEL_CLEANUP
3861 static gboolean
block_start(void *hook_data
, void *call_data
)
3863 LttvTracefileState
*self
= (LttvTracefileState
*)call_data
;
3865 LttvTracefileState
*tfcs
;
3867 LttvTraceState
*tcs
= (LttvTraceState
*)(self
->parent
.t_context
);
3869 LttEventPosition
*ep
;
3871 guint i
, nb_block
, nb_event
, nb_tracefile
;
3875 LttvAttribute
*saved_states_tree
, *saved_state_tree
;
3877 LttvAttributeValue value
;
3879 ep
= ltt_event_position_new();
3881 nb_tracefile
= tcs
->parent
.tracefiles
->len
;
3883 /* Count the number of events added since the last block end in any
3886 for(i
= 0 ; i
< nb_tracefile
; i
++) {
3888 LTTV_TRACEFILE_STATE(&g_array_index(tcs
->parent
.tracefiles
,
3889 LttvTracefileContext
, i
));
3890 ltt_event_position(tfcs
->parent
.e
, ep
);
3891 ltt_event_position_get(ep
, &nb_block
, &nb_event
, &tf
);
3892 tcs
->nb_event
+= nb_event
- tfcs
->saved_position
;
3893 tfcs
->saved_position
= nb_event
;
3897 if(tcs
->nb_event
>= tcs
->save_interval
) {
3898 saved_states_tree
= lttv_attribute_find_subdir(tcs
->parent
.t_a
,
3899 LTTV_STATE_SAVED_STATES
);
3900 saved_state_tree
= g_object_new(LTTV_ATTRIBUTE_TYPE
, NULL
);
3901 value
= lttv_attribute_add(saved_states_tree
,
3902 lttv_attribute_get_number(saved_states_tree
), LTTV_GOBJECT
);
3903 *(value
.v_gobject
) = (GObject
*)saved_state_tree
;
3904 value
= lttv_attribute_add(saved_state_tree
, LTTV_STATE_TIME
, LTTV_TIME
);
3905 *(value
.v_time
) = self
->parent
.timestamp
;
3906 lttv_state_save(tcs
, saved_state_tree
);
3908 g_debug("Saving state at time %lu.%lu", self
->parent
.timestamp
.tv_sec
,
3909 self
->parent
.timestamp
.tv_nsec
);
3911 *(tcs
->max_time_state_recomputed_in_seek
) = self
->parent
.timestamp
;
3917 static gboolean
block_end(void *hook_data
, void *call_data
)
3919 LttvTracefileState
*self
= (LttvTracefileState
*)call_data
;
3921 LttvTraceState
*tcs
= (LttvTraceState
*)(self
->parent
.t_context
);
3925 LttEventPosition
*ep
;
3927 guint nb_block
, nb_event
;
3929 ep
= ltt_event_position_new();
3930 ltt_event_position(self
->parent
.e
, ep
);
3931 ltt_event_position_get(ep
, &nb_block
, &nb_event
, &tf
);
3932 tcs
->nb_event
+= nb_event
- self
->saved_position
+ 1;
3933 self
->saved_position
= 0;
3934 *(tcs
->max_time_state_recomputed_in_seek
) = self
->parent
.timestamp
;
3941 void lttv_state_save_add_event_hooks(LttvTracesetState
*self
)
3943 LttvTraceset
*traceset
= self
->parent
.ts
;
3945 guint i
, j
, nb_trace
, nb_tracefile
;
3949 LttvTracefileState
*tfs
;
3951 LttvTraceHook hook_start
, hook_end
;
3953 nb_trace
= lttv_traceset_number(traceset
);
3954 for(i
= 0 ; i
< nb_trace
; i
++) {
3955 ts
= (LttvTraceState
*)self
->parent
.traces
[i
];
3957 lttv_trace_find_hook(ts
->parent
.t
, "core","block_start",NULL
,
3958 NULL
, NULL
, block_start
, &hook_start
);
3959 lttv_trace_find_hook(ts
->parent
.t
, "core","block_end",NULL
,
3960 NULL
, NULL
, block_end
, &hook_end
);
3962 nb_tracefile
= ts
->parent
.tracefiles
->len
;
3964 for(j
= 0 ; j
< nb_tracefile
; j
++) {
3966 LTTV_TRACEFILE_STATE(&g_array_index(ts
->parent
.tracefiles
,
3967 LttvTracefileContext
, j
));
3968 lttv_hooks_add(lttv_hooks_by_id_find(tfs
->parent
.event_by_id
,
3969 hook_start
.id
), hook_start
.h
, NULL
, LTTV_PRIO_STATE
);
3970 lttv_hooks_add(lttv_hooks_by_id_find(tfs
->parent
.event_by_id
,
3971 hook_end
.id
), hook_end
.h
, NULL
, LTTV_PRIO_STATE
);
3977 void lttv_state_save_add_event_hooks(LttvTraceset
*traceset
)
3980 guint i
, j
, nb_trace
, nb_tracefile
;
3984 LttvTracefileState
*tfs
;
3987 if(!traceset
->has_precomputed_states
) {
3988 guint
*event_count
= g_new(guint
, 1);
3991 lttv_hooks_add(traceset
->event_hooks
,
3992 state_save_event_hook
,
3996 #ifdef BABEL_CLEANUP
3997 nb_trace
= lttv_traceset_number(traceset
);
3998 for(i
= 0 ; i
< nb_trace
; i
++) {
4000 ts
= (LttvTraceState
*)self
->parent
.traces
[i
];
4001 nb_tracefile
= ts
->parent
.tracefiles
->len
;
4003 if(ts
->has_precomputed_states
) continue;
4005 guint
*event_count
= g_new(guint
, 1);
4008 for(j
= 0 ; j
< nb_tracefile
; j
++) {
4010 LTTV_TRACEFILE_STATE(g_array_index(ts
->parent
.tracefiles
,
4011 LttvTracefileContext
*, j
));
4012 lttv_hooks_add(tfs
->parent
.event
,
4013 state_save_event_hook
,
4020 lttv_process_traceset_begin(traceset
,
4021 NULL
, NULL
, NULL
, NULL
, NULL
);
4026 gint
lttv_state_save_hook_add_event_hooks(void *hook_data
, void *call_data
)
4028 LttvTraceset
*ts
= (LttvTraceset
*)(call_data
);
4030 lttv_state_save_add_event_hooks(ts
);
4037 void lttv_state_save_remove_event_hooks(LttvTracesetState
*self
)
4039 LttvTraceset
*traceset
= self
->parent
.ts
;
4041 guint i
, j
, nb_trace
, nb_tracefile
;
4045 LttvTracefileState
*tfs
;
4047 LttvTraceHook hook_start
, hook_end
;
4049 nb_trace
= lttv_traceset_number(traceset
);
4050 for(i
= 0 ; i
< nb_trace
; i
++) {
4051 ts
= LTTV_TRACE_STATE(self
->parent
.traces
[i
]);
4053 lttv_trace_find_hook(ts
->parent
.t
, "core","block_start",NULL
,
4054 NULL
, NULL
, block_start
, &hook_start
);
4056 lttv_trace_find_hook(ts
->parent
.t
, "core","block_end",NULL
,
4057 NULL
, NULL
, block_end
, &hook_end
);
4059 nb_tracefile
= ts
->parent
.tracefiles
->len
;
4061 for(j
= 0 ; j
< nb_tracefile
; j
++) {
4063 LTTV_TRACEFILE_STATE(&g_array_index(ts
->parent
.tracefiles
,
4064 LttvTracefileContext
, j
));
4065 lttv_hooks_remove_data(lttv_hooks_by_id_find(
4066 tfs
->parent
.event_by_id
, hook_start
.id
), hook_start
.h
, NULL
);
4067 lttv_hooks_remove_data(lttv_hooks_by_id_find(
4068 tfs
->parent
.event_by_id
, hook_end
.id
), hook_end
.h
, NULL
);
4074 void lttv_state_save_remove_event_hooks(LttvTraceset
*traceset
)
4077 guint i
, j
, nb_trace
, nb_tracefile
;
4081 LttvTracefileState
*tfs
;
4083 LttvHooks
*after_trace
= lttv_hooks_new();
4084 guint
*event_count
= NULL
;
4086 lttv_hooks_add(after_trace
,
4087 state_save_after_trace_hook
,
4092 lttv_process_traceset_end(traceset
,
4093 NULL
, after_trace
, NULL
, NULL
);
4095 lttv_hooks_destroy(after_trace
);
4097 //nb_trace = lttv_traceset_number(traceset);
4099 event_count
= lttv_hooks_remove(traceset
->event_hooks
,
4100 state_save_event_hook
);
4102 if(event_count
) g_free(event_count
);
4104 #ifdef BABEL_CLEANUP
4105 for(i
= 0 ; i
< nb_trace
; i
++) {
4107 ts
= (LttvTraceState
*)self
->parent
.traces
[i
];
4108 nb_tracefile
= ts
->parent
.tracefiles
->len
;
4110 if(ts
->has_precomputed_states
) continue;
4112 guint
*event_count
= NULL
;
4114 for(j
= 0 ; j
< nb_tracefile
; j
++) {
4116 LTTV_TRACEFILE_STATE(g_array_index(ts
->parent
.tracefiles
,
4117 LttvTracefileContext
*, j
));
4118 event_count
= lttv_hooks_remove(tfs
->parent
.event
,
4119 state_save_event_hook
);
4121 if(event_count
) g_free(event_count
);
4126 gint
lttv_state_save_hook_remove_event_hooks(void *hook_data
, void *call_data
)
4128 LttvTraceset
*ts
= (LttvTraceset
*)(call_data
);
4130 lttv_state_save_remove_event_hooks(ts
);
4136 void lttv_state_traceset_seek_time(LttvTraceset
*traceset
, LttTime t
)
4138 lttv_state_traceset_seek_time_closest(traceset
,
4140 lttv_process_traceset_middle(traceset
, t
, G_MAXUINT
,
4144 void lttv_state_traceset_seek_position(LttvTraceset
*traceset
, LttvTracesetPosition
*position
)
4146 LttTime t
= lttv_traceset_position_get_time(position
);
4148 lttv_state_traceset_seek_time_closest(traceset
,
4150 lttv_process_traceset_middle(traceset
,
4156 void lttv_state_traceset_seek_time_closest(LttvTraceset
*traceset
, LttTime t
)
4160 int min_pos
, mid_pos
, max_pos
;
4162 guint call_rest
= 0;
4163 guint resto_start
= 0;
4166 LttvAttributeValue value
;
4168 LttvAttributeType type
;
4170 LttvAttributeName name
;
4174 LttvAttribute
*saved_states_tree
, *saved_state_tree
, *closest_tree
= NULL
;
4176 LttTime closest_tree_time
, restored_time
;
4178 //g_tree_destroy(self->parent.pqueue);
4179 //self->parent.pqueue = g_tree_new(compare_tracefile);
4181 g_info("Entering seek_time_closest for time %lu.%lu", t
.tv_sec
, t
.tv_nsec
);
4183 nb_trace
= lttv_traceset_number(traceset
);
4184 for(i
= 0 ; i
< nb_trace
; i
++) {
4186 LttvTrace
*trace
= lttv_traceset_get(traceset
, i
);
4187 LttvTraceState
*tstate
= trace
->state
;
4189 if(ltt_time_compare(t
, *(tstate
->max_time_state_recomputed_in_seek
)) < 0) {
4190 saved_states_tree
= lttv_attribute_find_subdir(trace
->a
,
4191 LTTV_STATE_SAVED_STATES
);
4194 if(saved_states_tree
) {
4195 max_pos
= lttv_attribute_get_number(saved_states_tree
) - 1;
4196 mid_pos
= max_pos
/ 2;
4197 while(min_pos
< max_pos
) {
4198 type
= lttv_attribute_get(saved_states_tree
, mid_pos
,
4199 &name
, &value
, &is_named
);
4200 g_assert(type
== LTTV_GOBJECT
);
4201 saved_state_tree
= *((LttvAttribute
**)(value
.v_gobject
));
4202 type
= lttv_attribute_get_by_name(saved_state_tree
,
4203 LTTV_STATE_TIME
, &value
);
4204 g_assert(type
== LTTV_TIME
);
4205 if(ltt_time_compare(*(value
.v_time
), t
) < 0) {
4207 closest_tree
= saved_state_tree
;
4208 closest_tree_time
= *(value
.v_time
);
4210 else max_pos
= mid_pos
- 1;
4212 mid_pos
= (min_pos
+ max_pos
+ 1) / 2;
4216 /* restore the closest earlier saved state */
4218 if(ltt_time_compare(restored_time
, closest_tree_time
) == 0) {
4220 lttv_state_restore(tstate
, closest_tree
);
4222 restored_time
= closest_tree_time
;
4225 g_debug("State: restored time mismatch between traces");
4232 /* There is no saved state, yet we want to have it. Restart at T0 */
4238 /* We want to seek quickly without restoring/updating the state */
4245 if(resto_start
|| resto_at
) {
4246 // Restore init state and seek so
4247 for(i
= 0 ; i
< nb_trace
; i
++) {
4249 LttvTrace
*trace
= lttv_traceset_get(traceset
, i
);
4250 LttvTraceState
*tstate
= trace
->state
;
4252 restore_init_state(tstate
);
4255 // If t > max saved state
4257 lttv_process_traceset_seek_time(traceset
, t
);
4258 } else if (resto_start
) {
4259 // If no saved state
4260 lttv_process_traceset_seek_time(traceset
, ltt_time_zero
);
4264 g_info("NOT Calling restore");
4267 // Seek at checkpoint
4268 lttv_process_traceset_seek_time(traceset
, restored_time
);
4276 #ifdef BABEL_CLEANUP
4277 static void traceset_state_instance_init (GTypeInstance
*instance
, gpointer g_class
)
4282 static void traceset_state_finalize (LttvTracesetState
*self
)
4284 G_OBJECT_CLASS(g_type_class_peek(LTTV_TRACESET_CONTEXT_TYPE
))->
4285 finalize(G_OBJECT(self
));
4289 static void traceset_state_class_init (LttvTracesetContextClass
*klass
)
4291 GObjectClass
*gobject_class
= G_OBJECT_CLASS(klass
);
4293 gobject_class
->finalize
= (void (*)(GObject
*self
)) traceset_state_finalize
;
4294 klass
->init
= (void (*)(LttvTracesetContext
*self
, LttvTraceset
*ts
))init
;
4295 klass
->fini
= (void (*)(LttvTracesetContext
*self
))fini
;
4296 klass
->new_traceset_context
= new_traceset_context
;
4297 klass
->new_trace_context
= new_trace_context
;
4298 klass
->new_tracefile_context
= new_tracefile_context
;
4302 GType
lttv_traceset_state_get_type(void)
4304 static GType type
= 0;
4306 static const GTypeInfo info
= {
4307 sizeof (LttvTracesetStateClass
),
4308 NULL
, /* base_init */
4309 NULL
, /* base_finalize */
4310 (GClassInitFunc
) traceset_state_class_init
, /* class_init */
4311 NULL
, /* class_finalize */
4312 NULL
, /* class_data */
4313 sizeof (LttvTracesetState
),
4314 0, /* n_preallocs */
4315 (GInstanceInitFunc
) traceset_state_instance_init
, /* instance_init */
4316 NULL
/* value handling */
4319 type
= g_type_register_static (LTTV_TRACESET_CONTEXT_TYPE
, "LttvTracesetStateType",
4327 static void trace_state_instance_init (GTypeInstance
*instance
, gpointer g_class
)
4332 static void trace_state_finalize (LttvTraceState
*self
)
4334 G_OBJECT_CLASS(g_type_class_peek(LTTV_TRACE_CONTEXT_TYPE
))->
4335 finalize(G_OBJECT(self
));
4339 static void trace_state_class_init (LttvTraceStateClass
*klass
)
4341 GObjectClass
*gobject_class
= G_OBJECT_CLASS(klass
);
4343 gobject_class
->finalize
= (void (*)(GObject
*self
)) trace_state_finalize
;
4344 klass
->state_save
= state_save
;
4345 klass
->state_restore
= state_restore
;
4346 klass
->state_saved_free
= state_saved_free
;
4350 GType
lttv_trace_state_get_type(void)
4352 static GType type
= 0;
4354 static const GTypeInfo info
= {
4355 sizeof (LttvTraceStateClass
),
4356 NULL
, /* base_init */
4357 NULL
, /* base_finalize */
4358 (GClassInitFunc
) trace_state_class_init
, /* class_init */
4359 NULL
, /* class_finalize */
4360 NULL
, /* class_data */
4361 sizeof (LttvTraceState
),
4362 0, /* n_preallocs */
4363 (GInstanceInitFunc
) trace_state_instance_init
, /* instance_init */
4364 NULL
/* value handling */
4367 type
= g_type_register_static (LTTV_TRACE_CONTEXT_TYPE
,
4368 "LttvTraceStateType", &info
, 0);
4374 static void tracefile_state_instance_init (GTypeInstance
*instance
,
4380 static void tracefile_state_finalize (LttvTracefileState
*self
)
4382 G_OBJECT_CLASS(g_type_class_peek(LTTV_TRACEFILE_CONTEXT_TYPE
))->
4383 finalize(G_OBJECT(self
));
4387 static void tracefile_state_class_init (LttvTracefileStateClass
*klass
)
4389 GObjectClass
*gobject_class
= G_OBJECT_CLASS(klass
);
4391 gobject_class
->finalize
= (void (*)(GObject
*self
)) tracefile_state_finalize
;
4395 GType
lttv_tracefile_state_get_type(void)
4397 static GType type
= 0;
4399 static const GTypeInfo info
= {
4400 sizeof (LttvTracefileStateClass
),
4401 NULL
, /* base_init */
4402 NULL
, /* base_finalize */
4403 (GClassInitFunc
) tracefile_state_class_init
, /* class_init */
4404 NULL
, /* class_finalize */
4405 NULL
, /* class_data */
4406 sizeof (LttvTracefileState
),
4407 0, /* n_preallocs */
4408 (GInstanceInitFunc
) tracefile_state_instance_init
, /* instance_init */
4409 NULL
/* value handling */
4412 type
= g_type_register_static (LTTV_TRACEFILE_CONTEXT_TYPE
,
4413 "LttvTracefileStateType", &info
, 0);
4419 static void module_init(void)
4421 LTTV_STATE_UNNAMED
= g_quark_from_string("");
4422 LTTV_STATE_UNBRANDED
= g_quark_from_string("");
4423 LTTV_STATE_MODE_UNKNOWN
= g_quark_from_string("MODE_UNKNOWN");
4424 LTTV_STATE_USER_MODE
= g_quark_from_string("USER_MODE");
4425 LTTV_STATE_MAYBE_USER_MODE
= g_quark_from_string("MAYBE_USER_MODE");
4426 LTTV_STATE_SYSCALL
= g_quark_from_string("SYSCALL");
4427 LTTV_STATE_MAYBE_SYSCALL
= g_quark_from_string("MAYBE_SYSCALL");
4428 LTTV_STATE_TRAP
= g_quark_from_string("TRAP");
4429 LTTV_STATE_MAYBE_TRAP
= g_quark_from_string("MAYBE_TRAP");
4430 LTTV_STATE_IRQ
= g_quark_from_string("IRQ");
4431 LTTV_STATE_SOFT_IRQ
= g_quark_from_string("SOFTIRQ");
4432 LTTV_STATE_SUBMODE_UNKNOWN
= g_quark_from_string("UNKNOWN");
4433 LTTV_STATE_SUBMODE_NONE
= g_quark_from_string("NONE");
4434 LTTV_STATE_WAIT_FORK
= g_quark_from_string("WAIT_FORK");
4435 LTTV_STATE_WAIT_CPU
= g_quark_from_string("WAIT_CPU");
4436 LTTV_STATE_EXIT
= g_quark_from_string("EXIT");
4437 LTTV_STATE_ZOMBIE
= g_quark_from_string("ZOMBIE");
4438 LTTV_STATE_WAIT
= g_quark_from_string("WAIT");
4439 LTTV_STATE_RUN
= g_quark_from_string("RUN");
4440 LTTV_STATE_DEAD
= g_quark_from_string("DEAD");
4441 LTTV_STATE_USER_THREAD
= g_quark_from_string("USER_THREAD");
4442 LTTV_STATE_KERNEL_THREAD
= g_quark_from_string("KERNEL_THREAD");
4443 LTTV_STATE_TRACEFILES
= g_quark_from_string("tracefiles");
4444 LTTV_STATE_PROCESSES
= g_quark_from_string("processes");
4445 LTTV_STATE_PROCESS
= g_quark_from_string("process");
4446 LTTV_STATE_RUNNING_PROCESS
= g_quark_from_string("running_process");
4447 LTTV_STATE_POSITION
= g_quark_from_string("position");
4448 LTTV_STATE_SAVED_STATES
= g_quark_from_string("saved states");
4449 LTTV_STATE_SAVED_STATES_TIME
= g_quark_from_string("saved states time");
4450 LTTV_STATE_TIME
= g_quark_from_string("time");
4451 LTTV_STATE_HOOKS
= g_quark_from_string("saved state hooks");
4452 LTTV_STATE_NAME_TABLES
= g_quark_from_string("name tables");
4453 LTTV_STATE_TRACE_STATE_USE_COUNT
=
4454 g_quark_from_string("trace_state_use_count");
4455 LTTV_STATE_RESOURCE_CPUS
= g_quark_from_string("cpu resource states");
4456 LTTV_STATE_RESOURCE_CPUS
= g_quark_from_string("cpu count");
4457 LTTV_STATE_RESOURCE_IRQS
= g_quark_from_string("irq resource states");
4458 LTTV_STATE_RESOURCE_SOFT_IRQS
= g_quark_from_string("soft irq resource states");
4459 LTTV_STATE_RESOURCE_TRAPS
= g_quark_from_string("trap resource states");
4460 LTTV_STATE_RESOURCE_BLKDEVS
= g_quark_from_string("blkdevs resource states");
4462 LTT_CHANNEL_FD_STATE
= g_quark_from_string("fd_state");
4463 LTT_CHANNEL_GLOBAL_STATE
= g_quark_from_string("global_state");
4464 LTT_CHANNEL_IRQ_STATE
= g_quark_from_string("irq_state");
4465 LTT_CHANNEL_MODULE_STATE
= g_quark_from_string("module_state");
4466 LTT_CHANNEL_NETIF_STATE
= g_quark_from_string("netif_state");
4467 LTT_CHANNEL_SOFTIRQ_STATE
= g_quark_from_string("softirq_state");
4468 LTT_CHANNEL_SWAP_STATE
= g_quark_from_string("swap_state");
4469 LTT_CHANNEL_SYSCALL_STATE
= g_quark_from_string("syscall_state");
4470 LTT_CHANNEL_TASK_STATE
= g_quark_from_string("task_state");
4471 LTT_CHANNEL_VM_STATE
= g_quark_from_string("vm_state");
4472 LTT_CHANNEL_KPROBE_STATE
= g_quark_from_string("kprobe_state");
4473 LTT_CHANNEL_FS
= g_quark_from_string("fs");
4474 LTT_CHANNEL_KERNEL
= g_quark_from_string("kernel");
4475 LTT_CHANNEL_MM
= g_quark_from_string("mm");
4476 LTT_CHANNEL_USERSPACE
= g_quark_from_string("userspace");
4477 LTT_CHANNEL_BLOCK
= g_quark_from_string("block");
4479 LTT_EVENT_SYSCALL_ENTRY
= g_quark_from_string("syscall_entry");
4480 LTT_EVENT_SYSCALL_EXIT
= g_quark_from_string("syscall_exit");
4481 //LTT_EVENT_TRAP_ENTRY = g_quark_from_string("trap_entry");
4482 //LTT_EVENT_TRAP_EXIT = g_quark_from_string("trap_exit");
4483 LTT_EVENT_PAGE_FAULT_ENTRY
= g_quark_from_string("page_fault_entry");
4484 LTT_EVENT_PAGE_FAULT_EXIT
= g_quark_from_string("page_fault_exit");
4485 LTT_EVENT_PAGE_FAULT_NOSEM_ENTRY
= g_quark_from_string("page_fault_nosem_entry");
4486 LTT_EVENT_PAGE_FAULT_NOSEM_EXIT
= g_quark_from_string("page_fault_nosem_exit");
4487 LTT_EVENT_IRQ_ENTRY
= g_quark_from_string("irq_entry");
4488 LTT_EVENT_IRQ_EXIT
= g_quark_from_string("irq_exit");
4489 LTT_EVENT_SOFT_IRQ_RAISE
= g_quark_from_string("softirq_raise");
4490 LTT_EVENT_SOFT_IRQ_ENTRY
= g_quark_from_string("softirq_entry");
4491 LTT_EVENT_SOFT_IRQ_EXIT
= g_quark_from_string("softirq_exit");
4492 LTT_EVENT_SCHED_SCHEDULE
= g_quark_from_string("sched_schedule");
4493 LTT_EVENT_SCHED_TRY_WAKEUP
= g_quark_from_string("sched_try_wakeup");
4494 LTT_EVENT_PROCESS_FORK
= g_quark_from_string("process_fork");
4495 LTT_EVENT_KTHREAD_CREATE
= g_quark_from_string("kthread_create");
4496 LTT_EVENT_PROCESS_EXIT
= g_quark_from_string("process_exit");
4497 LTT_EVENT_PROCESS_FREE
= g_quark_from_string("process_free");
4498 LTT_EVENT_EXEC
= g_quark_from_string("exec");
4499 LTT_EVENT_PROCESS_STATE
= g_quark_from_string("process_state");
4500 LTT_EVENT_STATEDUMP_END
= g_quark_from_string("statedump_end");
4501 LTT_EVENT_FUNCTION_ENTRY
= g_quark_from_string("function_entry");
4502 LTT_EVENT_FUNCTION_EXIT
= g_quark_from_string("function_exit");
4503 LTT_EVENT_THREAD_BRAND
= g_quark_from_string("thread_brand");
4504 LTT_EVENT_REQUEST_ISSUE
= g_quark_from_string("_blk_request_issue");
4505 LTT_EVENT_REQUEST_COMPLETE
= g_quark_from_string("_blk_request_complete");
4506 LTT_EVENT_LIST_INTERRUPT
= g_quark_from_string("interrupt");
4507 LTT_EVENT_SYS_CALL_TABLE
= g_quark_from_string("sys_call_table");
4508 LTT_EVENT_SOFTIRQ_VEC
= g_quark_from_string("softirq_vec");
4509 LTT_EVENT_KPROBE_TABLE
= g_quark_from_string("kprobe_table");
4510 LTT_EVENT_KPROBE
= g_quark_from_string("kprobe");
4511 LTT_EVENT_OPEN
= g_quark_from_string("open");
4512 LTT_EVENT_READ
= g_quark_from_string("read");
4513 LTT_EVENT_POLL_EVENT
= g_quark_from_string("poll_event");
4515 LTT_FIELD_SYSCALL_ID
= g_quark_from_string("syscall_id");
4516 LTT_FIELD_TRAP_ID
= g_quark_from_string("trap_id");
4517 LTT_FIELD_IRQ_ID
= g_quark_from_string("irq_id");
4518 LTT_FIELD_SOFT_IRQ_ID
= g_quark_from_string("softirq_id");
4519 LTT_FIELD_PREV_PID
= g_quark_from_string("prev_pid");
4520 LTT_FIELD_NEXT_PID
= g_quark_from_string("next_pid");
4521 LTT_FIELD_PREV_STATE
= g_quark_from_string("prev_state");
4522 LTT_FIELD_PARENT_PID
= g_quark_from_string("parent_pid");
4523 LTT_FIELD_CHILD_PID
= g_quark_from_string("child_pid");
4524 LTT_FIELD_PID
= g_quark_from_string("pid");
4525 LTT_FIELD_TGID
= g_quark_from_string("tgid");
4526 LTT_FIELD_CHILD_TGID
= g_quark_from_string("child_tgid");
4527 LTT_FIELD_FILENAME
= g_quark_from_string("filename");
4528 LTT_FIELD_NAME
= g_quark_from_string("name");
4529 LTT_FIELD_TYPE
= g_quark_from_string("type");
4530 LTT_FIELD_MODE
= g_quark_from_string("mode");
4531 LTT_FIELD_SUBMODE
= g_quark_from_string("submode");
4532 LTT_FIELD_STATUS
= g_quark_from_string("status");
4533 LTT_FIELD_THIS_FN
= g_quark_from_string("this_fn");
4534 LTT_FIELD_CALL_SITE
= g_quark_from_string("call_site");
4535 LTT_FIELD_MAJOR
= g_quark_from_string("major");
4536 LTT_FIELD_MINOR
= g_quark_from_string("minor");
4537 LTT_FIELD_OPERATION
= g_quark_from_string("direction");
4538 LTT_FIELD_ACTION
= g_quark_from_string("action");
4539 LTT_FIELD_ID
= g_quark_from_string("id");
4540 LTT_FIELD_ADDRESS
= g_quark_from_string("address");
4541 LTT_FIELD_SYMBOL
= g_quark_from_string("symbol");
4542 LTT_FIELD_IP
= g_quark_from_string("ip");
4543 LTT_FIELD_FD
= g_quark_from_string("fd");
4544 LTT_FIELD_STATE
= g_quark_from_string("state");
4545 LTT_FIELD_CPU_ID
= g_quark_from_string("cpu_id");
4547 LTTV_CPU_UNKNOWN
= g_quark_from_string("unknown");
4548 LTTV_CPU_IDLE
= g_quark_from_string("idle");
4549 LTTV_CPU_BUSY
= g_quark_from_string("busy");
4550 LTTV_CPU_IRQ
= g_quark_from_string("irq");
4551 LTTV_CPU_SOFT_IRQ
= g_quark_from_string("softirq");
4552 LTTV_CPU_TRAP
= g_quark_from_string("trap");
4554 LTTV_IRQ_UNKNOWN
= g_quark_from_string("unknown");
4555 LTTV_IRQ_IDLE
= g_quark_from_string("idle");
4556 LTTV_IRQ_BUSY
= g_quark_from_string("busy");
4558 LTTV_BDEV_UNKNOWN
= g_quark_from_string("unknown");
4559 LTTV_BDEV_IDLE
= g_quark_from_string("idle");
4560 LTTV_BDEV_BUSY_READING
= g_quark_from_string("busy_reading");
4561 LTTV_BDEV_BUSY_WRITING
= g_quark_from_string("busy_writing");
4564 static void module_destroy()
4569 LTTV_MODULE("state", "State computation", \
4570 "Update the system state, possibly saving it at intervals", \
4571 module_init
, module_destroy
)