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 <ltt/trace.h>
29 #include <ltt/event.h>
31 #include <ltt/marker-desc.h>
34 #include <ltt/ltt-private.h>
39 * usertrace is there only to be able to update the current CPU of the
40 * usertraces when there is a schedchange. it is a way to link the ProcessState
41 * to the associated usertrace. Link only created upon thread creation.
43 * The cpu id is necessary : it gives us back the current ProcessState when we
44 * are considering data from the usertrace.
47 #define PREALLOCATED_EXECUTION_STACK 10
53 LTT_CHANNEL_GLOBAL_STATE
,
54 LTT_CHANNEL_IRQ_STATE
,
55 LTT_CHANNEL_MODULE_STATE
,
56 LTT_CHANNEL_NETIF_STATE
,
57 LTT_CHANNEL_SOFTIRQ_STATE
,
58 LTT_CHANNEL_SWAP_STATE
,
59 LTT_CHANNEL_SYSCALL_STATE
,
60 LTT_CHANNEL_TASK_STATE
,
62 LTT_CHANNEL_KPROBE_STATE
,
66 LTT_CHANNEL_USERSPACE
,
72 LTT_EVENT_SYSCALL_ENTRY
,
73 LTT_EVENT_SYSCALL_EXIT
,
74 LTT_EVENT_PAGE_FAULT_NOSEM_ENTRY
,
75 LTT_EVENT_PAGE_FAULT_NOSEM_EXIT
,
76 LTT_EVENT_PAGE_FAULT_ENTRY
,
77 LTT_EVENT_PAGE_FAULT_EXIT
,
82 LTT_EVENT_SOFT_IRQ_RAISE
,
83 LTT_EVENT_SOFT_IRQ_ENTRY
,
84 LTT_EVENT_SOFT_IRQ_EXIT
,
85 LTT_EVENT_SCHED_SCHEDULE
,
86 LTT_EVENT_SCHED_TRY_WAKEUP
,
87 LTT_EVENT_PROCESS_FORK
,
88 LTT_EVENT_KTHREAD_CREATE
,
89 LTT_EVENT_PROCESS_EXIT
,
90 LTT_EVENT_PROCESS_FREE
,
92 LTT_EVENT_PROCESS_STATE
,
93 LTT_EVENT_STATEDUMP_END
,
94 LTT_EVENT_FUNCTION_ENTRY
,
95 LTT_EVENT_FUNCTION_EXIT
,
96 LTT_EVENT_THREAD_BRAND
,
97 LTT_EVENT_REQUEST_ISSUE
,
98 LTT_EVENT_REQUEST_COMPLETE
,
99 LTT_EVENT_LIST_INTERRUPT
,
100 LTT_EVENT_SYS_CALL_TABLE
,
101 LTT_EVENT_SOFTIRQ_VEC
,
102 LTT_EVENT_KPROBE_TABLE
,
106 LTT_EVENT_POLL_EVENT
;
111 LTT_FIELD_SYSCALL_ID
,
114 LTT_FIELD_SOFT_IRQ_ID
,
117 LTT_FIELD_PREV_STATE
,
118 LTT_FIELD_PARENT_PID
,
122 LTT_FIELD_CHILD_TGID
,
142 LTTV_STATE_MODE_UNKNOWN
,
143 LTTV_STATE_USER_MODE
,
150 LTTV_STATE_SUBMODE_UNKNOWN
,
151 LTTV_STATE_SUBMODE_NONE
;
155 LTTV_STATE_WAIT_FORK
,
164 LTTV_STATE_UNBRANDED
;
167 LTTV_STATE_USER_THREAD
,
168 LTTV_STATE_KERNEL_THREAD
;
186 LTTV_BDEV_BUSY_READING
,
187 LTTV_BDEV_BUSY_WRITING
;
190 LTTV_STATE_TRACEFILES
,
191 LTTV_STATE_PROCESSES
,
193 LTTV_STATE_RUNNING_PROCESS
,
195 LTTV_STATE_SAVED_STATES
,
196 LTTV_STATE_SAVED_STATES_TIME
,
199 LTTV_STATE_NAME_TABLES
,
200 LTTV_STATE_TRACE_STATE_USE_COUNT
,
201 LTTV_STATE_RESOURCE_CPUS
,
202 LTTV_STATE_RESOURCE_CPUS_COUNT
,
203 LTTV_STATE_RESOURCE_IRQS
,
204 LTTV_STATE_RESOURCE_SOFT_IRQS
,
205 LTTV_STATE_RESOURCE_TRAPS
,
206 LTTV_STATE_RESOURCE_BLKDEVS
;
208 static void create_max_time(LttvTraceState
*tcs
);
210 static void get_max_time(LttvTraceState
*tcs
);
212 static void free_max_time(LttvTraceState
*tcs
);
214 static void create_name_tables(LttvTraceState
*tcs
);
216 static void get_name_tables(LttvTraceState
*tcs
);
218 static void free_name_tables(LttvTraceState
*tcs
);
220 static void free_saved_state(LttvTraceState
*tcs
);
222 static void lttv_state_free_process_table(GHashTable
*processes
);
224 static void lttv_trace_states_read_raw(LttvTraceState
*tcs
, FILE *fp
,
225 GPtrArray
*quarktable
);
227 /* Resource function prototypes */
228 static LttvBdevState
*get_hashed_bdevstate(LttvTraceState
*ts
, guint16 devcode
);
229 static LttvBdevState
*bdevstate_new(void);
230 static void bdevstate_free(LttvBdevState
*);
231 static void bdevstate_free_cb(gpointer key
, gpointer value
, gpointer user_data
);
232 static LttvBdevState
*bdevstate_copy(LttvBdevState
*bds
);
235 #if (__SIZEOF_LONG__ == 4)
236 guint
guint64_hash(gconstpointer key
)
238 guint64 ukey
= *(const guint64
*)key
;
240 return (guint
)ukey
^ (guint
)(ukey
>> 32);
243 gboolean
guint64_equal(gconstpointer a
, gconstpointer b
)
245 guint64 ua
= *(const guint64
*)a
;
246 guint64 ub
= *(const guint64
*)b
;
252 void lttv_state_save(LttvTraceState
*self
, LttvAttribute
*container
)
254 LTTV_TRACE_STATE_GET_CLASS(self
)->state_save(self
, container
);
258 void lttv_state_restore(LttvTraceState
*self
, LttvAttribute
*container
)
260 LTTV_TRACE_STATE_GET_CLASS(self
)->state_restore(self
, container
);
264 void lttv_state_state_saved_free(LttvTraceState
*self
,
265 LttvAttribute
*container
)
267 LTTV_TRACE_STATE_GET_CLASS(self
)->state_saved_free(self
, container
);
271 guint
process_hash(gconstpointer key
)
273 guint pid
= ((const LttvProcessState
*)key
)->pid
;
274 return (pid
>>8 ^ pid
>>4 ^ pid
>>2 ^ pid
) ;
278 /* If the hash table hash function is well distributed,
279 * the process_equal should compare different pid */
280 gboolean
process_equal(gconstpointer a
, gconstpointer b
)
282 const LttvProcessState
*process_a
, *process_b
;
285 process_a
= (const LttvProcessState
*)a
;
286 process_b
= (const LttvProcessState
*)b
;
288 if(likely(process_a
->pid
!= process_b
->pid
)) ret
= FALSE
;
289 else if(likely(process_a
->pid
== 0 &&
290 process_a
->cpu
!= process_b
->cpu
)) ret
= FALSE
;
295 static void delete_usertrace(gpointer key
, gpointer value
, gpointer user_data
)
297 g_tree_destroy((GTree
*)value
);
300 static void lttv_state_free_usertraces(GHashTable
*usertraces
)
302 g_hash_table_foreach(usertraces
, delete_usertrace
, NULL
);
303 g_hash_table_destroy(usertraces
);
306 gboolean
rettrue(gpointer key
, gpointer value
, gpointer user_data
)
311 static guint
check_expand(nb
, id
)
316 return max(id
+ 1, nb
* 2);
319 static void expand_name_table(LttvTraceState
*ts
, GQuark
**table
,
320 guint nb
, guint new_nb
)
322 /* Expand an incomplete table */
323 GQuark
*old_table
= *table
;
324 *table
= g_new(GQuark
, new_nb
);
325 memcpy(*table
, old_table
, nb
* sizeof(GQuark
));
328 static void fill_name_table(LttvTraceState
*ts
, GQuark
*table
, guint nb
,
329 guint new_nb
, const char *def_string
)
332 GString
*fe_name
= g_string_new("");
333 for(i
= nb
; i
< new_nb
; i
++) {
334 g_string_printf(fe_name
, "%s %d", def_string
, i
);
335 table
[i
] = g_quark_from_string(fe_name
->str
);
337 g_string_free(fe_name
, TRUE
);
340 static void expand_syscall_table(LttvTraceState
*ts
, int id
)
342 guint new_nb
= check_expand(ts
->nb_syscalls
, id
);
343 if(likely(new_nb
== ts
->nb_syscalls
))
345 expand_name_table(ts
, &ts
->syscall_names
, ts
->nb_syscalls
, new_nb
);
346 fill_name_table(ts
, ts
->syscall_names
, ts
->nb_syscalls
, new_nb
, "syscall");
347 /* Update the table size */
348 ts
->nb_syscalls
= new_nb
;
351 static void expand_kprobe_table(LttvTraceState
*ts
, guint64 ip
, char *symbol
)
353 #if (__SIZEOF_LONG__ == 4)
354 guint64
*ip_ptr
= g_new(guint64
, 1);
355 g_hash_table_insert(ts
->kprobe_hash
, ip_ptr
,
356 (gpointer
)(glong
)g_quark_from_string(symbol
));
358 g_hash_table_insert(ts
->kprobe_hash
, (gpointer
)ip
,
359 (gpointer
)(glong
)g_quark_from_string(symbol
));
363 static void expand_trap_table(LttvTraceState
*ts
, int id
)
365 guint new_nb
= check_expand(ts
->nb_traps
, id
);
367 if(likely(new_nb
== ts
->nb_traps
))
369 expand_name_table(ts
, &ts
->trap_names
, ts
->nb_traps
, new_nb
);
370 fill_name_table(ts
, ts
->trap_names
, ts
->nb_traps
, new_nb
, "trap");
371 /* Update the table size */
372 ts
->nb_traps
= new_nb
;
374 LttvTrapState
*old_table
= ts
->trap_states
;
375 ts
->trap_states
= g_new(LttvTrapState
, new_nb
);
376 memcpy(ts
->trap_states
, old_table
,
377 ts
->nb_traps
* sizeof(LttvTrapState
));
378 for(i
= ts
->nb_traps
; i
< new_nb
; i
++)
379 ts
->trap_states
[i
].running
= 0;
382 static void expand_irq_table(LttvTraceState
*ts
, int id
)
384 guint new_nb
= check_expand(ts
->nb_irqs
, id
);
386 if(likely(new_nb
== ts
->nb_irqs
))
388 expand_name_table(ts
, &ts
->irq_names
, ts
->nb_irqs
, new_nb
);
389 fill_name_table(ts
, ts
->irq_names
, ts
->nb_irqs
, new_nb
, "irq");
391 LttvIRQState
*old_table
= ts
->irq_states
;
392 ts
->irq_states
= g_new(LttvIRQState
, new_nb
);
393 memcpy(ts
->irq_states
, old_table
, ts
->nb_irqs
* sizeof(LttvIRQState
));
394 for(i
= ts
->nb_irqs
; i
< new_nb
; i
++) {
395 ts
->irq_states
[i
].mode_stack
= g_array_new(FALSE
, FALSE
, sizeof(LttvIRQMode
));
398 /* Update the table size */
399 ts
->nb_irqs
= new_nb
;
402 static void expand_soft_irq_table(LttvTraceState
*ts
, int id
)
404 guint new_nb
= check_expand(ts
->nb_soft_irqs
, id
);
406 if(likely(new_nb
== ts
->nb_soft_irqs
))
408 expand_name_table(ts
, &ts
->soft_irq_names
, ts
->nb_soft_irqs
, new_nb
);
409 fill_name_table(ts
, ts
->soft_irq_names
, ts
->nb_soft_irqs
, new_nb
, "softirq");
411 LttvSoftIRQState
*old_table
= ts
->soft_irq_states
;
412 ts
->soft_irq_states
= g_new(LttvSoftIRQState
, new_nb
);
413 memcpy(ts
->soft_irq_states
, old_table
,
414 ts
->nb_soft_irqs
* sizeof(LttvSoftIRQState
));
415 for(i
= ts
->nb_soft_irqs
; i
< new_nb
; i
++)
416 ts
->soft_irq_states
[i
].running
= 0;
418 /* Update the table size */
419 ts
->nb_soft_irqs
= new_nb
;
423 restore_init_state(LttvTraceState
*self
)
425 guint i
, nb_cpus
, nb_irqs
, nb_soft_irqs
, nb_traps
;
427 //LttvTracefileState *tfcs;
429 LttTime start_time
, end_time
;
431 /* Free the process tables */
432 if(self
->processes
!= NULL
) lttv_state_free_process_table(self
->processes
);
433 if(self
->usertraces
!= NULL
) lttv_state_free_usertraces(self
->usertraces
);
434 self
->processes
= g_hash_table_new(process_hash
, process_equal
);
435 self
->usertraces
= g_hash_table_new(g_direct_hash
, g_direct_equal
);
438 /* Seek time to beginning */
439 // Mathieu : fix : don't seek traceset here : causes inconsistency in seek
440 // closest. It's the tracecontext job to seek the trace to the beginning
441 // anyway : the init state might be used at the middle of the trace as well...
442 //g_tree_destroy(self->parent.ts_context->pqueue);
443 //self->parent.ts_context->pqueue = g_tree_new(compare_tracefile);
445 ltt_trace_time_span_get(self
->parent
.t
, &start_time
, &end_time
);
447 //lttv_process_trace_seek_time(&self->parent, ltt_time_zero);
449 nb_cpus
= ltt_trace_get_num_cpu(self
->parent
.t
);
450 nb_irqs
= self
->nb_irqs
;
451 nb_soft_irqs
= self
->nb_soft_irqs
;
452 nb_traps
= self
->nb_traps
;
454 /* Put the per cpu running_process to beginning state : process 0. */
455 for(i
=0; i
< nb_cpus
; i
++) {
456 LttvExecutionState
*es
;
457 self
->running_process
[i
] = lttv_state_create_process(self
, NULL
, i
, 0, 0,
458 LTTV_STATE_UNNAMED
, &start_time
);
459 /* We are not sure is it's a kernel thread or normal thread, put the
460 * bottom stack state to unknown */
461 self
->running_process
[i
]->execution_stack
=
462 g_array_set_size(self
->running_process
[i
]->execution_stack
, 1);
463 es
= self
->running_process
[i
]->state
=
464 &g_array_index(self
->running_process
[i
]->execution_stack
,
465 LttvExecutionState
, 0);
466 es
->t
= LTTV_STATE_MODE_UNKNOWN
;
467 es
->s
= LTTV_STATE_UNNAMED
;
469 //self->running_process[i]->state->s = LTTV_STATE_RUN;
470 self
->running_process
[i
]->cpu
= i
;
472 /* reset cpu states */
473 if(self
->cpu_states
[i
].mode_stack
->len
> 0) {
474 g_array_remove_range(self
->cpu_states
[i
].mode_stack
, 0, self
->cpu_states
[i
].mode_stack
->len
);
475 if(self
->cpu_states
[i
].irq_stack
->len
)
476 g_array_remove_range(self
->cpu_states
[i
].irq_stack
, 0, self
->cpu_states
[i
].irq_stack
->len
);
477 if(self
->cpu_states
[i
].softirq_stack
->len
)
478 g_array_remove_range(self
->cpu_states
[i
].softirq_stack
, 0, self
->cpu_states
[i
].softirq_stack
->len
);
479 if(self
->cpu_states
[i
].trap_stack
->len
)
480 g_array_remove_range(self
->cpu_states
[i
].trap_stack
, 0, self
->cpu_states
[i
].trap_stack
->len
);
484 /* reset irq states */
485 for(i
=0; i
<nb_irqs
; i
++) {
486 if(self
->irq_states
[i
].mode_stack
->len
> 0)
487 g_array_remove_range(self
->irq_states
[i
].mode_stack
, 0, self
->irq_states
[i
].mode_stack
->len
);
490 /* reset softirq states */
491 for(i
=0; i
<nb_soft_irqs
; i
++) {
492 self
->soft_irq_states
[i
].pending
= 0;
493 self
->soft_irq_states
[i
].running
= 0;
496 /* reset trap states */
497 for(i
=0; i
<nb_traps
; i
++) {
498 self
->trap_states
[i
].running
= 0;
501 /* reset bdev states */
502 g_hash_table_foreach(self
->bdev_states
, bdevstate_free_cb
, NULL
);
503 //g_hash_table_steal_all(self->bdev_states);
504 g_hash_table_foreach_steal(self
->bdev_states
, rettrue
, NULL
);
507 nb_tracefile
= self
->parent
.tracefiles
->len
;
509 for(i
= 0 ; i
< nb_tracefile
; i
++) {
511 LTTV_TRACEFILE_STATE(g_array_index(self
->parent
.tracefiles
,
512 LttvTracefileContext
*, i
));
513 ltt_trace_time_span_get(self
->parent
.t
, &tfcs
->parent
.timestamp
, NULL
);
514 // tfcs->saved_position = 0;
515 tfcs
->process
= lttv_state_create_process(tfcs
, NULL
,0);
516 tfcs
->process
->state
->s
= LTTV_STATE_RUN
;
517 tfcs
->process
->last_cpu
= tfcs
->cpu_name
;
518 tfcs
->process
->last_cpu_index
= ltt_tracefile_num(((LttvTracefileContext
*)tfcs
)->tf
);
523 //static LttTime time_zero = {0,0};
525 static gint
compare_usertraces(gconstpointer a
, gconstpointer b
,
528 const LttTime
*t1
= (const LttTime
*)a
;
529 const LttTime
*t2
= (const LttTime
*)b
;
531 return ltt_time_compare(*t1
, *t2
);
534 static void free_usertrace_key(gpointer data
)
539 #define MAX_STRING_LEN 4096
542 state_load_saved_states(LttvTraceState
*tcs
)
545 GPtrArray
*quarktable
;
546 const char *trace_path
;
550 tcs
->has_precomputed_states
= FALSE
;
554 gchar buf
[MAX_STRING_LEN
];
557 trace_path
= g_quark_to_string(ltt_trace_name(tcs
->parent
.t
));
558 strncpy(path
, trace_path
, PATH_MAX
-1);
559 count
= strnlen(trace_path
, PATH_MAX
-1);
560 // quarktable : open, test
561 strncat(path
, "/precomputed/quarktable", PATH_MAX
-count
-1);
562 fp
= fopen(path
, "r");
564 quarktable
= g_ptr_array_sized_new(4096);
566 /* Index 0 is null */
568 if(hdr
== EOF
) return;
569 g_assert(hdr
== HDR_QUARKS
);
573 if(hdr
== EOF
) break;
574 g_assert(hdr
== HDR_QUARK
);
575 g_ptr_array_set_size(quarktable
, q
+1);
578 fread(&buf
[i
], sizeof(gchar
), 1, fp
);
579 if(buf
[i
] == '\0' || feof(fp
)) break;
582 len
= strnlen(buf
, MAX_STRING_LEN
-1);
583 g_ptr_array_index (quarktable
, q
) = g_new(gchar
, len
+1);
584 strncpy(g_ptr_array_index (quarktable
, q
), buf
, len
+1);
590 // saved_states : open, test
591 strncpy(path
, trace_path
, PATH_MAX
-1);
592 count
= strnlen(trace_path
, PATH_MAX
-1);
593 strncat(path
, "/precomputed/states", PATH_MAX
-count
-1);
594 fp
= fopen(path
, "r");
598 if(hdr
!= HDR_TRACE
) goto end
;
600 lttv_trace_states_read_raw(tcs
, fp
, quarktable
);
602 tcs
->has_precomputed_states
= TRUE
;
607 /* Free the quarktable */
608 for(i
=0; i
<quarktable
->len
; i
++) {
609 string
= g_ptr_array_index (quarktable
, i
);
612 g_ptr_array_free(quarktable
, TRUE
);
617 init(LttvTracesetState
*self
, LttvTraceset
*ts
)
619 guint i
, j
, nb_trace
, nb_tracefile
, nb_cpu
;
622 LttvTraceContext
*tc
;
626 LttvTracefileState
*tfcs
;
628 LttvAttributeValue v
;
630 LTTV_TRACESET_CONTEXT_CLASS(g_type_class_peek(LTTV_TRACESET_CONTEXT_TYPE
))->
631 init((LttvTracesetContext
*)self
, ts
);
633 nb_trace
= lttv_traceset_number(ts
);
634 for(i
= 0 ; i
< nb_trace
; i
++) {
635 tc
= self
->parent
.traces
[i
];
636 tcs
= LTTV_TRACE_STATE(tc
);
637 tcs
->save_interval
= LTTV_STATE_SAVE_INTERVAL
;
638 lttv_attribute_find(tcs
->parent
.t_a
, LTTV_STATE_TRACE_STATE_USE_COUNT
,
642 if(*(v
.v_uint
) == 1) {
643 create_name_tables(tcs
);
644 create_max_time(tcs
);
646 get_name_tables(tcs
);
649 nb_tracefile
= tc
->tracefiles
->len
;
650 nb_cpu
= ltt_trace_get_num_cpu(tc
->t
);
651 nb_irq
= tcs
->nb_irqs
;
652 tcs
->processes
= NULL
;
653 tcs
->usertraces
= NULL
;
654 tcs
->running_process
= g_new(LttvProcessState
*, nb_cpu
);
656 /* init cpu resource stuff */
657 tcs
->cpu_states
= g_new(LttvCPUState
, nb_cpu
);
658 for(j
= 0; j
<nb_cpu
; j
++) {
659 tcs
->cpu_states
[j
].mode_stack
= g_array_new(FALSE
, FALSE
, sizeof(LttvCPUMode
));
660 tcs
->cpu_states
[j
].irq_stack
= g_array_new(FALSE
, FALSE
, sizeof(gint
));
661 tcs
->cpu_states
[j
].softirq_stack
= g_array_new(FALSE
, FALSE
, sizeof(gint
));
662 tcs
->cpu_states
[j
].trap_stack
= g_array_new(FALSE
, FALSE
, sizeof(gint
));
663 g_assert(tcs
->cpu_states
[j
].mode_stack
!= NULL
);
666 /* init irq resource stuff */
667 tcs
->irq_states
= g_new(LttvIRQState
, nb_irq
);
668 for(j
= 0; j
<nb_irq
; j
++) {
669 tcs
->irq_states
[j
].mode_stack
= g_array_new(FALSE
, FALSE
, sizeof(LttvIRQMode
));
670 g_assert(tcs
->irq_states
[j
].mode_stack
!= NULL
);
673 /* init soft irq stuff */
674 /* the kernel has a statically fixed max of 32 softirqs */
675 tcs
->soft_irq_states
= g_new(LttvSoftIRQState
, tcs
->nb_soft_irqs
);
677 /* init trap stuff */
678 tcs
->trap_states
= g_new(LttvTrapState
, tcs
->nb_traps
);
680 /* init bdev resource stuff */
681 tcs
->bdev_states
= g_hash_table_new(g_int_hash
, g_int_equal
);
683 restore_init_state(tcs
);
684 for(j
= 0 ; j
< nb_tracefile
; j
++) {
686 LTTV_TRACEFILE_STATE(g_array_index(tc
->tracefiles
,
687 LttvTracefileContext
*, j
));
688 tfcs
->tracefile_name
= ltt_tracefile_name(tfcs
->parent
.tf
);
689 tfcs
->cpu
= ltt_tracefile_cpu(tfcs
->parent
.tf
);
690 tfcs
->cpu_state
= &(tcs
->cpu_states
[tfcs
->cpu
]);
691 if(ltt_tracefile_tid(tfcs
->parent
.tf
) != 0) {
692 /* It's a Usertrace */
693 guint tid
= ltt_tracefile_tid(tfcs
->parent
.tf
);
694 GTree
*usertrace_tree
= (GTree
*)g_hash_table_lookup(tcs
->usertraces
,
695 GUINT_TO_POINTER(tid
));
696 if(!usertrace_tree
) {
697 usertrace_tree
= g_tree_new_full(compare_usertraces
,
698 NULL
, free_usertrace_key
, NULL
);
699 g_hash_table_insert(tcs
->usertraces
,
700 GUINT_TO_POINTER(tid
), usertrace_tree
);
702 LttTime
*timestamp
= g_new(LttTime
, 1);
703 *timestamp
= ltt_interpolate_time_from_tsc(tfcs
->parent
.tf
,
704 ltt_tracefile_creation(tfcs
->parent
.tf
));
705 g_tree_insert(usertrace_tree
, timestamp
, tfcs
);
709 /* See if the trace has saved states */
710 state_load_saved_states(tcs
);
715 fini(LttvTracesetState
*self
)
721 //LttvTracefileState *tfcs;
723 LttvAttributeValue v
;
725 nb_trace
= lttv_traceset_number(LTTV_TRACESET_CONTEXT(self
)->ts
);
726 for(i
= 0 ; i
< nb_trace
; i
++) {
727 tcs
= (LttvTraceState
*)(LTTV_TRACESET_CONTEXT(self
)->traces
[i
]);
728 lttv_attribute_find(tcs
->parent
.t_a
, LTTV_STATE_TRACE_STATE_USE_COUNT
,
731 g_assert(*(v
.v_uint
) != 0);
734 if(*(v
.v_uint
) == 0) {
735 free_name_tables(tcs
);
737 free_saved_state(tcs
);
739 g_free(tcs
->running_process
);
740 tcs
->running_process
= NULL
;
741 lttv_state_free_process_table(tcs
->processes
);
742 lttv_state_free_usertraces(tcs
->usertraces
);
743 tcs
->processes
= NULL
;
744 tcs
->usertraces
= NULL
;
746 LTTV_TRACESET_CONTEXT_CLASS(g_type_class_peek(LTTV_TRACESET_CONTEXT_TYPE
))->
747 fini((LttvTracesetContext
*)self
);
751 static LttvTracesetContext
*
752 new_traceset_context(LttvTracesetContext
*self
)
754 return LTTV_TRACESET_CONTEXT(g_object_new(LTTV_TRACESET_STATE_TYPE
, NULL
));
758 static LttvTraceContext
*
759 new_trace_context(LttvTracesetContext
*self
)
761 return LTTV_TRACE_CONTEXT(g_object_new(LTTV_TRACE_STATE_TYPE
, NULL
));
765 static LttvTracefileContext
*
766 new_tracefile_context(LttvTracesetContext
*self
)
768 return LTTV_TRACEFILE_CONTEXT(g_object_new(LTTV_TRACEFILE_STATE_TYPE
, NULL
));
772 /* Write the process state of the trace */
774 static void write_process_state(gpointer key
, gpointer value
,
777 LttvProcessState
*process
;
779 LttvExecutionState
*es
;
781 FILE *fp
= (FILE *)user_data
;
786 process
= (LttvProcessState
*)value
;
788 " <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",
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
),
797 process
->cpu
, process
->free_events
);
799 for(i
= 0 ; i
< process
->execution_stack
->len
; i
++) {
800 es
= &g_array_index(process
->execution_stack
, LttvExecutionState
, i
);
801 fprintf(fp
, " <ES MODE=\"%s\" SUBMODE=\"%s\" ENTRY_S=%lu ENTRY_NS=%lu",
802 g_quark_to_string(es
->t
), g_quark_to_string(es
->n
),
803 es
->entry
.tv_sec
, es
->entry
.tv_nsec
);
804 fprintf(fp
, " CHANGE_S=%lu CHANGE_NS=%lu STATUS=\"%s\"/>\n",
805 es
->change
.tv_sec
, es
->change
.tv_nsec
, g_quark_to_string(es
->s
));
808 for(i
= 0 ; i
< process
->user_stack
->len
; i
++) {
809 address
= g_array_index(process
->user_stack
, guint64
, i
);
810 fprintf(fp
, " <USER_STACK ADDRESS=\"%" PRIu64
"\"/>\n",
814 if(process
->usertrace
) {
815 fprintf(fp
, " <USERTRACE NAME=\"%s\" CPU=%u\n/>",
816 g_quark_to_string(process
->usertrace
->tracefile_name
),
817 process
->usertrace
->cpu
);
821 fprintf(fp
, " </PROCESS>\n");
825 void lttv_state_write(LttvTraceState
*self
, LttTime t
, FILE *fp
)
827 guint i
, nb_tracefile
, nb_block
, offset
;
830 LttvTracefileState
*tfcs
;
834 LttEventPosition
*ep
;
838 ep
= ltt_event_position_new();
840 fprintf(fp
,"<PROCESS_STATE TIME_S=%lu TIME_NS=%lu>\n", t
.tv_sec
, t
.tv_nsec
);
842 g_hash_table_foreach(self
->processes
, write_process_state
, fp
);
844 nb_cpus
= ltt_trace_get_num_cpu(self
->parent
.t
);
845 for(i
=0;i
<nb_cpus
;i
++) {
846 fprintf(fp
," <CPU NUM=%u RUNNING_PROCESS=%u>\n",
847 i
, self
->running_process
[i
]->pid
);
850 nb_tracefile
= self
->parent
.tracefiles
->len
;
852 for(i
= 0 ; i
< nb_tracefile
; i
++) {
854 LTTV_TRACEFILE_STATE(g_array_index(self
->parent
.tracefiles
,
855 LttvTracefileContext
*, i
));
856 fprintf(fp
, " <TRACEFILE TIMESTAMP_S=%lu TIMESTAMP_NS=%lu",
857 tfcs
->parent
.timestamp
.tv_sec
,
858 tfcs
->parent
.timestamp
.tv_nsec
);
859 LttEvent
*e
= ltt_tracefile_get_event(tfcs
->parent
.tf
);
860 if(e
== NULL
) fprintf(fp
,"/>\n");
862 ltt_event_position(e
, ep
);
863 ltt_event_position_get(ep
, &tf
, &nb_block
, &offset
, &tsc
);
864 fprintf(fp
, " BLOCK=%u OFFSET=%u TSC=%" PRIu64
"/>\n", nb_block
, offset
,
869 fprintf(fp
,"</PROCESS_STATE>\n");
873 static void write_process_state_raw(gpointer key
, gpointer value
,
876 LttvProcessState
*process
;
878 LttvExecutionState
*es
;
880 FILE *fp
= (FILE *)user_data
;
885 process
= (LttvProcessState
*)value
;
886 fputc(HDR_PROCESS
, fp
);
887 //fwrite(&header, sizeof(header), 1, fp);
888 //fprintf(fp, "%s", g_quark_to_string(process->type));
890 fwrite(&process
->type
, sizeof(process
->type
), 1, fp
);
891 //fprintf(fp, "%s", g_quark_to_string(process->name));
893 fwrite(&process
->name
, sizeof(process
->name
), 1, fp
);
894 //fprintf(fp, "%s", g_quark_to_string(process->brand));
896 fwrite(&process
->brand
, sizeof(process
->brand
), 1, fp
);
897 fwrite(&process
->pid
, sizeof(process
->pid
), 1, fp
);
898 fwrite(&process
->free_events
, sizeof(process
->free_events
), 1, fp
);
899 fwrite(&process
->tgid
, sizeof(process
->tgid
), 1, fp
);
900 fwrite(&process
->ppid
, sizeof(process
->ppid
), 1, fp
);
901 fwrite(&process
->cpu
, sizeof(process
->cpu
), 1, fp
);
902 fwrite(&process
->creation_time
, sizeof(process
->creation_time
), 1, fp
);
903 fwrite(&process
->insertion_time
, sizeof(process
->insertion_time
), 1, fp
);
907 " <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",
908 process
, process
->pid
, process
->tgid
, process
->ppid
,
909 g_quark_to_string(process
->type
),
910 process
->creation_time
.tv_sec
,
911 process
->creation_time
.tv_nsec
,
912 process
->insertion_time
.tv_sec
,
913 process
->insertion_time
.tv_nsec
,
914 g_quark_to_string(process
->name
),
915 g_quark_to_string(process
->brand
),
919 for(i
= 0 ; i
< process
->execution_stack
->len
; i
++) {
920 es
= &g_array_index(process
->execution_stack
, LttvExecutionState
, i
);
923 //fprintf(fp, "%s", g_quark_to_string(es->t));
925 fwrite(&es
->t
, sizeof(es
->t
), 1, fp
);
926 //fprintf(fp, "%s", g_quark_to_string(es->n));
928 fwrite(&es
->n
, sizeof(es
->n
), 1, fp
);
929 //fprintf(fp, "%s", g_quark_to_string(es->s));
931 fwrite(&es
->s
, sizeof(es
->s
), 1, fp
);
932 fwrite(&es
->entry
, sizeof(es
->entry
), 1, fp
);
933 fwrite(&es
->change
, sizeof(es
->change
), 1, fp
);
934 fwrite(&es
->cum_cpu_time
, sizeof(es
->cum_cpu_time
), 1, fp
);
936 fprintf(fp
, " <ES MODE=\"%s\" SUBMODE=\"%s\" ENTRY_S=%lu ENTRY_NS=%lu",
937 g_quark_to_string(es
->t
), g_quark_to_string(es
->n
),
938 es
->entry
.tv_sec
, es
->entry
.tv_nsec
);
939 fprintf(fp
, " CHANGE_S=%lu CHANGE_NS=%lu STATUS=\"%s\"/>\n",
940 es
->change
.tv_sec
, es
->change
.tv_nsec
, g_quark_to_string(es
->s
));
944 for(i
= 0 ; i
< process
->user_stack
->len
; i
++) {
945 address
= g_array_index(process
->user_stack
, guint64
, i
);
946 fputc(HDR_USER_STACK
, fp
);
947 fwrite(&address
, sizeof(address
), 1, fp
);
949 fprintf(fp
, " <USER_STACK ADDRESS=\"%llu\"/>\n",
954 if(process
->usertrace
) {
955 fputc(HDR_USERTRACE
, fp
);
956 //fprintf(fp, "%s", g_quark_to_string(process->usertrace->tracefile_name));
958 fwrite(&process
->usertrace
->tracefile_name
,
959 sizeof(process
->usertrace
->tracefile_name
), 1, fp
);
960 fwrite(&process
->usertrace
->cpu
, sizeof(process
->usertrace
->cpu
), 1, fp
);
962 fprintf(fp
, " <USERTRACE NAME=\"%s\" CPU=%u\n/>",
963 g_quark_to_string(process
->usertrace
->tracefile_name
),
964 process
->usertrace
->cpu
);
971 void lttv_state_write_raw(LttvTraceState
*self
, LttTime t
, FILE *fp
)
973 guint i
, nb_tracefile
, nb_block
, offset
;
976 LttvTracefileState
*tfcs
;
980 LttEventPosition
*ep
;
984 ep
= ltt_event_position_new();
986 //fprintf(fp,"<PROCESS_STATE TIME_S=%lu TIME_NS=%lu>\n", t.tv_sec, t.tv_nsec);
987 fputc(HDR_PROCESS_STATE
, fp
);
988 fwrite(&t
, sizeof(t
), 1, fp
);
990 g_hash_table_foreach(self
->processes
, write_process_state_raw
, fp
);
992 nb_cpus
= ltt_trace_get_num_cpu(self
->parent
.t
);
993 for(i
=0;i
<nb_cpus
;i
++) {
995 fwrite(&i
, sizeof(i
), 1, fp
); /* cpu number */
996 fwrite(&self
->running_process
[i
]->pid
,
997 sizeof(self
->running_process
[i
]->pid
), 1, fp
);
998 //fprintf(fp," <CPU NUM=%u RUNNING_PROCESS=%u>\n",
999 // i, self->running_process[i]->pid);
1002 nb_tracefile
= self
->parent
.tracefiles
->len
;
1004 for(i
= 0 ; i
< nb_tracefile
; i
++) {
1006 LTTV_TRACEFILE_STATE(g_array_index(self
->parent
.tracefiles
,
1007 LttvTracefileContext
*, i
));
1008 // fprintf(fp, " <TRACEFILE TIMESTAMP_S=%lu TIMESTAMP_NS=%lu",
1009 // tfcs->parent.timestamp.tv_sec,
1010 // tfcs->parent.timestamp.tv_nsec);
1011 fputc(HDR_TRACEFILE
, fp
);
1012 fwrite(&tfcs
->parent
.timestamp
, sizeof(tfcs
->parent
.timestamp
), 1, fp
);
1013 /* Note : if timestamp if LTT_TIME_INFINITE, there will be no
1014 * position following : end of trace */
1015 LttEvent
*e
= ltt_tracefile_get_event(tfcs
->parent
.tf
);
1017 ltt_event_position(e
, ep
);
1018 ltt_event_position_get(ep
, &tf
, &nb_block
, &offset
, &tsc
);
1019 //fprintf(fp, " BLOCK=%u OFFSET=%u TSC=%llu/>\n", nb_block, offset,
1021 fwrite(&nb_block
, sizeof(nb_block
), 1, fp
);
1022 fwrite(&offset
, sizeof(offset
), 1, fp
);
1023 fwrite(&tsc
, sizeof(tsc
), 1, fp
);
1030 /* Read process state from a file */
1032 /* Called because a HDR_PROCESS was found */
1033 static void read_process_state_raw(LttvTraceState
*self
, FILE *fp
,
1034 GPtrArray
*quarktable
)
1036 LttvExecutionState
*es
;
1037 LttvProcessState
*process
, *parent_process
;
1038 LttvProcessState tmp
;
1043 /* TODO : check return value */
1044 fread(&tmp
.type
, sizeof(tmp
.type
), 1, fp
);
1045 fread(&tmp
.name
, sizeof(tmp
.name
), 1, fp
);
1046 fread(&tmp
.brand
, sizeof(tmp
.brand
), 1, fp
);
1047 fread(&tmp
.pid
, sizeof(tmp
.pid
), 1, fp
);
1048 fread(&tmp
.free_events
, sizeof(tmp
.free_events
), 1, fp
);
1049 fread(&tmp
.tgid
, sizeof(tmp
.tgid
), 1, fp
);
1050 fread(&tmp
.ppid
, sizeof(tmp
.ppid
), 1, fp
);
1051 fread(&tmp
.cpu
, sizeof(tmp
.cpu
), 1, fp
);
1052 fread(&tmp
.creation_time
, sizeof(tmp
.creation_time
), 1, fp
);
1053 fread(&tmp
.insertion_time
, sizeof(tmp
.insertion_time
), 1, fp
);
1056 process
= lttv_state_find_process(self
, tmp
.cpu
, tmp
.pid
);
1058 /* We must link to the parent */
1059 parent_process
= lttv_state_find_process_or_create(self
, ANY_CPU
, tmp
.ppid
,
1061 process
= lttv_state_find_process(self
, ANY_CPU
, tmp
.pid
);
1062 if(process
== NULL
) {
1063 process
= lttv_state_create_process(self
, parent_process
, tmp
.cpu
,
1065 g_quark_from_string((gchar
*)g_ptr_array_index(quarktable
, tmp
.name
)),
1066 &tmp
.creation_time
);
1069 process
->insertion_time
= tmp
.insertion_time
;
1070 process
->creation_time
= tmp
.creation_time
;
1071 process
->type
= g_quark_from_string(
1072 (gchar
*)g_ptr_array_index(quarktable
, tmp
.type
));
1073 process
->tgid
= tmp
.tgid
;
1074 process
->ppid
= tmp
.ppid
;
1075 process
->brand
= g_quark_from_string(
1076 (gchar
*)g_ptr_array_index(quarktable
, tmp
.brand
));
1078 g_quark_from_string((gchar
*)g_ptr_array_index(quarktable
, tmp
.name
));
1079 process
->free_events
= tmp
.free_events
;
1082 if(feof(fp
) || ferror(fp
)) goto end_loop
;
1084 gint hdr
= fgetc(fp
);
1085 if(hdr
== EOF
) goto end_loop
;
1089 process
->execution_stack
=
1090 g_array_set_size(process
->execution_stack
,
1091 process
->execution_stack
->len
+ 1);
1092 es
= &g_array_index(process
->execution_stack
, LttvExecutionState
,
1093 process
->execution_stack
->len
-1);
1094 process
->state
= es
;
1096 fread(&es
->t
, sizeof(es
->t
), 1, fp
);
1097 es
->t
= g_quark_from_string(
1098 (gchar
*)g_ptr_array_index(quarktable
, es
->t
));
1099 fread(&es
->n
, sizeof(es
->n
), 1, fp
);
1100 es
->n
= g_quark_from_string(
1101 (gchar
*)g_ptr_array_index(quarktable
, es
->n
));
1102 fread(&es
->s
, sizeof(es
->s
), 1, fp
);
1103 es
->s
= g_quark_from_string(
1104 (gchar
*)g_ptr_array_index(quarktable
, es
->s
));
1105 fread(&es
->entry
, sizeof(es
->entry
), 1, fp
);
1106 fread(&es
->change
, sizeof(es
->change
), 1, fp
);
1107 fread(&es
->cum_cpu_time
, sizeof(es
->cum_cpu_time
), 1, fp
);
1109 case HDR_USER_STACK
:
1110 process
->user_stack
= g_array_set_size(process
->user_stack
,
1111 process
->user_stack
->len
+ 1);
1112 address
= &g_array_index(process
->user_stack
, guint64
,
1113 process
->user_stack
->len
-1);
1114 fread(address
, sizeof(address
), 1, fp
);
1115 process
->current_function
= *address
;
1118 fread(&tmpq
, sizeof(tmpq
), 1, fp
);
1119 fread(&process
->usertrace
->cpu
, sizeof(process
->usertrace
->cpu
), 1, fp
);
1131 /* Called because a HDR_PROCESS_STATE was found */
1132 /* Append a saved state to the trace states */
1133 void lttv_state_read_raw(LttvTraceState
*self
, FILE *fp
, GPtrArray
*quarktable
)
1135 guint i
, nb_tracefile
, nb_block
, offset
;
1137 LttvTracefileState
*tfcs
;
1139 LttEventPosition
*ep
;
1147 LttvAttribute
*saved_states_tree
, *saved_state_tree
;
1149 LttvAttributeValue value
;
1150 GTree
*pqueue
= self
->parent
.ts_context
->pqueue
;
1151 ep
= ltt_event_position_new();
1153 restore_init_state(self
);
1155 fread(&t
, sizeof(t
), 1, fp
);
1158 if(feof(fp
) || ferror(fp
)) goto end_loop
;
1160 if(hdr
== EOF
) goto end_loop
;
1164 /* Call read_process_state_raw */
1165 read_process_state_raw(self
, fp
, quarktable
);
1173 case HDR_USER_STACK
:
1175 case HDR_PROCESS_STATE
:
1181 g_error("Error while parsing saved state file : unknown data header %d",
1187 nb_cpus
= ltt_trace_get_num_cpu(self
->parent
.t
);
1188 for(i
=0;i
<nb_cpus
;i
++) {
1191 g_assert(hdr
== HDR_CPU
);
1192 fread(&cpu_num
, sizeof(cpu_num
), 1, fp
); /* cpu number */
1193 g_assert(i
== cpu_num
);
1194 fread(&self
->running_process
[i
]->pid
,
1195 sizeof(self
->running_process
[i
]->pid
), 1, fp
);
1198 nb_tracefile
= self
->parent
.tracefiles
->len
;
1200 for(i
= 0 ; i
< nb_tracefile
; i
++) {
1202 LTTV_TRACEFILE_STATE(g_array_index(self
->parent
.tracefiles
,
1203 LttvTracefileContext
*, i
));
1204 // fprintf(fp, " <TRACEFILE TIMESTAMP_S=%lu TIMESTAMP_NS=%lu",
1205 // tfcs->parent.timestamp.tv_sec,
1206 // tfcs->parent.timestamp.tv_nsec);
1207 g_tree_remove(pqueue
, &tfcs
->parent
);
1209 g_assert(hdr
== HDR_TRACEFILE
);
1210 fread(&tfcs
->parent
.timestamp
, sizeof(tfcs
->parent
.timestamp
), 1, fp
);
1211 /* Note : if timestamp if LTT_TIME_INFINITE, there will be no
1212 * position following : end of trace */
1213 if(ltt_time_compare(tfcs
->parent
.timestamp
, ltt_time_infinite
) != 0) {
1214 fread(&nb_block
, sizeof(nb_block
), 1, fp
);
1215 fread(&offset
, sizeof(offset
), 1, fp
);
1216 fread(&tsc
, sizeof(tsc
), 1, fp
);
1217 ltt_event_position_set(ep
, tfcs
->parent
.tf
, nb_block
, offset
, tsc
);
1218 gint ret
= ltt_tracefile_seek_position(tfcs
->parent
.tf
, ep
);
1220 g_tree_insert(pqueue
, &tfcs
->parent
, &tfcs
->parent
);
1225 saved_states_tree
= lttv_attribute_find_subdir(self
->parent
.t_a
,
1226 LTTV_STATE_SAVED_STATES
);
1227 saved_state_tree
= g_object_new(LTTV_ATTRIBUTE_TYPE
, NULL
);
1228 value
= lttv_attribute_add(saved_states_tree
,
1229 lttv_attribute_get_number(saved_states_tree
), LTTV_GOBJECT
);
1230 *(value
.v_gobject
) = (GObject
*)saved_state_tree
;
1231 value
= lttv_attribute_add(saved_state_tree
, LTTV_STATE_TIME
, LTTV_TIME
);
1232 *(value
.v_time
) = t
;
1233 lttv_state_save(self
, saved_state_tree
);
1234 g_debug("Saving state at time %lu.%lu", t
.tv_sec
,
1237 *(self
->max_time_state_recomputed_in_seek
) = t
;
1241 /* Called when a HDR_TRACE is found */
1242 void lttv_trace_states_read_raw(LttvTraceState
*tcs
, FILE *fp
,
1243 GPtrArray
*quarktable
)
1248 if(feof(fp
) || ferror(fp
)) goto end_loop
;
1250 if(hdr
== EOF
) goto end_loop
;
1253 case HDR_PROCESS_STATE
:
1254 /* Call read_process_state_raw */
1255 lttv_state_read_raw(tcs
, fp
, quarktable
);
1263 case HDR_USER_STACK
:
1267 g_error("Error while parsing saved state file :"
1268 " unexpected data header %d",
1272 g_error("Error while parsing saved state file : unknown data header %d",
1277 *(tcs
->max_time_state_recomputed_in_seek
) = tcs
->parent
.time_span
.end_time
;
1278 restore_init_state(tcs
);
1279 lttv_process_trace_seek_time(&tcs
->parent
, ltt_time_zero
);
1285 /* Copy each process from an existing hash table to a new one */
1287 static void copy_process_state(gpointer key
, gpointer value
,gpointer user_data
)
1289 LttvProcessState
*process
, *new_process
;
1291 GHashTable
*new_processes
= (GHashTable
*)user_data
;
1295 process
= (LttvProcessState
*)value
;
1296 new_process
= g_new(LttvProcessState
, 1);
1297 *new_process
= *process
;
1298 new_process
->execution_stack
= g_array_sized_new(FALSE
, FALSE
,
1299 sizeof(LttvExecutionState
), PREALLOCATED_EXECUTION_STACK
);
1300 new_process
->execution_stack
=
1301 g_array_set_size(new_process
->execution_stack
,
1302 process
->execution_stack
->len
);
1303 for(i
= 0 ; i
< process
->execution_stack
->len
; i
++) {
1304 g_array_index(new_process
->execution_stack
, LttvExecutionState
, i
) =
1305 g_array_index(process
->execution_stack
, LttvExecutionState
, i
);
1307 new_process
->state
= &g_array_index(new_process
->execution_stack
,
1308 LttvExecutionState
, new_process
->execution_stack
->len
- 1);
1309 new_process
->user_stack
= g_array_sized_new(FALSE
, FALSE
,
1310 sizeof(guint64
), 0);
1311 new_process
->user_stack
=
1312 g_array_set_size(new_process
->user_stack
,
1313 process
->user_stack
->len
);
1314 for(i
= 0 ; i
< process
->user_stack
->len
; i
++) {
1315 g_array_index(new_process
->user_stack
, guint64
, i
) =
1316 g_array_index(process
->user_stack
, guint64
, i
);
1318 new_process
->current_function
= process
->current_function
;
1320 /* fd hash table stuff */
1326 /* copy every item in the hash table */
1327 new_process
->fds
= g_hash_table_new(g_direct_hash
, g_direct_equal
);
1329 g_hash_table_iter_init(&it
, process
->fds
);
1330 while (g_hash_table_iter_next (&it
, (void *)&key
, (void *)&value
)) {
1331 g_hash_table_insert(new_process
->fds
, &key
, &value
);
1335 /* When done creating the new process state, insert it in the
1337 g_hash_table_insert(new_processes
, new_process
, new_process
);
1341 static GHashTable
*lttv_state_copy_process_table(GHashTable
*processes
)
1343 GHashTable
*new_processes
= g_hash_table_new(process_hash
, process_equal
);
1345 g_hash_table_foreach(processes
, copy_process_state
, new_processes
);
1346 return new_processes
;
1349 static LttvCPUState
*lttv_state_copy_cpu_states(LttvCPUState
*states
, guint n
)
1352 LttvCPUState
*retval
;
1354 retval
= g_new(LttvCPUState
, n
);
1356 for(i
=0; i
<n
; i
++) {
1357 retval
[i
].irq_stack
= g_array_new(FALSE
, FALSE
, sizeof(gint
));
1358 g_array_set_size(retval
[i
].irq_stack
, states
[i
].irq_stack
->len
);
1359 for(j
=0; j
<states
[i
].irq_stack
->len
; j
++) {
1360 g_array_index(retval
[i
].irq_stack
, gint
, j
) = g_array_index(states
[i
].irq_stack
, gint
, j
);
1363 retval
[i
].softirq_stack
= g_array_new(FALSE
, FALSE
, sizeof(gint
));
1364 g_array_set_size(retval
[i
].softirq_stack
, states
[i
].softirq_stack
->len
);
1365 for(j
=0; j
<states
[i
].softirq_stack
->len
; j
++) {
1366 g_array_index(retval
[i
].softirq_stack
, gint
, j
) = g_array_index(states
[i
].softirq_stack
, gint
, j
);
1369 retval
[i
].trap_stack
= g_array_new(FALSE
, FALSE
, sizeof(gint
));
1370 g_array_set_size(retval
[i
].trap_stack
, states
[i
].trap_stack
->len
);
1371 for(j
=0; j
<states
[i
].trap_stack
->len
; j
++) {
1372 g_array_index(retval
[i
].trap_stack
, gint
, j
) = g_array_index(states
[i
].trap_stack
, gint
, j
);
1375 retval
[i
].mode_stack
= g_array_new(FALSE
, FALSE
, sizeof(LttvCPUMode
));
1376 g_array_set_size(retval
[i
].mode_stack
, states
[i
].mode_stack
->len
);
1377 for(j
=0; j
<states
[i
].mode_stack
->len
; j
++) {
1378 g_array_index(retval
[i
].mode_stack
, GQuark
, j
) = g_array_index(states
[i
].mode_stack
, GQuark
, j
);
1385 static void lttv_state_free_cpu_states(LttvCPUState
*states
, guint n
)
1389 for(i
=0; i
<n
; i
++) {
1390 g_array_free(states
[i
].mode_stack
, TRUE
);
1391 g_array_free(states
[i
].irq_stack
, TRUE
);
1392 g_array_free(states
[i
].softirq_stack
, TRUE
);
1393 g_array_free(states
[i
].trap_stack
, TRUE
);
1399 static LttvIRQState
*lttv_state_copy_irq_states(LttvIRQState
*states
, guint n
)
1402 LttvIRQState
*retval
;
1404 retval
= g_new(LttvIRQState
, n
);
1406 for(i
=0; i
<n
; i
++) {
1407 retval
[i
].mode_stack
= g_array_new(FALSE
, FALSE
, sizeof(LttvIRQMode
));
1408 g_array_set_size(retval
[i
].mode_stack
, states
[i
].mode_stack
->len
);
1409 for(j
=0; j
<states
[i
].mode_stack
->len
; j
++) {
1410 g_array_index(retval
[i
].mode_stack
, GQuark
, j
) = g_array_index(states
[i
].mode_stack
, GQuark
, j
);
1417 static void lttv_state_free_irq_states(LttvIRQState
*states
, guint n
)
1421 for(i
=0; i
<n
; i
++) {
1422 g_array_free(states
[i
].mode_stack
, TRUE
);
1428 static LttvSoftIRQState
*lttv_state_copy_soft_irq_states(LttvSoftIRQState
*states
, guint n
)
1431 LttvSoftIRQState
*retval
;
1433 retval
= g_new(LttvSoftIRQState
, n
);
1435 for(i
=0; i
<n
; i
++) {
1436 retval
[i
].pending
= states
[i
].pending
;
1437 retval
[i
].running
= states
[i
].running
;
1443 static void lttv_state_free_soft_irq_states(LttvSoftIRQState
*states
, guint n
)
1448 static LttvTrapState
*lttv_state_copy_trap_states(LttvTrapState
*states
, guint n
)
1451 LttvTrapState
*retval
;
1453 retval
= g_new(LttvTrapState
, n
);
1455 for(i
=0; i
<n
; i
++) {
1456 retval
[i
].running
= states
[i
].running
;
1462 static void lttv_state_free_trap_states(LttvTrapState
*states
, guint n
)
1467 /* bdevstate stuff */
1469 static LttvBdevState
*get_hashed_bdevstate(LttvTraceState
*ts
, guint16 devcode
)
1471 gint devcode_gint
= devcode
;
1472 gpointer bdev
= g_hash_table_lookup(ts
->bdev_states
, &devcode_gint
);
1474 LttvBdevState
*bdevstate
= g_new(LttvBdevState
, 1);
1475 bdevstate
->mode_stack
= g_array_new(FALSE
, FALSE
, sizeof(GQuark
));
1477 gint
* key
= g_new(gint
, 1);
1479 g_hash_table_insert(ts
->bdev_states
, key
, bdevstate
);
1487 static LttvBdevState
*bdevstate_new(void)
1489 LttvBdevState
*retval
;
1490 retval
= g_new(LttvBdevState
, 1);
1491 retval
->mode_stack
= g_array_new(FALSE
, FALSE
, sizeof(GQuark
));
1496 static void bdevstate_free(LttvBdevState
*bds
)
1498 g_array_free(bds
->mode_stack
, TRUE
);
1502 static void bdevstate_free_cb(gpointer key
, gpointer value
, gpointer user_data
)
1504 LttvBdevState
*bds
= (LttvBdevState
*) value
;
1506 bdevstate_free(bds
);
1509 static LttvBdevState
*bdevstate_copy(LttvBdevState
*bds
)
1511 LttvBdevState
*retval
;
1513 retval
= bdevstate_new();
1514 g_array_insert_vals(retval
->mode_stack
, 0, bds
->mode_stack
->data
, bds
->mode_stack
->len
);
1519 static void insert_and_copy_bdev_state(gpointer k
, gpointer v
, gpointer u
)
1521 //GHashTable *ht = (GHashTable *)u;
1522 LttvBdevState
*bds
= (LttvBdevState
*)v
;
1523 LttvBdevState
*newbds
;
1525 newbds
= bdevstate_copy(bds
);
1527 g_hash_table_insert(u
, k
, newbds
);
1530 static GHashTable
*lttv_state_copy_blkdev_hashtable(GHashTable
*ht
)
1534 retval
= g_hash_table_new(g_int_hash
, g_int_equal
);
1536 g_hash_table_foreach(ht
, insert_and_copy_bdev_state
, retval
);
1541 /* Free a hashtable and the LttvBdevState structures its values
1544 static void lttv_state_free_blkdev_hashtable(GHashTable
*ht
)
1546 g_hash_table_foreach(ht
, bdevstate_free_cb
, NULL
);
1547 g_hash_table_destroy(ht
);
1550 /* The saved state for each trace contains a member "processes", which
1551 stores a copy of the process table, and a member "tracefiles" with
1552 one entry per tracefile. Each tracefile has a "process" member pointing
1553 to the current process and a "position" member storing the tracefile
1554 position (needed to seek to the current "next" event. */
1556 static void state_save(LttvTraceState
*self
, LttvAttribute
*container
)
1558 guint i
, nb_tracefile
, nb_cpus
, nb_irqs
, nb_soft_irqs
, nb_traps
;
1560 LttvTracefileState
*tfcs
;
1562 LttvAttribute
*tracefiles_tree
, *tracefile_tree
;
1564 guint
*running_process
;
1566 LttvAttributeValue value
;
1568 LttEventPosition
*ep
;
1570 tracefiles_tree
= lttv_attribute_find_subdir(container
,
1571 LTTV_STATE_TRACEFILES
);
1573 value
= lttv_attribute_add(container
, LTTV_STATE_PROCESSES
,
1575 *(value
.v_pointer
) = lttv_state_copy_process_table(self
->processes
);
1577 /* Add the currently running processes array */
1578 nb_cpus
= ltt_trace_get_num_cpu(self
->parent
.t
);
1579 running_process
= g_new(guint
, nb_cpus
);
1580 for(i
=0;i
<nb_cpus
;i
++) {
1581 running_process
[i
] = self
->running_process
[i
]->pid
;
1583 value
= lttv_attribute_add(container
, LTTV_STATE_RUNNING_PROCESS
,
1585 *(value
.v_pointer
) = running_process
;
1587 g_info("State save");
1589 nb_tracefile
= self
->parent
.tracefiles
->len
;
1591 for(i
= 0 ; i
< nb_tracefile
; i
++) {
1593 LTTV_TRACEFILE_STATE(g_array_index(self
->parent
.tracefiles
,
1594 LttvTracefileContext
*, i
));
1595 tracefile_tree
= g_object_new(LTTV_ATTRIBUTE_TYPE
, NULL
);
1596 value
= lttv_attribute_add(tracefiles_tree
, i
,
1598 *(value
.v_gobject
) = (GObject
*)tracefile_tree
;
1600 value
= lttv_attribute_add(tracefile_tree
, LTTV_STATE_PROCESS
,
1602 *(value
.v_uint
) = tfcs
->process
->pid
;
1604 value
= lttv_attribute_add(tracefile_tree
, LTTV_STATE_EVENT
,
1606 /* Only save the position if the tfs has not infinite time. */
1607 //if(!g_tree_lookup(self->parent.ts_context->pqueue, &tfcs->parent)
1608 // && current_tfcs != tfcs) {
1609 if(ltt_time_compare(tfcs
->parent
.timestamp
, ltt_time_infinite
) == 0) {
1610 *(value
.v_pointer
) = NULL
;
1612 LttEvent
*e
= ltt_tracefile_get_event(tfcs
->parent
.tf
);
1613 ep
= ltt_event_position_new();
1614 ltt_event_position(e
, ep
);
1615 *(value
.v_pointer
) = ep
;
1617 guint nb_block
, offset
;
1620 ltt_event_position_get(ep
, &tf
, &nb_block
, &offset
, &tsc
);
1621 g_info("Block %u offset %u tsc %" PRIu64
" time %lu.%lu", nb_block
, offset
,
1623 tfcs
->parent
.timestamp
.tv_sec
, tfcs
->parent
.timestamp
.tv_nsec
);
1627 /* save the cpu state */
1629 value
= lttv_attribute_add(container
, LTTV_STATE_RESOURCE_CPUS_COUNT
,
1631 *(value
.v_uint
) = nb_cpus
;
1633 value
= lttv_attribute_add(container
, LTTV_STATE_RESOURCE_CPUS
,
1635 *(value
.v_pointer
) = lttv_state_copy_cpu_states(self
->cpu_states
, nb_cpus
);
1638 /* save the irq state */
1639 nb_irqs
= self
->nb_irqs
;
1641 value
= lttv_attribute_add(container
, LTTV_STATE_RESOURCE_IRQS
,
1643 *(value
.v_pointer
) = lttv_state_copy_irq_states(self
->irq_states
, nb_irqs
);
1646 /* save the soft irq state */
1647 nb_soft_irqs
= self
->nb_soft_irqs
;
1649 value
= lttv_attribute_add(container
, LTTV_STATE_RESOURCE_SOFT_IRQS
,
1651 *(value
.v_pointer
) = lttv_state_copy_soft_irq_states(self
->soft_irq_states
, nb_soft_irqs
);
1654 /* save the trap state */
1655 nb_traps
= self
->nb_traps
;
1657 value
= lttv_attribute_add(container
, LTTV_STATE_RESOURCE_TRAPS
,
1659 *(value
.v_pointer
) = lttv_state_copy_trap_states(self
->trap_states
, nb_traps
);
1662 /* save the blkdev states */
1663 value
= lttv_attribute_add(container
, LTTV_STATE_RESOURCE_BLKDEVS
,
1665 *(value
.v_pointer
) = lttv_state_copy_blkdev_hashtable(self
->bdev_states
);
1669 static void state_restore(LttvTraceState
*self
, LttvAttribute
*container
)
1671 guint i
, nb_tracefile
, pid
, nb_cpus
, nb_irqs
, nb_soft_irqs
, nb_traps
;
1673 LttvTracefileState
*tfcs
;
1675 LttvAttribute
*tracefiles_tree
, *tracefile_tree
;
1677 guint
*running_process
;
1679 LttvAttributeType type
;
1681 LttvAttributeValue value
;
1683 LttvAttributeName name
;
1687 LttEventPosition
*ep
;
1689 LttvTracesetContext
*tsc
= self
->parent
.ts_context
;
1691 tracefiles_tree
= lttv_attribute_find_subdir(container
,
1692 LTTV_STATE_TRACEFILES
);
1694 type
= lttv_attribute_get_by_name(container
, LTTV_STATE_PROCESSES
,
1696 g_assert(type
== LTTV_POINTER
);
1697 lttv_state_free_process_table(self
->processes
);
1698 self
->processes
= lttv_state_copy_process_table(*(value
.v_pointer
));
1700 /* Add the currently running processes array */
1701 nb_cpus
= ltt_trace_get_num_cpu(self
->parent
.t
);
1702 type
= lttv_attribute_get_by_name(container
, LTTV_STATE_RUNNING_PROCESS
,
1704 g_assert(type
== LTTV_POINTER
);
1705 running_process
= *(value
.v_pointer
);
1706 for(i
=0;i
<nb_cpus
;i
++) {
1707 pid
= running_process
[i
];
1708 self
->running_process
[i
] = lttv_state_find_process(self
, i
, pid
);
1709 g_assert(self
->running_process
[i
] != NULL
);
1712 nb_tracefile
= self
->parent
.tracefiles
->len
;
1714 //g_tree_destroy(tsc->pqueue);
1715 //tsc->pqueue = g_tree_new(compare_tracefile);
1717 /* restore cpu resource states */
1718 type
= lttv_attribute_get_by_name(container
, LTTV_STATE_RESOURCE_CPUS
, &value
);
1719 g_assert(type
== LTTV_POINTER
);
1720 lttv_state_free_cpu_states(self
->cpu_states
, nb_cpus
);
1721 self
->cpu_states
= lttv_state_copy_cpu_states(*(value
.v_pointer
), nb_cpus
);
1723 /* restore irq resource states */
1724 nb_irqs
= self
->nb_irqs
;
1725 type
= lttv_attribute_get_by_name(container
, LTTV_STATE_RESOURCE_IRQS
, &value
);
1726 g_assert(type
== LTTV_POINTER
);
1727 lttv_state_free_irq_states(self
->irq_states
, nb_irqs
);
1728 self
->irq_states
= lttv_state_copy_irq_states(*(value
.v_pointer
), nb_irqs
);
1730 /* restore soft irq resource states */
1731 nb_soft_irqs
= self
->nb_soft_irqs
;
1732 type
= lttv_attribute_get_by_name(container
, LTTV_STATE_RESOURCE_SOFT_IRQS
, &value
);
1733 g_assert(type
== LTTV_POINTER
);
1734 lttv_state_free_soft_irq_states(self
->soft_irq_states
, nb_soft_irqs
);
1735 self
->soft_irq_states
= lttv_state_copy_soft_irq_states(*(value
.v_pointer
), nb_soft_irqs
);
1737 /* restore trap resource states */
1738 nb_traps
= self
->nb_traps
;
1739 type
= lttv_attribute_get_by_name(container
, LTTV_STATE_RESOURCE_TRAPS
, &value
);
1740 g_assert(type
== LTTV_POINTER
);
1741 lttv_state_free_trap_states(self
->trap_states
, nb_traps
);
1742 self
->trap_states
= lttv_state_copy_trap_states(*(value
.v_pointer
), nb_traps
);
1744 /* restore the blkdev states */
1745 type
= lttv_attribute_get_by_name(container
, LTTV_STATE_RESOURCE_BLKDEVS
, &value
);
1746 g_assert(type
== LTTV_POINTER
);
1747 lttv_state_free_blkdev_hashtable(self
->bdev_states
);
1748 self
->bdev_states
= lttv_state_copy_blkdev_hashtable(*(value
.v_pointer
));
1750 for(i
= 0 ; i
< nb_tracefile
; i
++) {
1752 LTTV_TRACEFILE_STATE(g_array_index(self
->parent
.tracefiles
,
1753 LttvTracefileContext
*, i
));
1754 type
= lttv_attribute_get(tracefiles_tree
, i
, &name
, &value
, &is_named
);
1755 g_assert(type
== LTTV_GOBJECT
);
1756 tracefile_tree
= *((LttvAttribute
**)(value
.v_gobject
));
1758 type
= lttv_attribute_get_by_name(tracefile_tree
, LTTV_STATE_PROCESS
,
1760 g_assert(type
== LTTV_UINT
);
1761 pid
= *(value
.v_uint
);
1762 tfcs
->process
= lttv_state_find_process_or_create(tfcs
, pid
);
1764 type
= lttv_attribute_get_by_name(tracefile_tree
, LTTV_STATE_EVENT
,
1766 g_assert(type
== LTTV_POINTER
);
1767 //g_assert(*(value.v_pointer) != NULL);
1768 ep
= *(value
.v_pointer
);
1769 g_assert(tfcs
->parent
.t_context
!= NULL
);
1771 tfcs
->cpu_state
= &self
->cpu_states
[tfcs
->cpu
];
1773 LttvTracefileContext
*tfc
= LTTV_TRACEFILE_CONTEXT(tfcs
);
1774 g_tree_remove(tsc
->pqueue
, tfc
);
1777 g_assert(ltt_tracefile_seek_position(tfc
->tf
, ep
) == 0);
1778 tfc
->timestamp
= ltt_event_time(ltt_tracefile_get_event(tfc
->tf
));
1779 g_assert(ltt_time_compare(tfc
->timestamp
, ltt_time_infinite
) != 0);
1780 g_tree_insert(tsc
->pqueue
, tfc
, tfc
);
1781 g_info("Restoring state for a tf at time %lu.%lu", tfc
->timestamp
.tv_sec
, tfc
->timestamp
.tv_nsec
);
1783 tfc
->timestamp
= ltt_time_infinite
;
1789 static void state_saved_free(LttvTraceState
*self
, LttvAttribute
*container
)
1791 guint i
, nb_tracefile
, nb_cpus
, nb_irqs
, nb_softirqs
;
1793 LttvTracefileState
*tfcs
;
1795 LttvAttribute
*tracefiles_tree
, *tracefile_tree
;
1797 guint
*running_process
;
1799 LttvAttributeType type
;
1801 LttvAttributeValue value
;
1803 LttvAttributeName name
;
1807 tracefiles_tree
= lttv_attribute_find_subdir(container
,
1808 LTTV_STATE_TRACEFILES
);
1809 g_object_ref(G_OBJECT(tracefiles_tree
));
1810 lttv_attribute_remove_by_name(container
, LTTV_STATE_TRACEFILES
);
1812 type
= lttv_attribute_get_by_name(container
, LTTV_STATE_PROCESSES
,
1814 g_assert(type
== LTTV_POINTER
);
1815 lttv_state_free_process_table(*(value
.v_pointer
));
1816 *(value
.v_pointer
) = NULL
;
1817 lttv_attribute_remove_by_name(container
, LTTV_STATE_PROCESSES
);
1819 /* Free running processes array */
1820 type
= lttv_attribute_get_by_name(container
, LTTV_STATE_RUNNING_PROCESS
,
1822 g_assert(type
== LTTV_POINTER
);
1823 running_process
= *(value
.v_pointer
);
1824 g_free(running_process
);
1826 /* free cpu resource states */
1827 type
= lttv_attribute_get_by_name(container
, LTTV_STATE_RESOURCE_CPUS_COUNT
, &value
);
1828 g_assert(type
== LTTV_UINT
);
1829 nb_cpus
= *value
.v_uint
;
1830 type
= lttv_attribute_get_by_name(container
, LTTV_STATE_RESOURCE_CPUS
, &value
);
1831 g_assert(type
== LTTV_POINTER
);
1832 lttv_state_free_cpu_states(*(value
.v_pointer
), nb_cpus
);
1834 /* free irq resource states */
1835 nb_irqs
= self
->nb_irqs
;
1836 type
= lttv_attribute_get_by_name(container
, LTTV_STATE_RESOURCE_IRQS
, &value
);
1837 g_assert(type
== LTTV_POINTER
);
1838 lttv_state_free_irq_states(*(value
.v_pointer
), nb_irqs
);
1840 /* free softirq resource states */
1841 nb_softirqs
= self
->nb_irqs
;
1842 type
= lttv_attribute_get_by_name(container
, LTTV_STATE_RESOURCE_SOFT_IRQS
, &value
);
1843 g_assert(type
== LTTV_POINTER
);
1844 lttv_state_free_soft_irq_states(*(value
.v_pointer
), nb_softirqs
);
1846 /* free the blkdev states */
1847 type
= lttv_attribute_get_by_name(container
, LTTV_STATE_RESOURCE_BLKDEVS
, &value
);
1848 g_assert(type
== LTTV_POINTER
);
1849 lttv_state_free_blkdev_hashtable(*(value
.v_pointer
));
1851 nb_tracefile
= self
->parent
.tracefiles
->len
;
1853 for(i
= 0 ; i
< nb_tracefile
; i
++) {
1855 LTTV_TRACEFILE_STATE(g_array_index(self
->parent
.tracefiles
,
1856 LttvTracefileContext
*, i
));
1857 type
= lttv_attribute_get(tracefiles_tree
, i
, &name
, &value
, &is_named
);
1858 g_assert(type
== LTTV_GOBJECT
);
1859 tracefile_tree
= *((LttvAttribute
**)(value
.v_gobject
));
1861 type
= lttv_attribute_get_by_name(tracefile_tree
, LTTV_STATE_EVENT
,
1863 g_assert(type
== LTTV_POINTER
);
1864 if(*(value
.v_pointer
) != NULL
) g_free(*(value
.v_pointer
));
1866 g_object_unref(G_OBJECT(tracefiles_tree
));
1870 static void free_saved_state(LttvTraceState
*self
)
1874 LttvAttributeType type
;
1876 LttvAttributeValue value
;
1878 LttvAttributeName name
;
1882 LttvAttribute
*saved_states
;
1884 saved_states
= lttv_attribute_find_subdir(self
->parent
.t_a
,
1885 LTTV_STATE_SAVED_STATES
);
1887 nb
= lttv_attribute_get_number(saved_states
);
1888 for(i
= 0 ; i
< nb
; i
++) {
1889 type
= lttv_attribute_get(saved_states
, i
, &name
, &value
, &is_named
);
1890 g_assert(type
== LTTV_GOBJECT
);
1891 state_saved_free(self
, *((LttvAttribute
**)value
.v_gobject
));
1894 lttv_attribute_remove_by_name(self
->parent
.t_a
, LTTV_STATE_SAVED_STATES
);
1899 create_max_time(LttvTraceState
*tcs
)
1901 LttvAttributeValue v
;
1903 lttv_attribute_find(tcs
->parent
.t_a
, LTTV_STATE_SAVED_STATES_TIME
,
1905 g_assert(*(v
.v_pointer
) == NULL
);
1906 *(v
.v_pointer
) = g_new(LttTime
,1);
1907 *((LttTime
*)*(v
.v_pointer
)) = ltt_time_zero
;
1912 get_max_time(LttvTraceState
*tcs
)
1914 LttvAttributeValue v
;
1916 lttv_attribute_find(tcs
->parent
.t_a
, LTTV_STATE_SAVED_STATES_TIME
,
1918 g_assert(*(v
.v_pointer
) != NULL
);
1919 tcs
->max_time_state_recomputed_in_seek
= (LttTime
*)*(v
.v_pointer
);
1924 free_max_time(LttvTraceState
*tcs
)
1926 LttvAttributeValue v
;
1928 lttv_attribute_find(tcs
->parent
.t_a
, LTTV_STATE_SAVED_STATES_TIME
,
1930 g_free(*(v
.v_pointer
));
1931 *(v
.v_pointer
) = NULL
;
1935 typedef struct _LttvNameTables
{
1936 // FIXME GQuark *eventtype_names;
1937 GQuark
*syscall_names
;
1943 GQuark
*soft_irq_names
;
1945 GHashTable
*kprobe_hash
;
1950 create_name_tables(LttvTraceState
*tcs
)
1954 GString
*fe_name
= g_string_new("");
1956 LttvNameTables
*name_tables
= g_new(LttvNameTables
, 1);
1958 LttvAttributeValue v
;
1962 lttv_attribute_find(tcs
->parent
.t_a
, LTTV_STATE_NAME_TABLES
,
1964 g_assert(*(v
.v_pointer
) == NULL
);
1965 *(v
.v_pointer
) = name_tables
;
1967 hooks
= g_array_sized_new(FALSE
, FALSE
, sizeof(LttvTraceHook
), 1);
1969 if(!lttv_trace_find_hook(tcs
->parent
.t
,
1971 LTT_EVENT_SYSCALL_ENTRY
,
1972 FIELD_ARRAY(LTT_FIELD_SYSCALL_ID
),
1973 NULL
, NULL
, &hooks
)) {
1975 // th = lttv_trace_hook_get_first(&th);
1977 // t = ltt_field_type(lttv_trace_get_hook_field(th, 0));
1978 // nb = ltt_type_element_number(t);
1980 // name_tables->syscall_names = g_new(GQuark, nb);
1981 // name_tables->nb_syscalls = nb;
1983 // for(i = 0 ; i < nb ; i++) {
1984 // name_tables->syscall_names[i] = ltt_enum_string_get(t, i);
1985 // if(!name_tables->syscall_names[i]) {
1986 // GString *string = g_string_new("");
1987 // g_string_printf(string, "syscall %u", i);
1988 // name_tables->syscall_names[i] = g_quark_from_string(string->str);
1989 // g_string_free(string, TRUE);
1993 name_tables
->nb_syscalls
= 256;
1994 name_tables
->syscall_names
= g_new(GQuark
, 256);
1995 for(i
= 0 ; i
< 256 ; i
++) {
1996 g_string_printf(fe_name
, "syscall %d", i
);
1997 name_tables
->syscall_names
[i
] = g_quark_from_string(fe_name
->str
);
2000 name_tables
->syscall_names
= NULL
;
2001 name_tables
->nb_syscalls
= 0;
2003 lttv_trace_hook_remove_all(&hooks
);
2005 if(!lttv_trace_find_hook(tcs
->parent
.t
,
2007 LTT_EVENT_TRAP_ENTRY
,
2008 FIELD_ARRAY(LTT_FIELD_TRAP_ID
),
2009 NULL
, NULL
, &hooks
) ||
2010 !lttv_trace_find_hook(tcs
->parent
.t
,
2012 LTT_EVENT_PAGE_FAULT_ENTRY
,
2013 FIELD_ARRAY(LTT_FIELD_TRAP_ID
),
2014 NULL
, NULL
, &hooks
)) {
2016 // th = lttv_trace_hook_get_first(&th);
2018 // t = ltt_field_type(lttv_trace_get_hook_field(th, 0));
2019 // //nb = ltt_type_element_number(t);
2021 // name_tables->trap_names = g_new(GQuark, nb);
2022 // for(i = 0 ; i < nb ; i++) {
2023 // name_tables->trap_names[i] = g_quark_from_string(
2024 // ltt_enum_string_get(t, i));
2027 name_tables
->nb_traps
= 256;
2028 name_tables
->trap_names
= g_new(GQuark
, 256);
2029 for(i
= 0 ; i
< 256 ; i
++) {
2030 g_string_printf(fe_name
, "trap %d", i
);
2031 name_tables
->trap_names
[i
] = g_quark_from_string(fe_name
->str
);
2034 name_tables
->trap_names
= NULL
;
2035 name_tables
->nb_traps
= 0;
2037 lttv_trace_hook_remove_all(&hooks
);
2039 if(!lttv_trace_find_hook(tcs
->parent
.t
,
2041 LTT_EVENT_IRQ_ENTRY
,
2042 FIELD_ARRAY(LTT_FIELD_IRQ_ID
),
2043 NULL
, NULL
, &hooks
)) {
2046 name_tables->irq_names = g_new(GQuark, nb);
2047 for(i = 0 ; i < nb ; i++) {
2048 name_tables->irq_names[i] = g_quark_from_string(ltt_enum_string_get(t, i));
2052 name_tables
->nb_irqs
= 256;
2053 name_tables
->irq_names
= g_new(GQuark
, 256);
2054 for(i
= 0 ; i
< 256 ; i
++) {
2055 g_string_printf(fe_name
, "irq %d", i
);
2056 name_tables
->irq_names
[i
] = g_quark_from_string(fe_name
->str
);
2059 name_tables
->nb_irqs
= 0;
2060 name_tables
->irq_names
= NULL
;
2062 lttv_trace_hook_remove_all(&hooks
);
2064 name_tables->soft_irq_names = g_new(GQuark, nb);
2065 for(i = 0 ; i < nb ; i++) {
2066 name_tables->soft_irq_names[i] = g_quark_from_string(ltt_enum_string_get(t, i));
2070 /* the kernel is limited to 32 statically defined softirqs */
2071 name_tables
->nb_softirqs
= 32;
2072 name_tables
->soft_irq_names
= g_new(GQuark
, name_tables
->nb_softirqs
);
2073 for(i
= 0 ; i
< name_tables
->nb_softirqs
; i
++) {
2074 g_string_printf(fe_name
, "softirq %d", i
);
2075 name_tables
->soft_irq_names
[i
] = g_quark_from_string(fe_name
->str
);
2077 g_array_free(hooks
, TRUE
);
2079 g_string_free(fe_name
, TRUE
);
2081 #if (__SIZEOF_LONG__ == 4)
2082 name_tables
->kprobe_hash
= g_hash_table_new_full(guint64_hash
, guint64_equal
,
2085 name_tables
->kprobe_hash
= g_hash_table_new(g_direct_hash
, g_direct_equal
);
2091 get_name_tables(LttvTraceState
*tcs
)
2093 LttvNameTables
*name_tables
;
2095 LttvAttributeValue v
;
2097 lttv_attribute_find(tcs
->parent
.t_a
, LTTV_STATE_NAME_TABLES
,
2099 g_assert(*(v
.v_pointer
) != NULL
);
2100 name_tables
= (LttvNameTables
*)*(v
.v_pointer
);
2101 //tcs->eventtype_names = name_tables->eventtype_names;
2102 tcs
->syscall_names
= name_tables
->syscall_names
;
2103 tcs
->nb_syscalls
= name_tables
->nb_syscalls
;
2104 tcs
->trap_names
= name_tables
->trap_names
;
2105 tcs
->nb_traps
= name_tables
->nb_traps
;
2106 tcs
->irq_names
= name_tables
->irq_names
;
2107 tcs
->soft_irq_names
= name_tables
->soft_irq_names
;
2108 tcs
->nb_irqs
= name_tables
->nb_irqs
;
2109 tcs
->nb_soft_irqs
= name_tables
->nb_softirqs
;
2110 tcs
->kprobe_hash
= name_tables
->kprobe_hash
;
2115 free_name_tables(LttvTraceState
*tcs
)
2117 LttvNameTables
*name_tables
;
2119 LttvAttributeValue v
;
2121 lttv_attribute_find(tcs
->parent
.t_a
, LTTV_STATE_NAME_TABLES
,
2123 name_tables
= (LttvNameTables
*)*(v
.v_pointer
);
2124 *(v
.v_pointer
) = NULL
;
2126 // g_free(name_tables->eventtype_names);
2127 if(name_tables
->syscall_names
) g_free(name_tables
->syscall_names
);
2128 if(name_tables
->trap_names
) g_free(name_tables
->trap_names
);
2129 if(name_tables
->irq_names
) g_free(name_tables
->irq_names
);
2130 if(name_tables
->soft_irq_names
) g_free(name_tables
->soft_irq_names
);
2131 if(name_tables
) g_free(name_tables
);
2132 if(name_tables
) g_hash_table_destroy(name_tables
->kprobe_hash
);
2135 #ifdef HASH_TABLE_DEBUG
2137 static void test_process(gpointer key
, gpointer value
, gpointer user_data
)
2139 LttvProcessState
*process
= (LttvProcessState
*)value
;
2141 /* Test for process corruption */
2142 guint stack_len
= process
->execution_stack
->len
;
2145 static void hash_table_check(GHashTable
*table
)
2147 g_hash_table_foreach(table
, test_process
, NULL
);
2153 /* clears the stack and sets the state passed as argument */
2154 static void cpu_set_base_mode(LttvCPUState
*cpust
, LttvCPUMode state
)
2156 g_array_set_size(cpust
->mode_stack
, 1);
2157 ((GQuark
*)cpust
->mode_stack
->data
)[0] = state
;
2160 static void cpu_push_mode(LttvCPUState
*cpust
, LttvCPUMode state
)
2162 g_array_set_size(cpust
->mode_stack
, cpust
->mode_stack
->len
+ 1);
2163 ((GQuark
*)cpust
->mode_stack
->data
)[cpust
->mode_stack
->len
- 1] = state
;
2166 static void cpu_pop_mode(LttvCPUState
*cpust
)
2168 if(cpust
->mode_stack
->len
<= 1)
2169 cpu_set_base_mode(cpust
, LTTV_CPU_UNKNOWN
);
2171 g_array_set_size(cpust
->mode_stack
, cpust
->mode_stack
->len
- 1);
2174 /* clears the stack and sets the state passed as argument */
2175 static void bdev_set_base_mode(LttvBdevState
*bdevst
, LttvBdevMode state
)
2177 g_array_set_size(bdevst
->mode_stack
, 1);
2178 ((GQuark
*)bdevst
->mode_stack
->data
)[0] = state
;
2181 static void bdev_push_mode(LttvBdevState
*bdevst
, LttvBdevMode state
)
2183 g_array_set_size(bdevst
->mode_stack
, bdevst
->mode_stack
->len
+ 1);
2184 ((GQuark
*)bdevst
->mode_stack
->data
)[bdevst
->mode_stack
->len
- 1] = state
;
2187 static void bdev_pop_mode(LttvBdevState
*bdevst
)
2189 if(bdevst
->mode_stack
->len
<= 1)
2190 bdev_set_base_mode(bdevst
, LTTV_BDEV_UNKNOWN
);
2192 g_array_set_size(bdevst
->mode_stack
, bdevst
->mode_stack
->len
- 1);
2195 static void irq_set_base_mode(LttvIRQState
*irqst
, LttvIRQMode state
)
2197 g_array_set_size(irqst
->mode_stack
, 1);
2198 ((GQuark
*)irqst
->mode_stack
->data
)[0] = state
;
2201 static void irq_push_mode(LttvIRQState
*irqst
, LttvIRQMode state
)
2203 g_array_set_size(irqst
->mode_stack
, irqst
->mode_stack
->len
+ 1);
2204 ((GQuark
*)irqst
->mode_stack
->data
)[irqst
->mode_stack
->len
- 1] = state
;
2207 static void irq_pop_mode(LttvIRQState
*irqst
)
2209 if(irqst
->mode_stack
->len
<= 1)
2210 irq_set_base_mode(irqst
, LTTV_IRQ_UNKNOWN
);
2212 g_array_set_size(irqst
->mode_stack
, irqst
->mode_stack
->len
- 1);
2215 static void push_state(LttvTracefileState
*tfs
, LttvExecutionMode t
,
2218 LttvExecutionState
*es
;
2220 LttvTraceState
*ts
= (LttvTraceState
*)tfs
->parent
.t_context
;
2221 guint cpu
= tfs
->cpu
;
2223 #ifdef HASH_TABLE_DEBUG
2224 hash_table_check(ts
->processes
);
2226 LttvProcessState
*process
= ts
->running_process
[cpu
];
2228 guint depth
= process
->execution_stack
->len
;
2230 process
->execution_stack
=
2231 g_array_set_size(process
->execution_stack
, depth
+ 1);
2234 &g_array_index(process
->execution_stack
, LttvExecutionState
, depth
- 1);
2236 es
= &g_array_index(process
->execution_stack
, LttvExecutionState
, depth
);
2239 es
->entry
= es
->change
= tfs
->parent
.timestamp
;
2240 es
->cum_cpu_time
= ltt_time_zero
;
2241 es
->s
= process
->state
->s
;
2242 process
->state
= es
;
2246 * return 1 when empty, else 0 */
2247 int lttv_state_pop_state_cleanup(LttvProcessState
*process
,
2248 LttvTracefileState
*tfs
)
2250 guint depth
= process
->execution_stack
->len
;
2256 process
->execution_stack
=
2257 g_array_set_size(process
->execution_stack
, depth
- 1);
2258 process
->state
= &g_array_index(process
->execution_stack
, LttvExecutionState
,
2260 process
->state
->change
= tfs
->parent
.timestamp
;
2265 static void pop_state(LttvTracefileState
*tfs
, LttvExecutionMode t
)
2267 guint cpu
= tfs
->cpu
;
2268 LttvTraceState
*ts
= (LttvTraceState
*)tfs
->parent
.t_context
;
2269 LttvProcessState
*process
= ts
->running_process
[cpu
];
2271 guint depth
= process
->execution_stack
->len
;
2273 if(process
->state
->t
!= t
){
2274 g_info("Different execution mode type (%lu.%09lu): ignore it\n",
2275 tfs
->parent
.timestamp
.tv_sec
, tfs
->parent
.timestamp
.tv_nsec
);
2276 g_info("process state has %s when pop_int is %s\n",
2277 g_quark_to_string(process
->state
->t
),
2278 g_quark_to_string(t
));
2279 g_info("{ %u, %u, %s, %s, %s }\n",
2282 g_quark_to_string(process
->name
),
2283 g_quark_to_string(process
->brand
),
2284 g_quark_to_string(process
->state
->s
));
2289 g_info("Trying to pop last state on stack (%lu.%09lu): ignore it\n",
2290 tfs
->parent
.timestamp
.tv_sec
, tfs
->parent
.timestamp
.tv_nsec
);
2294 process
->execution_stack
=
2295 g_array_set_size(process
->execution_stack
, depth
- 1);
2296 process
->state
= &g_array_index(process
->execution_stack
, LttvExecutionState
,
2298 process
->state
->change
= tfs
->parent
.timestamp
;
2301 struct search_result
{
2302 const LttTime
*time
; /* Requested time */
2303 LttTime
*best
; /* Best result */
2306 static gint
search_usertrace(gconstpointer a
, gconstpointer b
)
2308 const LttTime
*elem_time
= (const LttTime
*)a
;
2309 /* Explicit non const cast */
2310 struct search_result
*res
= (struct search_result
*)b
;
2312 if(ltt_time_compare(*elem_time
, *(res
->time
)) < 0) {
2313 /* The usertrace was created before the schedchange */
2314 /* Get larger keys */
2316 } else if(ltt_time_compare(*elem_time
, *(res
->time
)) >= 0) {
2317 /* The usertrace was created after the schedchange time */
2318 /* Get smaller keys */
2320 if(ltt_time_compare(*elem_time
, *res
->best
) < 0) {
2321 res
->best
= (LttTime
*)elem_time
;
2324 res
->best
= (LttTime
*)elem_time
;
2331 static LttvTracefileState
*ltt_state_usertrace_find(LttvTraceState
*tcs
,
2332 guint pid
, const LttTime
*timestamp
)
2334 LttvTracefileState
*tfs
= NULL
;
2335 struct search_result res
;
2336 /* Find the usertrace associated with a pid and time interval.
2337 * Search in the usertraces by PID (within a hash) and then, for each
2338 * corresponding element of the array, find the first one with creation
2339 * timestamp the lowest, but higher or equal to "timestamp". */
2340 res
.time
= timestamp
;
2342 GTree
*usertrace_tree
= g_hash_table_lookup(tcs
->usertraces
,
2343 GUINT_TO_POINTER(pid
));
2344 if(usertrace_tree
) {
2345 g_tree_search(usertrace_tree
, search_usertrace
, &res
);
2347 tfs
= g_tree_lookup(usertrace_tree
, res
.best
);
2353 /* Return a new and initialized LttvProcessState structure */
2356 lttv_state_create_process(LttvTraceState
*tcs
, LttvProcessState
*parent
,
2357 guint cpu
, guint pid
, guint tgid
, GQuark name
, const LttTime
*timestamp
)
2359 LttvProcessState
*process
= g_new(LttvProcessState
, 1);
2361 LttvExecutionState
*es
;
2366 process
->tgid
= tgid
;
2368 process
->name
= name
;
2369 process
->brand
= LTTV_STATE_UNBRANDED
;
2370 //process->last_cpu = tfs->cpu_name;
2371 //process->last_cpu_index = ltt_tracefile_num(((LttvTracefileContext*)tfs)->tf);
2372 process
->type
= LTTV_STATE_USER_THREAD
;
2373 process
->usertrace
= ltt_state_usertrace_find(tcs
, pid
, timestamp
);
2374 process
->current_function
= 0; //function 0x0 by default.
2376 g_info("Process %u, core %p", process
->pid
, process
);
2377 g_hash_table_insert(tcs
->processes
, process
, process
);
2380 process
->ppid
= parent
->pid
;
2381 process
->creation_time
= *timestamp
;
2384 /* No parent. This process exists but we are missing all information about
2385 its creation. The birth time is set to zero but we remember the time of
2390 process
->creation_time
= ltt_time_zero
;
2393 process
->insertion_time
= *timestamp
;
2394 sprintf(buffer
,"%d-%lu.%lu",pid
, process
->creation_time
.tv_sec
,
2395 process
->creation_time
.tv_nsec
);
2396 process
->pid_time
= g_quark_from_string(buffer
);
2398 process
->free_events
= 0;
2399 //process->last_cpu = tfs->cpu_name;
2400 //process->last_cpu_index = ltt_tracefile_num(((LttvTracefileContext*)tfs)->tf);
2401 process
->execution_stack
= g_array_sized_new(FALSE
, FALSE
,
2402 sizeof(LttvExecutionState
), PREALLOCATED_EXECUTION_STACK
);
2403 process
->execution_stack
= g_array_set_size(process
->execution_stack
, 2);
2404 es
= process
->state
= &g_array_index(process
->execution_stack
,
2405 LttvExecutionState
, 0);
2406 es
->t
= LTTV_STATE_USER_MODE
;
2407 es
->n
= LTTV_STATE_SUBMODE_NONE
;
2408 es
->entry
= *timestamp
;
2409 //g_assert(timestamp->tv_sec != 0);
2410 es
->change
= *timestamp
;
2411 es
->cum_cpu_time
= ltt_time_zero
;
2412 es
->s
= LTTV_STATE_RUN
;
2414 es
= process
->state
= &g_array_index(process
->execution_stack
,
2415 LttvExecutionState
, 1);
2416 es
->t
= LTTV_STATE_SYSCALL
;
2417 es
->n
= LTTV_STATE_SUBMODE_NONE
;
2418 es
->entry
= *timestamp
;
2419 //g_assert(timestamp->tv_sec != 0);
2420 es
->change
= *timestamp
;
2421 es
->cum_cpu_time
= ltt_time_zero
;
2422 es
->s
= LTTV_STATE_WAIT_FORK
;
2424 /* Allocate an empty function call stack. If it's empty, use 0x0. */
2425 process
->user_stack
= g_array_sized_new(FALSE
, FALSE
,
2426 sizeof(guint64
), 0);
2428 process
->fds
= g_hash_table_new(g_direct_hash
, g_direct_equal
);
2433 LttvProcessState
*lttv_state_find_process(LttvTraceState
*ts
, guint cpu
,
2436 LttvProcessState key
;
2437 LttvProcessState
*process
;
2441 process
= g_hash_table_lookup(ts
->processes
, &key
);
2446 lttv_state_find_process_or_create(LttvTraceState
*ts
, guint cpu
, guint pid
,
2447 const LttTime
*timestamp
)
2449 LttvProcessState
*process
= lttv_state_find_process(ts
, cpu
, pid
);
2450 LttvExecutionState
*es
;
2452 /* Put ltt_time_zero creation time for unexisting processes */
2453 if(unlikely(process
== NULL
)) {
2454 process
= lttv_state_create_process(ts
,
2455 NULL
, cpu
, pid
, 0, LTTV_STATE_UNNAMED
, timestamp
);
2456 /* We are not sure is it's a kernel thread or normal thread, put the
2457 * bottom stack state to unknown */
2458 process
->execution_stack
=
2459 g_array_set_size(process
->execution_stack
, 1);
2460 process
->state
= es
=
2461 &g_array_index(process
->execution_stack
, LttvExecutionState
, 0);
2462 es
->t
= LTTV_STATE_MODE_UNKNOWN
;
2463 es
->s
= LTTV_STATE_UNNAMED
;
2468 /* FIXME : this function should be called when we receive an event telling that
2469 * release_task has been called in the kernel. In happens generally when
2470 * the parent waits for its child termination, but may also happens in special
2471 * cases in the child's exit : when the parent ignores its children SIGCCHLD or
2472 * has the flag SA_NOCLDWAIT. It can also happen when the child is part
2473 * of a killed thread group, but isn't the leader.
2475 static int exit_process(LttvTracefileState
*tfs
, LttvProcessState
*process
)
2477 LttvTraceState
*ts
= LTTV_TRACE_STATE(tfs
->parent
.t_context
);
2478 LttvProcessState key
;
2480 /* Wait for both schedule with exit dead and process free to happen.
2481 * They can happen in any order. */
2482 if (++(process
->free_events
) < 2)
2485 key
.pid
= process
->pid
;
2486 key
.cpu
= process
->cpu
;
2487 g_hash_table_remove(ts
->processes
, &key
);
2488 g_array_free(process
->execution_stack
, TRUE
);
2489 g_array_free(process
->user_stack
, TRUE
);
2491 /* the following also clears the content */
2492 g_hash_table_destroy(process
->fds
);
2499 static void free_process_state(gpointer key
, gpointer value
,gpointer user_data
)
2501 g_array_free(((LttvProcessState
*)value
)->execution_stack
, TRUE
);
2502 g_array_free(((LttvProcessState
*)value
)->user_stack
, TRUE
);
2504 /* the following also clears the content */
2505 g_hash_table_destroy(((LttvProcessState
*)value
)->fds
);
2511 static void lttv_state_free_process_table(GHashTable
*processes
)
2513 g_hash_table_foreach(processes
, free_process_state
, NULL
);
2514 g_hash_table_destroy(processes
);
2518 static gboolean
syscall_entry(void *hook_data
, void *call_data
)
2520 LttvTracefileState
*s
= (LttvTracefileState
*)call_data
;
2522 LttvTraceState
*ts
= (LttvTraceState
*)s
->parent
.t_context
;
2523 LttvProcessState
*process
= ts
->running_process
[cpu
];
2524 LttEvent
*e
= ltt_tracefile_get_event(s
->parent
.tf
);
2525 LttvTraceHook
*th
= (LttvTraceHook
*)hook_data
;
2526 struct marker_field
*f
= lttv_trace_get_hook_field(th
, 0);
2527 LttvExecutionSubmode submode
;
2529 guint syscall
= ltt_event_get_unsigned(e
, f
);
2530 expand_syscall_table(ts
, syscall
);
2531 submode
= ((LttvTraceState
*)(s
->parent
.t_context
))->syscall_names
[syscall
];
2532 /* There can be no system call from PID 0 : unknown state */
2533 if(process
->pid
!= 0)
2534 push_state(s
, LTTV_STATE_SYSCALL
, submode
);
2539 static gboolean
syscall_exit(void *hook_data
, void *call_data
)
2541 LttvTracefileState
*s
= (LttvTracefileState
*)call_data
;
2543 LttvTraceState
*ts
= (LttvTraceState
*)s
->parent
.t_context
;
2544 LttvProcessState
*process
= ts
->running_process
[cpu
];
2546 /* There can be no system call from PID 0 : unknown state */
2547 if(process
->pid
!= 0)
2548 pop_state(s
, LTTV_STATE_SYSCALL
);
2553 static gboolean
trap_entry(void *hook_data
, void *call_data
)
2555 LttvTracefileState
*s
= (LttvTracefileState
*)call_data
;
2556 LttvTraceState
*ts
= (LttvTraceState
*)s
->parent
.t_context
;
2557 LttEvent
*e
= ltt_tracefile_get_event(s
->parent
.tf
);
2558 LttvTraceHook
*th
= (LttvTraceHook
*)hook_data
;
2559 struct marker_field
*f
= lttv_trace_get_hook_field(th
, 0);
2561 LttvExecutionSubmode submode
;
2563 guint64 trap
= ltt_event_get_long_unsigned(e
, f
);
2565 expand_trap_table(ts
, trap
);
2567 submode
= ((LttvTraceState
*)(s
->parent
.t_context
))->trap_names
[trap
];
2569 push_state(s
, LTTV_STATE_TRAP
, submode
);
2571 /* update cpu status */
2572 cpu_push_mode(s
->cpu_state
, LTTV_CPU_TRAP
);
2574 /* update trap status */
2575 g_array_append_val(s
->cpu_state
->trap_stack
, trap
);
2576 ts
->trap_states
[trap
].running
++;
2581 static gboolean
trap_exit(void *hook_data
, void *call_data
)
2583 LttvTracefileState
*s
= (LttvTracefileState
*)call_data
;
2584 LttvTraceState
*ts
= (LttvTraceState
*)s
->parent
.t_context
;
2586 pop_state(s
, LTTV_STATE_TRAP
);
2588 /* update cpu status */
2589 cpu_pop_mode(s
->cpu_state
);
2591 /* update trap status */
2592 if (s
->cpu_state
->trap_stack
->len
> 0) {
2593 gint last
= g_array_index(s
->cpu_state
->trap_stack
, gint
, s
->cpu_state
->trap_stack
->len
-1);
2594 if(ts
->trap_states
[last
].running
)
2595 ts
->trap_states
[last
].running
--;
2596 g_array_remove_index(s
->cpu_state
->trap_stack
, s
->cpu_state
->trap_stack
->len
-1);
2601 static gboolean
irq_entry(void *hook_data
, void *call_data
)
2603 LttvTracefileState
*s
= (LttvTracefileState
*)call_data
;
2604 LttvTraceState
*ts
= (LttvTraceState
*)s
->parent
.t_context
;
2605 LttEvent
*e
= ltt_tracefile_get_event(s
->parent
.tf
);
2606 //guint8 ev_id = ltt_event_eventtype_id(e);
2607 LttvTraceHook
*th
= (LttvTraceHook
*)hook_data
;
2608 struct marker_field
*f
= lttv_trace_get_hook_field(th
, 0);
2610 LttvExecutionSubmode submode
;
2611 guint64 irq
= ltt_event_get_long_unsigned(e
, f
);
2613 expand_irq_table(ts
, irq
);
2615 submode
= ((LttvTraceState
*)(s
->parent
.t_context
))->irq_names
[irq
];
2617 /* Do something with the info about being in user or system mode when int? */
2618 push_state(s
, LTTV_STATE_IRQ
, submode
);
2620 /* update cpu status */
2621 cpu_push_mode(s
->cpu_state
, LTTV_CPU_IRQ
);
2623 /* update irq status */
2624 g_array_append_val(s
->cpu_state
->irq_stack
, irq
);
2625 irq_push_mode(&ts
->irq_states
[irq
], LTTV_IRQ_BUSY
);
2630 static gboolean
soft_irq_exit(void *hook_data
, void *call_data
)
2632 LttvTracefileState
*s
= (LttvTracefileState
*)call_data
;
2633 LttvTraceState
*ts
= (LttvTraceState
*)s
->parent
.t_context
;
2635 pop_state(s
, LTTV_STATE_SOFT_IRQ
);
2637 /* update cpu status */
2638 cpu_pop_mode(s
->cpu_state
);
2640 /* update softirq status */
2641 if (s
->cpu_state
->softirq_stack
->len
> 0) {
2642 gint last
= g_array_index(s
->cpu_state
->softirq_stack
, gint
, s
->cpu_state
->softirq_stack
->len
-1);
2643 if(ts
->soft_irq_states
[last
].running
)
2644 ts
->soft_irq_states
[last
].running
--;
2645 g_array_remove_index(s
->cpu_state
->softirq_stack
, s
->cpu_state
->softirq_stack
->len
-1);
2650 static gboolean
irq_exit(void *hook_data
, void *call_data
)
2652 LttvTracefileState
*s
= (LttvTracefileState
*)call_data
;
2653 LttvTraceState
*ts
= (LttvTraceState
*)s
->parent
.t_context
;
2655 pop_state(s
, LTTV_STATE_IRQ
);
2657 /* update cpu status */
2658 cpu_pop_mode(s
->cpu_state
);
2660 /* update irq status */
2661 if (s
->cpu_state
->irq_stack
->len
> 0) {
2662 gint last
= g_array_index(s
->cpu_state
->irq_stack
, gint
, s
->cpu_state
->irq_stack
->len
-1);
2663 g_array_remove_index(s
->cpu_state
->irq_stack
, s
->cpu_state
->irq_stack
->len
-1);
2664 irq_pop_mode(&ts
->irq_states
[last
]);
2670 static gboolean
soft_irq_raise(void *hook_data
, void *call_data
)
2672 LttvTracefileState
*s
= (LttvTracefileState
*)call_data
;
2673 LttvTraceState
*ts
= (LttvTraceState
*)s
->parent
.t_context
;
2674 LttEvent
*e
= ltt_tracefile_get_event(s
->parent
.tf
);
2675 //guint8 ev_id = ltt_event_eventtype_id(e);
2676 LttvTraceHook
*th
= (LttvTraceHook
*)hook_data
;
2677 struct marker_field
*f
= lttv_trace_get_hook_field(th
, 0);
2679 LttvExecutionSubmode submode
;
2680 guint64 softirq
= ltt_event_get_long_unsigned(e
, f
);
2681 guint64 nb_softirqs
= ((LttvTraceState
*)(s
->parent
.t_context
))->nb_soft_irqs
;
2683 if(softirq
< nb_softirqs
) {
2684 submode
= ((LttvTraceState
*)(s
->parent
.t_context
))->soft_irq_names
[softirq
];
2686 /* Fixup an incomplete irq table */
2687 GString
*string
= g_string_new("");
2688 g_string_printf(string
, "softirq %" PRIu64
, softirq
);
2689 submode
= g_quark_from_string(string
->str
);
2690 g_string_free(string
, TRUE
);
2693 /* update softirq status */
2694 /* a soft irq raises are not cumulative */
2695 ts
->soft_irq_states
[softirq
].pending
=1;
2700 static gboolean
soft_irq_entry(void *hook_data
, void *call_data
)
2702 LttvTracefileState
*s
= (LttvTracefileState
*)call_data
;
2703 LttvTraceState
*ts
= (LttvTraceState
*)s
->parent
.t_context
;
2704 LttEvent
*e
= ltt_tracefile_get_event(s
->parent
.tf
);
2705 //guint8 ev_id = ltt_event_eventtype_id(e);
2706 LttvTraceHook
*th
= (LttvTraceHook
*)hook_data
;
2707 struct marker_field
*f
= lttv_trace_get_hook_field(th
, 0);
2708 LttvExecutionSubmode submode
;
2709 guint64 softirq
= ltt_event_get_long_unsigned(e
, f
);
2710 expand_soft_irq_table(ts
, softirq
);
2711 submode
= ((LttvTraceState
*)(s
->parent
.t_context
))->soft_irq_names
[softirq
];
2713 /* Do something with the info about being in user or system mode when int? */
2714 push_state(s
, LTTV_STATE_SOFT_IRQ
, submode
);
2716 /* update cpu status */
2717 cpu_push_mode(s
->cpu_state
, LTTV_CPU_SOFT_IRQ
);
2719 /* update softirq status */
2720 g_array_append_val(s
->cpu_state
->softirq_stack
, softirq
);
2721 if(ts
->soft_irq_states
[softirq
].pending
)
2722 ts
->soft_irq_states
[softirq
].pending
--;
2723 ts
->soft_irq_states
[softirq
].running
++;
2728 static gboolean
enum_interrupt(void *hook_data
, void *call_data
)
2730 LttvTracefileState
*s
= (LttvTracefileState
*)call_data
;
2731 LttvTraceState
*ts
= (LttvTraceState
*)s
->parent
.t_context
;
2732 LttEvent
*e
= ltt_tracefile_get_event(s
->parent
.tf
);
2733 //guint8 ev_id = ltt_event_eventtype_id(e);
2734 LttvTraceHook
*th
= (LttvTraceHook
*)hook_data
;
2736 GQuark action
= g_quark_from_string(ltt_event_get_string(e
,
2737 lttv_trace_get_hook_field(th
, 0)));
2738 guint irq
= ltt_event_get_long_unsigned(e
, lttv_trace_get_hook_field(th
, 1));
2740 expand_irq_table(ts
, irq
);
2741 ts
->irq_names
[irq
] = action
;
2747 static gboolean
bdev_request_issue(void *hook_data
, void *call_data
)
2749 LttvTracefileState
*s
= (LttvTracefileState
*)call_data
;
2750 LttvTraceState
*ts
= (LttvTraceState
*)s
->parent
.t_context
;
2751 LttEvent
*e
= ltt_tracefile_get_event(s
->parent
.tf
);
2752 //guint8 ev_id = ltt_event_eventtype_id(e);
2753 LttvTraceHook
*th
= (LttvTraceHook
*)hook_data
;
2755 guint major
= ltt_event_get_long_unsigned(e
,
2756 lttv_trace_get_hook_field(th
, 0));
2757 guint minor
= ltt_event_get_long_unsigned(e
,
2758 lttv_trace_get_hook_field(th
, 1));
2759 guint oper
= ltt_event_get_long_unsigned(e
,
2760 lttv_trace_get_hook_field(th
, 2));
2761 guint16 devcode
= MKDEV(major
,minor
);
2763 /* have we seen this block device before? */
2764 gpointer bdev
= get_hashed_bdevstate(ts
, devcode
);
2767 bdev_push_mode(bdev
, LTTV_BDEV_BUSY_READING
);
2769 bdev_push_mode(bdev
, LTTV_BDEV_BUSY_WRITING
);
2774 static gboolean
bdev_request_complete(void *hook_data
, void *call_data
)
2776 LttvTracefileState
*s
= (LttvTracefileState
*)call_data
;
2777 LttvTraceState
*ts
= (LttvTraceState
*)s
->parent
.t_context
;
2778 LttEvent
*e
= ltt_tracefile_get_event(s
->parent
.tf
);
2779 LttvTraceHook
*th
= (LttvTraceHook
*)hook_data
;
2781 guint major
= ltt_event_get_long_unsigned(e
,
2782 lttv_trace_get_hook_field(th
, 0));
2783 guint minor
= ltt_event_get_long_unsigned(e
,
2784 lttv_trace_get_hook_field(th
, 1));
2785 //guint oper = ltt_event_get_long_unsigned(e,
2786 // lttv_trace_get_hook_field(th, 2));
2787 guint16 devcode
= MKDEV(major
,minor
);
2789 /* have we seen this block device before? */
2790 gpointer bdev
= get_hashed_bdevstate(ts
, devcode
);
2792 /* update block device */
2793 bdev_pop_mode(bdev
);
2798 static void push_function(LttvTracefileState
*tfs
, guint64 funcptr
)
2802 LttvTraceState
*ts
= (LttvTraceState
*)tfs
->parent
.t_context
;
2803 guint cpu
= tfs
->cpu
;
2804 LttvProcessState
*process
= ts
->running_process
[cpu
];
2806 guint depth
= process
->user_stack
->len
;
2808 process
->user_stack
=
2809 g_array_set_size(process
->user_stack
, depth
+ 1);
2811 new_func
= &g_array_index(process
->user_stack
, guint64
, depth
);
2812 *new_func
= funcptr
;
2813 process
->current_function
= funcptr
;
2816 static void pop_function(LttvTracefileState
*tfs
, guint64 funcptr
)
2818 guint cpu
= tfs
->cpu
;
2819 LttvTraceState
*ts
= (LttvTraceState
*)tfs
->parent
.t_context
;
2820 LttvProcessState
*process
= ts
->running_process
[cpu
];
2822 if(process
->current_function
!= funcptr
){
2823 g_info("Different functions (%lu.%09lu): ignore it\n",
2824 tfs
->parent
.timestamp
.tv_sec
, tfs
->parent
.timestamp
.tv_nsec
);
2825 g_info("process state has %" PRIu64
" when pop_function is %" PRIu64
"\n",
2826 process
->current_function
, funcptr
);
2827 g_info("{ %u, %u, %s, %s, %s }\n",
2830 g_quark_to_string(process
->name
),
2831 g_quark_to_string(process
->brand
),
2832 g_quark_to_string(process
->state
->s
));
2835 guint depth
= process
->user_stack
->len
;
2838 g_info("Trying to pop last function on stack (%lu.%09lu): ignore it\n",
2839 tfs
->parent
.timestamp
.tv_sec
, tfs
->parent
.timestamp
.tv_nsec
);
2843 process
->user_stack
=
2844 g_array_set_size(process
->user_stack
, depth
- 1);
2845 process
->current_function
=
2846 g_array_index(process
->user_stack
, guint64
, depth
- 2);
2850 static gboolean
function_entry(void *hook_data
, void *call_data
)
2852 LttvTracefileState
*s
= (LttvTracefileState
*)call_data
;
2853 LttEvent
*e
= ltt_tracefile_get_event(s
->parent
.tf
);
2854 //guint8 ev_id = ltt_event_eventtype_id(e);
2855 LttvTraceHook
*th
= (LttvTraceHook
*)hook_data
;
2856 struct marker_field
*f
= lttv_trace_get_hook_field(th
, 0);
2857 guint64 funcptr
= ltt_event_get_long_unsigned(e
, f
);
2859 push_function(s
, funcptr
);
2863 static gboolean
function_exit(void *hook_data
, void *call_data
)
2865 LttvTracefileState
*s
= (LttvTracefileState
*)call_data
;
2866 LttEvent
*e
= ltt_tracefile_get_event(s
->parent
.tf
);
2867 //guint8 ev_id = ltt_event_eventtype_id(e);
2868 LttvTraceHook
*th
= (LttvTraceHook
*)hook_data
;
2869 struct marker_field
*f
= lttv_trace_get_hook_field(th
, 0);
2870 guint64 funcptr
= ltt_event_get_long_unsigned(e
, f
);
2872 pop_function(s
, funcptr
);
2876 static gboolean
dump_syscall(void *hook_data
, void *call_data
)
2878 LttvTracefileState
*s
= (LttvTracefileState
*)call_data
;
2879 LttvTraceState
*ts
= (LttvTraceState
*)s
->parent
.t_context
;
2880 LttEvent
*e
= ltt_tracefile_get_event(s
->parent
.tf
);
2881 LttvTraceHook
*th
= (LttvTraceHook
*)hook_data
;
2886 id
= ltt_event_get_unsigned(e
, lttv_trace_get_hook_field(th
, 0));
2887 address
= ltt_event_get_long_unsigned(e
, lttv_trace_get_hook_field(th
, 1));
2888 symbol
= ltt_event_get_string(e
, lttv_trace_get_hook_field(th
, 2));
2890 expand_syscall_table(ts
, id
);
2891 ts
->syscall_names
[id
] = g_quark_from_string(symbol
);
2896 static gboolean
dump_kprobe(void *hook_data
, void *call_data
)
2898 LttvTracefileState
*s
= (LttvTracefileState
*)call_data
;
2899 LttvTraceState
*ts
= (LttvTraceState
*)s
->parent
.t_context
;
2900 LttEvent
*e
= ltt_tracefile_get_event(s
->parent
.tf
);
2901 LttvTraceHook
*th
= (LttvTraceHook
*)hook_data
;
2905 ip
= ltt_event_get_long_unsigned(e
, lttv_trace_get_hook_field(th
, 0));
2906 symbol
= ltt_event_get_string(e
, lttv_trace_get_hook_field(th
, 1));
2908 expand_kprobe_table(ts
, ip
, symbol
);
2913 static gboolean
dump_softirq(void *hook_data
, void *call_data
)
2915 LttvTracefileState
*s
= (LttvTracefileState
*)call_data
;
2916 LttvTraceState
*ts
= (LttvTraceState
*)s
->parent
.t_context
;
2917 LttEvent
*e
= ltt_tracefile_get_event(s
->parent
.tf
);
2918 LttvTraceHook
*th
= (LttvTraceHook
*)hook_data
;
2923 id
= ltt_event_get_unsigned(e
, lttv_trace_get_hook_field(th
, 0));
2924 address
= ltt_event_get_long_unsigned(e
, lttv_trace_get_hook_field(th
, 1));
2925 symbol
= ltt_event_get_string(e
, lttv_trace_get_hook_field(th
, 2));
2927 expand_soft_irq_table(ts
, id
);
2928 ts
->soft_irq_names
[id
] = g_quark_from_string(symbol
);
2933 static gboolean
schedchange(void *hook_data
, void *call_data
)
2935 LttvTracefileState
*s
= (LttvTracefileState
*)call_data
;
2937 LttvTraceState
*ts
= (LttvTraceState
*)s
->parent
.t_context
;
2938 LttvProcessState
*process
= ts
->running_process
[cpu
];
2939 //LttvProcessState *old_process = ts->running_process[cpu];
2941 LttEvent
*e
= ltt_tracefile_get_event(s
->parent
.tf
);
2942 LttvTraceHook
*th
= (LttvTraceHook
*)hook_data
;
2943 guint pid_in
, pid_out
;
2946 pid_out
= ltt_event_get_unsigned(e
, lttv_trace_get_hook_field(th
, 0));
2947 pid_in
= ltt_event_get_unsigned(e
, lttv_trace_get_hook_field(th
, 1));
2948 state_out
= ltt_event_get_long_int(e
, lttv_trace_get_hook_field(th
, 2));
2950 if(likely(process
!= NULL
)) {
2952 /* We could not know but it was not the idle process executing.
2953 This should only happen at the beginning, before the first schedule
2954 event, and when the initial information (current process for each CPU)
2955 is missing. It is not obvious how we could, after the fact, compensate
2956 the wrongly attributed statistics. */
2958 //This test only makes sense once the state is known and if there is no
2959 //missing events. We need to silently ignore schedchange coming after a
2960 //process_free, or it causes glitches. (FIXME)
2961 //if(unlikely(process->pid != pid_out)) {
2962 // g_assert(process->pid == 0);
2964 if(process
->pid
== 0
2965 && process
->state
->t
== LTTV_STATE_MODE_UNKNOWN
) {
2967 /* Scheduling out of pid 0 at beginning of the trace :
2968 * we know for sure it is in syscall mode at this point. */
2969 g_assert(process
->execution_stack
->len
== 1);
2970 process
->state
->t
= LTTV_STATE_SYSCALL
;
2971 process
->state
->s
= LTTV_STATE_WAIT
;
2972 process
->state
->change
= s
->parent
.timestamp
;
2973 process
->state
->entry
= s
->parent
.timestamp
;
2976 if(unlikely(process
->state
->s
== LTTV_STATE_EXIT
)) {
2977 process
->state
->s
= LTTV_STATE_ZOMBIE
;
2978 process
->state
->change
= s
->parent
.timestamp
;
2980 if(unlikely(state_out
== 0)) process
->state
->s
= LTTV_STATE_WAIT_CPU
;
2981 else process
->state
->s
= LTTV_STATE_WAIT
;
2982 process
->state
->change
= s
->parent
.timestamp
;
2985 if(state_out
== 32 || state_out
== 64) { /* EXIT_DEAD || TASK_DEAD */
2986 /* see sched.h for states */
2987 if (!exit_process(s
, process
)) {
2988 process
->state
->s
= LTTV_STATE_DEAD
;
2989 process
->state
->change
= s
->parent
.timestamp
;
2994 process
= ts
->running_process
[cpu
] =
2995 lttv_state_find_process_or_create(
2996 (LttvTraceState
*)s
->parent
.t_context
,
2998 &s
->parent
.timestamp
);
2999 process
->state
->s
= LTTV_STATE_RUN
;
3001 if(process
->usertrace
)
3002 process
->usertrace
->cpu
= cpu
;
3003 // process->last_cpu_index = ltt_tracefile_num(((LttvTracefileContext*)s)->tf);
3004 process
->state
->change
= s
->parent
.timestamp
;
3006 /* update cpu status */
3008 /* going to idle task */
3009 cpu_set_base_mode(s
->cpu_state
, LTTV_CPU_IDLE
);
3011 /* scheduling a real task.
3012 * we must be careful here:
3013 * if we just schedule()'ed to a process that is
3014 * in a trap, we must put the cpu in trap mode
3016 cpu_set_base_mode(s
->cpu_state
, LTTV_CPU_BUSY
);
3017 if(process
->state
->t
== LTTV_STATE_TRAP
)
3018 cpu_push_mode(s
->cpu_state
, LTTV_CPU_TRAP
);
3024 static gboolean
process_fork(void *hook_data
, void *call_data
)
3026 LttvTracefileState
*s
= (LttvTracefileState
*)call_data
;
3027 LttEvent
*e
= ltt_tracefile_get_event(s
->parent
.tf
);
3028 LttvTraceHook
*th
= (LttvTraceHook
*)hook_data
;
3030 guint child_pid
; /* In the Linux Kernel, there is one PID per thread. */
3031 guint child_tgid
; /* tgid in the Linux kernel is the "real" POSIX PID. */
3032 //LttvProcessState *zombie_process;
3034 LttvTraceState
*ts
= (LttvTraceState
*)s
->parent
.t_context
;
3035 LttvProcessState
*process
= ts
->running_process
[cpu
];
3036 LttvProcessState
*child_process
;
3037 struct marker_field
*f
;
3040 parent_pid
= ltt_event_get_unsigned(e
, lttv_trace_get_hook_field(th
, 0));
3043 child_pid
= ltt_event_get_unsigned(e
, lttv_trace_get_hook_field(th
, 1));
3044 s
->parent
.target_pid
= child_pid
;
3047 f
= lttv_trace_get_hook_field(th
, 2);
3049 child_tgid
= ltt_event_get_unsigned(e
, f
);
3053 /* Mathieu : it seems like the process might have been scheduled in before the
3054 * fork, and, in a rare case, might be the current process. This might happen
3055 * in a SMP case where we don't have enough precision on the clocks.
3057 * Test reenabled after precision fixes on time. (Mathieu) */
3059 zombie_process
= lttv_state_find_process(ts
, ANY_CPU
, child_pid
);
3061 if(unlikely(zombie_process
!= NULL
)) {
3062 /* Reutilisation of PID. Only now we are sure that the old PID
3063 * has been released. FIXME : should know when release_task happens instead.
3065 guint num_cpus
= ltt_trace_get_num_cpu(ts
->parent
.t
);
3067 for(i
=0; i
< num_cpus
; i
++) {
3068 g_assert(zombie_process
!= ts
->running_process
[i
]);
3071 exit_process(s
, zombie_process
);
3074 g_assert(process
->pid
!= child_pid
);
3075 // FIXME : Add this test in the "known state" section
3076 // g_assert(process->pid == parent_pid);
3077 child_process
= lttv_state_find_process(ts
, ANY_CPU
, child_pid
);
3078 if(child_process
== NULL
) {
3079 child_process
= lttv_state_create_process(ts
, process
, cpu
,
3080 child_pid
, child_tgid
,
3081 LTTV_STATE_UNNAMED
, &s
->parent
.timestamp
);
3083 /* The process has already been created : due to time imprecision between
3084 * multiple CPUs : it has been scheduled in before creation. Note that we
3085 * shouldn't have this kind of imprecision.
3087 * Simply put a correct parent.
3089 g_error("Process %u has been created at [%lu.%09lu] "
3090 "and inserted at [%lu.%09lu] before \n"
3091 "fork on cpu %u[%lu.%09lu].\n"
3092 "Probably an unsynchronized TSC problem on the traced machine.",
3094 child_process
->creation_time
.tv_sec
,
3095 child_process
->creation_time
.tv_nsec
,
3096 child_process
->insertion_time
.tv_sec
,
3097 child_process
->insertion_time
.tv_nsec
,
3098 cpu
, ltt_event_time(e
).tv_sec
, ltt_event_time(e
).tv_nsec
);
3099 //g_assert(0); /* This is a problematic case : the process has been created
3100 // before the fork event */
3101 child_process
->ppid
= process
->pid
;
3102 child_process
->tgid
= child_tgid
;
3104 g_assert(child_process
->name
== LTTV_STATE_UNNAMED
);
3105 child_process
->name
= process
->name
;
3106 child_process
->brand
= process
->brand
;
3111 /* We stamp a newly created process as kernel_thread.
3112 * The thread should not be running yet. */
3113 static gboolean
process_kernel_thread(void *hook_data
, void *call_data
)
3115 LttvTracefileState
*s
= (LttvTracefileState
*)call_data
;
3116 LttEvent
*e
= ltt_tracefile_get_event(s
->parent
.tf
);
3117 LttvTraceHook
*th
= (LttvTraceHook
*)hook_data
;
3119 LttvTraceState
*ts
= (LttvTraceState
*)s
->parent
.t_context
;
3120 LttvProcessState
*process
;
3121 LttvExecutionState
*es
;
3124 pid
= (guint
)ltt_event_get_long_unsigned(e
, lttv_trace_get_hook_field(th
, 0));
3125 s
->parent
.target_pid
= pid
;
3127 process
= lttv_state_find_process_or_create(ts
, ANY_CPU
, pid
,
3129 if (process
->state
->s
!= LTTV_STATE_DEAD
) {
3130 process
->execution_stack
=
3131 g_array_set_size(process
->execution_stack
, 1);
3132 es
= process
->state
=
3133 &g_array_index(process
->execution_stack
, LttvExecutionState
, 0);
3134 es
->t
= LTTV_STATE_SYSCALL
;
3136 process
->type
= LTTV_STATE_KERNEL_THREAD
;
3141 static gboolean
process_exit(void *hook_data
, void *call_data
)
3143 LttvTracefileState
*s
= (LttvTracefileState
*)call_data
;
3144 LttEvent
*e
= ltt_tracefile_get_event(s
->parent
.tf
);
3145 LttvTraceHook
*th
= (LttvTraceHook
*)hook_data
;
3147 LttvTraceState
*ts
= (LttvTraceState
*)s
->parent
.t_context
;
3148 LttvProcessState
*process
; // = ts->running_process[cpu];
3150 pid
= ltt_event_get_unsigned(e
, lttv_trace_get_hook_field(th
, 0));
3151 s
->parent
.target_pid
= pid
;
3153 // FIXME : Add this test in the "known state" section
3154 // g_assert(process->pid == pid);
3156 process
= lttv_state_find_process(ts
, ANY_CPU
, pid
);
3157 if(likely(process
!= NULL
)) {
3158 process
->state
->s
= LTTV_STATE_EXIT
;
3163 static gboolean
process_free(void *hook_data
, void *call_data
)
3165 LttvTracefileState
*s
= (LttvTracefileState
*)call_data
;
3166 LttvTraceState
*ts
= (LttvTraceState
*)s
->parent
.t_context
;
3167 LttEvent
*e
= ltt_tracefile_get_event(s
->parent
.tf
);
3168 LttvTraceHook
*th
= (LttvTraceHook
*)hook_data
;
3170 LttvProcessState
*process
;
3172 /* PID of the process to release */
3173 release_pid
= ltt_event_get_unsigned(e
, lttv_trace_get_hook_field(th
, 0));
3174 s
->parent
.target_pid
= release_pid
;
3176 g_assert(release_pid
!= 0);
3178 process
= lttv_state_find_process(ts
, ANY_CPU
, release_pid
);
3179 if(likely(process
!= NULL
))
3180 exit_process(s
, process
);
3183 if(likely(process
!= NULL
)) {
3184 /* release_task is happening at kernel level : we can now safely release
3185 * the data structure of the process */
3186 //This test is fun, though, as it may happen that
3187 //at time t : CPU 0 : process_free
3188 //at time t+150ns : CPU 1 : schedule out
3189 //Clearly due to time imprecision, we disable it. (Mathieu)
3190 //If this weird case happen, we have no choice but to put the
3191 //Currently running process on the cpu to 0.
3192 //I re-enable it following time precision fixes. (Mathieu)
3193 //Well, in the case where an process is freed by a process on another CPU
3194 //and still scheduled, it happens that this is the schedchange that will
3195 //drop the last reference count. Do not free it here!
3196 guint num_cpus
= ltt_trace_get_num_cpu(ts
->parent
.t
);
3198 for(i
=0; i
< num_cpus
; i
++) {
3199 //g_assert(process != ts->running_process[i]);
3200 if(process
== ts
->running_process
[i
]) {
3201 //ts->running_process[i] = lttv_state_find_process(ts, i, 0);
3205 if(i
== num_cpus
) /* process is not scheduled */
3206 exit_process(s
, process
);
3213 static gboolean
process_exec(void *hook_data
, void *call_data
)
3215 LttvTracefileState
*s
= (LttvTracefileState
*)call_data
;
3216 LttvTraceState
*ts
= (LttvTraceState
*)s
->parent
.t_context
;
3217 LttEvent
*e
= ltt_tracefile_get_event(s
->parent
.tf
);
3218 LttvTraceHook
*th
= (LttvTraceHook
*)hook_data
;
3221 LttvProcessState
*process
= ts
->running_process
[cpu
];
3223 #if 0//how to use a sequence that must be transformed in a string
3224 /* PID of the process to release */
3225 guint64 name_len
= ltt_event_field_element_number(e
,
3226 lttv_trace_get_hook_field(th
, 0));
3227 //name = ltt_event_get_string(e, lttv_trace_get_hook_field(th, 0));
3228 LttField
*child
= ltt_event_field_element_select(e
,
3229 lttv_trace_get_hook_field(th
, 0), 0);
3231 (gchar
*)(ltt_event_data(e
)+ltt_event_field_offset(e
, child
));
3232 gchar
*null_term_name
= g_new(gchar
, name_len
+1);
3233 memcpy(null_term_name
, name_begin
, name_len
);
3234 null_term_name
[name_len
] = '\0';
3235 process
->name
= g_quark_from_string(null_term_name
);
3238 process
->name
= g_quark_from_string(ltt_event_get_string(e
,
3239 lttv_trace_get_hook_field(th
, 0)));
3240 process
->brand
= LTTV_STATE_UNBRANDED
;
3241 //g_free(null_term_name);
3245 static gboolean
thread_brand(void *hook_data
, void *call_data
)
3247 LttvTracefileState
*s
= (LttvTracefileState
*)call_data
;
3248 LttvTraceState
*ts
= (LttvTraceState
*)s
->parent
.t_context
;
3249 LttEvent
*e
= ltt_tracefile_get_event(s
->parent
.tf
);
3250 LttvTraceHook
*th
= (LttvTraceHook
*)hook_data
;
3253 LttvProcessState
*process
= ts
->running_process
[cpu
];
3255 name
= ltt_event_get_string(e
, lttv_trace_get_hook_field(th
, 0));
3256 process
->brand
= g_quark_from_string(name
);
3261 static gboolean
fs_open(void *hook_data
, void *call_data
)
3263 LttvTracefileState
*s
= (LttvTracefileState
*)call_data
;
3264 LttvTraceState
*ts
= (LttvTraceState
*)s
->parent
.t_context
;
3265 LttEvent
*e
= ltt_tracefile_get_event(s
->parent
.tf
);
3266 LttvTraceHook
*th
= (LttvTraceHook
*)hook_data
;
3267 struct marker_field
*f
;
3271 LttvProcessState
*process
= ts
->running_process
[cpu
];
3273 f
= lttv_trace_get_hook_field(th
, 0);
3274 fd
= ltt_event_get_int(e
, f
);
3276 f
= lttv_trace_get_hook_field(th
, 1);
3277 filename
= ltt_event_get_string(e
, f
);
3279 g_hash_table_insert(process
->fds
, fd
, g_quark_from_string(filename
));
3284 static void fix_process(gpointer key
, gpointer value
,
3287 LttvProcessState
*process
;
3288 LttvExecutionState
*es
;
3289 process
= (LttvProcessState
*)value
;
3290 LttTime
*timestamp
= (LttTime
*)user_data
;
3292 if(process
->type
== LTTV_STATE_KERNEL_THREAD
) {
3293 es
= &g_array_index(process
->execution_stack
, LttvExecutionState
, 0);
3294 if(es
->t
== LTTV_STATE_MODE_UNKNOWN
) {
3295 es
->t
= LTTV_STATE_SYSCALL
;
3296 es
->n
= LTTV_STATE_SUBMODE_NONE
;
3297 es
->entry
= *timestamp
;
3298 es
->change
= *timestamp
;
3299 es
->cum_cpu_time
= ltt_time_zero
;
3300 if(es
->s
== LTTV_STATE_UNNAMED
)
3301 es
->s
= LTTV_STATE_WAIT
;
3304 es
= &g_array_index(process
->execution_stack
, LttvExecutionState
, 0);
3305 if(es
->t
== LTTV_STATE_MODE_UNKNOWN
) {
3306 es
->t
= LTTV_STATE_USER_MODE
;
3307 es
->n
= LTTV_STATE_SUBMODE_NONE
;
3308 es
->entry
= *timestamp
;
3309 //g_assert(timestamp->tv_sec != 0);
3310 es
->change
= *timestamp
;
3311 es
->cum_cpu_time
= ltt_time_zero
;
3312 if(es
->s
== LTTV_STATE_UNNAMED
)
3313 es
->s
= LTTV_STATE_RUN
;
3315 if(process
->execution_stack
->len
== 1) {
3316 /* Still in bottom unknown mode, means never did a system call
3317 * May be either in user mode, syscall mode, running or waiting.*/
3318 /* FIXME : we may be tagging syscall mode when being user mode */
3319 process
->execution_stack
=
3320 g_array_set_size(process
->execution_stack
, 2);
3321 es
= process
->state
= &g_array_index(process
->execution_stack
,
3322 LttvExecutionState
, 1);
3323 es
->t
= LTTV_STATE_SYSCALL
;
3324 es
->n
= LTTV_STATE_SUBMODE_NONE
;
3325 es
->entry
= *timestamp
;
3326 //g_assert(timestamp->tv_sec != 0);
3327 es
->change
= *timestamp
;
3328 es
->cum_cpu_time
= ltt_time_zero
;
3329 if(es
->s
== LTTV_STATE_WAIT_FORK
)
3330 es
->s
= LTTV_STATE_WAIT
;
3336 static gboolean
statedump_end(void *hook_data
, void *call_data
)
3338 LttvTracefileState
*s
= (LttvTracefileState
*)call_data
;
3339 LttvTraceState
*ts
= (LttvTraceState
*)s
->parent
.t_context
;
3340 LttvTracefileContext
*tfc
= (LttvTracefileContext
*)call_data
;
3341 //LttEvent *e = ltt_tracefile_get_event(s->parent.tf);
3342 //LttvTraceHook *th = (LttvTraceHook *)hook_data;
3344 /* For all processes */
3345 /* if kernel thread, if stack[0] is unknown, set to syscall mode, wait */
3346 /* else, if stack[0] is unknown, set to user mode, running */
3348 g_hash_table_foreach(ts
->processes
, fix_process
, &tfc
->timestamp
);
3353 static gboolean
enum_process_state(void *hook_data
, void *call_data
)
3355 LttvTracefileState
*s
= (LttvTracefileState
*)call_data
;
3356 LttEvent
*e
= ltt_tracefile_get_event(s
->parent
.tf
);
3357 //It's slow : optimise later by doing this before reading trace.
3358 LttvTraceHook
*th
= (LttvTraceHook
*)hook_data
;
3364 LttvTraceState
*ts
= (LttvTraceState
*)s
->parent
.t_context
;
3365 LttvProcessState
*process
= ts
->running_process
[cpu
];
3366 LttvProcessState
*parent_process
;
3367 struct marker_field
*f
;
3368 GQuark type
, mode
, submode
, status
;
3369 LttvExecutionState
*es
;
3373 pid
= ltt_event_get_unsigned(e
, lttv_trace_get_hook_field(th
, 0));
3374 s
->parent
.target_pid
= pid
;
3377 parent_pid
= ltt_event_get_unsigned(e
, lttv_trace_get_hook_field(th
, 1));
3380 command
= ltt_event_get_string(e
, lttv_trace_get_hook_field(th
, 2));
3383 f
= lttv_trace_get_hook_field(th
, 3);
3384 type
= ltt_enum_string_get(f
, ltt_event_get_unsigned(e
, f
));
3386 //FIXME: type is rarely used, enum must match possible types.
3389 f
= lttv_trace_get_hook_field(th
, 4);
3390 mode
= ltt_enum_string_get(f
,ltt_event_get_unsigned(e
, f
));
3393 f
= lttv_trace_get_hook_field(th
, 5);
3394 submode
= ltt_enum_string_get(f
, ltt_event_get_unsigned(e
, f
));
3397 f
= lttv_trace_get_hook_field(th
, 6);
3398 status
= ltt_enum_string_get(f
, ltt_event_get_unsigned(e
, f
));
3401 f
= lttv_trace_get_hook_field(th
, 7);
3403 tgid
= ltt_event_get_unsigned(e
, f
);
3408 nb_cpus
= ltt_trace_get_num_cpu(ts
->parent
.t
);
3409 for(i
=0; i
<nb_cpus
; i
++) {
3410 process
= lttv_state_find_process(ts
, i
, pid
);
3411 g_assert(process
!= NULL
);
3413 process
->ppid
= parent_pid
;
3414 process
->tgid
= tgid
;
3415 process
->name
= g_quark_from_string(command
);
3417 &g_array_index(process
->execution_stack
, LttvExecutionState
, 0);
3418 process
->type
= LTTV_STATE_KERNEL_THREAD
;
3422 /* The process might exist if a process was forked while performing the
3424 process
= lttv_state_find_process(ts
, ANY_CPU
, pid
);
3425 if(process
== NULL
) {
3426 parent_process
= lttv_state_find_process(ts
, ANY_CPU
, parent_pid
);
3427 process
= lttv_state_create_process(ts
, parent_process
, cpu
,
3428 pid
, tgid
, g_quark_from_string(command
),
3429 &s
->parent
.timestamp
);
3431 /* Keep the stack bottom : a running user mode */
3432 /* Disabled because of inconsistencies in the current statedump states. */
3433 if(type
== LTTV_STATE_KERNEL_THREAD
) {
3434 /* Only keep the bottom
3435 * FIXME Kernel thread : can be in syscall or interrupt or trap. */
3436 /* Will cause expected trap when in fact being syscall (even after end of
3438 * Will cause expected interrupt when being syscall. (only before end of
3439 * statedump event) */
3440 // This will cause a "popping last state on stack, ignoring it."
3441 process
->execution_stack
= g_array_set_size(process
->execution_stack
, 1);
3442 es
= process
->state
= &g_array_index(process
->execution_stack
,
3443 LttvExecutionState
, 0);
3444 process
->type
= LTTV_STATE_KERNEL_THREAD
;
3445 es
->t
= LTTV_STATE_MODE_UNKNOWN
;
3446 es
->s
= LTTV_STATE_UNNAMED
;
3447 es
->n
= LTTV_STATE_SUBMODE_UNKNOWN
;
3449 es
->t
= LTTV_STATE_SYSCALL
;
3454 /* User space process :
3455 * bottom : user mode
3456 * either currently running or scheduled out.
3457 * can be scheduled out because interrupted in (user mode or in syscall)
3458 * or because of an explicit call to the scheduler in syscall. Note that
3459 * the scheduler call comes after the irq_exit, so never in interrupt
3461 // temp workaround : set size to 1 : only have user mode bottom of stack.
3462 // will cause g_info message of expected syscall mode when in fact being
3463 // in user mode. Can also cause expected trap when in fact being user
3464 // mode in the event of a page fault reenabling interrupts in the handler.
3465 // Expected syscall and trap can also happen after the end of statedump
3466 // This will cause a "popping last state on stack, ignoring it."
3467 process
->execution_stack
= g_array_set_size(process
->execution_stack
, 1);
3468 es
= process
->state
= &g_array_index(process
->execution_stack
,
3469 LttvExecutionState
, 0);
3470 es
->t
= LTTV_STATE_MODE_UNKNOWN
;
3471 es
->s
= LTTV_STATE_UNNAMED
;
3472 es
->n
= LTTV_STATE_SUBMODE_UNKNOWN
;
3474 es
->t
= LTTV_STATE_USER_MODE
;
3482 es
= process
->state
= &g_array_index(process
->execution_stack
,
3483 LttvExecutionState
, 1);
3484 es
->t
= LTTV_STATE_MODE_UNKNOWN
;
3485 es
->s
= LTTV_STATE_UNNAMED
;
3486 es
->n
= LTTV_STATE_SUBMODE_UNKNOWN
;
3490 /* The process has already been created :
3491 * Probably was forked while dumping the process state or
3492 * was simply scheduled in prior to get the state dump event.
3494 process
->ppid
= parent_pid
;
3495 process
->tgid
= tgid
;
3496 process
->name
= g_quark_from_string(command
);
3497 process
->type
= type
;
3499 &g_array_index(process
->execution_stack
, LttvExecutionState
, 0);
3501 if(es
->t
== LTTV_STATE_MODE_UNKNOWN
) {
3502 if(type
== LTTV_STATE_KERNEL_THREAD
)
3503 es
->t
= LTTV_STATE_SYSCALL
;
3505 es
->t
= LTTV_STATE_USER_MODE
;
3508 /* Don't mess around with the stack, it will eventually become
3509 * ok after the end of state dump. */
3516 gint
lttv_state_hook_add_event_hooks(void *hook_data
, void *call_data
)
3518 LttvTracesetState
*tss
= (LttvTracesetState
*)(call_data
);
3520 lttv_state_add_event_hooks(tss
);
3525 void lttv_state_add_event_hooks(LttvTracesetState
*self
)
3527 LttvTraceset
*traceset
= self
->parent
.ts
;
3529 guint i
, j
, k
, nb_trace
, nb_tracefile
;
3533 LttvTracefileState
*tfs
;
3539 LttvAttributeValue val
;
3541 nb_trace
= lttv_traceset_number(traceset
);
3542 for(i
= 0 ; i
< nb_trace
; i
++) {
3543 ts
= (LttvTraceState
*)self
->parent
.traces
[i
];
3545 /* Find the eventtype id for the following events and register the
3546 associated by id hooks. */
3548 hooks
= g_array_sized_new(FALSE
, FALSE
, sizeof(LttvTraceHook
), 20);
3549 //hooks = g_array_set_size(hooks, 19); // Max possible number of hooks.
3552 lttv_trace_find_hook(ts
->parent
.t
,
3554 LTT_EVENT_SYSCALL_ENTRY
,
3555 FIELD_ARRAY(LTT_FIELD_SYSCALL_ID
),
3556 syscall_entry
, NULL
, &hooks
);
3558 lttv_trace_find_hook(ts
->parent
.t
,
3560 LTT_EVENT_SYSCALL_EXIT
,
3562 syscall_exit
, NULL
, &hooks
);
3564 lttv_trace_find_hook(ts
->parent
.t
,
3566 LTT_EVENT_TRAP_ENTRY
,
3567 FIELD_ARRAY(LTT_FIELD_TRAP_ID
),
3568 trap_entry
, NULL
, &hooks
);
3570 lttv_trace_find_hook(ts
->parent
.t
,
3572 LTT_EVENT_TRAP_EXIT
,
3574 trap_exit
, NULL
, &hooks
);
3576 lttv_trace_find_hook(ts
->parent
.t
,
3578 LTT_EVENT_PAGE_FAULT_ENTRY
,
3579 FIELD_ARRAY(LTT_FIELD_TRAP_ID
),
3580 trap_entry
, NULL
, &hooks
);
3582 lttv_trace_find_hook(ts
->parent
.t
,
3584 LTT_EVENT_PAGE_FAULT_EXIT
,
3586 trap_exit
, NULL
, &hooks
);
3588 lttv_trace_find_hook(ts
->parent
.t
,
3590 LTT_EVENT_PAGE_FAULT_NOSEM_ENTRY
,
3591 FIELD_ARRAY(LTT_FIELD_TRAP_ID
),
3592 trap_entry
, NULL
, &hooks
);
3594 lttv_trace_find_hook(ts
->parent
.t
,
3596 LTT_EVENT_PAGE_FAULT_NOSEM_EXIT
,
3598 trap_exit
, NULL
, &hooks
);
3600 lttv_trace_find_hook(ts
->parent
.t
,
3602 LTT_EVENT_IRQ_ENTRY
,
3603 FIELD_ARRAY(LTT_FIELD_IRQ_ID
),
3604 irq_entry
, NULL
, &hooks
);
3606 lttv_trace_find_hook(ts
->parent
.t
,
3610 irq_exit
, NULL
, &hooks
);
3612 lttv_trace_find_hook(ts
->parent
.t
,
3614 LTT_EVENT_SOFT_IRQ_RAISE
,
3615 FIELD_ARRAY(LTT_FIELD_SOFT_IRQ_ID
),
3616 soft_irq_raise
, NULL
, &hooks
);
3618 lttv_trace_find_hook(ts
->parent
.t
,
3620 LTT_EVENT_SOFT_IRQ_ENTRY
,
3621 FIELD_ARRAY(LTT_FIELD_SOFT_IRQ_ID
),
3622 soft_irq_entry
, NULL
, &hooks
);
3624 lttv_trace_find_hook(ts
->parent
.t
,
3626 LTT_EVENT_SOFT_IRQ_EXIT
,
3628 soft_irq_exit
, NULL
, &hooks
);
3630 lttv_trace_find_hook(ts
->parent
.t
,
3632 LTT_EVENT_SCHED_SCHEDULE
,
3633 FIELD_ARRAY(LTT_FIELD_PREV_PID
, LTT_FIELD_NEXT_PID
,
3634 LTT_FIELD_PREV_STATE
),
3635 schedchange
, NULL
, &hooks
);
3637 lttv_trace_find_hook(ts
->parent
.t
,
3639 LTT_EVENT_PROCESS_FORK
,
3640 FIELD_ARRAY(LTT_FIELD_PARENT_PID
, LTT_FIELD_CHILD_PID
,
3641 LTT_FIELD_CHILD_TGID
),
3642 process_fork
, NULL
, &hooks
);
3644 lttv_trace_find_hook(ts
->parent
.t
,
3646 LTT_EVENT_KTHREAD_CREATE
,
3647 FIELD_ARRAY(LTT_FIELD_PID
),
3648 process_kernel_thread
, NULL
, &hooks
);
3650 lttv_trace_find_hook(ts
->parent
.t
,
3652 LTT_EVENT_PROCESS_EXIT
,
3653 FIELD_ARRAY(LTT_FIELD_PID
),
3654 process_exit
, NULL
, &hooks
);
3656 lttv_trace_find_hook(ts
->parent
.t
,
3658 LTT_EVENT_PROCESS_FREE
,
3659 FIELD_ARRAY(LTT_FIELD_PID
),
3660 process_free
, NULL
, &hooks
);
3662 lttv_trace_find_hook(ts
->parent
.t
,
3665 FIELD_ARRAY(LTT_FIELD_FILENAME
),
3666 process_exec
, NULL
, &hooks
);
3668 lttv_trace_find_hook(ts
->parent
.t
,
3669 LTT_CHANNEL_USERSPACE
,
3670 LTT_EVENT_THREAD_BRAND
,
3671 FIELD_ARRAY(LTT_FIELD_NAME
),
3672 thread_brand
, NULL
, &hooks
);
3674 /* statedump-related hooks */
3675 lttv_trace_find_hook(ts
->parent
.t
,
3676 LTT_CHANNEL_TASK_STATE
,
3677 LTT_EVENT_PROCESS_STATE
,
3678 FIELD_ARRAY(LTT_FIELD_PID
, LTT_FIELD_PARENT_PID
, LTT_FIELD_NAME
,
3679 LTT_FIELD_TYPE
, LTT_FIELD_MODE
, LTT_FIELD_SUBMODE
,
3680 LTT_FIELD_STATUS
, LTT_FIELD_TGID
),
3681 enum_process_state
, NULL
, &hooks
);
3683 lttv_trace_find_hook(ts
->parent
.t
,
3684 LTT_CHANNEL_GLOBAL_STATE
,
3685 LTT_EVENT_STATEDUMP_END
,
3687 statedump_end
, NULL
, &hooks
);
3689 lttv_trace_find_hook(ts
->parent
.t
,
3690 LTT_CHANNEL_IRQ_STATE
,
3691 LTT_EVENT_LIST_INTERRUPT
,
3692 FIELD_ARRAY(LTT_FIELD_ACTION
, LTT_FIELD_IRQ_ID
),
3693 enum_interrupt
, NULL
, &hooks
);
3695 lttv_trace_find_hook(ts
->parent
.t
,
3697 LTT_EVENT_REQUEST_ISSUE
,
3698 FIELD_ARRAY(LTT_FIELD_MAJOR
, LTT_FIELD_MINOR
, LTT_FIELD_OPERATION
),
3699 bdev_request_issue
, NULL
, &hooks
);
3701 lttv_trace_find_hook(ts
->parent
.t
,
3703 LTT_EVENT_REQUEST_COMPLETE
,
3704 FIELD_ARRAY(LTT_FIELD_MAJOR
, LTT_FIELD_MINOR
, LTT_FIELD_OPERATION
),
3705 bdev_request_complete
, NULL
, &hooks
);
3707 lttv_trace_find_hook(ts
->parent
.t
,
3708 LTT_CHANNEL_USERSPACE
,
3709 LTT_EVENT_FUNCTION_ENTRY
,
3710 FIELD_ARRAY(LTT_FIELD_THIS_FN
, LTT_FIELD_CALL_SITE
),
3711 function_entry
, NULL
, &hooks
);
3713 lttv_trace_find_hook(ts
->parent
.t
,
3714 LTT_CHANNEL_USERSPACE
,
3715 LTT_EVENT_FUNCTION_EXIT
,
3716 FIELD_ARRAY(LTT_FIELD_THIS_FN
, LTT_FIELD_CALL_SITE
),
3717 function_exit
, NULL
, &hooks
);
3719 lttv_trace_find_hook(ts
->parent
.t
,
3720 LTT_CHANNEL_SYSCALL_STATE
,
3721 LTT_EVENT_SYS_CALL_TABLE
,
3722 FIELD_ARRAY(LTT_FIELD_ID
, LTT_FIELD_ADDRESS
, LTT_FIELD_SYMBOL
),
3723 dump_syscall
, NULL
, &hooks
);
3725 lttv_trace_find_hook(ts
->parent
.t
,
3726 LTT_CHANNEL_KPROBE_STATE
,
3727 LTT_EVENT_KPROBE_TABLE
,
3728 FIELD_ARRAY(LTT_FIELD_IP
, LTT_FIELD_SYMBOL
),
3729 dump_kprobe
, NULL
, &hooks
);
3731 lttv_trace_find_hook(ts
->parent
.t
,
3732 LTT_CHANNEL_SOFTIRQ_STATE
,
3733 LTT_EVENT_SOFTIRQ_VEC
,
3734 FIELD_ARRAY(LTT_FIELD_ID
, LTT_FIELD_ADDRESS
, LTT_FIELD_SYMBOL
),
3735 dump_softirq
, NULL
, &hooks
);
3737 lttv_trace_find_hook(ts
->parent
.t
,
3740 FIELD_ARRAY(LTT_FIELD_FD
, LTT_FIELD_FILENAME
),
3741 fs_open
, NULL
, &hooks
);
3743 /* Add these hooks to each event_by_id hooks list */
3745 nb_tracefile
= ts
->parent
.tracefiles
->len
;
3747 for(j
= 0 ; j
< nb_tracefile
; j
++) {
3749 LTTV_TRACEFILE_STATE(g_array_index(ts
->parent
.tracefiles
,
3750 LttvTracefileContext
*, j
));
3752 for(k
= 0 ; k
< hooks
->len
; k
++) {
3753 th
= &g_array_index(hooks
, LttvTraceHook
, k
);
3754 if (th
->mdata
== tfs
->parent
.tf
->mdata
)
3756 lttv_hooks_by_id_find(tfs
->parent
.event_by_id
, th
->id
),
3762 lttv_attribute_find(ts
->parent
.a
, LTTV_STATE_HOOKS
, LTTV_POINTER
, &val
);
3763 *(val
.v_pointer
) = hooks
;
3767 gint
lttv_state_hook_remove_event_hooks(void *hook_data
, void *call_data
)
3769 LttvTracesetState
*tss
= (LttvTracesetState
*)(call_data
);
3771 lttv_state_remove_event_hooks(tss
);
3776 void lttv_state_remove_event_hooks(LttvTracesetState
*self
)
3778 LttvTraceset
*traceset
= self
->parent
.ts
;
3780 guint i
, j
, k
, nb_trace
, nb_tracefile
;
3784 LttvTracefileState
*tfs
;
3790 LttvAttributeValue val
;
3792 nb_trace
= lttv_traceset_number(traceset
);
3793 for(i
= 0 ; i
< nb_trace
; i
++) {
3794 ts
= LTTV_TRACE_STATE(self
->parent
.traces
[i
]);
3796 lttv_attribute_find(ts
->parent
.a
, LTTV_STATE_HOOKS
, LTTV_POINTER
, &val
);
3797 hooks
= *(val
.v_pointer
);
3799 /* Remove these hooks from each event_by_id hooks list */
3801 nb_tracefile
= ts
->parent
.tracefiles
->len
;
3803 for(j
= 0 ; j
< nb_tracefile
; j
++) {
3805 LTTV_TRACEFILE_STATE(g_array_index(ts
->parent
.tracefiles
,
3806 LttvTracefileContext
*, j
));
3808 for(k
= 0 ; k
< hooks
->len
; k
++) {
3809 th
= &g_array_index(hooks
, LttvTraceHook
, k
);
3810 if (th
->mdata
== tfs
->parent
.tf
->mdata
)
3811 lttv_hooks_remove_data(
3812 lttv_hooks_by_id_find(tfs
->parent
.event_by_id
, th
->id
),
3817 lttv_trace_hook_remove_all(&hooks
);
3818 g_array_free(hooks
, TRUE
);
3822 static gboolean
state_save_event_hook(void *hook_data
, void *call_data
)
3824 guint
*event_count
= (guint
*)hook_data
;
3826 /* Only save at LTTV_STATE_SAVE_INTERVAL */
3827 if(likely((*event_count
)++ < LTTV_STATE_SAVE_INTERVAL
))
3832 LttvTracefileState
*self
= (LttvTracefileState
*)call_data
;
3834 LttvTraceState
*tcs
= (LttvTraceState
*)(self
->parent
.t_context
);
3836 LttvAttribute
*saved_states_tree
, *saved_state_tree
;
3838 LttvAttributeValue value
;
3840 saved_states_tree
= lttv_attribute_find_subdir(tcs
->parent
.t_a
,
3841 LTTV_STATE_SAVED_STATES
);
3842 saved_state_tree
= g_object_new(LTTV_ATTRIBUTE_TYPE
, NULL
);
3843 value
= lttv_attribute_add(saved_states_tree
,
3844 lttv_attribute_get_number(saved_states_tree
), LTTV_GOBJECT
);
3845 *(value
.v_gobject
) = (GObject
*)saved_state_tree
;
3846 value
= lttv_attribute_add(saved_state_tree
, LTTV_STATE_TIME
, LTTV_TIME
);
3847 *(value
.v_time
) = self
->parent
.timestamp
;
3848 lttv_state_save(tcs
, saved_state_tree
);
3849 g_debug("Saving state at time %lu.%lu", self
->parent
.timestamp
.tv_sec
,
3850 self
->parent
.timestamp
.tv_nsec
);
3852 *(tcs
->max_time_state_recomputed_in_seek
) = self
->parent
.timestamp
;
3857 static gboolean
state_save_after_trace_hook(void *hook_data
, void *call_data
)
3859 LttvTraceState
*tcs
= (LttvTraceState
*)(call_data
);
3861 *(tcs
->max_time_state_recomputed_in_seek
) = tcs
->parent
.time_span
.end_time
;
3866 guint
lttv_state_current_cpu(LttvTracefileState
*tfs
)
3874 static gboolean
block_start(void *hook_data
, void *call_data
)
3876 LttvTracefileState
*self
= (LttvTracefileState
*)call_data
;
3878 LttvTracefileState
*tfcs
;
3880 LttvTraceState
*tcs
= (LttvTraceState
*)(self
->parent
.t_context
);
3882 LttEventPosition
*ep
;
3884 guint i
, nb_block
, nb_event
, nb_tracefile
;
3888 LttvAttribute
*saved_states_tree
, *saved_state_tree
;
3890 LttvAttributeValue value
;
3892 ep
= ltt_event_position_new();
3894 nb_tracefile
= tcs
->parent
.tracefiles
->len
;
3896 /* Count the number of events added since the last block end in any
3899 for(i
= 0 ; i
< nb_tracefile
; i
++) {
3901 LTTV_TRACEFILE_STATE(&g_array_index(tcs
->parent
.tracefiles
,
3902 LttvTracefileContext
, i
));
3903 ltt_event_position(tfcs
->parent
.e
, ep
);
3904 ltt_event_position_get(ep
, &nb_block
, &nb_event
, &tf
);
3905 tcs
->nb_event
+= nb_event
- tfcs
->saved_position
;
3906 tfcs
->saved_position
= nb_event
;
3910 if(tcs
->nb_event
>= tcs
->save_interval
) {
3911 saved_states_tree
= lttv_attribute_find_subdir(tcs
->parent
.t_a
,
3912 LTTV_STATE_SAVED_STATES
);
3913 saved_state_tree
= g_object_new(LTTV_ATTRIBUTE_TYPE
, NULL
);
3914 value
= lttv_attribute_add(saved_states_tree
,
3915 lttv_attribute_get_number(saved_states_tree
), LTTV_GOBJECT
);
3916 *(value
.v_gobject
) = (GObject
*)saved_state_tree
;
3917 value
= lttv_attribute_add(saved_state_tree
, LTTV_STATE_TIME
, LTTV_TIME
);
3918 *(value
.v_time
) = self
->parent
.timestamp
;
3919 lttv_state_save(tcs
, saved_state_tree
);
3921 g_debug("Saving state at time %lu.%lu", self
->parent
.timestamp
.tv_sec
,
3922 self
->parent
.timestamp
.tv_nsec
);
3924 *(tcs
->max_time_state_recomputed_in_seek
) = self
->parent
.timestamp
;
3930 static gboolean
block_end(void *hook_data
, void *call_data
)
3932 LttvTracefileState
*self
= (LttvTracefileState
*)call_data
;
3934 LttvTraceState
*tcs
= (LttvTraceState
*)(self
->parent
.t_context
);
3938 LttEventPosition
*ep
;
3940 guint nb_block
, nb_event
;
3942 ep
= ltt_event_position_new();
3943 ltt_event_position(self
->parent
.e
, ep
);
3944 ltt_event_position_get(ep
, &nb_block
, &nb_event
, &tf
);
3945 tcs
->nb_event
+= nb_event
- self
->saved_position
+ 1;
3946 self
->saved_position
= 0;
3947 *(tcs
->max_time_state_recomputed_in_seek
) = self
->parent
.timestamp
;
3954 void lttv_state_save_add_event_hooks(LttvTracesetState
*self
)
3956 LttvTraceset
*traceset
= self
->parent
.ts
;
3958 guint i
, j
, nb_trace
, nb_tracefile
;
3962 LttvTracefileState
*tfs
;
3964 LttvTraceHook hook_start
, hook_end
;
3966 nb_trace
= lttv_traceset_number(traceset
);
3967 for(i
= 0 ; i
< nb_trace
; i
++) {
3968 ts
= (LttvTraceState
*)self
->parent
.traces
[i
];
3970 lttv_trace_find_hook(ts
->parent
.t
, "core","block_start",NULL
,
3971 NULL
, NULL
, block_start
, &hook_start
);
3972 lttv_trace_find_hook(ts
->parent
.t
, "core","block_end",NULL
,
3973 NULL
, NULL
, block_end
, &hook_end
);
3975 nb_tracefile
= ts
->parent
.tracefiles
->len
;
3977 for(j
= 0 ; j
< nb_tracefile
; j
++) {
3979 LTTV_TRACEFILE_STATE(&g_array_index(ts
->parent
.tracefiles
,
3980 LttvTracefileContext
, j
));
3981 lttv_hooks_add(lttv_hooks_by_id_find(tfs
->parent
.event_by_id
,
3982 hook_start
.id
), hook_start
.h
, NULL
, LTTV_PRIO_STATE
);
3983 lttv_hooks_add(lttv_hooks_by_id_find(tfs
->parent
.event_by_id
,
3984 hook_end
.id
), hook_end
.h
, NULL
, LTTV_PRIO_STATE
);
3990 void lttv_state_save_add_event_hooks(LttvTracesetState
*self
)
3992 LttvTraceset
*traceset
= self
->parent
.ts
;
3994 guint i
, j
, nb_trace
, nb_tracefile
;
3998 LttvTracefileState
*tfs
;
4001 nb_trace
= lttv_traceset_number(traceset
);
4002 for(i
= 0 ; i
< nb_trace
; i
++) {
4004 ts
= (LttvTraceState
*)self
->parent
.traces
[i
];
4005 nb_tracefile
= ts
->parent
.tracefiles
->len
;
4007 if(ts
->has_precomputed_states
) continue;
4009 guint
*event_count
= g_new(guint
, 1);
4012 for(j
= 0 ; j
< nb_tracefile
; j
++) {
4014 LTTV_TRACEFILE_STATE(g_array_index(ts
->parent
.tracefiles
,
4015 LttvTracefileContext
*, j
));
4016 lttv_hooks_add(tfs
->parent
.event
,
4017 state_save_event_hook
,
4024 lttv_process_traceset_begin(&self
->parent
,
4025 NULL
, NULL
, NULL
, NULL
, NULL
);
4029 gint
lttv_state_save_hook_add_event_hooks(void *hook_data
, void *call_data
)
4031 LttvTracesetState
*tss
= (LttvTracesetState
*)(call_data
);
4033 lttv_state_save_add_event_hooks(tss
);
4040 void lttv_state_save_remove_event_hooks(LttvTracesetState
*self
)
4042 LttvTraceset
*traceset
= self
->parent
.ts
;
4044 guint i
, j
, nb_trace
, nb_tracefile
;
4048 LttvTracefileState
*tfs
;
4050 LttvTraceHook hook_start
, hook_end
;
4052 nb_trace
= lttv_traceset_number(traceset
);
4053 for(i
= 0 ; i
< nb_trace
; i
++) {
4054 ts
= LTTV_TRACE_STATE(self
->parent
.traces
[i
]);
4056 lttv_trace_find_hook(ts
->parent
.t
, "core","block_start",NULL
,
4057 NULL
, NULL
, block_start
, &hook_start
);
4059 lttv_trace_find_hook(ts
->parent
.t
, "core","block_end",NULL
,
4060 NULL
, NULL
, block_end
, &hook_end
);
4062 nb_tracefile
= ts
->parent
.tracefiles
->len
;
4064 for(j
= 0 ; j
< nb_tracefile
; j
++) {
4066 LTTV_TRACEFILE_STATE(&g_array_index(ts
->parent
.tracefiles
,
4067 LttvTracefileContext
, j
));
4068 lttv_hooks_remove_data(lttv_hooks_by_id_find(
4069 tfs
->parent
.event_by_id
, hook_start
.id
), hook_start
.h
, NULL
);
4070 lttv_hooks_remove_data(lttv_hooks_by_id_find(
4071 tfs
->parent
.event_by_id
, hook_end
.id
), hook_end
.h
, NULL
);
4077 void lttv_state_save_remove_event_hooks(LttvTracesetState
*self
)
4079 LttvTraceset
*traceset
= self
->parent
.ts
;
4081 guint i
, j
, nb_trace
, nb_tracefile
;
4085 LttvTracefileState
*tfs
;
4087 LttvHooks
*after_trace
= lttv_hooks_new();
4089 lttv_hooks_add(after_trace
,
4090 state_save_after_trace_hook
,
4095 lttv_process_traceset_end(&self
->parent
,
4096 NULL
, after_trace
, NULL
, NULL
, NULL
);
4098 lttv_hooks_destroy(after_trace
);
4100 nb_trace
= lttv_traceset_number(traceset
);
4101 for(i
= 0 ; i
< nb_trace
; i
++) {
4103 ts
= (LttvTraceState
*)self
->parent
.traces
[i
];
4104 nb_tracefile
= ts
->parent
.tracefiles
->len
;
4106 if(ts
->has_precomputed_states
) continue;
4108 guint
*event_count
= NULL
;
4110 for(j
= 0 ; j
< nb_tracefile
; j
++) {
4112 LTTV_TRACEFILE_STATE(g_array_index(ts
->parent
.tracefiles
,
4113 LttvTracefileContext
*, j
));
4114 event_count
= lttv_hooks_remove(tfs
->parent
.event
,
4115 state_save_event_hook
);
4117 if(event_count
) g_free(event_count
);
4121 gint
lttv_state_save_hook_remove_event_hooks(void *hook_data
, void *call_data
)
4123 LttvTracesetState
*tss
= (LttvTracesetState
*)(call_data
);
4125 lttv_state_save_remove_event_hooks(tss
);
4130 void lttv_state_traceset_seek_time_closest(LttvTracesetState
*self
, LttTime t
)
4132 LttvTraceset
*traceset
= self
->parent
.ts
;
4136 int min_pos
, mid_pos
, max_pos
;
4138 guint call_rest
= 0;
4140 LttvTraceState
*tcs
;
4142 LttvAttributeValue value
;
4144 LttvAttributeType type
;
4146 LttvAttributeName name
;
4150 LttvAttribute
*saved_states_tree
, *saved_state_tree
, *closest_tree
= NULL
;
4152 //g_tree_destroy(self->parent.pqueue);
4153 //self->parent.pqueue = g_tree_new(compare_tracefile);
4155 g_info("Entering seek_time_closest for time %lu.%lu", t
.tv_sec
, t
.tv_nsec
);
4157 nb_trace
= lttv_traceset_number(traceset
);
4158 for(i
= 0 ; i
< nb_trace
; i
++) {
4159 tcs
= (LttvTraceState
*)self
->parent
.traces
[i
];
4161 if(ltt_time_compare(t
, *(tcs
->max_time_state_recomputed_in_seek
)) < 0) {
4162 saved_states_tree
= lttv_attribute_find_subdir(tcs
->parent
.t_a
,
4163 LTTV_STATE_SAVED_STATES
);
4166 if(saved_states_tree
) {
4167 max_pos
= lttv_attribute_get_number(saved_states_tree
) - 1;
4168 mid_pos
= max_pos
/ 2;
4169 while(min_pos
< max_pos
) {
4170 type
= lttv_attribute_get(saved_states_tree
, mid_pos
, &name
, &value
,
4172 g_assert(type
== LTTV_GOBJECT
);
4173 saved_state_tree
= *((LttvAttribute
**)(value
.v_gobject
));
4174 type
= lttv_attribute_get_by_name(saved_state_tree
, LTTV_STATE_TIME
,
4176 g_assert(type
== LTTV_TIME
);
4177 if(ltt_time_compare(*(value
.v_time
), t
) < 0) {
4179 closest_tree
= saved_state_tree
;
4181 else max_pos
= mid_pos
- 1;
4183 mid_pos
= (min_pos
+ max_pos
+ 1) / 2;
4187 /* restore the closest earlier saved state */
4189 lttv_state_restore(tcs
, closest_tree
);
4193 /* There is no saved state, yet we want to have it. Restart at T0 */
4195 restore_init_state(tcs
);
4196 lttv_process_trace_seek_time(&(tcs
->parent
), ltt_time_zero
);
4199 /* We want to seek quickly without restoring/updating the state */
4201 restore_init_state(tcs
);
4202 lttv_process_trace_seek_time(&(tcs
->parent
), t
);
4205 if(!call_rest
) g_info("NOT Calling restore");
4210 traceset_state_instance_init (GTypeInstance
*instance
, gpointer g_class
)
4216 traceset_state_finalize (LttvTracesetState
*self
)
4218 G_OBJECT_CLASS(g_type_class_peek(LTTV_TRACESET_CONTEXT_TYPE
))->
4219 finalize(G_OBJECT(self
));
4224 traceset_state_class_init (LttvTracesetContextClass
*klass
)
4226 GObjectClass
*gobject_class
= G_OBJECT_CLASS(klass
);
4228 gobject_class
->finalize
= (void (*)(GObject
*self
)) traceset_state_finalize
;
4229 klass
->init
= (void (*)(LttvTracesetContext
*self
, LttvTraceset
*ts
))init
;
4230 klass
->fini
= (void (*)(LttvTracesetContext
*self
))fini
;
4231 klass
->new_traceset_context
= new_traceset_context
;
4232 klass
->new_trace_context
= new_trace_context
;
4233 klass
->new_tracefile_context
= new_tracefile_context
;
4238 lttv_traceset_state_get_type(void)
4240 static GType type
= 0;
4242 static const GTypeInfo info
= {
4243 sizeof (LttvTracesetStateClass
),
4244 NULL
, /* base_init */
4245 NULL
, /* base_finalize */
4246 (GClassInitFunc
) traceset_state_class_init
, /* class_init */
4247 NULL
, /* class_finalize */
4248 NULL
, /* class_data */
4249 sizeof (LttvTracesetState
),
4250 0, /* n_preallocs */
4251 (GInstanceInitFunc
) traceset_state_instance_init
, /* instance_init */
4252 NULL
/* value handling */
4255 type
= g_type_register_static (LTTV_TRACESET_CONTEXT_TYPE
, "LttvTracesetStateType",
4263 trace_state_instance_init (GTypeInstance
*instance
, gpointer g_class
)
4269 trace_state_finalize (LttvTraceState
*self
)
4271 G_OBJECT_CLASS(g_type_class_peek(LTTV_TRACE_CONTEXT_TYPE
))->
4272 finalize(G_OBJECT(self
));
4277 trace_state_class_init (LttvTraceStateClass
*klass
)
4279 GObjectClass
*gobject_class
= G_OBJECT_CLASS(klass
);
4281 gobject_class
->finalize
= (void (*)(GObject
*self
)) trace_state_finalize
;
4282 klass
->state_save
= state_save
;
4283 klass
->state_restore
= state_restore
;
4284 klass
->state_saved_free
= state_saved_free
;
4289 lttv_trace_state_get_type(void)
4291 static GType type
= 0;
4293 static const GTypeInfo info
= {
4294 sizeof (LttvTraceStateClass
),
4295 NULL
, /* base_init */
4296 NULL
, /* base_finalize */
4297 (GClassInitFunc
) trace_state_class_init
, /* class_init */
4298 NULL
, /* class_finalize */
4299 NULL
, /* class_data */
4300 sizeof (LttvTraceState
),
4301 0, /* n_preallocs */
4302 (GInstanceInitFunc
) trace_state_instance_init
, /* instance_init */
4303 NULL
/* value handling */
4306 type
= g_type_register_static (LTTV_TRACE_CONTEXT_TYPE
,
4307 "LttvTraceStateType", &info
, 0);
4314 tracefile_state_instance_init (GTypeInstance
*instance
, gpointer g_class
)
4320 tracefile_state_finalize (LttvTracefileState
*self
)
4322 G_OBJECT_CLASS(g_type_class_peek(LTTV_TRACEFILE_CONTEXT_TYPE
))->
4323 finalize(G_OBJECT(self
));
4328 tracefile_state_class_init (LttvTracefileStateClass
*klass
)
4330 GObjectClass
*gobject_class
= G_OBJECT_CLASS(klass
);
4332 gobject_class
->finalize
= (void (*)(GObject
*self
)) tracefile_state_finalize
;
4337 lttv_tracefile_state_get_type(void)
4339 static GType type
= 0;
4341 static const GTypeInfo info
= {
4342 sizeof (LttvTracefileStateClass
),
4343 NULL
, /* base_init */
4344 NULL
, /* base_finalize */
4345 (GClassInitFunc
) tracefile_state_class_init
, /* class_init */
4346 NULL
, /* class_finalize */
4347 NULL
, /* class_data */
4348 sizeof (LttvTracefileState
),
4349 0, /* n_preallocs */
4350 (GInstanceInitFunc
) tracefile_state_instance_init
, /* instance_init */
4351 NULL
/* value handling */
4354 type
= g_type_register_static (LTTV_TRACEFILE_CONTEXT_TYPE
,
4355 "LttvTracefileStateType", &info
, 0);
4361 static void module_init()
4363 LTTV_STATE_UNNAMED
= g_quark_from_string("");
4364 LTTV_STATE_UNBRANDED
= g_quark_from_string("");
4365 LTTV_STATE_MODE_UNKNOWN
= g_quark_from_string("MODE_UNKNOWN");
4366 LTTV_STATE_USER_MODE
= g_quark_from_string("USER_MODE");
4367 LTTV_STATE_SYSCALL
= g_quark_from_string("SYSCALL");
4368 LTTV_STATE_TRAP
= g_quark_from_string("TRAP");
4369 LTTV_STATE_IRQ
= g_quark_from_string("IRQ");
4370 LTTV_STATE_SOFT_IRQ
= g_quark_from_string("SOFTIRQ");
4371 LTTV_STATE_SUBMODE_UNKNOWN
= g_quark_from_string("UNKNOWN");
4372 LTTV_STATE_SUBMODE_NONE
= g_quark_from_string("NONE");
4373 LTTV_STATE_WAIT_FORK
= g_quark_from_string("WAIT_FORK");
4374 LTTV_STATE_WAIT_CPU
= g_quark_from_string("WAIT_CPU");
4375 LTTV_STATE_EXIT
= g_quark_from_string("EXIT");
4376 LTTV_STATE_ZOMBIE
= g_quark_from_string("ZOMBIE");
4377 LTTV_STATE_WAIT
= g_quark_from_string("WAIT");
4378 LTTV_STATE_RUN
= g_quark_from_string("RUN");
4379 LTTV_STATE_DEAD
= g_quark_from_string("DEAD");
4380 LTTV_STATE_USER_THREAD
= g_quark_from_string("USER_THREAD");
4381 LTTV_STATE_KERNEL_THREAD
= g_quark_from_string("KERNEL_THREAD");
4382 LTTV_STATE_TRACEFILES
= g_quark_from_string("tracefiles");
4383 LTTV_STATE_PROCESSES
= g_quark_from_string("processes");
4384 LTTV_STATE_PROCESS
= g_quark_from_string("process");
4385 LTTV_STATE_RUNNING_PROCESS
= g_quark_from_string("running_process");
4386 LTTV_STATE_EVENT
= g_quark_from_string("event");
4387 LTTV_STATE_SAVED_STATES
= g_quark_from_string("saved states");
4388 LTTV_STATE_SAVED_STATES_TIME
= g_quark_from_string("saved states time");
4389 LTTV_STATE_TIME
= g_quark_from_string("time");
4390 LTTV_STATE_HOOKS
= g_quark_from_string("saved state hooks");
4391 LTTV_STATE_NAME_TABLES
= g_quark_from_string("name tables");
4392 LTTV_STATE_TRACE_STATE_USE_COUNT
=
4393 g_quark_from_string("trace_state_use_count");
4394 LTTV_STATE_RESOURCE_CPUS
= g_quark_from_string("cpu resource states");
4395 LTTV_STATE_RESOURCE_CPUS
= g_quark_from_string("cpu count");
4396 LTTV_STATE_RESOURCE_IRQS
= g_quark_from_string("irq resource states");
4397 LTTV_STATE_RESOURCE_SOFT_IRQS
= g_quark_from_string("soft irq resource states");
4398 LTTV_STATE_RESOURCE_TRAPS
= g_quark_from_string("trap resource states");
4399 LTTV_STATE_RESOURCE_BLKDEVS
= g_quark_from_string("blkdevs resource states");
4401 LTT_CHANNEL_FD_STATE
= g_quark_from_string("fd_state");
4402 LTT_CHANNEL_GLOBAL_STATE
= g_quark_from_string("global_state");
4403 LTT_CHANNEL_IRQ_STATE
= g_quark_from_string("irq_state");
4404 LTT_CHANNEL_MODULE_STATE
= g_quark_from_string("module_state");
4405 LTT_CHANNEL_NETIF_STATE
= g_quark_from_string("netif_state");
4406 LTT_CHANNEL_SOFTIRQ_STATE
= g_quark_from_string("softirq_state");
4407 LTT_CHANNEL_SWAP_STATE
= g_quark_from_string("swap_state");
4408 LTT_CHANNEL_SYSCALL_STATE
= g_quark_from_string("syscall_state");
4409 LTT_CHANNEL_TASK_STATE
= g_quark_from_string("task_state");
4410 LTT_CHANNEL_VM_STATE
= g_quark_from_string("vm_state");
4411 LTT_CHANNEL_KPROBE_STATE
= g_quark_from_string("kprobe_state");
4412 LTT_CHANNEL_FS
= g_quark_from_string("fs");
4413 LTT_CHANNEL_KERNEL
= g_quark_from_string("kernel");
4414 LTT_CHANNEL_MM
= g_quark_from_string("mm");
4415 LTT_CHANNEL_USERSPACE
= g_quark_from_string("userspace");
4416 LTT_CHANNEL_BLOCK
= g_quark_from_string("block");
4418 LTT_EVENT_SYSCALL_ENTRY
= g_quark_from_string("syscall_entry");
4419 LTT_EVENT_SYSCALL_EXIT
= g_quark_from_string("syscall_exit");
4420 LTT_EVENT_TRAP_ENTRY
= g_quark_from_string("trap_entry");
4421 LTT_EVENT_TRAP_EXIT
= g_quark_from_string("trap_exit");
4422 LTT_EVENT_PAGE_FAULT_ENTRY
= g_quark_from_string("page_fault_entry");
4423 LTT_EVENT_PAGE_FAULT_EXIT
= g_quark_from_string("page_fault_exit");
4424 LTT_EVENT_PAGE_FAULT_NOSEM_ENTRY
= g_quark_from_string("page_fault_nosem_entry");
4425 LTT_EVENT_PAGE_FAULT_NOSEM_EXIT
= g_quark_from_string("page_fault_nosem_exit");
4426 LTT_EVENT_IRQ_ENTRY
= g_quark_from_string("irq_entry");
4427 LTT_EVENT_IRQ_EXIT
= g_quark_from_string("irq_exit");
4428 LTT_EVENT_SOFT_IRQ_RAISE
= g_quark_from_string("softirq_raise");
4429 LTT_EVENT_SOFT_IRQ_ENTRY
= g_quark_from_string("softirq_entry");
4430 LTT_EVENT_SOFT_IRQ_EXIT
= g_quark_from_string("softirq_exit");
4431 LTT_EVENT_SCHED_SCHEDULE
= g_quark_from_string("sched_schedule");
4432 LTT_EVENT_SCHED_TRY_WAKEUP
= g_quark_from_string("sched_try_wakeup");
4433 LTT_EVENT_PROCESS_FORK
= g_quark_from_string("process_fork");
4434 LTT_EVENT_KTHREAD_CREATE
= g_quark_from_string("kthread_create");
4435 LTT_EVENT_PROCESS_EXIT
= g_quark_from_string("process_exit");
4436 LTT_EVENT_PROCESS_FREE
= g_quark_from_string("process_free");
4437 LTT_EVENT_EXEC
= g_quark_from_string("exec");
4438 LTT_EVENT_PROCESS_STATE
= g_quark_from_string("process_state");
4439 LTT_EVENT_STATEDUMP_END
= g_quark_from_string("statedump_end");
4440 LTT_EVENT_FUNCTION_ENTRY
= g_quark_from_string("function_entry");
4441 LTT_EVENT_FUNCTION_EXIT
= g_quark_from_string("function_exit");
4442 LTT_EVENT_THREAD_BRAND
= g_quark_from_string("thread_brand");
4443 LTT_EVENT_REQUEST_ISSUE
= g_quark_from_string("_blk_request_issue");
4444 LTT_EVENT_REQUEST_COMPLETE
= g_quark_from_string("_blk_request_complete");
4445 LTT_EVENT_LIST_INTERRUPT
= g_quark_from_string("interrupt");
4446 LTT_EVENT_SYS_CALL_TABLE
= g_quark_from_string("sys_call_table");
4447 LTT_EVENT_SOFTIRQ_VEC
= g_quark_from_string("softirq_vec");
4448 LTT_EVENT_KPROBE_TABLE
= g_quark_from_string("kprobe_table");
4449 LTT_EVENT_KPROBE
= g_quark_from_string("kprobe");
4450 LTT_EVENT_OPEN
= g_quark_from_string("open");
4451 LTT_EVENT_READ
= g_quark_from_string("read");
4452 LTT_EVENT_POLL_EVENT
= g_quark_from_string("poll_event");
4454 LTT_FIELD_SYSCALL_ID
= g_quark_from_string("syscall_id");
4455 LTT_FIELD_TRAP_ID
= g_quark_from_string("trap_id");
4456 LTT_FIELD_IRQ_ID
= g_quark_from_string("irq_id");
4457 LTT_FIELD_SOFT_IRQ_ID
= g_quark_from_string("softirq_id");
4458 LTT_FIELD_PREV_PID
= g_quark_from_string("prev_pid");
4459 LTT_FIELD_NEXT_PID
= g_quark_from_string("next_pid");
4460 LTT_FIELD_PREV_STATE
= g_quark_from_string("prev_state");
4461 LTT_FIELD_PARENT_PID
= g_quark_from_string("parent_pid");
4462 LTT_FIELD_CHILD_PID
= g_quark_from_string("child_pid");
4463 LTT_FIELD_PID
= g_quark_from_string("pid");
4464 LTT_FIELD_TGID
= g_quark_from_string("tgid");
4465 LTT_FIELD_CHILD_TGID
= g_quark_from_string("child_tgid");
4466 LTT_FIELD_FILENAME
= g_quark_from_string("filename");
4467 LTT_FIELD_NAME
= g_quark_from_string("name");
4468 LTT_FIELD_TYPE
= g_quark_from_string("type");
4469 LTT_FIELD_MODE
= g_quark_from_string("mode");
4470 LTT_FIELD_SUBMODE
= g_quark_from_string("submode");
4471 LTT_FIELD_STATUS
= g_quark_from_string("status");
4472 LTT_FIELD_THIS_FN
= g_quark_from_string("this_fn");
4473 LTT_FIELD_CALL_SITE
= g_quark_from_string("call_site");
4474 LTT_FIELD_MAJOR
= g_quark_from_string("major");
4475 LTT_FIELD_MINOR
= g_quark_from_string("minor");
4476 LTT_FIELD_OPERATION
= g_quark_from_string("direction");
4477 LTT_FIELD_ACTION
= g_quark_from_string("action");
4478 LTT_FIELD_ID
= g_quark_from_string("id");
4479 LTT_FIELD_ADDRESS
= g_quark_from_string("address");
4480 LTT_FIELD_SYMBOL
= g_quark_from_string("symbol");
4481 LTT_FIELD_IP
= g_quark_from_string("ip");
4482 LTT_FIELD_FD
= g_quark_from_string("fd");
4484 LTTV_CPU_UNKNOWN
= g_quark_from_string("unknown");
4485 LTTV_CPU_IDLE
= g_quark_from_string("idle");
4486 LTTV_CPU_BUSY
= g_quark_from_string("busy");
4487 LTTV_CPU_IRQ
= g_quark_from_string("irq");
4488 LTTV_CPU_SOFT_IRQ
= g_quark_from_string("softirq");
4489 LTTV_CPU_TRAP
= g_quark_from_string("trap");
4491 LTTV_IRQ_UNKNOWN
= g_quark_from_string("unknown");
4492 LTTV_IRQ_IDLE
= g_quark_from_string("idle");
4493 LTTV_IRQ_BUSY
= g_quark_from_string("busy");
4495 LTTV_BDEV_UNKNOWN
= g_quark_from_string("unknown");
4496 LTTV_BDEV_IDLE
= g_quark_from_string("idle");
4497 LTTV_BDEV_BUSY_READING
= g_quark_from_string("busy_reading");
4498 LTTV_BDEV_BUSY_WRITING
= g_quark_from_string("busy_writing");
4501 static void module_destroy()
4506 LTTV_MODULE("state", "State computation", \
4507 "Update the system state, possibly saving it at intervals", \
4508 module_init
, module_destroy
)