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);
2151 process
->state
= &g_array_index(process
->execution_stack
, LttvExecutionState
,
2153 process
->state
->change
= lttv_event_get_timestamp(event
);
2155 if((process
->state
->t
== LTTV_STATE_MODE_UNKNOWN
) && (t
== LTTV_STATE_SYSCALL
)) {
2156 //Force state at running
2157 process
->state
->t
= LTTV_STATE_USER_MODE
;
2158 process
->state
->s
= LTTV_STATE_RUN
;
2162 struct search_result
{
2163 const LttTime
*time
; /* Requested time */
2164 LttTime
*best
; /* Best result */
2167 /* Return a new and initialized LttvProcessState structure */
2169 LttvProcessState
*lttv_state_create_process(LttvTraceState
*tcs
,
2170 LttvProcessState
*parent
, guint cpu
, guint pid
,
2171 guint tgid
, GQuark name
, const LttTime
*timestamp
)
2173 LttvProcessState
*process
= g_new(LttvProcessState
, 1);
2175 LttvExecutionState
*es
;
2180 process
->tgid
= tgid
;
2182 process
->name
= name
;
2183 process
->brand
= LTTV_STATE_UNBRANDED
;
2184 //process->last_cpu = tfs->cpu_name;
2185 //process->last_cpu_index = ltt_tracefile_num(((LttvTracefileContext*)tfs)->tf);
2186 process
->type
= LTTV_STATE_USER_THREAD
;
2188 g_info("Process %u, core %p", process
->pid
, process
);
2189 g_hash_table_insert(tcs
->processes
, process
, process
);
2192 process
->ppid
= parent
->pid
;
2193 process
->creation_time
= *timestamp
;
2196 /* No parent. This process exists but we are missing all information about
2197 its creation. The birth time is set to zero but we remember the time of
2202 process
->creation_time
= ltt_time_zero
;
2205 process
->insertion_time
= *timestamp
;
2206 sprintf(buffer
,"%d-%lu.%lu",pid
, process
->creation_time
.tv_sec
,
2207 process
->creation_time
.tv_nsec
);
2208 process
->pid_time
= g_quark_from_string(buffer
);
2210 process
->free_events
= 0;
2211 //process->last_cpu = tfs->cpu_name;
2212 //process->last_cpu_index = ltt_tracefile_num(((LttvTracefileContext*)tfs)->tf);
2213 process
->execution_stack
= g_array_sized_new(FALSE
, FALSE
,
2214 sizeof(LttvExecutionState
), PREALLOCATED_EXECUTION_STACK
);
2215 process
->execution_stack
= g_array_set_size(process
->execution_stack
, 2);
2216 es
= process
->state
= &g_array_index(process
->execution_stack
,
2217 LttvExecutionState
, 0);
2218 es
->t
= LTTV_STATE_USER_MODE
;
2219 es
->n
= LTTV_STATE_SUBMODE_NONE
;
2220 es
->entry
= *timestamp
;
2221 //g_assert(timestamp->tv_sec != 0);
2222 es
->change
= *timestamp
;
2223 es
->cum_cpu_time
= ltt_time_zero
;
2224 es
->s
= LTTV_STATE_RUN
;
2226 es
= process
->state
= &g_array_index(process
->execution_stack
,
2227 LttvExecutionState
, 1);
2228 es
->t
= LTTV_STATE_SYSCALL
;
2229 es
->n
= LTTV_STATE_SUBMODE_NONE
;
2230 es
->entry
= *timestamp
;
2231 //g_assert(timestamp->tv_sec != 0);
2232 es
->change
= *timestamp
;
2233 es
->cum_cpu_time
= ltt_time_zero
;
2234 es
->s
= LTTV_STATE_WAIT_FORK
;
2236 /* Allocate an empty function call stack. If it's empty, use 0x0. */
2237 #ifdef BABEL_CLEANUP
2238 //process->user_stack = g_array_sized_new(FALSE, FALSE,
2239 // sizeof(guint64), 0);
2241 process
->fds
= g_hash_table_new(g_direct_hash
, g_direct_equal
);
2247 lttv_state_find_process(LttvTraceState
*ts
, guint cpu
, guint pid
)
2249 LttvProcessState key
;
2250 LttvProcessState
*process
;
2254 process
= g_hash_table_lookup(ts
->processes
, &key
);
2258 LttvProcessState
*lttv_state_find_process_or_create(LttvTraceState
*ts
,
2259 guint cpu
, guint pid
, const LttTime
*timestamp
)
2261 LttvProcessState
*process
= lttv_state_find_process(ts
, cpu
, pid
);
2262 LttvExecutionState
*es
;
2264 /* Put ltt_time_zero creation time for unexisting processes */
2265 if(unlikely(process
== NULL
)) {
2266 process
= lttv_state_create_process(ts
,
2267 NULL
, cpu
, pid
, 0, LTTV_STATE_UNNAMED
, timestamp
);
2268 /* We are not sure is it's a kernel thread or normal thread, put the
2269 * bottom stack state to unknown */
2270 process
->execution_stack
=
2271 g_array_set_size(process
->execution_stack
, 1);
2272 process
->state
= es
=
2273 &g_array_index(process
->execution_stack
, LttvExecutionState
, 0);
2274 es
->t
= LTTV_STATE_MODE_UNKNOWN
;
2275 es
->s
= LTTV_STATE_UNNAMED
;
2280 /* FIXME : this function should be called when we receive an event telling that
2281 * release_task has been called in the kernel. In happens generally when
2282 * the parent waits for its child termination, but may also happens in special
2283 * cases in the child's exit : when the parent ignores its children SIGCCHLD or
2284 * has the flag SA_NOCLDWAIT. It can also happen when the child is part
2285 * of a killed thread group, but isn't the leader.
2287 static int exit_process(LttvEvent
*event
, LttvProcessState
*process
)
2289 LttvTraceState
*ts
= event
->state
;
2290 LttvProcessState key
;
2292 /* Wait for both schedule with exit dead and process free to happen.
2293 * They can happen in any order. */
2294 if (++(process
->free_events
) < 2)
2297 key
.pid
= process
->pid
;
2298 key
.cpu
= process
->cpu
;
2299 g_hash_table_remove(ts
->processes
, &key
);
2300 g_array_free(process
->execution_stack
, TRUE
);
2302 /* the following also clears the content */
2303 g_hash_table_destroy(process
->fds
);
2310 static void free_process_state(gpointer key
, gpointer value
,gpointer user_data
)
2312 g_array_free(((LttvProcessState
*)value
)->execution_stack
, TRUE
);
2314 /* the following also clears the content */
2315 g_hash_table_destroy(((LttvProcessState
*)value
)->fds
);
2321 static void lttv_state_free_process_table(GHashTable
*processes
)
2323 g_hash_table_foreach(processes
, free_process_state
, NULL
);
2324 g_hash_table_destroy(processes
);
2328 static gboolean
syscall_entry(void *hook_data
, void *call_data
)
2333 LttvProcessState
*process
;
2334 LttvExecutionSubmode submode
;
2335 char syscall_name
[200];
2337 event
= (LttvEvent
*) call_data
;
2338 if (strncmp(lttv_traceset_get_name_from_event(event
),
2339 "sys_", sizeof("sys_") - 1) != 0)
2342 strncpy(syscall_name
,lttv_traceset_get_name_from_event(event
)+4,200);
2344 cpu
= lttv_traceset_get_cpuid_from_event(event
);
2346 process
= ts
->running_process
[cpu
];
2348 submode
= g_quark_from_string(syscall_name
);
2349 /* There can be no system call from PID 0 : unknown state */
2350 if(process
->pid
!= 0)
2351 push_state(event
, ts
, LTTV_STATE_SYSCALL
, submode
);
2356 static gboolean
syscall_exit(void *hook_data
, void *call_data
)
2361 LttvProcessState
*process
;
2364 event
= (LttvEvent
*) call_data
;
2365 if (strcmp(lttv_traceset_get_name_from_event(event
),
2366 "exit_syscall") != 0)
2369 cpu
= lttv_traceset_get_cpuid_from_event(event
);
2371 process
= ts
->running_process
[cpu
];
2373 /* There can be no system call from PID 0 : unknown state */
2374 if (process
->pid
!= 0)
2375 pop_state(event
, ts
, LTTV_STATE_SYSCALL
);
2379 #ifdef BABEL_CLEANUP
2380 static gboolean
trap_entry(void *hook_data
, void *call_data
)
2382 LttvTracefileState
*s
= (LttvTracefileState
*)call_data
;
2383 LttvTraceState
*ts
= (LttvTraceState
*)s
->parent
.t_context
;
2384 LttEvent
*e
= ltt_tracefile_get_event(s
->parent
.tf
);
2385 LttvTraceHook
*th
= (LttvTraceHook
*)hook_data
;
2386 struct marker_field
*f
= lttv_trace_get_hook_field(th
, 0);
2387 LttvNameTables
*nt
= ((LttvTraceState
*)(s
->parent
.t_context
))->name_tables
;
2389 LttvExecutionSubmode submode
;
2391 guint64 trap
= ltt_event_get_long_unsigned(e
, f
);
2393 expand_trap_table(ts
, trap
);
2395 submode
= nt
->trap_names
[trap
];
2397 push_state(s
, LTTV_STATE_TRAP
, submode
);
2399 /* update cpu status */
2400 cpu_push_mode(s
->cpu_state
, LTTV_CPU_TRAP
);
2402 /* update trap status */
2403 g_array_append_val(s
->cpu_state
->trap_stack
, trap
);
2404 ts
->trap_states
[trap
].running
++;
2409 static gboolean
trap_exit(void *hook_data
, void *call_data
)
2411 LttvTracefileState
*s
= (LttvTracefileState
*)call_data
;
2412 LttvTraceState
*ts
= (LttvTraceState
*)s
->parent
.t_context
;
2414 pop_state(s
, LTTV_STATE_TRAP
);
2416 /* update cpu status */
2417 cpu_pop_mode(s
->cpu_state
);
2419 /* update trap status */
2420 if (s
->cpu_state
->trap_stack
->len
> 0) {
2421 gint last
= g_array_index(s
->cpu_state
->trap_stack
, gint
,
2422 s
->cpu_state
->trap_stack
->len
-1);
2423 if(ts
->trap_states
[last
].running
)
2424 ts
->trap_states
[last
].running
--;
2425 g_array_remove_index(s
->cpu_state
->trap_stack
,
2426 s
->cpu_state
->trap_stack
->len
-1);
2430 #endif /* BABEL_CLEANUP */
2432 static gboolean
irq_entry(void *hook_data
, void *call_data
)
2438 LttvExecutionSubmode submode
;
2442 event
= (LttvEvent
*) call_data
;
2443 if (strcmp(lttv_traceset_get_name_from_event(event
),
2444 "irq_handler_entry") != 0)
2447 cpu
= lttv_traceset_get_cpuid_from_event(event
);
2450 nt
= ts
->name_tables
;
2451 irq
= lttv_event_get_long(event
, "irq");
2453 expand_irq_table(ts
, irq
);
2455 submode
= nt
->irq_names
[irq
];
2457 /* Do something with the info about being in user or system mode when int? */
2458 push_state(event
, ts
, LTTV_STATE_IRQ
, submode
);
2460 /* update cpu status */
2461 cpu_push_mode(&(ts
->cpu_states
[cpu
]), LTTV_CPU_IRQ
);
2463 /* update irq status */
2464 g_array_append_val(ts
->cpu_states
[cpu
].irq_stack
, irq
);
2465 irq_push_mode(&ts
->irq_states
[irq
], LTTV_IRQ_BUSY
);
2470 static gboolean
soft_irq_exit(void *hook_data
, void *call_data
)
2476 LttvCPUState
*cpu_state
;
2478 event
= (LttvEvent
*) call_data
;
2479 if (strcmp(lttv_traceset_get_name_from_event(event
),
2480 "softirq_exit") != 0)
2483 cpu
= lttv_traceset_get_cpuid_from_event(event
);
2486 cpu_state
= &(ts
->cpu_states
[cpu
]);
2487 pop_state(event
, ts
, LTTV_STATE_SOFT_IRQ
);
2489 /* update cpu status */
2490 cpu_pop_mode(cpu_state
);
2492 /* update softirq status */
2493 if (cpu_state
->softirq_stack
->len
> 0) {
2494 gint last
= g_array_index(cpu_state
->softirq_stack
, gint
, cpu_state
->softirq_stack
->len
-1);
2495 if(ts
->soft_irq_states
[last
].running
)
2496 ts
->soft_irq_states
[last
].running
--;
2497 g_array_remove_index(cpu_state
->softirq_stack
, cpu_state
->softirq_stack
->len
-1);
2502 static gboolean
irq_exit(void *hook_data
, void *call_data
)
2508 LttvCPUState
*cpu_state
;
2510 event
= (LttvEvent
*) call_data
;
2511 if (strcmp(lttv_traceset_get_name_from_event(event
),
2512 "irq_handler_exit") != 0)
2515 cpu
= lttv_traceset_get_cpuid_from_event(event
);
2517 cpu_state
= &(ts
->cpu_states
[cpu
]);
2519 pop_state(event
, ts
, LTTV_STATE_IRQ
);
2521 /* update cpu status */
2522 cpu_pop_mode(cpu_state
);
2524 /* update irq status */
2525 if (cpu_state
->irq_stack
->len
> 0) {
2526 gint last
= g_array_index(cpu_state
->irq_stack
, gint
, cpu_state
->irq_stack
->len
-1);
2527 g_array_remove_index(cpu_state
->irq_stack
, cpu_state
->irq_stack
->len
-1);
2528 irq_pop_mode(&ts
->irq_states
[last
]);
2534 static gboolean
soft_irq_raise(void *hook_data
, void *call_data
)
2542 event
= (LttvEvent
*) call_data
;
2543 if (strcmp(lttv_traceset_get_name_from_event(event
),
2544 "softirq_raise") != 0)
2547 //cpu = lttv_traceset_get_cpuid_from_event(event);
2549 softirq
= lttv_event_get_long_unsigned(event
, "vec");
2551 expand_soft_irq_table(ts
, softirq
);
2553 /* update softirq status */
2554 /* a soft irq raises are not cumulative */
2555 ts
->soft_irq_states
[softirq
].pending
=1;
2560 static gboolean
soft_irq_entry(void *hook_data
, void *call_data
)
2565 LttvExecutionSubmode submode
;
2569 event
= (LttvEvent
*) call_data
;
2570 if (strcmp(lttv_traceset_get_name_from_event(event
),
2571 "softirq_entry") != 0)
2574 cpu
= lttv_traceset_get_cpuid_from_event(event
);
2580 softirq
= lttv_event_get_long_unsigned(event
, "vec");
2581 expand_soft_irq_table(ts
, softirq
);
2582 nt
= ts
->name_tables
;
2583 submode
= nt
->soft_irq_names
[softirq
];
2585 /* Do something with the info about being in user or system mode when int? */
2586 push_state(event
, ts
, LTTV_STATE_SOFT_IRQ
, submode
);
2588 /* update cpu status */
2589 cpu_push_mode(&(ts
->cpu_states
[cpu
]), LTTV_CPU_SOFT_IRQ
);
2591 /* update softirq status */
2592 g_array_append_val(ts
->cpu_states
[cpu
].softirq_stack
, softirq
);
2593 if (ts
->soft_irq_states
[softirq
].pending
)
2594 ts
->soft_irq_states
[softirq
].pending
--;
2595 ts
->soft_irq_states
[softirq
].running
++;
2600 static gboolean
enum_interrupt(void *hook_data
, void *call_data
)
2610 event
= (LttvEvent
*) call_data
;
2611 if (strcmp(lttv_traceset_get_name_from_event(event
),
2612 "lttng_statedump_interrupt") != 0)
2616 nt
= ts
->name_tables
;
2617 irq
= lttv_event_get_long_unsigned(event
, "irq");
2618 action
= g_quark_from_string(lttv_event_get_string(event
,
2620 expand_irq_table(ts
, irq
);
2621 nt
->irq_names
[irq
] = action
;
2626 #ifdef BABEL_CLEANUP
2627 static gboolean
bdev_request_issue(void *hook_data
, void *call_data
)
2638 event
= (LttvEvent
*) call_data
;
2639 if (strcmp(lttv_traceset_get_name_from_event(event
),
2640 "block_rq_issue") != 0)
2644 major
= lttv_event_get_long_unsigned(event
,);
2646 minor
= lttv_event_get_long_unsigned(event
,);
2648 oper
= lttv_event_get_long_unsigned(event
,);
2650 devcode
= MKDEV(major
,minor
);
2652 /* have we seen this block device before? */
2653 bdev
= get_hashed_bdevstate(ts
, devcode
);
2655 bdev_push_mode(bdev
, LTTV_BDEV_BUSY_READING
);
2657 bdev_push_mode(bdev
, LTTV_BDEV_BUSY_WRITING
);
2662 static gboolean
bdev_request_complete(void *hook_data
, void *call_data
)
2664 LttvTracefileState
*s
= (LttvTracefileState
*)call_data
;
2665 LttvTraceState
*ts
= (LttvTraceState
*)s
->parent
.t_context
;
2666 LttEvent
*e
= ltt_tracefile_get_event(s
->parent
.tf
);
2667 LttvTraceHook
*th
= (LttvTraceHook
*)hook_data
;
2669 guint major
= ltt_event_get_long_unsigned(e
,
2670 lttv_trace_get_hook_field(th
, 0));
2671 guint minor
= ltt_event_get_long_unsigned(e
,
2672 lttv_trace_get_hook_field(th
, 1));
2673 //guint oper = ltt_event_get_long_unsigned(e,
2674 // lttv_trace_get_hook_field(th, 2));
2675 guint32 devcode
= MKDEV(major
,minor
);
2677 /* have we seen this block device before? */
2678 gpointer bdev
= get_hashed_bdevstate(ts
, devcode
);
2680 /* update block device */
2681 bdev_pop_mode(bdev
);
2686 #ifdef BABEL_CLEANUP
2687 // We dont have the syscall table in LTTng 2.0
2688 static gboolean
dump_syscall(void *hook_data
, void *call_data
)
2690 LttvTracefileState
*s
= (LttvTracefileState
*)call_data
;
2691 LttvTraceState
*ts
= (LttvTraceState
*)s
->parent
.t_context
;
2692 LttvNameTables
*nt
= ts
->name_tables
;
2693 LttEvent
*e
= ltt_tracefile_get_event(s
->parent
.tf
);
2694 LttvTraceHook
*th
= (LttvTraceHook
*)hook_data
;
2698 id
= ltt_event_get_unsigned(e
, lttv_trace_get_hook_field(th
, 0));
2699 symbol
= ltt_event_get_string(e
, lttv_trace_get_hook_field(th
, 2));
2701 expand_syscall_table(ts
, id
);
2702 nt
->syscall_names
[id
] = g_quark_from_string(symbol
);
2707 static gboolean
dump_kprobe(void *hook_data
, void *call_data
)
2709 LttvTracefileState
*s
= (LttvTracefileState
*)call_data
;
2710 LttvTraceState
*ts
= (LttvTraceState
*)s
->parent
.t_context
;
2711 LttEvent
*e
= ltt_tracefile_get_event(s
->parent
.tf
);
2712 LttvTraceHook
*th
= (LttvTraceHook
*)hook_data
;
2716 ip
= ltt_event_get_long_unsigned(e
, lttv_trace_get_hook_field(th
, 0));
2717 symbol
= ltt_event_get_string(e
, lttv_trace_get_hook_field(th
, 1));
2719 expand_kprobe_table(ts
, ip
, symbol
);
2724 #ifdef BABEL_CLEANUP
2725 static gboolean
dump_softirq(void *hook_data
, void *call_data
)
2728 LttvTracefileState
*s
= (LttvTracefileState
*)call_data
;
2729 LttvTraceState
*ts
= (LttvTraceState
*)s
->parent
.t_context
;
2730 LttvNameTables
*nt
= ts
->name_tables
;
2731 LttEvent
*e
= ltt_tracefile_get_event(s
->parent
.tf
);
2732 LttvTraceHook
*th
= (LttvTraceHook
*)hook_data
;
2736 id
= ltt_event_get_unsigned(e
, lttv_trace_get_hook_field(th
, 0));
2737 symbol
= ltt_event_get_string(e
, lttv_trace_get_hook_field(th
, 2));
2739 expand_soft_irq_table(ts
, id
);
2740 nt
->soft_irq_names
[id
] = g_quark_from_string(symbol
);
2746 static gboolean
sched_try_wakeup(void *hook_data
, void *call_data
)
2750 LttvProcessState
*process
;
2755 event
= (LttvEvent
*) call_data
;
2756 if (strcmp(lttv_traceset_get_name_from_event(event
),
2757 "sched_wakeup") != 0)
2762 woken_pid
= lttv_event_get_long(event
, "tid");
2763 woken_cpu
= lttv_event_get_long(event
, "target_cpu");
2765 timestamp
= lttv_event_get_timestamp(event
);
2766 process
= lttv_state_find_process_or_create(
2768 woken_cpu
, woken_pid
,
2771 if (process
->state
->s
== LTTV_STATE_WAIT
|| process
->state
->s
== LTTV_STATE_WAIT_FORK
)
2773 process
->state
->s
= LTTV_STATE_WAIT_CPU
;
2774 process
->state
->change
= timestamp
;
2777 g_debug("Wakeup: process %d on CPU %u\n", woken_pid
, woken_cpu
);
2782 static gboolean
schedchange(void *hook_data
, void *call_data
)
2787 LttvProcessState
*process
;
2790 //LttvProcessState *old_process = ts->running_process[cpu];
2792 guint pid_in
, pid_out
;
2794 //TODO ybrosseau 2012-07-13: manage this 20 in a constact or dynamically
2797 event
= (LttvEvent
*) call_data
;
2798 if (strcmp(lttv_traceset_get_name_from_event(event
),
2799 "sched_switch") != 0)
2802 cpu
= lttv_traceset_get_cpuid_from_event(event
);
2804 process
= ts
->running_process
[cpu
];
2805 pid_out
= lttv_event_get_long(event
, "prev_tid");
2806 pid_in
= lttv_event_get_long(event
, "next_tid");
2807 state_out
= lttv_event_get_long(event
, "prev_state");
2809 strncpy(next_comm
, lttv_event_get_string(event
, "next_comm"), 20);
2810 next_comm
[20-1] = '\0';
2812 timestamp
= lttv_event_get_timestamp(event
);
2814 if(likely(process
!= NULL
)) {
2816 /* We could not know but it was not the idle process executing.
2817 This should only happen at the beginning, before the first schedule
2818 event, and when the initial information (current process for each CPU)
2819 is missing. It is not obvious how we could, after the fact, compensate
2820 the wrongly attributed statistics. */
2822 //This test only makes sense once the state is known and if there is no
2823 //missing events. We need to silently ignore schedchange coming after a
2824 //process_free, or it causes glitches. (FIXME)
2825 //if(unlikely(process->pid != pid_out)) {
2826 // g_assert(process->pid == 0);
2828 if(process
->pid
== 0
2829 && process
->state
->t
== LTTV_STATE_MODE_UNKNOWN
) {
2832 * Scheduling out of pid 0 at beginning of the trace.
2833 * We are typically in system call mode at this point although
2834 * (FIXME) we might be in a trap handler.
2836 g_assert(process
->execution_stack
->len
== 1);
2837 process
->state
->t
= LTTV_STATE_SYSCALL
;
2838 process
->state
->s
= LTTV_STATE_WAIT
;
2839 process
->state
->change
= timestamp
;
2840 process
->state
->entry
= timestamp
;
2843 if(unlikely(process
->state
->s
== LTTV_STATE_EXIT
)) {
2844 process
->state
->s
= LTTV_STATE_ZOMBIE
;
2845 process
->state
->change
= timestamp
;
2847 if(unlikely(state_out
== 0)) process
->state
->s
= LTTV_STATE_WAIT_CPU
;
2848 else process
->state
->s
= LTTV_STATE_WAIT
;
2849 process
->state
->change
= timestamp
;
2852 if(state_out
== 32 || state_out
== 64) { /* EXIT_DEAD || TASK_DEAD */
2853 /* see sched.h for states */
2854 if (!exit_process(event
, process
)) {
2855 process
->state
->s
= LTTV_STATE_DEAD
;
2856 process
->state
->change
= timestamp
;
2861 process
= ts
->running_process
[cpu
] = lttv_state_find_process_or_create(
2865 process
->state
->s
= LTTV_STATE_RUN
;
2867 // process->last_cpu_index = ltt_tracefile_num(((LttvTracefileContext*)s)->tf);
2868 process
->state
->change
= timestamp
;
2869 process
->name
= g_quark_from_string(next_comm
);
2871 /* update cpu status */
2873 /* going to idle task */
2874 cpu_set_base_mode(&(ts
->cpu_states
[cpu
]), LTTV_CPU_IDLE
);
2876 /* scheduling a real task.
2877 * we must be careful here:
2878 * if we just schedule()'ed to a process that is
2879 * in a trap, we must put the cpu in trap mode
2881 cpu_set_base_mode(&(ts
->cpu_states
[cpu
]), LTTV_CPU_BUSY
);
2882 if(process
->state
->t
== LTTV_STATE_TRAP
)
2883 cpu_push_mode(&(ts
->cpu_states
[cpu
]), LTTV_CPU_TRAP
);
2889 static gboolean
process_fork(void *hook_data
, void *call_data
)
2893 LttvProcessState
*process
;
2894 LttvProcessState
*child_process
;
2895 guint child_pid
; /* In the Linux Kernel, there is one PID per thread. */
2896 guint child_tgid
; /* tgid in the Linux kernel is the "real" POSIX PID. */
2897 //LttvProcessState *zombie_process;
2901 event
= (LttvEvent
*) call_data
;
2902 if (strcmp(lttv_traceset_get_name_from_event(event
),
2903 "sched_process_fork") != 0)
2905 cpu
= lttv_traceset_get_cpuid_from_event(event
);
2907 process
= ts
->running_process
[cpu
];
2908 timestamp
= lttv_event_get_timestamp(event
);
2910 /* Skip Parent PID param */
2913 child_pid
= lttv_event_get_long(event
, "child_tid");
2914 //ts->target_pid = child_pid;
2920 /* Mathieu : it seems like the process might have been scheduled in before the
2921 * fork, and, in a rare case, might be the current process. This might happen
2922 * in a SMP case where we don't have enough precision on the clocks.
2924 * Test reenabled after precision fixes on time. (Mathieu) */
2926 zombie_process
= lttv_state_find_process(ts
, ANY_CPU
, child_pid
);
2928 if(unlikely(zombie_process
!= NULL
)) {
2929 /* Reutilisation of PID. Only now we are sure that the old PID
2930 * has been released. FIXME : should know when release_task happens instead.
2932 guint num_cpus
= ltt_trace_get_num_cpu(ts
->parent
.t
);
2934 for(i
=0; i
< num_cpus
; i
++) {
2935 g_assert(zombie_process
!= ts
->running_process
[i
]);
2938 exit_process(s
, zombie_process
);
2941 g_assert(process
->pid
!= child_pid
);
2942 // FIXME : Add this test in the "known state" section
2943 // g_assert(process->pid == parent_pid);
2944 child_process
= lttv_state_find_process(ts
, ANY_CPU
, child_pid
);
2945 if(child_process
== NULL
) {
2946 child_process
= lttv_state_create_process(ts
, process
, cpu
,
2947 child_pid
, child_tgid
,
2948 LTTV_STATE_UNNAMED
, ×tamp
);
2950 /* The process has already been created : due to time imprecision between
2951 * multiple CPUs : it has been scheduled in before creation. Note that we
2952 * shouldn't have this kind of imprecision.
2954 * Simply put a correct parent.
2956 g_error("Process %u has been created at [%lu.%09lu] "
2957 "and inserted at [%lu.%09lu] before \n"
2958 "fork on cpu %u[%lu.%09lu].\n"
2959 "Probably an unsynchronized TSC problem on the traced machine.",
2961 child_process
->creation_time
.tv_sec
,
2962 child_process
->creation_time
.tv_nsec
,
2963 child_process
->insertion_time
.tv_sec
,
2964 child_process
->insertion_time
.tv_nsec
,
2965 cpu
, timestamp
.tv_sec
, timestamp
.tv_nsec
);
2966 //g_assert(0); /* This is a problematic case : the process has been created
2967 // before the fork event */
2968 child_process
->ppid
= process
->pid
;
2969 child_process
->tgid
= child_tgid
;
2971 g_assert(child_process
->name
== LTTV_STATE_UNNAMED
);
2972 child_process
->name
= process
->name
;
2973 child_process
->brand
= process
->brand
;
2978 #ifdef BABEL_CLEANUP
2979 //NO KTHREAD_CREATE in LTTng 2.0
2980 /* We stamp a newly created process as kernel_thread.
2981 * The thread should not be running yet. */
2982 static gboolean
process_kernel_thread(void *hook_data
, void *call_data
)
2984 LttvTracefileState
*s
= (LttvTracefileState
*)call_data
;
2985 LttEvent
*e
= ltt_tracefile_get_event(s
->parent
.tf
);
2986 LttvTraceHook
*th
= (LttvTraceHook
*)hook_data
;
2988 LttvTraceState
*ts
= (LttvTraceState
*)s
->parent
.t_context
;
2989 LttvProcessState
*process
;
2990 LttvExecutionState
*es
;
2993 pid
= (guint
)ltt_event_get_long_unsigned(e
, lttv_trace_get_hook_field(th
, 0));
2994 //s->parent.target_pid = pid;
2996 process
= lttv_state_find_process_or_create(ts
, ANY_CPU
, pid
,
2998 if (process
->state
->s
!= LTTV_STATE_DEAD
) {
2999 process
->execution_stack
=
3000 g_array_set_size(process
->execution_stack
, 1);
3001 es
= process
->state
=
3002 &g_array_index(process
->execution_stack
, LttvExecutionState
, 0);
3003 es
->t
= LTTV_STATE_SYSCALL
;
3005 process
->type
= LTTV_STATE_KERNEL_THREAD
;
3010 static gboolean
process_exit(void *hook_data
, void *call_data
)
3016 LttvProcessState
*process
; // = ts->running_process[cpu];
3018 event
= (LttvEvent
*) call_data
;
3019 if (strcmp(lttv_traceset_get_name_from_event(event
),
3020 "sched_process_exit") != 0)
3022 cpu
= lttv_traceset_get_cpuid_from_event(event
);
3024 process
= ts
->running_process
[cpu
];
3026 pid
= lttv_event_get_long(event
, "tid");
3027 //s->parent.target_pid = pid;
3029 // FIXME : Add this test in the "known state" section
3030 // g_assert(process->pid == pid);
3032 process
= lttv_state_find_process(ts
, ANY_CPU
, pid
);
3033 if(likely(process
!= NULL
)) {
3034 process
->state
->s
= LTTV_STATE_EXIT
;
3039 static gboolean
process_free(void *hook_data
, void *call_data
)
3045 LttvProcessState
*process
;
3047 event
= (LttvEvent
*) call_data
;
3048 if (strcmp(lttv_traceset_get_name_from_event(event
),
3049 "sched_process_free") != 0)
3051 cpu
= lttv_traceset_get_cpuid_from_event(event
);
3053 process
= ts
->running_process
[cpu
];
3055 /* PID of the process to release */
3056 release_pid
= lttv_event_get_long(event
, "_tid");
3057 //s->parent.target_pid = release_pid;
3059 g_assert(release_pid
!= 0);
3061 process
= lttv_state_find_process(ts
, ANY_CPU
, release_pid
);
3062 if(likely(process
!= NULL
))
3063 exit_process(event
, process
);
3067 if(likely(process
!= NULL
)) {
3068 /* release_task is happening at kernel level : we can now safely release
3069 * the data structure of the process */
3070 //This test is fun, though, as it may happen that
3071 //at time t : CPU 0 : process_free
3072 //at time t+150ns : CPU 1 : schedule out
3073 //Clearly due to time imprecision, we disable it. (Mathieu)
3074 //If this weird case happen, we have no choice but to put the
3075 //Currently running process on the cpu to 0.
3076 //I re-enable it following time precision fixes. (Mathieu)
3077 //Well, in the case where an process is freed by a process on another CPU
3078 //and still scheduled, it happens that this is the schedchange that will
3079 //drop the last reference count. Do not free it here!
3080 guint num_cpus
= ltt_trace_get_num_cpu(ts
->parent
.t
);
3082 for(i
=0; i
< num_cpus
; i
++) {
3083 //g_assert(process != ts->running_process[i]);
3084 if(process
== ts
->running_process
[i
]) {
3085 //ts->running_process[i] = lttv_state_find_process(ts, i, 0);
3089 if(i
== num_cpus
) /* process is not scheduled */
3090 exit_process(s
, process
);
3098 static gboolean
process_exec(void *hook_data
, void *call_data
)
3104 LttvProcessState
*process
;
3106 event
= (LttvEvent
*) call_data
;
3107 if (strcmp(lttv_traceset_get_name_from_event(event
),
3110 cpu
= lttv_traceset_get_cpuid_from_event(event
);
3112 process
= ts
->running_process
[cpu
];
3114 #if 0//how to use a sequence that must be transformed in a string
3115 /* PID of the process to release */
3116 guint64 name_len
= ltt_event_field_element_number(e
,
3117 lttv_trace_get_hook_field(th
, 0));
3118 //name = ltt_event_get_string(e, lttv_trace_get_hook_field(th, 0));
3119 LttField
*child
= ltt_event_field_element_select(e
,
3120 lttv_trace_get_hook_field(th
, 0), 0);
3122 (gchar
*)(ltt_event_data(e
)+ltt_event_field_offset(e
, child
));
3123 gchar
*null_term_name
= g_new(gchar
, name_len
+1);
3124 memcpy(null_term_name
, name_begin
, name_len
);
3125 null_term_name
[name_len
] = '\0';
3126 process
->name
= g_quark_from_string(null_term_name
);
3129 process
->name
= g_quark_from_string(lttv_event_get_string(event
,
3131 process
->brand
= LTTV_STATE_UNBRANDED
;
3132 //g_free(null_term_name);
3135 #ifdef BABEL_CLEANUP
3136 static gboolean
thread_brand(void *hook_data
, void *call_data
)
3138 LttvTracefileState
*s
= (LttvTracefileState
*)call_data
;
3139 LttvTraceState
*ts
= (LttvTraceState
*)s
->parent
.t_context
;
3140 LttEvent
*e
= ltt_tracefile_get_event(s
->parent
.tf
);
3141 LttvTraceHook
*th
= (LttvTraceHook
*)hook_data
;
3144 LttvProcessState
*process
= ts
->running_process
[cpu
];
3146 name
= ltt_event_get_string(e
, lttv_trace_get_hook_field(th
, 0));
3147 process
->brand
= g_quark_from_string(name
);
3153 // TODO We only have sys_open, without the FD
3154 // manage to do somehting better
3155 static gboolean
fs_open(void *hook_data
, void *call_data
)
3157 LttvTracefileState
*s
= (LttvTracefileState
*)call_data
;
3158 LttvTraceState
*ts
= (LttvTraceState
*)s
->parent
.t_context
;
3159 LttEvent
*e
= ltt_tracefile_get_event(s
->parent
.tf
);
3160 LttvTraceHook
*th
= (LttvTraceHook
*)hook_data
;
3161 struct marker_field
*f
;
3165 LttvProcessState
*process
= ts
->running_process
[cpu
];
3167 f
= lttv_trace_get_hook_field(th
, 0);
3168 fd
= ltt_event_get_int(e
, f
);
3170 f
= lttv_trace_get_hook_field(th
, 1);
3171 filename
= ltt_event_get_string(e
, f
);
3173 g_hash_table_insert(process
->fds
, (gpointer
)(long)fd
,
3174 (gpointer
)(unsigned long)g_quark_from_string(filename
));
3179 static void print_stack(LttvProcessState
*process
)
3181 LttvExecutionState
*es
;
3184 g_debug("Execution stack for process %u %s:\n",
3185 process
->pid
, g_quark_to_string(process
->name
));
3187 for (i
= 0; i
< process
->execution_stack
->len
; i
++) {
3188 es
= &g_array_index(process
->execution_stack
,
3189 LttvExecutionState
, i
);
3190 g_debug("Depth %d mode %s submode %s status %s\n",
3191 i
, g_quark_to_string(es
->t
),
3192 g_quark_to_string(es
->n
),
3193 g_quark_to_string(es
->s
));
3198 static void fix_process(gpointer key
, gpointer value
, gpointer user_data
)
3200 LttvProcessState
*process
;
3201 LttvExecutionState
*es
;
3202 process
= (LttvProcessState
*)value
;
3203 LttTime
*timestamp
= (LttTime
*)user_data
;
3205 print_stack(process
);
3207 if(process
->type
== LTTV_STATE_KERNEL_THREAD
) {
3208 es
= &g_array_index(process
->execution_stack
, LttvExecutionState
, 0);
3209 if(es
->t
== LTTV_STATE_MAYBE_SYSCALL
) {
3210 es
->t
= LTTV_STATE_SYSCALL
;
3211 es
->n
= LTTV_STATE_SUBMODE_NONE
;
3212 es
->entry
= *timestamp
;
3213 es
->change
= *timestamp
;
3214 es
->cum_cpu_time
= ltt_time_zero
;
3215 if(es
->s
== LTTV_STATE_UNNAMED
)
3216 es
->s
= LTTV_STATE_WAIT
;
3219 es
= &g_array_index(process
->execution_stack
, LttvExecutionState
, 0);
3220 if(es
->t
== LTTV_STATE_MAYBE_USER_MODE
) {
3221 es
->t
= LTTV_STATE_USER_MODE
;
3222 es
->n
= LTTV_STATE_SUBMODE_NONE
;
3223 es
->entry
= *timestamp
;
3224 //g_assert(timestamp->tv_sec != 0);
3225 es
->change
= *timestamp
;
3226 es
->cum_cpu_time
= ltt_time_zero
;
3227 if(es
->s
== LTTV_STATE_UNNAMED
)
3228 es
->s
= LTTV_STATE_RUN
;
3230 if(process
->execution_stack
->len
== 1) {
3231 /* Still in bottom unknown mode, means we either:
3232 * - never did a system call
3233 * - are scheduled out from user mode.
3234 * May be either in user mode, syscall mode, running or waiting.*/
3235 /* CHECK : we may be tagging syscall mode when being user mode
3236 * (should be fixed now) */
3237 if (es
->s
== LTTV_STATE_WAIT_CPU
) {
3238 /* nothing to do: scheduled out from userspace */
3240 process
->execution_stack
=
3241 g_array_set_size(process
->execution_stack
, 2);
3242 es
= process
->state
= &g_array_index(process
->execution_stack
,
3243 LttvExecutionState
, 1);
3244 es
->t
= LTTV_STATE_SYSCALL
;
3245 es
->n
= LTTV_STATE_SUBMODE_NONE
;
3246 es
->entry
= *timestamp
;
3247 //g_assert(timestamp->tv_sec != 0);
3248 es
->change
= *timestamp
;
3249 es
->cum_cpu_time
= ltt_time_zero
;
3250 if(es
->s
== LTTV_STATE_WAIT_FORK
)
3251 es
->s
= LTTV_STATE_WAIT
;
3258 static gboolean
statedump_end(void *hook_data
, void *call_data
)
3263 //LttEvent *e = ltt_tracefile_get_event(s->parent.tf);
3264 //LttvTraceHook *th = (LttvTraceHook *)hook_data;
3265 event
= (LttvEvent
*) call_data
;
3266 if (strcmp(lttv_traceset_get_name_from_event(event
),
3267 "lttng_statedump_end") != 0)
3271 timestamp
= lttv_event_get_timestamp(event
);
3273 /* For all processes */
3274 /* if kernel thread, if stack[0] is unknown, set to syscall mode, wait */
3275 /* else, if stack[0] is unknown, set to user mode, running */
3277 g_hash_table_foreach(ts
->processes
, fix_process
, ×tamp
);
3282 static gboolean
enum_process_state(void *hook_data
, void *call_data
)
3292 LttvProcessState
*parent_process
;
3293 LttvProcessState
*process
;
3296 LttvExecutionState
*es
;
3299 event
= (LttvEvent
*) call_data
;
3300 if (strcmp(lttv_traceset_get_name_from_event(event
),
3301 "lttng_statedump_process_state") != 0)
3303 cpu
= lttv_traceset_get_cpuid_from_event(event
);
3305 process
= ts
->running_process
[cpu
];
3306 timestamp
= lttv_event_get_timestamp(event
);
3309 pid
= lttv_event_get_long(event
, "tid");
3310 //s->parent.target_pid = pid;
3313 parent_pid
= lttv_event_get_long(event
, "ppid");
3316 command
= lttv_event_get_string(event
, "name");
3320 type
= lttv_event_get_long(event
, "type");
3322 //FIXME: type is rarely used, enum must match possible types.
3324 /* Skip mode 4th param */
3326 /* Skip submode 5th param */
3328 /* Skip status 6th param */
3330 tgid
= lttv_event_get_long(event
, "pid");
3333 nb_cpus
= lttv_trace_get_num_cpu(ts
->trace
);
3334 for(i
=0; i
<nb_cpus
; i
++) {
3335 process
= lttv_state_find_process(ts
, i
, pid
);
3336 g_assert(process
!= NULL
);
3338 process
->ppid
= parent_pid
;
3339 process
->tgid
= tgid
;
3340 process
->name
= g_quark_from_string(command
);
3341 es
= &g_array_index(process
->execution_stack
, LttvExecutionState
, 0);
3342 process
->type
= LTTV_STATE_KERNEL_THREAD
;
3346 /* The process might exist if a process was forked while performing the
3348 process
= lttv_state_find_process(ts
, ANY_CPU
, pid
);
3349 if(process
== NULL
) {
3350 parent_process
= lttv_state_find_process(ts
, ANY_CPU
, parent_pid
);
3351 process
= lttv_state_create_process(ts
, parent_process
, cpu
,
3352 pid
, tgid
, g_quark_from_string(command
),
3355 /* Keep the stack bottom : a running user mode */
3356 /* Disabled because of inconsistencies in the current statedump states. */
3357 //if(type == LTTV_STATE_KERNEL_THREAD) {
3359 /* Only keep the bottom
3360 * FIXME Kernel thread : can be in syscall or interrupt or trap. */
3361 /* Will cause expected trap when in fact being syscall (even after end of
3363 * Will cause expected interrupt when being syscall. (only before end of
3364 * statedump event) */
3365 // This will cause a "popping last state on stack, ignoring it."
3366 process
->execution_stack
= g_array_set_size(process
->execution_stack
, 1);
3367 es
= process
->state
= &g_array_index(process
->execution_stack
,
3368 LttvExecutionState
, 0);
3369 process
->type
= LTTV_STATE_KERNEL_THREAD
;
3370 es
->t
= LTTV_STATE_MAYBE_SYSCALL
;
3371 es
->s
= LTTV_STATE_UNNAMED
;
3372 es
->n
= LTTV_STATE_SUBMODE_UNKNOWN
;
3376 /* User space process :
3377 * bottom : user mode
3378 * either currently running or scheduled out.
3379 * can be scheduled out because interrupted in (user mode or in syscall)
3380 * or because of an explicit call to the scheduler in syscall. Note that
3381 * the scheduler call comes after the irq_exit, so never in interrupt
3383 // temp workaround : set size to 1 : only have user mode bottom of stack.
3384 // will cause g_info message of expected syscall mode when in fact being
3385 // in user mode. Can also cause expected trap when in fact being user
3386 // mode in the event of a page fault reenabling interrupts in the handler.
3387 // Expected syscall and trap can also happen after the end of statedump
3388 // This will cause a "popping last state on stack, ignoring it."
3389 process
->execution_stack
= g_array_set_size(process
->execution_stack
, 1);
3390 es
= process
->state
= &g_array_index(process
->execution_stack
,
3391 LttvExecutionState
, 0);
3392 es
->t
= LTTV_STATE_MAYBE_USER_MODE
;
3393 es
->s
= LTTV_STATE_UNNAMED
;
3394 es
->n
= LTTV_STATE_SUBMODE_UNKNOWN
;
3401 es
= process
->state
= &g_array_index(process
->execution_stack
,
3402 LttvExecutionState
, 1);
3403 es
->t
= LTTV_STATE_MODE_UNKNOWN
;
3404 es
->s
= LTTV_STATE_UNNAMED
;
3405 es
->n
= LTTV_STATE_SUBMODE_UNKNOWN
;
3409 /* The process has already been created :
3410 * Probably was forked while dumping the process state or
3411 * was simply scheduled in prior to get the state dump event.
3413 process
->ppid
= parent_pid
;
3414 process
->tgid
= tgid
;
3415 process
->name
= g_quark_from_string(command
);
3416 process
->type
= type
;
3417 es
= &g_array_index(process
->execution_stack
, LttvExecutionState
, 0);
3419 if(es
->t
== LTTV_STATE_MODE_UNKNOWN
) {
3420 if(type
== LTTV_STATE_KERNEL_THREAD
)
3421 es
->t
= LTTV_STATE_SYSCALL
;
3423 es
->t
= LTTV_STATE_USER_MODE
;
3426 /* Don't mess around with the stack, it will eventually become
3427 * ok after the end of state dump. */
3436 gint
lttv_state_hook_add_event_hooks(void *hook_data
, void *call_data
)
3438 LttvTraceset
*traceset
= (LttvTraceset
*)(call_data
);
3440 lttv_state_add_event_hooks(traceset
);
3445 void lttv_state_add_event_hooks(LttvTraceset
*traceset
)
3449 LttvAttributeValue value
;
3450 LttvHooks
*event_hook
;
3451 #ifdef BABEL_CLEANUP
3452 LttvIAttribute
*attributes
= LTTV_IATTRIBUTE(lttv_global_attributes());
3453 result
= lttv_iattribute_find_by_path(attributes
, "hooks/event",
3454 LTTV_POINTER
, &value
);
3456 event_hook
= *(value
.v_pointer
);
3458 //TODO ybrosseau 2012-07-12: Validate that using traceset hooks instead of the global one is valid
3459 //Use traceset hooks
3460 event_hook
= lttv_traceset_get_hooks(traceset
);
3461 g_assert(event_hook
);
3463 lttv_hooks_add(event_hook
,syscall_entry
, NULL
, LTTV_PRIO_STATE
);
3464 lttv_hooks_add(event_hook
,syscall_exit
, NULL
, LTTV_PRIO_STATE
);
3465 lttv_hooks_add(event_hook
,irq_entry
, NULL
, LTTV_PRIO_STATE
);
3466 lttv_hooks_add(event_hook
,irq_exit
, NULL
, LTTV_PRIO_STATE
);
3467 lttv_hooks_add(event_hook
,soft_irq_raise
, NULL
, LTTV_PRIO_STATE
);
3468 lttv_hooks_add(event_hook
,soft_irq_entry
, NULL
, LTTV_PRIO_STATE
);
3469 lttv_hooks_add(event_hook
,soft_irq_exit
, NULL
, LTTV_PRIO_STATE
);
3470 lttv_hooks_add(event_hook
,schedchange
, NULL
, LTTV_PRIO_STATE
);
3471 lttv_hooks_add(event_hook
,sched_try_wakeup
, NULL
, LTTV_PRIO_STATE
);
3472 lttv_hooks_add(event_hook
,process_exit
, NULL
, LTTV_PRIO_STATE
);
3473 lttv_hooks_add(event_hook
,process_free
, NULL
, LTTV_PRIO_STATE
);
3474 lttv_hooks_add(event_hook
,process_fork
, NULL
, LTTV_PRIO_STATE
);
3475 lttv_hooks_add(event_hook
,process_exec
, NULL
, LTTV_PRIO_STATE
);
3476 lttv_hooks_add(event_hook
,enum_process_state
, NULL
, LTTV_PRIO_STATE
);
3477 lttv_hooks_add(event_hook
,statedump_end
, NULL
, LTTV_PRIO_STATE
);
3478 lttv_hooks_add(event_hook
,enum_interrupt
, NULL
, LTTV_PRIO_STATE
);
3480 #ifdef BABEL_CLEANUP //For the whole function this time
3481 guint i
, j
, k
, nb_trace
;
3484 // LttvTraceHook *th;
3485 LttvAttributeValue val
;
3487 nb_trace
= lttv_traceset_number(traceset
);
3488 for (i
= 0 ; i
< nb_trace
; i
++) {
3489 ts
= lttv_traceset_get(traceset
, i
)-;
3491 /* Find the eventtype id for the following events and register the
3492 associated by id hooks. */
3494 hooks
= g_array_sized_new(FALSE
, FALSE
, sizeof(LttvTraceHook
), 20);
3495 //hooks = g_array_set_size(hooks, 19); // Max possible number of hooks.
3498 lttv_trace_find_hook(tss
->parent
.t
,
3500 LTT_EVENT_SYSCALL_ENTRY
,
3501 FIELD_ARRAY(LTT_FIELD_SYSCALL_ID
),
3502 syscall_entry
, NULL
, &hooks
);
3504 lttv_trace_find_hook(ts
->parent
.t
,
3506 LTT_EVENT_SYSCALL_EXIT
,
3508 syscall_exit
, NULL
, &hooks
);
3510 #ifdef BABEL_CLEANUP
3511 lttv_trace_find_hook(ts
->parent
.t
,
3513 LTT_EVENT_TRAP_ENTRY
,
3514 FIELD_ARRAY(LTT_FIELD_TRAP_ID
),
3515 trap_entry
, NULL
, &hooks
);
3517 lttv_trace_find_hook(ts
->parent
.t
,
3519 LTT_EVENT_TRAP_EXIT
,
3521 trap_exit
, NULL
, &hooks
);
3522 #endif /* BABEL_CLEANUP */
3524 lttv_trace_find_hook(ts
->parent
.t
,
3526 LTT_EVENT_PAGE_FAULT_ENTRY
,
3527 FIELD_ARRAY(LTT_FIELD_TRAP_ID
),
3528 trap_entry
, NULL
, &hooks
);
3530 lttv_trace_find_hook(ts
->parent
.t
,
3532 LTT_EVENT_PAGE_FAULT_EXIT
,
3534 trap_exit
, NULL
, &hooks
);
3536 #ifdef BABEL_CLEANUP
3537 lttv_trace_find_hook(ts
->parent
.t
,
3539 LTT_EVENT_PAGE_FAULT_NOSEM_ENTRY
,
3540 FIELD_ARRAY(LTT_FIELD_TRAP_ID
),
3541 trap_entry
, NULL
, &hooks
);
3543 lttv_trace_find_hook(ts
->parent
.t
,
3545 LTT_EVENT_PAGE_FAULT_NOSEM_EXIT
,
3547 trap_exit
, NULL
, &hooks
);
3548 #endif /* BABEL_CLEANUP */
3550 lttv_trace_find_hook(ts
->parent
.t
,
3552 LTT_EVENT_IRQ_ENTRY
,
3553 FIELD_ARRAY(LTT_FIELD_IRQ_ID
),
3554 irq_entry
, NULL
, &hooks
);
3556 lttv_trace_find_hook(ts
->parent
.t
,
3560 irq_exit
, NULL
, &hooks
);
3562 lttv_trace_find_hook(ts
->parent
.t
,
3564 LTT_EVENT_SOFT_IRQ_RAISE
,
3565 FIELD_ARRAY(LTT_FIELD_SOFT_IRQ_ID
),
3566 soft_irq_raise
, NULL
, &hooks
);
3568 lttv_trace_find_hook(ts
->parent
.t
,
3570 LTT_EVENT_SOFT_IRQ_ENTRY
,
3571 FIELD_ARRAY(LTT_FIELD_SOFT_IRQ_ID
),
3572 soft_irq_entry
, NULL
, &hooks
);
3574 lttv_trace_find_hook(ts
->parent
.t
,
3576 LTT_EVENT_SOFT_IRQ_EXIT
,
3578 soft_irq_exit
, NULL
, &hooks
);
3580 lttv_trace_find_hook(ts
->parent
.t
,
3582 LTT_EVENT_SCHED_SCHEDULE
,
3583 FIELD_ARRAY(LTT_FIELD_PREV_PID
, LTT_FIELD_NEXT_PID
,
3584 LTT_FIELD_PREV_STATE
),
3585 schedchange
, NULL
, &hooks
);
3587 lttv_trace_find_hook(ts
->parent
.t
,
3589 LTT_EVENT_SCHED_TRY_WAKEUP
,
3590 FIELD_ARRAY(LTT_FIELD_PID
, LTT_FIELD_CPU_ID
, LTT_FIELD_STATE
),
3591 sched_try_wakeup
, NULL
, &hooks
);
3593 lttv_trace_find_hook(ts
->parent
.t
,
3595 LTT_EVENT_PROCESS_FORK
,
3596 FIELD_ARRAY(LTT_FIELD_PARENT_PID
, LTT_FIELD_CHILD_PID
,
3597 LTT_FIELD_CHILD_TGID
),
3598 process_fork
, NULL
, &hooks
);
3600 lttv_trace_find_hook(ts
->parent
.t
,
3602 LTT_EVENT_KTHREAD_CREATE
,
3603 FIELD_ARRAY(LTT_FIELD_PID
),
3604 process_kernel_thread
, NULL
, &hooks
);
3606 lttv_trace_find_hook(ts
->parent
.t
,
3608 LTT_EVENT_PROCESS_EXIT
,
3609 FIELD_ARRAY(LTT_FIELD_PID
),
3610 process_exit
, NULL
, &hooks
);
3612 lttv_trace_find_hook(ts
->parent
.t
,
3614 LTT_EVENT_PROCESS_FREE
,
3615 FIELD_ARRAY(LTT_FIELD_PID
),
3616 process_free
, NULL
, &hooks
);
3618 lttv_trace_find_hook(ts
->parent
.t
,
3621 FIELD_ARRAY(LTT_FIELD_FILENAME
),
3622 process_exec
, NULL
, &hooks
);
3624 lttv_trace_find_hook(ts
->parent
.t
,
3625 LTT_CHANNEL_USERSPACE
,
3626 LTT_EVENT_THREAD_BRAND
,
3627 FIELD_ARRAY(LTT_FIELD_NAME
),
3628 thread_brand
, NULL
, &hooks
);
3630 /* statedump-related hooks */
3631 lttv_trace_find_hook(ts
->parent
.t
,
3632 LTT_CHANNEL_TASK_STATE
,
3633 LTT_EVENT_PROCESS_STATE
,
3634 FIELD_ARRAY(LTT_FIELD_PID
, LTT_FIELD_PARENT_PID
, LTT_FIELD_NAME
,
3635 LTT_FIELD_TYPE
, LTT_FIELD_MODE
, LTT_FIELD_SUBMODE
,
3636 LTT_FIELD_STATUS
, LTT_FIELD_TGID
),
3637 enum_process_state
, NULL
, &hooks
);
3639 lttv_trace_find_hook(ts
->parent
.t
,
3640 LTT_CHANNEL_GLOBAL_STATE
,
3641 LTT_EVENT_STATEDUMP_END
,
3643 statedump_end
, NULL
, &hooks
);
3645 lttv_trace_find_hook(ts
->parent
.t
,
3646 LTT_CHANNEL_IRQ_STATE
,
3647 LTT_EVENT_LIST_INTERRUPT
,
3648 FIELD_ARRAY(LTT_FIELD_ACTION
, LTT_FIELD_IRQ_ID
),
3649 enum_interrupt
, NULL
, &hooks
);
3651 lttv_trace_find_hook(ts
->parent
.t
,
3653 LTT_EVENT_REQUEST_ISSUE
,
3654 FIELD_ARRAY(LTT_FIELD_MAJOR
, LTT_FIELD_MINOR
, LTT_FIELD_OPERATION
),
3655 bdev_request_issue
, NULL
, &hooks
);
3657 lttv_trace_find_hook(ts
->parent
.t
,
3659 LTT_EVENT_REQUEST_COMPLETE
,
3660 FIELD_ARRAY(LTT_FIELD_MAJOR
, LTT_FIELD_MINOR
, LTT_FIELD_OPERATION
),
3661 bdev_request_complete
, NULL
, &hooks
);
3663 lttv_trace_find_hook(ts
->parent
.t
,
3664 LTT_CHANNEL_USERSPACE
,
3665 LTT_EVENT_FUNCTION_ENTRY
,
3666 FIELD_ARRAY(LTT_FIELD_THIS_FN
, LTT_FIELD_CALL_SITE
),
3667 function_entry
, NULL
, &hooks
);
3669 lttv_trace_find_hook(ts
->parent
.t
,
3670 LTT_CHANNEL_USERSPACE
,
3671 LTT_EVENT_FUNCTION_EXIT
,
3672 FIELD_ARRAY(LTT_FIELD_THIS_FN
, LTT_FIELD_CALL_SITE
),
3673 function_exit
, NULL
, &hooks
);
3675 lttv_trace_find_hook(ts
->parent
.t
,
3676 LTT_CHANNEL_SYSCALL_STATE
,
3677 LTT_EVENT_SYS_CALL_TABLE
,
3678 FIELD_ARRAY(LTT_FIELD_ID
, LTT_FIELD_ADDRESS
, LTT_FIELD_SYMBOL
),
3679 dump_syscall
, NULL
, &hooks
);
3681 lttv_trace_find_hook(ts
->parent
.t
,
3682 LTT_CHANNEL_KPROBE_STATE
,
3683 LTT_EVENT_KPROBE_TABLE
,
3684 FIELD_ARRAY(LTT_FIELD_IP
, LTT_FIELD_SYMBOL
),
3685 dump_kprobe
, NULL
, &hooks
);
3687 lttv_trace_find_hook(ts
->parent
.t
,
3688 LTT_CHANNEL_SOFTIRQ_STATE
,
3689 LTT_EVENT_SOFTIRQ_VEC
,
3690 FIELD_ARRAY(LTT_FIELD_ID
, LTT_FIELD_ADDRESS
, LTT_FIELD_SYMBOL
),
3691 dump_softirq
, NULL
, &hooks
);
3693 lttv_trace_find_hook(ts
->parent
.t
,
3696 FIELD_ARRAY(LTT_FIELD_FD
, LTT_FIELD_FILENAME
),
3697 fs_open
, NULL
, &hooks
);
3699 /* Add these hooks to each event_by_id hooks list */
3701 nb_tracefile
= ts
->parent
.tracefiles
->len
;
3703 for(j
= 0 ; j
< nb_tracefile
; j
++) {
3705 LTTV_TRACEFILE_STATE(g_array_index(ts
->parent
.tracefiles
,
3706 LttvTracefileContext
*, j
));
3708 for(k
= 0 ; k
< hooks
->len
; k
++) {
3709 th
= &g_array_index(hooks
, LttvTraceHook
, k
);
3710 if (th
->mdata
== tfs
->parent
.tf
->mdata
)
3712 lttv_hooks_by_id_find(tfs
->parent
.event_by_id
, th
->id
),
3718 lttv_attribute_find(ts
->parent
.a
, LTTV_STATE_HOOKS
, LTTV_POINTER
, &val
);
3719 *(val
.v_pointer
) = hooks
;
3724 gint
lttv_state_hook_remove_event_hooks(void *hook_data
, void *call_data
)
3727 LttvTraceset
*traceset
= (LttvTraceset
*)(call_data
);
3729 lttv_state_remove_event_hooks(traceset
);
3734 void lttv_state_remove_event_hooks(LttvTraceset
*traceset
)
3737 guint i
, j
, k
, nb_trace
, nb_tracefile
;
3739 //LttvTraceState *ts;
3743 //LttvTraceHook *th;
3745 //LttvAttributeValue val;
3747 LttvHooks
*event_hook
;
3748 //TODO ybrosseau 2012-07-17 validate this. Reversed what's done in the add
3749 event_hook
= lttv_traceset_get_hooks(traceset
);
3751 g_assert(event_hook
);
3754 lttv_hooks_remove(event_hook
,syscall_entry
);
3755 lttv_hooks_remove(event_hook
,syscall_exit
);
3756 lttv_hooks_remove(event_hook
,irq_entry
);
3757 lttv_hooks_remove(event_hook
,irq_exit
);
3758 lttv_hooks_remove(event_hook
,soft_irq_raise
);
3759 lttv_hooks_remove(event_hook
,soft_irq_entry
);
3760 lttv_hooks_remove(event_hook
,soft_irq_exit
);
3761 lttv_hooks_remove(event_hook
,schedchange
);
3762 lttv_hooks_remove(event_hook
,sched_try_wakeup
);
3763 lttv_hooks_remove(event_hook
,process_exit
);
3764 lttv_hooks_remove(event_hook
,process_free
);
3765 lttv_hooks_remove(event_hook
,process_exec
);
3766 lttv_hooks_remove(event_hook
,enum_process_state
);
3767 lttv_hooks_remove(event_hook
,statedump_end
);
3768 lttv_hooks_remove(event_hook
,enum_interrupt
);
3769 #ifdef BABEL_CLEANUP
3770 nb_trace
= lttv_traceset_number(traceset
);
3771 for(i
= 0 ; i
< nb_trace
; i
++) {
3772 ts
= lttv_traceset_get(i
);
3774 lttv_attribute_find(ts
->parent
.a
, LTTV_STATE_HOOKS
, LTTV_POINTER
, &val
);
3775 hooks
= *(val
.v_pointer
);
3777 /* Remove these hooks from each event_by_id hooks list */
3779 nb_tracefile
= ts
->parent
.tracefiles
->len
;
3781 for(j
= 0 ; j
< nb_tracefile
; j
++) {
3783 LTTV_TRACEFILE_STATE(g_array_index(ts
->parent
.tracefiles
,
3784 LttvTracefileContext
*, j
));
3786 for(k
= 0 ; k
< hooks
->len
; k
++) {
3787 th
= &g_array_index(hooks
, LttvTraceHook
, k
);
3788 if (th
->mdata
== tfs
->parent
.tf
->mdata
)
3789 lttv_hooks_remove_data(
3790 lttv_hooks_by_id_find(tfs
->parent
.event_by_id
, th
->id
),
3795 lttv_trace_hook_remove_all(&hooks
);
3796 g_array_free(hooks
, TRUE
);
3802 static gboolean
state_save_event_hook(void *hook_data
, void *call_data
)
3804 guint
*event_count
= (guint
*)hook_data
;
3806 /* Only save at LTTV_STATE_SAVE_INTERVAL */
3807 if(likely((*event_count
)++ < LTTV_STATE_SAVE_INTERVAL
))
3812 LttvEvent
*event
= (LttvEvent
*)call_data
;
3814 LttvTraceset
*traceset
= lttv_trace_get_traceset(event
->state
->trace
);
3816 LttvAttribute
*saved_states_tree
, *saved_state_tree
;
3818 LttvAttributeValue value
;
3819 LttTime currentTime
;
3821 currentTime
= lttv_event_get_timestamp(event
);
3822 int nb_trace
= lttv_traceset_number(traceset
);
3823 for(i
= 0 ; i
< nb_trace
; i
++) {
3825 LttvTrace
*trace
= lttv_traceset_get(traceset
, i
);
3826 LttvTraceState
*tstate
= trace
->state
;
3827 saved_states_tree
= lttv_attribute_find_subdir(trace
->a
,
3828 LTTV_STATE_SAVED_STATES
);
3830 saved_state_tree
= g_object_new(LTTV_ATTRIBUTE_TYPE
, NULL
);
3831 value
= lttv_attribute_add(saved_states_tree
,
3832 lttv_attribute_get_number(saved_states_tree
), LTTV_GOBJECT
);
3833 *(value
.v_gobject
) = (GObject
*)saved_state_tree
;
3836 value
= lttv_attribute_add(saved_state_tree
, LTTV_STATE_TIME
, LTTV_TIME
);
3837 *(value
.v_time
) = currentTime
;
3839 lttv_state_save(tstate
, saved_state_tree
);
3840 g_debug("Saving state at time %lu.%lu", currentTime
.tv_sec
,
3841 currentTime
.tv_nsec
);
3843 *(tstate
->max_time_state_recomputed_in_seek
) = currentTime
;
3848 static gboolean
state_save_after_trace_hook(void *hook_data
, void *call_data
)
3850 #warning "Would we move max_time to traceset"
3851 LttvTrace
*trace
= (LttvTrace
*)(call_data
);
3852 LttvTraceState
*tcs
= trace
->state
;
3853 TimeInterval time_span
= lttv_traceset_get_time_span_real(lttv_trace_get_traceset(trace
));
3855 *(tcs
->max_time_state_recomputed_in_seek
) = time_span
.end_time
;
3859 #ifdef BABEL_CLEANUP
3860 guint
lttv_state_current_cpu(LttvTracefileState
*tfs
)
3865 #endif //BABEL_CLEANUP
3868 static gboolean
block_start(void *hook_data
, void *call_data
)
3870 LttvTracefileState
*self
= (LttvTracefileState
*)call_data
;
3872 LttvTracefileState
*tfcs
;
3874 LttvTraceState
*tcs
= (LttvTraceState
*)(self
->parent
.t_context
);
3876 LttEventPosition
*ep
;
3878 guint i
, nb_block
, nb_event
, nb_tracefile
;
3882 LttvAttribute
*saved_states_tree
, *saved_state_tree
;
3884 LttvAttributeValue value
;
3886 ep
= ltt_event_position_new();
3888 nb_tracefile
= tcs
->parent
.tracefiles
->len
;
3890 /* Count the number of events added since the last block end in any
3893 for(i
= 0 ; i
< nb_tracefile
; i
++) {
3895 LTTV_TRACEFILE_STATE(&g_array_index(tcs
->parent
.tracefiles
,
3896 LttvTracefileContext
, i
));
3897 ltt_event_position(tfcs
->parent
.e
, ep
);
3898 ltt_event_position_get(ep
, &nb_block
, &nb_event
, &tf
);
3899 tcs
->nb_event
+= nb_event
- tfcs
->saved_position
;
3900 tfcs
->saved_position
= nb_event
;
3904 if(tcs
->nb_event
>= tcs
->save_interval
) {
3905 saved_states_tree
= lttv_attribute_find_subdir(tcs
->parent
.t_a
,
3906 LTTV_STATE_SAVED_STATES
);
3907 saved_state_tree
= g_object_new(LTTV_ATTRIBUTE_TYPE
, NULL
);
3908 value
= lttv_attribute_add(saved_states_tree
,
3909 lttv_attribute_get_number(saved_states_tree
), LTTV_GOBJECT
);
3910 *(value
.v_gobject
) = (GObject
*)saved_state_tree
;
3911 value
= lttv_attribute_add(saved_state_tree
, LTTV_STATE_TIME
, LTTV_TIME
);
3912 *(value
.v_time
) = self
->parent
.timestamp
;
3913 lttv_state_save(tcs
, saved_state_tree
);
3915 g_debug("Saving state at time %lu.%lu", self
->parent
.timestamp
.tv_sec
,
3916 self
->parent
.timestamp
.tv_nsec
);
3918 *(tcs
->max_time_state_recomputed_in_seek
) = self
->parent
.timestamp
;
3924 static gboolean
block_end(void *hook_data
, void *call_data
)
3926 LttvTracefileState
*self
= (LttvTracefileState
*)call_data
;
3928 LttvTraceState
*tcs
= (LttvTraceState
*)(self
->parent
.t_context
);
3932 LttEventPosition
*ep
;
3934 guint nb_block
, nb_event
;
3936 ep
= ltt_event_position_new();
3937 ltt_event_position(self
->parent
.e
, ep
);
3938 ltt_event_position_get(ep
, &nb_block
, &nb_event
, &tf
);
3939 tcs
->nb_event
+= nb_event
- self
->saved_position
+ 1;
3940 self
->saved_position
= 0;
3941 *(tcs
->max_time_state_recomputed_in_seek
) = self
->parent
.timestamp
;
3948 void lttv_state_save_add_event_hooks(LttvTracesetState
*self
)
3950 LttvTraceset
*traceset
= self
->parent
.ts
;
3952 guint i
, j
, nb_trace
, nb_tracefile
;
3956 LttvTracefileState
*tfs
;
3958 LttvTraceHook hook_start
, hook_end
;
3960 nb_trace
= lttv_traceset_number(traceset
);
3961 for(i
= 0 ; i
< nb_trace
; i
++) {
3962 ts
= (LttvTraceState
*)self
->parent
.traces
[i
];
3964 lttv_trace_find_hook(ts
->parent
.t
, "core","block_start",NULL
,
3965 NULL
, NULL
, block_start
, &hook_start
);
3966 lttv_trace_find_hook(ts
->parent
.t
, "core","block_end",NULL
,
3967 NULL
, NULL
, block_end
, &hook_end
);
3969 nb_tracefile
= ts
->parent
.tracefiles
->len
;
3971 for(j
= 0 ; j
< nb_tracefile
; j
++) {
3973 LTTV_TRACEFILE_STATE(&g_array_index(ts
->parent
.tracefiles
,
3974 LttvTracefileContext
, j
));
3975 lttv_hooks_add(lttv_hooks_by_id_find(tfs
->parent
.event_by_id
,
3976 hook_start
.id
), hook_start
.h
, NULL
, LTTV_PRIO_STATE
);
3977 lttv_hooks_add(lttv_hooks_by_id_find(tfs
->parent
.event_by_id
,
3978 hook_end
.id
), hook_end
.h
, NULL
, LTTV_PRIO_STATE
);
3984 void lttv_state_save_add_event_hooks(LttvTraceset
*traceset
)
3987 guint i
, j
, nb_trace
, nb_tracefile
;
3991 LttvTracefileState
*tfs
;
3994 if(!traceset
->has_precomputed_states
) {
3995 guint
*event_count
= g_new(guint
, 1);
3998 lttv_hooks_add(traceset
->event_hooks
,
3999 state_save_event_hook
,
4003 #ifdef BABEL_CLEANUP
4004 nb_trace
= lttv_traceset_number(traceset
);
4005 for(i
= 0 ; i
< nb_trace
; i
++) {
4007 ts
= (LttvTraceState
*)self
->parent
.traces
[i
];
4008 nb_tracefile
= ts
->parent
.tracefiles
->len
;
4010 if(ts
->has_precomputed_states
) continue;
4012 guint
*event_count
= g_new(guint
, 1);
4015 for(j
= 0 ; j
< nb_tracefile
; j
++) {
4017 LTTV_TRACEFILE_STATE(g_array_index(ts
->parent
.tracefiles
,
4018 LttvTracefileContext
*, j
));
4019 lttv_hooks_add(tfs
->parent
.event
,
4020 state_save_event_hook
,
4027 lttv_process_traceset_begin(traceset
,
4028 NULL
, NULL
, NULL
, NULL
, NULL
);
4033 gint
lttv_state_save_hook_add_event_hooks(void *hook_data
, void *call_data
)
4035 LttvTraceset
*ts
= (LttvTraceset
*)(call_data
);
4037 lttv_state_save_add_event_hooks(ts
);
4044 void lttv_state_save_remove_event_hooks(LttvTracesetState
*self
)
4046 LttvTraceset
*traceset
= self
->parent
.ts
;
4048 guint i
, j
, nb_trace
, nb_tracefile
;
4052 LttvTracefileState
*tfs
;
4054 LttvTraceHook hook_start
, hook_end
;
4056 nb_trace
= lttv_traceset_number(traceset
);
4057 for(i
= 0 ; i
< nb_trace
; i
++) {
4058 ts
= LTTV_TRACE_STATE(self
->parent
.traces
[i
]);
4060 lttv_trace_find_hook(ts
->parent
.t
, "core","block_start",NULL
,
4061 NULL
, NULL
, block_start
, &hook_start
);
4063 lttv_trace_find_hook(ts
->parent
.t
, "core","block_end",NULL
,
4064 NULL
, NULL
, block_end
, &hook_end
);
4066 nb_tracefile
= ts
->parent
.tracefiles
->len
;
4068 for(j
= 0 ; j
< nb_tracefile
; j
++) {
4070 LTTV_TRACEFILE_STATE(&g_array_index(ts
->parent
.tracefiles
,
4071 LttvTracefileContext
, j
));
4072 lttv_hooks_remove_data(lttv_hooks_by_id_find(
4073 tfs
->parent
.event_by_id
, hook_start
.id
), hook_start
.h
, NULL
);
4074 lttv_hooks_remove_data(lttv_hooks_by_id_find(
4075 tfs
->parent
.event_by_id
, hook_end
.id
), hook_end
.h
, NULL
);
4081 void lttv_state_save_remove_event_hooks(LttvTraceset
*traceset
)
4084 guint i
, j
, nb_trace
, nb_tracefile
;
4088 LttvTracefileState
*tfs
;
4090 LttvHooks
*after_trace
= lttv_hooks_new();
4091 guint
*event_count
= NULL
;
4093 lttv_hooks_add(after_trace
,
4094 state_save_after_trace_hook
,
4099 lttv_process_traceset_end(traceset
,
4100 NULL
, after_trace
, NULL
, NULL
);
4102 lttv_hooks_destroy(after_trace
);
4104 //nb_trace = lttv_traceset_number(traceset);
4106 event_count
= lttv_hooks_remove(traceset
->event_hooks
,
4107 state_save_event_hook
);
4109 if(event_count
) g_free(event_count
);
4111 #ifdef BABEL_CLEANUP
4112 for(i
= 0 ; i
< nb_trace
; i
++) {
4114 ts
= (LttvTraceState
*)self
->parent
.traces
[i
];
4115 nb_tracefile
= ts
->parent
.tracefiles
->len
;
4117 if(ts
->has_precomputed_states
) continue;
4119 guint
*event_count
= NULL
;
4121 for(j
= 0 ; j
< nb_tracefile
; j
++) {
4123 LTTV_TRACEFILE_STATE(g_array_index(ts
->parent
.tracefiles
,
4124 LttvTracefileContext
*, j
));
4125 event_count
= lttv_hooks_remove(tfs
->parent
.event
,
4126 state_save_event_hook
);
4128 if(event_count
) g_free(event_count
);
4133 gint
lttv_state_save_hook_remove_event_hooks(void *hook_data
, void *call_data
)
4135 LttvTraceset
*ts
= (LttvTraceset
*)(call_data
);
4137 lttv_state_save_remove_event_hooks(ts
);
4143 void lttv_state_traceset_seek_time(LttvTraceset
*traceset
, LttTime t
)
4145 lttv_state_traceset_seek_time_closest(traceset
,
4147 lttv_process_traceset_middle(traceset
, t
, G_MAXUINT
,
4151 void lttv_state_traceset_seek_position(LttvTraceset
*traceset
, LttvTracesetPosition
*position
)
4153 LttTime t
= lttv_traceset_position_get_time(position
);
4155 lttv_state_traceset_seek_time_closest(traceset
,
4157 lttv_process_traceset_middle(traceset
,
4163 void lttv_state_traceset_seek_time_closest(LttvTraceset
*traceset
, LttTime t
)
4167 int min_pos
, mid_pos
, max_pos
;
4169 guint call_rest
= 0;
4170 guint resto_start
= 0;
4173 LttvAttributeValue value
;
4175 LttvAttributeType type
;
4177 LttvAttributeName name
;
4181 LttvAttribute
*saved_states_tree
, *saved_state_tree
, *closest_tree
= NULL
;
4183 LttTime closest_tree_time
, restored_time
;
4184 guint first_restored_time
= 1;
4186 //g_tree_destroy(self->parent.pqueue);
4187 //self->parent.pqueue = g_tree_new(compare_tracefile);
4189 g_debug("Entering seek_time_closest for time %lu.%lu", t
.tv_sec
, t
.tv_nsec
);
4191 nb_trace
= lttv_traceset_number(traceset
);
4192 for(i
= 0 ; i
< nb_trace
; i
++) {
4194 LttvTrace
*trace
= lttv_traceset_get(traceset
, i
);
4195 LttvTraceState
*tstate
= trace
->state
;
4197 if(ltt_time_compare(t
, *(tstate
->max_time_state_recomputed_in_seek
)) < 0) {
4198 saved_states_tree
= lttv_attribute_find_subdir(trace
->a
,
4199 LTTV_STATE_SAVED_STATES
);
4202 if(saved_states_tree
) {
4203 max_pos
= lttv_attribute_get_number(saved_states_tree
) - 1;
4204 mid_pos
= max_pos
/ 2;
4205 while(min_pos
< max_pos
) {
4206 type
= lttv_attribute_get(saved_states_tree
, mid_pos
,
4207 &name
, &value
, &is_named
);
4208 g_assert(type
== LTTV_GOBJECT
);
4209 saved_state_tree
= *((LttvAttribute
**)(value
.v_gobject
));
4210 type
= lttv_attribute_get_by_name(saved_state_tree
,
4211 LTTV_STATE_TIME
, &value
);
4212 g_assert(type
== LTTV_TIME
);
4213 if(ltt_time_compare(*(value
.v_time
), t
) < 0) {
4215 closest_tree
= saved_state_tree
;
4216 closest_tree_time
= *(value
.v_time
);
4218 else max_pos
= mid_pos
- 1;
4220 mid_pos
= (min_pos
+ max_pos
+ 1) / 2;
4224 /* restore the closest earlier saved state */
4226 if(first_restored_time
|| (ltt_time_compare(restored_time
, closest_tree_time
) == 0)) {
4227 first_restored_time
= 0;
4228 lttv_state_restore(tstate
, closest_tree
);
4230 restored_time
= closest_tree_time
;
4233 g_debug("State: restored time mismatch between traces");
4240 /* There is no saved state, yet we want to have it. Restart at T0 */
4246 /* We want to seek quickly without restoring/updating the state */
4253 if(resto_start
|| resto_at
) {
4254 // Restore init state and seek so
4255 for(i
= 0 ; i
< nb_trace
; i
++) {
4257 LttvTrace
*trace
= lttv_traceset_get(traceset
, i
);
4258 LttvTraceState
*tstate
= trace
->state
;
4260 restore_init_state(tstate
);
4263 // If t > max saved state
4265 lttv_process_traceset_seek_time(traceset
, t
);
4266 } else if (resto_start
) {
4267 // If no saved state
4268 lttv_process_traceset_seek_time(traceset
, ltt_time_zero
);
4272 g_info("NOT Calling restore");
4275 // Seek at checkpoint
4276 lttv_process_traceset_seek_time(traceset
, restored_time
);
4284 #ifdef BABEL_CLEANUP
4285 static void traceset_state_instance_init (GTypeInstance
*instance
, gpointer g_class
)
4290 static void traceset_state_finalize (LttvTracesetState
*self
)
4292 G_OBJECT_CLASS(g_type_class_peek(LTTV_TRACESET_CONTEXT_TYPE
))->
4293 finalize(G_OBJECT(self
));
4297 static void traceset_state_class_init (LttvTracesetContextClass
*klass
)
4299 GObjectClass
*gobject_class
= G_OBJECT_CLASS(klass
);
4301 gobject_class
->finalize
= (void (*)(GObject
*self
)) traceset_state_finalize
;
4302 klass
->init
= (void (*)(LttvTracesetContext
*self
, LttvTraceset
*ts
))init
;
4303 klass
->fini
= (void (*)(LttvTracesetContext
*self
))fini
;
4304 klass
->new_traceset_context
= new_traceset_context
;
4305 klass
->new_trace_context
= new_trace_context
;
4306 klass
->new_tracefile_context
= new_tracefile_context
;
4310 GType
lttv_traceset_state_get_type(void)
4312 static GType type
= 0;
4314 static const GTypeInfo info
= {
4315 sizeof (LttvTracesetStateClass
),
4316 NULL
, /* base_init */
4317 NULL
, /* base_finalize */
4318 (GClassInitFunc
) traceset_state_class_init
, /* class_init */
4319 NULL
, /* class_finalize */
4320 NULL
, /* class_data */
4321 sizeof (LttvTracesetState
),
4322 0, /* n_preallocs */
4323 (GInstanceInitFunc
) traceset_state_instance_init
, /* instance_init */
4324 NULL
/* value handling */
4327 type
= g_type_register_static (LTTV_TRACESET_CONTEXT_TYPE
, "LttvTracesetStateType",
4335 static void trace_state_instance_init (GTypeInstance
*instance
, gpointer g_class
)
4340 static void trace_state_finalize (LttvTraceState
*self
)
4342 G_OBJECT_CLASS(g_type_class_peek(LTTV_TRACE_CONTEXT_TYPE
))->
4343 finalize(G_OBJECT(self
));
4347 static void trace_state_class_init (LttvTraceStateClass
*klass
)
4349 GObjectClass
*gobject_class
= G_OBJECT_CLASS(klass
);
4351 gobject_class
->finalize
= (void (*)(GObject
*self
)) trace_state_finalize
;
4352 klass
->state_save
= state_save
;
4353 klass
->state_restore
= state_restore
;
4354 klass
->state_saved_free
= state_saved_free
;
4358 GType
lttv_trace_state_get_type(void)
4360 static GType type
= 0;
4362 static const GTypeInfo info
= {
4363 sizeof (LttvTraceStateClass
),
4364 NULL
, /* base_init */
4365 NULL
, /* base_finalize */
4366 (GClassInitFunc
) trace_state_class_init
, /* class_init */
4367 NULL
, /* class_finalize */
4368 NULL
, /* class_data */
4369 sizeof (LttvTraceState
),
4370 0, /* n_preallocs */
4371 (GInstanceInitFunc
) trace_state_instance_init
, /* instance_init */
4372 NULL
/* value handling */
4375 type
= g_type_register_static (LTTV_TRACE_CONTEXT_TYPE
,
4376 "LttvTraceStateType", &info
, 0);
4382 static void tracefile_state_instance_init (GTypeInstance
*instance
,
4388 static void tracefile_state_finalize (LttvTracefileState
*self
)
4390 G_OBJECT_CLASS(g_type_class_peek(LTTV_TRACEFILE_CONTEXT_TYPE
))->
4391 finalize(G_OBJECT(self
));
4395 static void tracefile_state_class_init (LttvTracefileStateClass
*klass
)
4397 GObjectClass
*gobject_class
= G_OBJECT_CLASS(klass
);
4399 gobject_class
->finalize
= (void (*)(GObject
*self
)) tracefile_state_finalize
;
4403 GType
lttv_tracefile_state_get_type(void)
4405 static GType type
= 0;
4407 static const GTypeInfo info
= {
4408 sizeof (LttvTracefileStateClass
),
4409 NULL
, /* base_init */
4410 NULL
, /* base_finalize */
4411 (GClassInitFunc
) tracefile_state_class_init
, /* class_init */
4412 NULL
, /* class_finalize */
4413 NULL
, /* class_data */
4414 sizeof (LttvTracefileState
),
4415 0, /* n_preallocs */
4416 (GInstanceInitFunc
) tracefile_state_instance_init
, /* instance_init */
4417 NULL
/* value handling */
4420 type
= g_type_register_static (LTTV_TRACEFILE_CONTEXT_TYPE
,
4421 "LttvTracefileStateType", &info
, 0);
4427 static void module_init(void)
4429 LTTV_STATE_UNNAMED
= g_quark_from_string("");
4430 LTTV_STATE_UNBRANDED
= g_quark_from_string("");
4431 LTTV_STATE_MODE_UNKNOWN
= g_quark_from_string("MODE_UNKNOWN");
4432 LTTV_STATE_USER_MODE
= g_quark_from_string("USER_MODE");
4433 LTTV_STATE_MAYBE_USER_MODE
= g_quark_from_string("MAYBE_USER_MODE");
4434 LTTV_STATE_SYSCALL
= g_quark_from_string("SYSCALL");
4435 LTTV_STATE_MAYBE_SYSCALL
= g_quark_from_string("MAYBE_SYSCALL");
4436 LTTV_STATE_TRAP
= g_quark_from_string("TRAP");
4437 LTTV_STATE_MAYBE_TRAP
= g_quark_from_string("MAYBE_TRAP");
4438 LTTV_STATE_IRQ
= g_quark_from_string("IRQ");
4439 LTTV_STATE_SOFT_IRQ
= g_quark_from_string("SOFTIRQ");
4440 LTTV_STATE_SUBMODE_UNKNOWN
= g_quark_from_string("UNKNOWN");
4441 LTTV_STATE_SUBMODE_NONE
= g_quark_from_string("NONE");
4442 LTTV_STATE_WAIT_FORK
= g_quark_from_string("WAIT_FORK");
4443 LTTV_STATE_WAIT_CPU
= g_quark_from_string("WAIT_CPU");
4444 LTTV_STATE_EXIT
= g_quark_from_string("EXIT");
4445 LTTV_STATE_ZOMBIE
= g_quark_from_string("ZOMBIE");
4446 LTTV_STATE_WAIT
= g_quark_from_string("WAIT");
4447 LTTV_STATE_RUN
= g_quark_from_string("RUN");
4448 LTTV_STATE_DEAD
= g_quark_from_string("DEAD");
4449 LTTV_STATE_USER_THREAD
= g_quark_from_string("USER_THREAD");
4450 LTTV_STATE_KERNEL_THREAD
= g_quark_from_string("KERNEL_THREAD");
4451 LTTV_STATE_TRACEFILES
= g_quark_from_string("tracefiles");
4452 LTTV_STATE_PROCESSES
= g_quark_from_string("processes");
4453 LTTV_STATE_PROCESS
= g_quark_from_string("process");
4454 LTTV_STATE_RUNNING_PROCESS
= g_quark_from_string("running_process");
4455 LTTV_STATE_POSITION
= g_quark_from_string("position");
4456 LTTV_STATE_SAVED_STATES
= g_quark_from_string("saved states");
4457 LTTV_STATE_SAVED_STATES_TIME
= g_quark_from_string("saved states time");
4458 LTTV_STATE_TIME
= g_quark_from_string("time");
4459 LTTV_STATE_HOOKS
= g_quark_from_string("saved state hooks");
4460 LTTV_STATE_NAME_TABLES
= g_quark_from_string("name tables");
4461 LTTV_STATE_TRACE_STATE_USE_COUNT
=
4462 g_quark_from_string("trace_state_use_count");
4463 LTTV_STATE_RESOURCE_CPUS
= g_quark_from_string("cpu resource states");
4464 LTTV_STATE_RESOURCE_CPUS
= g_quark_from_string("cpu count");
4465 LTTV_STATE_RESOURCE_IRQS
= g_quark_from_string("irq resource states");
4466 LTTV_STATE_RESOURCE_SOFT_IRQS
= g_quark_from_string("soft irq resource states");
4467 LTTV_STATE_RESOURCE_TRAPS
= g_quark_from_string("trap resource states");
4468 LTTV_STATE_RESOURCE_BLKDEVS
= g_quark_from_string("blkdevs resource states");
4470 LTT_CHANNEL_FD_STATE
= g_quark_from_string("fd_state");
4471 LTT_CHANNEL_GLOBAL_STATE
= g_quark_from_string("global_state");
4472 LTT_CHANNEL_IRQ_STATE
= g_quark_from_string("irq_state");
4473 LTT_CHANNEL_MODULE_STATE
= g_quark_from_string("module_state");
4474 LTT_CHANNEL_NETIF_STATE
= g_quark_from_string("netif_state");
4475 LTT_CHANNEL_SOFTIRQ_STATE
= g_quark_from_string("softirq_state");
4476 LTT_CHANNEL_SWAP_STATE
= g_quark_from_string("swap_state");
4477 LTT_CHANNEL_SYSCALL_STATE
= g_quark_from_string("syscall_state");
4478 LTT_CHANNEL_TASK_STATE
= g_quark_from_string("task_state");
4479 LTT_CHANNEL_VM_STATE
= g_quark_from_string("vm_state");
4480 LTT_CHANNEL_KPROBE_STATE
= g_quark_from_string("kprobe_state");
4481 LTT_CHANNEL_FS
= g_quark_from_string("fs");
4482 LTT_CHANNEL_KERNEL
= g_quark_from_string("kernel");
4483 LTT_CHANNEL_MM
= g_quark_from_string("mm");
4484 LTT_CHANNEL_USERSPACE
= g_quark_from_string("userspace");
4485 LTT_CHANNEL_BLOCK
= g_quark_from_string("block");
4487 LTT_EVENT_SYSCALL_ENTRY
= g_quark_from_string("syscall_entry");
4488 LTT_EVENT_SYSCALL_EXIT
= g_quark_from_string("syscall_exit");
4489 //LTT_EVENT_TRAP_ENTRY = g_quark_from_string("trap_entry");
4490 //LTT_EVENT_TRAP_EXIT = g_quark_from_string("trap_exit");
4491 LTT_EVENT_PAGE_FAULT_ENTRY
= g_quark_from_string("page_fault_entry");
4492 LTT_EVENT_PAGE_FAULT_EXIT
= g_quark_from_string("page_fault_exit");
4493 LTT_EVENT_PAGE_FAULT_NOSEM_ENTRY
= g_quark_from_string("page_fault_nosem_entry");
4494 LTT_EVENT_PAGE_FAULT_NOSEM_EXIT
= g_quark_from_string("page_fault_nosem_exit");
4495 LTT_EVENT_IRQ_ENTRY
= g_quark_from_string("irq_entry");
4496 LTT_EVENT_IRQ_EXIT
= g_quark_from_string("irq_exit");
4497 LTT_EVENT_SOFT_IRQ_RAISE
= g_quark_from_string("softirq_raise");
4498 LTT_EVENT_SOFT_IRQ_ENTRY
= g_quark_from_string("softirq_entry");
4499 LTT_EVENT_SOFT_IRQ_EXIT
= g_quark_from_string("softirq_exit");
4500 LTT_EVENT_SCHED_SCHEDULE
= g_quark_from_string("sched_schedule");
4501 LTT_EVENT_SCHED_TRY_WAKEUP
= g_quark_from_string("sched_try_wakeup");
4502 LTT_EVENT_PROCESS_FORK
= g_quark_from_string("process_fork");
4503 LTT_EVENT_KTHREAD_CREATE
= g_quark_from_string("kthread_create");
4504 LTT_EVENT_PROCESS_EXIT
= g_quark_from_string("process_exit");
4505 LTT_EVENT_PROCESS_FREE
= g_quark_from_string("process_free");
4506 LTT_EVENT_EXEC
= g_quark_from_string("exec");
4507 LTT_EVENT_PROCESS_STATE
= g_quark_from_string("process_state");
4508 LTT_EVENT_STATEDUMP_END
= g_quark_from_string("statedump_end");
4509 LTT_EVENT_FUNCTION_ENTRY
= g_quark_from_string("function_entry");
4510 LTT_EVENT_FUNCTION_EXIT
= g_quark_from_string("function_exit");
4511 LTT_EVENT_THREAD_BRAND
= g_quark_from_string("thread_brand");
4512 LTT_EVENT_REQUEST_ISSUE
= g_quark_from_string("_blk_request_issue");
4513 LTT_EVENT_REQUEST_COMPLETE
= g_quark_from_string("_blk_request_complete");
4514 LTT_EVENT_LIST_INTERRUPT
= g_quark_from_string("interrupt");
4515 LTT_EVENT_SYS_CALL_TABLE
= g_quark_from_string("sys_call_table");
4516 LTT_EVENT_SOFTIRQ_VEC
= g_quark_from_string("softirq_vec");
4517 LTT_EVENT_KPROBE_TABLE
= g_quark_from_string("kprobe_table");
4518 LTT_EVENT_KPROBE
= g_quark_from_string("kprobe");
4519 LTT_EVENT_OPEN
= g_quark_from_string("open");
4520 LTT_EVENT_READ
= g_quark_from_string("read");
4521 LTT_EVENT_POLL_EVENT
= g_quark_from_string("poll_event");
4523 LTT_FIELD_SYSCALL_ID
= g_quark_from_string("syscall_id");
4524 LTT_FIELD_TRAP_ID
= g_quark_from_string("trap_id");
4525 LTT_FIELD_IRQ_ID
= g_quark_from_string("irq_id");
4526 LTT_FIELD_SOFT_IRQ_ID
= g_quark_from_string("softirq_id");
4527 LTT_FIELD_PREV_PID
= g_quark_from_string("prev_pid");
4528 LTT_FIELD_NEXT_PID
= g_quark_from_string("next_pid");
4529 LTT_FIELD_PREV_STATE
= g_quark_from_string("prev_state");
4530 LTT_FIELD_PARENT_PID
= g_quark_from_string("parent_pid");
4531 LTT_FIELD_CHILD_PID
= g_quark_from_string("child_pid");
4532 LTT_FIELD_PID
= g_quark_from_string("pid");
4533 LTT_FIELD_TGID
= g_quark_from_string("tgid");
4534 LTT_FIELD_CHILD_TGID
= g_quark_from_string("child_tgid");
4535 LTT_FIELD_FILENAME
= g_quark_from_string("filename");
4536 LTT_FIELD_NAME
= g_quark_from_string("name");
4537 LTT_FIELD_TYPE
= g_quark_from_string("type");
4538 LTT_FIELD_MODE
= g_quark_from_string("mode");
4539 LTT_FIELD_SUBMODE
= g_quark_from_string("submode");
4540 LTT_FIELD_STATUS
= g_quark_from_string("status");
4541 LTT_FIELD_THIS_FN
= g_quark_from_string("this_fn");
4542 LTT_FIELD_CALL_SITE
= g_quark_from_string("call_site");
4543 LTT_FIELD_MAJOR
= g_quark_from_string("major");
4544 LTT_FIELD_MINOR
= g_quark_from_string("minor");
4545 LTT_FIELD_OPERATION
= g_quark_from_string("direction");
4546 LTT_FIELD_ACTION
= g_quark_from_string("action");
4547 LTT_FIELD_ID
= g_quark_from_string("id");
4548 LTT_FIELD_ADDRESS
= g_quark_from_string("address");
4549 LTT_FIELD_SYMBOL
= g_quark_from_string("symbol");
4550 LTT_FIELD_IP
= g_quark_from_string("ip");
4551 LTT_FIELD_FD
= g_quark_from_string("fd");
4552 LTT_FIELD_STATE
= g_quark_from_string("state");
4553 LTT_FIELD_CPU_ID
= g_quark_from_string("cpu_id");
4555 LTTV_CPU_UNKNOWN
= g_quark_from_string("unknown");
4556 LTTV_CPU_IDLE
= g_quark_from_string("idle");
4557 LTTV_CPU_BUSY
= g_quark_from_string("busy");
4558 LTTV_CPU_IRQ
= g_quark_from_string("irq");
4559 LTTV_CPU_SOFT_IRQ
= g_quark_from_string("softirq");
4560 LTTV_CPU_TRAP
= g_quark_from_string("trap");
4562 LTTV_IRQ_UNKNOWN
= g_quark_from_string("unknown");
4563 LTTV_IRQ_IDLE
= g_quark_from_string("idle");
4564 LTTV_IRQ_BUSY
= g_quark_from_string("busy");
4566 LTTV_BDEV_UNKNOWN
= g_quark_from_string("unknown");
4567 LTTV_BDEV_IDLE
= g_quark_from_string("idle");
4568 LTTV_BDEV_BUSY_READING
= g_quark_from_string("busy_reading");
4569 LTTV_BDEV_BUSY_WRITING
= g_quark_from_string("busy_writing");
4572 static void module_destroy()
4577 LTTV_MODULE("state", "State computation", \
4578 "Update the system state, possibly saving it at intervals", \
4579 module_init
, module_destroy
)